* [PATCH 1/2] video: Add i.MX23/28 framebuffer driver
From: Li Frank-B20596 @ 2011-02-10 9:15 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <201102100951.10977.jbe@pengutronix.de>
> > > +#define VDCTRL1 0x80
> > > +#define VDCTRL2 0x90
> > > +#define VDCTRL3 0xa0
> > > +#define VDCTRL4 0xb0
> >
> > Why you give up mx23/mx28 register define role, which generate from SOC
> > xml.
>
> Your macros prevent me from writing short and compact code. If you need
> more
> than one of these macros you always have to split each line to follow the
> 80
> columns rule. Unreadable.
>
> > There is a set header files for each mx23/mx28 module, which generate
> > from xml. I know original header files affect run time one Image.
> > But I think we can copy common part of such register definition because
> > That keep consistent with mx23/mx28 data sheet. Data sheet and header
> file
> > generate from one source xml.
> >
> > HW_<Module name>_<Register name>.
> > BM_<Module name>_<Register name>_Bit name.
>
> IMHO when I define the macros where they belong to, there is not need for
> this
> redundant HW_<Module name> or BW__<Module name> prefixes. They are just
> needless.
At first, someone complain name is longer. But during mx23/mx28 developing,
Everyone start enjoy such definition because there are not error happen about
register and bit position definition and identical map to silicon spec.
Developer needn't look up register header file when coding, just write down
Register name or bit name according to mx23/mx28 spec.
If you still think it is too long, I suggest keep HW_ and BM_ prefix to distinguish
Which one is register name, which one is bit mask.
Imx23/imx28 register have consistent convention.
HW_ is register name
BM_ is bit mask
BP_ is bit position.
BF_(x) is ((x<<BP)&BM_)
>
> Regards,
> Juergen
>
^ permalink raw reply
* [PATCH v2 0/7] clock/dpll autoidle support
From: Rajendra Nayak @ 2011-02-10 9:16 UTC (permalink / raw)
To: linux-arm-kernel
OMAP has various clock nodes and dpll's
which support hardware level autoidle.
Enabling hardware level autoidle provides
better power savings without much software
intervention.
This series does the following to help enable
hardware level autoidling using clock framework
for some of these nodes on OMAP3 and OMAP4
-1- Adds support for providing function pointers
for enabling/disabling autoidle in clkops
-2- Populates these in clkops for all OMAP3/4 dplls
-3- Enables all dpll autoidle late in boot on OMAP3 and OMAP4
-4- Adds support for mx postdivider autoidle (present
only on OMAP4) and enables it late in OMAP4 boot
Some of the patches in this series were earlier posted
and discussed as part of another series here
http://marc.info/?l=linux-omap&m=129681356402594&w=2
They are now posted as a seperate series as discussed
here
http://marc.info/?l=linux-omap&m=129713867702170&w=2
The patches are boot tested on OMAP3430sdp and
OMAP4430sdp.
The following changes since commit 100b33c8bd8a3235fd0b7948338d6cbb3db3c63d:
Linus Torvalds (1):
Linux 2.6.38-rc4
are available in the git repository at:
git://gitorious.org/omap-pm/linux.git dpll-autoidle-v2
Changes in v2:
-1- Added support for clkout_x2 autogating
-2- Populated dpll_usb_clkdcoldo_ck's missing
clksel register
Rajendra Nayak (7):
omap: clock: Check for enable/disable ops support
omap3: dpll: Populate clkops for dpll1_ck
omap: clock: Add allow_idle/deny_idle support in clkops
omap: dpll: Add allow_idle/deny_idle support for all DPLL's
omap: dpll: Enable all OMAP3/4 dpll autoidle late at boot
omap4: dpll: Add dpll api to control GATE_CTRL
omap4: dpll: Enable auto gate control for all MX postdividers
arch/arm/mach-omap2/clock.c | 25 +++++++++++---
arch/arm/mach-omap2/clock.h | 5 +++
arch/arm/mach-omap2/clock3xxx_data.c | 4 +-
arch/arm/mach-omap2/clock44xx_data.c | 54 +++++++++++++++++------------
arch/arm/mach-omap2/dpll3xxx.c | 57 +++++++++++++++++++++++++++++++
arch/arm/mach-omap2/pm34xx.c | 18 ++-------
arch/arm/mach-omap2/pm44xx.c | 4 ++
arch/arm/plat-omap/clock.c | 26 ++++++++++++++
arch/arm/plat-omap/include/plat/clock.h | 7 ++++
9 files changed, 156 insertions(+), 44 deletions(-)
^ permalink raw reply
* [PATCH v2 1/7] omap: clock: Check for enable/disable ops support
From: Rajendra Nayak @ 2011-02-10 9:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1297329400-5936-1-git-send-email-rnayak@ti.com>
Check if enable/disable operations are supported for a given
clock node before attempting to call them.
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
---
arch/arm/mach-omap2/clock.c | 14 +++++++++-----
1 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index 2a2f152..e0f017d 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -261,7 +261,8 @@ void omap2_clk_disable(struct clk *clk)
pr_debug("clock: %s: disabling in hardware\n", clk->name);
- clk->ops->disable(clk);
+ if (clk->ops && clk->ops->disable)
+ clk->ops->disable(clk);
if (clk->clkdm)
omap2_clkdm_clk_disable(clk->clkdm, clk);
@@ -312,10 +313,13 @@ int omap2_clk_enable(struct clk *clk)
}
}
- ret = clk->ops->enable(clk);
- if (ret) {
- WARN(1, "clock: %s: could not enable: %d\n", clk->name, ret);
- goto oce_err3;
+ if (clk->ops && clk->ops->enable) {
+ ret = clk->ops->enable(clk);
+ if (ret) {
+ WARN(1, "clock: %s: could not enable: %d\n",
+ clk->name, ret);
+ goto oce_err3;
+ }
}
return 0;
--
1.7.0.4
^ permalink raw reply related
* [PATCH v2 2/7] omap3: dpll: Populate clkops for dpll1_ck
From: Rajendra Nayak @ 2011-02-10 9:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1297329400-5936-2-git-send-email-rnayak@ti.com>
DPLL1 on omap3 is very similar to the rest of
the non-core dpll's.
Hence populate clkops_omap3_noncore_dpll_ops
as the clkops for it, instead of the
currently populated clkops_null.
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
---
arch/arm/mach-omap2/clock3xxx_data.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c
index 403a4a1..3e9d721 100644
--- a/arch/arm/mach-omap2/clock3xxx_data.c
+++ b/arch/arm/mach-omap2/clock3xxx_data.c
@@ -296,7 +296,7 @@ static struct dpll_data dpll1_dd = {
static struct clk dpll1_ck = {
.name = "dpll1_ck",
- .ops = &clkops_null,
+ .ops = &clkops_omap3_noncore_dpll_ops,
.parent = &sys_ck,
.dpll_data = &dpll1_dd,
.round_rate = &omap2_dpll_round_rate,
--
1.7.0.4
^ permalink raw reply related
* [PATCH v2 3/7] omap: clock: Add allow_idle/deny_idle support in clkops
From: Rajendra Nayak @ 2011-02-10 9:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1297329400-5936-3-git-send-email-rnayak@ti.com>
On OMAP various clock nodes (dpll's, mx post dividers, interface clocks)
support hardware level autogating which can be controlled from
software.
Support such functionality by adding two new function pointer
allow_idle and deny_idle in the clkops structure.
These function pointers can be populated for any clock
node which supports hardware level autogating.
Also add 2 new functions (omap_clk_enable_auotidle and
omap_clk_disable_autoidle) which can be called from
architecture specific PM core code, if hardware level
autogating (for all supported clock nodes) is to be
enabled or disabled.
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
---
arch/arm/plat-omap/clock.c | 26 ++++++++++++++++++++++++++
arch/arm/plat-omap/include/plat/clock.h | 6 ++++++
2 files changed, 32 insertions(+), 0 deletions(-)
diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c
index fc62fb5..6889c5a 100644
--- a/arch/arm/plat-omap/clock.c
+++ b/arch/arm/plat-omap/clock.c
@@ -335,6 +335,32 @@ struct clk *omap_clk_get_by_name(const char *name)
return ret;
}
+void omap_clk_enable_autoidle(void)
+{
+ struct clk *c;
+
+ mutex_lock(&clocks_mutex);
+
+ list_for_each_entry(c, &clocks, node)
+ if (c->ops->allow_idle)
+ c->ops->allow_idle(c);
+
+ mutex_unlock(&clocks_mutex);
+}
+
+void omap_clk_disable_autoidle(void)
+{
+ struct clk *c;
+
+ mutex_lock(&clocks_mutex);
+
+ list_for_each_entry(c, &clocks, node)
+ if (c->ops->deny_idle)
+ c->ops->deny_idle(c);
+
+ mutex_unlock(&clocks_mutex);
+}
+
/*
* Low level helpers
*/
diff --git a/arch/arm/plat-omap/include/plat/clock.h b/arch/arm/plat-omap/include/plat/clock.h
index 8eb0ada..167f1e0 100644
--- a/arch/arm/plat-omap/include/plat/clock.h
+++ b/arch/arm/plat-omap/include/plat/clock.h
@@ -25,6 +25,8 @@ struct clockdomain;
* @disable: fn ptr that enables the current clock in hardware
* @find_idlest: function returning the IDLEST register for the clock's IP blk
* @find_companion: function returning the "companion" clk reg for the clock
+ * @allow_idle: fn ptr that enables autoidle for the current clock in hardware
+ * @deny_idle: fn ptr that disables autoidle for the current clock in hardware
*
* A "companion" clk is an accompanying clock to the one being queried
* that must be enabled for the IP module connected to the clock to
@@ -42,6 +44,8 @@ struct clkops {
u8 *, u8 *);
void (*find_companion)(struct clk *, void __iomem **,
u8 *);
+ void (*allow_idle)(struct clk *);
+ void (*deny_idle)(struct clk *);
};
#ifdef CONFIG_ARCH_OMAP2PLUS
@@ -292,6 +296,8 @@ extern void clk_init_cpufreq_table(struct cpufreq_frequency_table **table);
extern void clk_exit_cpufreq_table(struct cpufreq_frequency_table **table);
#endif
extern struct clk *omap_clk_get_by_name(const char *name);
+extern void omap_clk_enable_autoidle(void);
+extern void omap_clk_disable_autoidle(void);
extern const struct clkops clkops_null;
--
1.7.0.4
^ permalink raw reply related
* [PATCH v2 4/7] omap: dpll: Add allow_idle/deny_idle support for all DPLL's
From: Rajendra Nayak @ 2011-02-10 9:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1297329400-5936-4-git-send-email-rnayak@ti.com>
All OMAP3/4 dpll's support hardware level autogating.
Populate allow_idle/deny_idle function pointers for all
DPLL's in clkops.
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
---
arch/arm/mach-omap2/clock.c | 8 +++++++-
arch/arm/mach-omap2/clock.h | 1 +
arch/arm/mach-omap2/clock3xxx_data.c | 2 +-
arch/arm/mach-omap2/clock44xx_data.c | 2 +-
4 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index e0f017d..909e3c5 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -377,10 +377,16 @@ int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent)
const struct clkops clkops_omap3_noncore_dpll_ops = {
.enable = omap3_noncore_dpll_enable,
.disable = omap3_noncore_dpll_disable,
+ .allow_idle = omap3_dpll_allow_idle,
+ .deny_idle = omap3_dpll_deny_idle,
};
-#endif
+const struct clkops clkops_omap3_core_dpll_ops = {
+ .allow_idle = omap3_dpll_allow_idle,
+ .deny_idle = omap3_dpll_deny_idle,
+};
+#endif
/*
* OMAP2+ clock reset and init functions
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
index 896584e..2a939e5 100644
--- a/arch/arm/mach-omap2/clock.h
+++ b/arch/arm/mach-omap2/clock.h
@@ -146,5 +146,6 @@ extern void omap2_clk_exit_cpufreq_table(struct cpufreq_frequency_table **table)
#endif
extern const struct clkops clkops_omap3_noncore_dpll_ops;
+extern const struct clkops clkops_omap3_core_dpll_ops;
#endif
diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c
index 3e9d721..7cf89f8 100644
--- a/arch/arm/mach-omap2/clock3xxx_data.c
+++ b/arch/arm/mach-omap2/clock3xxx_data.c
@@ -429,7 +429,7 @@ static struct dpll_data dpll3_dd = {
static struct clk dpll3_ck = {
.name = "dpll3_ck",
- .ops = &clkops_null,
+ .ops = &clkops_omap3_core_dpll_ops,
.parent = &sys_ck,
.dpll_data = &dpll3_dd,
.round_rate = &omap2_dpll_round_rate,
diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c
index de9ec8d..b843b6e 100644
--- a/arch/arm/mach-omap2/clock44xx_data.c
+++ b/arch/arm/mach-omap2/clock44xx_data.c
@@ -443,7 +443,7 @@ static struct clk dpll_core_ck = {
.parent = &sys_clkin_ck,
.dpll_data = &dpll_core_dd,
.init = &omap2_init_dpll_parent,
- .ops = &clkops_null,
+ .ops = &clkops_omap3_core_dpll_ops,
.recalc = &omap3_dpll_recalc,
};
--
1.7.0.4
^ permalink raw reply related
* [PATCH v2 5/7] omap: dpll: Enable all OMAP3/4 dpll autoidle late at boot
From: Rajendra Nayak @ 2011-02-10 9:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1297329400-5936-5-git-send-email-rnayak@ti.com>
Enable all dpll autoidle for OMAP4 and OMAP3 (OMAP3
already had dpll autoidle turned on, but was done
using low level cm accessor apis).
On OMAP3, replace the cm accessor apis doing this
with the now available support for doing this in
clock framework, using omap_clk_enable_autoidle().
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
---
arch/arm/mach-omap2/pm34xx.c | 18 ++++--------------
arch/arm/mach-omap2/pm44xx.c | 4 ++++
2 files changed, 8 insertions(+), 14 deletions(-)
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 2f864e4..5a101fa 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -38,6 +38,7 @@
#include <plat/prcm.h>
#include <plat/gpmc.h>
#include <plat/dma.h>
+#include <plat/clock.h>
#include <asm/tlbflush.h>
@@ -814,21 +815,10 @@ static void __init prcm_setup_regs(void)
omap_ctrl_writel(OMAP3430_AUTOIDLE_MASK, OMAP2_CONTROL_SYSCONFIG);
/*
- * Set all plls to autoidle. This is needed until autoidle is
- * enabled by clockfw
+ * Set all plls to autoidle.
+ * TODO: Add all the iclk autoidles in here as well.
*/
- omap2_cm_write_mod_reg(1 << OMAP3430_AUTO_IVA2_DPLL_SHIFT,
- OMAP3430_IVA2_MOD, CM_AUTOIDLE2);
- omap2_cm_write_mod_reg(1 << OMAP3430_AUTO_MPU_DPLL_SHIFT,
- MPU_MOD,
- CM_AUTOIDLE2);
- omap2_cm_write_mod_reg((1 << OMAP3430_AUTO_PERIPH_DPLL_SHIFT) |
- (1 << OMAP3430_AUTO_CORE_DPLL_SHIFT),
- PLL_MOD,
- CM_AUTOIDLE);
- omap2_cm_write_mod_reg(1 << OMAP3430ES2_AUTO_PERIPH2_DPLL_SHIFT,
- PLL_MOD,
- CM_AUTOIDLE2);
+ omap_clk_enable_autoidle();
/*
* Enable control of expternal oscillator through
diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
index 76cfff2..8431d41 100644
--- a/arch/arm/mach-omap2/pm44xx.c
+++ b/arch/arm/mach-omap2/pm44xx.c
@@ -15,6 +15,7 @@
#include <linux/list.h>
#include <linux/err.h>
#include <linux/slab.h>
+#include <plat/clock.h>
#include "powerdomain.h"
#include <mach/omap4-common.h>
@@ -111,6 +112,9 @@ static int __init omap4_pm_init(void)
pr_err("Failed to setup powerdomains\n");
goto err2;
}
+
+ /* Enable autoidle for all clks which support it*/
+ omap_clk_enable_autoidle();
#endif
#ifdef CONFIG_SUSPEND
--
1.7.0.4
^ permalink raw reply related
* [PATCH v2 6/7] omap4: dpll: Add dpll api to control GATE_CTRL
From: Rajendra Nayak @ 2011-02-10 9:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1297329400-5936-6-git-send-email-rnayak@ti.com>
On OMAP4, the dpll post divider outputs (MX outputs)
along with clockout_x2 output provide a way to allow/deny
hardware level autogating.
Allowing autoidle would mean that the hw would autogate
this clock when there is no dependency for it.
Denying idle would mean that this clock output will be
forced to stay enabled.
Add dpll api's to read/allow/deny idle control
for these dpll mx postdividers.
NOTE: The gatectrl bit set to 0 allows gatectrl,
and the bit set to 1 denies gatectrl.
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
---
arch/arm/mach-omap2/clock.h | 3 ++
arch/arm/mach-omap2/dpll3xxx.c | 57 +++++++++++++++++++++++++++++++
arch/arm/plat-omap/include/plat/clock.h | 1 +
3 files changed, 61 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
index 2a939e5..c450d69 100644
--- a/arch/arm/mach-omap2/clock.h
+++ b/arch/arm/mach-omap2/clock.h
@@ -65,6 +65,9 @@ u32 omap3_dpll_autoidle_read(struct clk *clk);
int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate);
int omap3_noncore_dpll_enable(struct clk *clk);
void omap3_noncore_dpll_disable(struct clk *clk);
+int omap4_dpllmx_gatectrl_read(struct clk *clk);
+void omap4_dpllmx_allow_gatectrl(struct clk *clk);
+void omap4_dpllmx_deny_gatectrl(struct clk *clk);
#ifdef CONFIG_OMAP_RESET_CLOCKS
void omap2_clk_disable_unused(struct clk *clk);
diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c
index f77022b..18912cf 100644
--- a/arch/arm/mach-omap2/dpll3xxx.c
+++ b/arch/arm/mach-omap2/dpll3xxx.c
@@ -34,6 +34,7 @@
#include "clock.h"
#include "cm2xxx_3xxx.h"
#include "cm-regbits-34xx.h"
+#include "cm-regbits-44xx.h"
/* CM_AUTOIDLE_PLL*.AUTO_* bit values */
#define DPLL_AUTOIDLE_DISABLE 0x0
@@ -612,3 +613,59 @@ unsigned long omap3_clkoutx2_recalc(struct clk *clk)
rate = clk->parent->rate * 2;
return rate;
}
+
+/* Supported only on OMAP4 */
+int omap4_dpllmx_gatectrl_read(struct clk *clk)
+{
+ u32 v;
+ u32 mask;
+
+ if (!clk || !clk->clksel_reg || !cpu_is_omap44xx())
+ return -EINVAL;
+
+ mask = clk->flags & CLOCK_CLKOUTX2 ?
+ OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK :
+ OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK;
+
+ v = __raw_readl(clk->clksel_reg);
+ v &= mask;
+ v >>= __ffs(mask);
+
+ return v;
+}
+
+void omap4_dpllmx_allow_gatectrl(struct clk *clk)
+{
+ u32 v;
+ u32 mask;
+
+ if (!clk || !clk->clksel_reg || !cpu_is_omap44xx())
+ return;
+
+ mask = clk->flags & CLOCK_CLKOUTX2 ?
+ OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK :
+ OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK;
+
+ v = __raw_readl(clk->clksel_reg);
+ /* Clear the bit to allow gatectrl */
+ v &= ~mask;
+ __raw_writel(v, clk->clksel_reg);
+}
+
+void omap4_dpllmx_deny_gatectrl(struct clk *clk)
+{
+ u32 v;
+ u32 mask;
+
+ if (!clk || !clk->clksel_reg || !cpu_is_omap44xx())
+ return;
+
+ mask = clk->flags & CLOCK_CLKOUTX2 ?
+ OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK :
+ OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK;
+
+ v = __raw_readl(clk->clksel_reg);
+ /* Set the bit to deny gatectrl */
+ v |= mask;
+ __raw_writel(v, clk->clksel_reg);
+}
diff --git a/arch/arm/plat-omap/include/plat/clock.h b/arch/arm/plat-omap/include/plat/clock.h
index 167f1e0..f2807dc 100644
--- a/arch/arm/plat-omap/include/plat/clock.h
+++ b/arch/arm/plat-omap/include/plat/clock.h
@@ -181,6 +181,7 @@ struct dpll_data {
#define CLOCK_NO_IDLE_PARENT (1 << 2)
#define ENABLE_ON_INIT (1 << 3) /* Enable upon framework init */
#define INVERT_ENABLE (1 << 4) /* 0 enables, 1 disables */
+#define CLOCK_CLKOUTX2 (1 << 5)
/**
* struct clk - OMAP struct clk
--
1.7.0.4
^ permalink raw reply related
* [PATCH v2 7/7] omap4: dpll: Enable auto gate control for all MX postdividers
From: Rajendra Nayak @ 2011-02-10 9:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1297329400-5936-7-git-send-email-rnayak@ti.com>
Enable hardware gate control for all dpll MX and X2 postdividers.
This requires the allow_idle/deny_idle functions to be
populated for all clock nodes (mx/x2 post dividers) in
clkops.
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
---
arch/arm/mach-omap2/clock.c | 5 +++
arch/arm/mach-omap2/clock.h | 1 +
arch/arm/mach-omap2/clock44xx_data.c | 52 +++++++++++++++++++--------------
3 files changed, 36 insertions(+), 22 deletions(-)
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index 909e3c5..6ec4c67 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -388,6 +388,11 @@ const struct clkops clkops_omap3_core_dpll_ops = {
#endif
+const struct clkops clkops_omap4_dpllmx_ops = {
+ .allow_idle = omap4_dpllmx_allow_gatectrl,
+ .deny_idle = omap4_dpllmx_deny_gatectrl,
+};
+
/*
* OMAP2+ clock reset and init functions
*/
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
index c450d69..0725a6a 100644
--- a/arch/arm/mach-omap2/clock.h
+++ b/arch/arm/mach-omap2/clock.h
@@ -150,5 +150,6 @@ extern void omap2_clk_exit_cpufreq_table(struct cpufreq_frequency_table **table)
extern const struct clkops clkops_omap3_noncore_dpll_ops;
extern const struct clkops clkops_omap3_core_dpll_ops;
+extern const struct clkops clkops_omap4_dpllmx_ops;
#endif
diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c
index b843b6e..dcbe105 100644
--- a/arch/arm/mach-omap2/clock44xx_data.c
+++ b/arch/arm/mach-omap2/clock44xx_data.c
@@ -278,8 +278,10 @@ static struct clk dpll_abe_ck = {
static struct clk dpll_abe_x2_ck = {
.name = "dpll_abe_x2_ck",
.parent = &dpll_abe_ck,
- .ops = &clkops_null,
+ .flags = CLOCK_CLKOUTX2,
+ .ops = &clkops_omap4_dpllmx_ops,
.recalc = &omap3_clkoutx2_recalc,
+ .clksel_reg = OMAP4430_CM_DIV_M2_DPLL_ABE,
};
static const struct clksel_rate div31_1to31_rates[] = {
@@ -328,7 +330,7 @@ static struct clk dpll_abe_m2x2_ck = {
.clksel = dpll_abe_m2x2_div,
.clksel_reg = OMAP4430_CM_DIV_M2_DPLL_ABE,
.clksel_mask = OMAP4430_DPLL_CLKOUT_DIV_MASK,
- .ops = &clkops_null,
+ .ops = &clkops_omap4_dpllmx_ops,
.recalc = &omap2_clksel_recalc,
.round_rate = &omap2_clksel_round_rate,
.set_rate = &omap2_clksel_set_rate,
@@ -395,7 +397,7 @@ static struct clk dpll_abe_m3x2_ck = {
.clksel = dpll_abe_m2x2_div,
.clksel_reg = OMAP4430_CM_DIV_M3_DPLL_ABE,
.clksel_mask = OMAP4430_DPLL_CLKOUTHIF_DIV_MASK,
- .ops = &clkops_null,
+ .ops = &clkops_omap4_dpllmx_ops,
.recalc = &omap2_clksel_recalc,
.round_rate = &omap2_clksel_round_rate,
.set_rate = &omap2_clksel_set_rate,
@@ -450,6 +452,7 @@ static struct clk dpll_core_ck = {
static struct clk dpll_core_x2_ck = {
.name = "dpll_core_x2_ck",
.parent = &dpll_core_ck,
+ .flags = CLOCK_CLKOUTX2,
.ops = &clkops_null,
.recalc = &omap3_clkoutx2_recalc,
};
@@ -465,7 +468,7 @@ static struct clk dpll_core_m6x2_ck = {
.clksel = dpll_core_m6x2_div,
.clksel_reg = OMAP4430_CM_DIV_M6_DPLL_CORE,
.clksel_mask = OMAP4430_HSDIVIDER_CLKOUT3_DIV_MASK,
- .ops = &clkops_null,
+ .ops = &clkops_omap4_dpllmx_ops,
.recalc = &omap2_clksel_recalc,
.round_rate = &omap2_clksel_round_rate,
.set_rate = &omap2_clksel_set_rate,
@@ -495,7 +498,7 @@ static struct clk dpll_core_m2_ck = {
.clksel = dpll_core_m2_div,
.clksel_reg = OMAP4430_CM_DIV_M2_DPLL_CORE,
.clksel_mask = OMAP4430_DPLL_CLKOUT_DIV_MASK,
- .ops = &clkops_null,
+ .ops = &clkops_omap4_dpllmx_ops,
.recalc = &omap2_clksel_recalc,
.round_rate = &omap2_clksel_round_rate,
.set_rate = &omap2_clksel_set_rate,
@@ -515,7 +518,7 @@ static struct clk dpll_core_m5x2_ck = {
.clksel = dpll_core_m6x2_div,
.clksel_reg = OMAP4430_CM_DIV_M5_DPLL_CORE,
.clksel_mask = OMAP4430_HSDIVIDER_CLKOUT2_DIV_MASK,
- .ops = &clkops_null,
+ .ops = &clkops_omap4_dpllmx_ops,
.recalc = &omap2_clksel_recalc,
.round_rate = &omap2_clksel_round_rate,
.set_rate = &omap2_clksel_set_rate,
@@ -581,7 +584,7 @@ static struct clk dpll_core_m4x2_ck = {
.clksel = dpll_core_m6x2_div,
.clksel_reg = OMAP4430_CM_DIV_M4_DPLL_CORE,
.clksel_mask = OMAP4430_HSDIVIDER_CLKOUT1_DIV_MASK,
- .ops = &clkops_null,
+ .ops = &clkops_omap4_dpllmx_ops,
.recalc = &omap2_clksel_recalc,
.round_rate = &omap2_clksel_round_rate,
.set_rate = &omap2_clksel_set_rate,
@@ -606,7 +609,7 @@ static struct clk dpll_abe_m2_ck = {
.clksel = dpll_abe_m2_div,
.clksel_reg = OMAP4430_CM_DIV_M2_DPLL_ABE,
.clksel_mask = OMAP4430_DPLL_CLKOUT_DIV_MASK,
- .ops = &clkops_null,
+ .ops = &clkops_omap4_dpllmx_ops,
.recalc = &omap2_clksel_recalc,
.round_rate = &omap2_clksel_round_rate,
.set_rate = &omap2_clksel_set_rate,
@@ -632,7 +635,7 @@ static struct clk dpll_core_m7x2_ck = {
.clksel = dpll_core_m6x2_div,
.clksel_reg = OMAP4430_CM_DIV_M7_DPLL_CORE,
.clksel_mask = OMAP4430_HSDIVIDER_CLKOUT4_DIV_MASK,
- .ops = &clkops_null,
+ .ops = &clkops_omap4_dpllmx_ops,
.recalc = &omap2_clksel_recalc,
.round_rate = &omap2_clksel_round_rate,
.set_rate = &omap2_clksel_set_rate,
@@ -689,6 +692,7 @@ static struct clk dpll_iva_ck = {
static struct clk dpll_iva_x2_ck = {
.name = "dpll_iva_x2_ck",
.parent = &dpll_iva_ck,
+ .flags = CLOCK_CLKOUTX2,
.ops = &clkops_null,
.recalc = &omap3_clkoutx2_recalc,
};
@@ -704,7 +708,7 @@ static struct clk dpll_iva_m4x2_ck = {
.clksel = dpll_iva_m4x2_div,
.clksel_reg = OMAP4430_CM_DIV_M4_DPLL_IVA,
.clksel_mask = OMAP4430_HSDIVIDER_CLKOUT1_DIV_MASK,
- .ops = &clkops_null,
+ .ops = &clkops_omap4_dpllmx_ops,
.recalc = &omap2_clksel_recalc,
.round_rate = &omap2_clksel_round_rate,
.set_rate = &omap2_clksel_set_rate,
@@ -716,7 +720,7 @@ static struct clk dpll_iva_m5x2_ck = {
.clksel = dpll_iva_m4x2_div,
.clksel_reg = OMAP4430_CM_DIV_M5_DPLL_IVA,
.clksel_mask = OMAP4430_HSDIVIDER_CLKOUT2_DIV_MASK,
- .ops = &clkops_null,
+ .ops = &clkops_omap4_dpllmx_ops,
.recalc = &omap2_clksel_recalc,
.round_rate = &omap2_clksel_round_rate,
.set_rate = &omap2_clksel_set_rate,
@@ -764,7 +768,7 @@ static struct clk dpll_mpu_m2_ck = {
.clksel = dpll_mpu_m2_div,
.clksel_reg = OMAP4430_CM_DIV_M2_DPLL_MPU,
.clksel_mask = OMAP4430_DPLL_CLKOUT_DIV_MASK,
- .ops = &clkops_null,
+ .ops = &clkops_omap4_dpllmx_ops,
.recalc = &omap2_clksel_recalc,
.round_rate = &omap2_clksel_round_rate,
.set_rate = &omap2_clksel_set_rate,
@@ -837,7 +841,7 @@ static struct clk dpll_per_m2_ck = {
.clksel = dpll_per_m2_div,
.clksel_reg = OMAP4430_CM_DIV_M2_DPLL_PER,
.clksel_mask = OMAP4430_DPLL_CLKOUT_DIV_MASK,
- .ops = &clkops_null,
+ .ops = &clkops_omap4_dpllmx_ops,
.recalc = &omap2_clksel_recalc,
.round_rate = &omap2_clksel_round_rate,
.set_rate = &omap2_clksel_set_rate,
@@ -846,8 +850,10 @@ static struct clk dpll_per_m2_ck = {
static struct clk dpll_per_x2_ck = {
.name = "dpll_per_x2_ck",
.parent = &dpll_per_ck,
- .ops = &clkops_null,
+ .flags = CLOCK_CLKOUTX2,
+ .ops = &clkops_omap4_dpllmx_ops,
.recalc = &omap3_clkoutx2_recalc,
+ .clksel_reg = OMAP4430_CM_DIV_M2_DPLL_PER,
};
static const struct clksel dpll_per_m2x2_div[] = {
@@ -861,7 +867,7 @@ static struct clk dpll_per_m2x2_ck = {
.clksel = dpll_per_m2x2_div,
.clksel_reg = OMAP4430_CM_DIV_M2_DPLL_PER,
.clksel_mask = OMAP4430_DPLL_CLKOUT_DIV_MASK,
- .ops = &clkops_null,
+ .ops = &clkops_omap4_dpllmx_ops,
.recalc = &omap2_clksel_recalc,
.round_rate = &omap2_clksel_round_rate,
.set_rate = &omap2_clksel_set_rate,
@@ -887,7 +893,7 @@ static struct clk dpll_per_m4x2_ck = {
.clksel = dpll_per_m2x2_div,
.clksel_reg = OMAP4430_CM_DIV_M4_DPLL_PER,
.clksel_mask = OMAP4430_HSDIVIDER_CLKOUT1_DIV_MASK,
- .ops = &clkops_null,
+ .ops = &clkops_omap4_dpllmx_ops,
.recalc = &omap2_clksel_recalc,
.round_rate = &omap2_clksel_round_rate,
.set_rate = &omap2_clksel_set_rate,
@@ -899,7 +905,7 @@ static struct clk dpll_per_m5x2_ck = {
.clksel = dpll_per_m2x2_div,
.clksel_reg = OMAP4430_CM_DIV_M5_DPLL_PER,
.clksel_mask = OMAP4430_HSDIVIDER_CLKOUT2_DIV_MASK,
- .ops = &clkops_null,
+ .ops = &clkops_omap4_dpllmx_ops,
.recalc = &omap2_clksel_recalc,
.round_rate = &omap2_clksel_round_rate,
.set_rate = &omap2_clksel_set_rate,
@@ -911,7 +917,7 @@ static struct clk dpll_per_m6x2_ck = {
.clksel = dpll_per_m2x2_div,
.clksel_reg = OMAP4430_CM_DIV_M6_DPLL_PER,
.clksel_mask = OMAP4430_HSDIVIDER_CLKOUT3_DIV_MASK,
- .ops = &clkops_null,
+ .ops = &clkops_omap4_dpllmx_ops,
.recalc = &omap2_clksel_recalc,
.round_rate = &omap2_clksel_round_rate,
.set_rate = &omap2_clksel_set_rate,
@@ -923,7 +929,7 @@ static struct clk dpll_per_m7x2_ck = {
.clksel = dpll_per_m2x2_div,
.clksel_reg = OMAP4430_CM_DIV_M7_DPLL_PER,
.clksel_mask = OMAP4430_HSDIVIDER_CLKOUT4_DIV_MASK,
- .ops = &clkops_null,
+ .ops = &clkops_omap4_dpllmx_ops,
.recalc = &omap2_clksel_recalc,
.round_rate = &omap2_clksel_round_rate,
.set_rate = &omap2_clksel_set_rate,
@@ -964,6 +970,7 @@ static struct clk dpll_unipro_ck = {
static struct clk dpll_unipro_x2_ck = {
.name = "dpll_unipro_x2_ck",
.parent = &dpll_unipro_ck,
+ .flags = CLOCK_CLKOUTX2,
.ops = &clkops_null,
.recalc = &omap3_clkoutx2_recalc,
};
@@ -979,7 +986,7 @@ static struct clk dpll_unipro_m2x2_ck = {
.clksel = dpll_unipro_m2x2_div,
.clksel_reg = OMAP4430_CM_DIV_M2_DPLL_UNIPRO,
.clksel_mask = OMAP4430_DPLL_CLKOUT_DIV_MASK,
- .ops = &clkops_null,
+ .ops = &clkops_omap4_dpllmx_ops,
.recalc = &omap2_clksel_recalc,
.round_rate = &omap2_clksel_round_rate,
.set_rate = &omap2_clksel_set_rate,
@@ -1028,7 +1035,8 @@ static struct clk dpll_usb_ck = {
static struct clk dpll_usb_clkdcoldo_ck = {
.name = "dpll_usb_clkdcoldo_ck",
.parent = &dpll_usb_ck,
- .ops = &clkops_null,
+ .ops = &clkops_omap4_dpllmx_ops,
+ .clksel_reg = OMAP4430_CM_CLKDCOLDO_DPLL_USB,
.recalc = &followparent_recalc,
};
@@ -1043,7 +1051,7 @@ static struct clk dpll_usb_m2_ck = {
.clksel = dpll_usb_m2_div,
.clksel_reg = OMAP4430_CM_DIV_M2_DPLL_USB,
.clksel_mask = OMAP4430_DPLL_CLKOUT_DIV_0_6_MASK,
- .ops = &clkops_null,
+ .ops = &clkops_omap4_dpllmx_ops,
.recalc = &omap2_clksel_recalc,
.round_rate = &omap2_clksel_round_rate,
.set_rate = &omap2_clksel_set_rate,
--
1.7.0.4
^ permalink raw reply related
* [PATCH] i.MX23/28 framebuffer driver
From: Domenico Andreoli @ 2011-02-10 9:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110209153716.GN9041@pengutronix.de>
Hi Sascha,
On Wed, Feb 09, 2011 at 04:37:16PM +0100, ext Sascha Hauer wrote:
> Hi Arnd,
>
> On Wed, Feb 09, 2011 at 03:47:11PM +0100, Arnd Bergmann wrote:
> >
> > Did you consider making the driver a KMS driver instead of
> > a frame buffer? I think the recommendation these days is
> > to start out with KMS for new drivers, which will be somewhat
> > simpler and give you a frame buffer device as well. I don't
> > think that there is a need to change over any drivers from
> > fb to kms though, since you've already done the work.
>
> I tried doing so for the i.MX51 which supports multiple displays on dvi
> and vga outputs and thus could make good use of KMS and friends. Anyway,
> I got stuck quite fast. The KMS stuff is tightly coupled with DRM/DRI
> and needs many many callbacks to implement. Additionally the userspace
> tools expect a nvidia/amd/intel driver and do not have a generic
> fallback. I think this stuff is good for implementing a full blown
> graphics driver, but is lacking support for simple framebuffer grapics.
> I'd love to go this way but it still requires a lot of work.
I will get the i.MX28 EVK within a couple of weeks. I'm curious of KMS,
which I don't know at all, and I would like to work on it. We could
join the efforts. What do you think?
Best regards,
Domenico
^ permalink raw reply
* [PXA] A question about PXA310 cpufreq for 806Mhz
From: Axel Lin @ 2011-02-10 9:22 UTC (permalink / raw)
To: linux-arm-kernel
hi,
I have a device equipped with 806Mhz PXA310 cpu.
After bootup, the system shows it is running with 624Mhz.
# cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq
624000
# cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq
624000
# cat /proc/cpuinfo
Processor : XScale-V3 based processor rev 2 (v5l)
BogoMIPS : 623.00
Features : swp half thumb fastmult edsp iwmmxt
CPU implementer : 0x69
CPU architecture: 5TE
CPU variant : 0x0
CPU part : 0x689
CPU revision : 2
Hardware : Getac PS236 Handheld Platform
Revision : 0000
Serial : 0000000000000000
I fix it by below patch and it looks ok on my device.
I'm not sure if this is a proper way to fix it, I appreciate to see your comments.
It is strange that I cannot find 806Mhz PXA31x CPU
in the datasheet Section 6.1 PXA3XX Processor Differences.
But in Section 6.7, Table 55: PXA31x Core PLL, Turbo and Run Mode Output Frequencies,
I do see 806Mhz support on the table.
Regards,
Axel
diff --git a/arch/arm/mach-pxa/cpufreq-pxa3xx.c b/arch/arm/mach-pxa/cpufreq-pxa3xx.c
index 88fbec0..abf7d7a 100644
--- a/arch/arm/mach-pxa/cpufreq-pxa3xx.c
+++ b/arch/arm/mach-pxa/cpufreq-pxa3xx.c
@@ -210,15 +210,14 @@ static int pxa3xx_cpufreq_init(struct cpufreq_policy *policy)
/* set default policy and cpuinfo */
policy->cpuinfo.min_freq = 104000;
- policy->cpuinfo.max_freq = (cpu_is_pxa320()) ? 806000 : 624000;
+ policy->cpuinfo.max_freq = (cpu_is_pxa300()) ? 624000 : 806000;
policy->cpuinfo.transition_latency = 1000; /* FIXME: 1 ms, assumed */
policy->max = pxa3xx_get_clk_frequency_khz(0);
policy->cur = policy->min = policy->max;
- if (cpu_is_pxa300() || cpu_is_pxa310())
+ if (cpu_is_pxa300())
ret = setup_freqs_table(policy, ARRAY_AND_SIZE(pxa300_freqs));
-
- if (cpu_is_pxa320())
+ else if (cpu_is_pxa310() || cpu_is_pxa320())
ret = setup_freqs_table(policy, ARRAY_AND_SIZE(pxa320_freqs));
if (ret) {
^ permalink raw reply related
* [PATCH 1/2] video: Add i.MX23/28 framebuffer driver
From: Li Frank-B20596 @ 2011-02-10 9:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1297257651-8002-2-git-send-email-s.hauer@pengutronix.de>
> +
> + /* if it was disabled, re-enable the mode again */
> + reg = readl(host->base + CTRL);
> + reg |= CTRL_DOTCLK_MODE;
> + writel(reg, host->base + CTRL);
writel(CTRL_DOTCLK_MODE, host->base + CTRL_SET)
CTRL_SET is CTRL+0x4
SET and CLR register is easier than Read and write back.
^ permalink raw reply
* [RFC, PATCH 3/3] clk: add warnings for incorrect enable/prepare semantics
From: Richard Zhao @ 2011-02-10 9:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1297233693.243373.411051105619.3.gpush@pororo>
Hi Jeremy,
On Wed, Feb 09, 2011 at 02:41:33PM +0800, Jeremy Kerr wrote:
> This change adds warnings to check for:
>
> 1) enabling a clock that hasn't been prepared; and
>
> 2) unpreparing a clock that is still enabled
>
> While the correctness can't be guaranteed, the warnings should cover
> most situations, and won't indicate false positives.
>
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
>
> ---
> drivers/clk/clk.c | 4 ++++
> 1 file changed, 4 insertions(+)
>
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index bbbdb0d..8c96623 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -29,6 +29,8 @@ EXPORT_SYMBOL_GPL(clk_prepare);
>
> void clk_unprepare(struct clk *clk)
> {
> + WARN_ON(clk->enable_count != 0);
> +
Other drivers may be using the clock and increased the enable_count.
This check may be moved to where we actually do unprepare.
Thanks
Richard
> mutex_lock(&clk->prepare_lock);
>
> WARN_ON(clk->prepare_count == 0);
> @@ -45,6 +47,8 @@ int clk_enable(struct clk *clk)
> unsigned long flags;
> int ret = 0;
>
> + WARN_ON(clk->prepare_count == 0);
> +
> spin_lock_irqsave(&clk->enable_lock, flags);
> if (clk->enable_count == 0 && clk->ops->enable)
> ret = clk->ops->enable(clk);
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>
^ permalink raw reply
* ARM: mmp: add Trizeps6 board support
From: Yupeng Schneider @ 2011-02-10 9:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <AANLkTi=AMOifp3nQqohk5fW0JTWPp7VNRgutp0h7bBxH@mail.gmail.com>
ok, i got it.
2011/2/10 Eric Miao <eric.y.miao@gmail.com>
> On Thu, Feb 10, 2011 at 8:39 AM, Yupeng Schneider
> <yupeng.schneider@ipms.fraunhofer.de> wrote:
> > Hello Eric,
> >
> > i have made a BSP for the Trizeps6 Modul based on pxa168 Processor. Here
> > is just a part of it, which now could be published, the other part could
> > not because of NDA. Now i have a question:
> >
> > The Trizeps6 uses the same baseboard (ConXS) as the Trizeps4. Where would
> > u to place the file conxs.c to make it accessible for mach-pxa und
> > mach-mmp?
> >
>
> I would recommend arch/arm/plat-pxa/ or arch/arm/common/ at this moment.
>
> > yours,
> > Y.
> >
> >
> >
> >
> >
> >
> >
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20110210/b3774127/attachment-0001.html>
^ permalink raw reply
* [PATCH 1/2] video: Add i.MX23/28 framebuffer driver
From: Juergen Beisert @ 2011-02-10 9:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <09EC74FE2C9E8444BF2FF67BD36E1D69167919@039-SN1MPN1-003.039d.mgd.msft.net>
Li Frank-B20596 wrote:
> > +
> > + /* if it was disabled, re-enable the mode again */
> > + reg = readl(host->base + CTRL);
> > + reg |= CTRL_DOTCLK_MODE;
> > + writel(reg, host->base + CTRL);
>
> writel(CTRL_DOTCLK_MODE, host->base + CTRL_SET)
> CTRL_SET is CTRL+0x4
> SET and CLR register is easier than Read and write back.
But you must always check, if the register really has such a SET and CLEAR
feature. Not all registers have this feature...
But in this case you are right.
But I would prefer:
#define SET 4
#define CLEAR 8
[...]
writel(CTRL_DOTCLK_MODE, host->base + CTRL + SET)
:-)
Regards,
Juergen
--
Pengutronix e.K. | Juergen Beisert |
Linux Solutions for Science and Industry | Phone: +49-8766-939 228 |
Vertretung Sued/Muenchen, Germany | Fax: +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de/ |
^ permalink raw reply
* [PATCH V3 1/1] ST SPEAr: PCIE gadget suppport
From: pratyush @ 2011-02-10 9:49 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110209152926.0126ac97.akpm@linux-foundation.org>
On 2/10/2011 4:59 AM, Andrew Morton wrote:
> On Thu, 3 Feb 2011 19:39:09 +0530
> Pratyush Anand <pratyush.anand@st.com> wrote:
>
>> This is a configurable gadget. can be configured by configfs interface. Any
>> IP available at PCIE bus can be programmed to be used by host
>> controller.It supoorts both INTX and MSI.
>> By default, gadget is configured for INTX and SYSRAM1 is mapped to BAR0
>> with size 0x1000
>>
>>
>> ...
>>
>> --- /dev/null
>> +++ b/Documentation/ABI/testing/configfs-spear-pcie-gadget
>> @@ -0,0 +1,30 @@
>> +What: /config/pcie-gadget
>> +Date: Feb 2011
>> +KernelVersion: 2.6.37
>> +Contact: Pratyush Anand <pratyush.anand@st.com>
>> +Description:
>> +
>> + Interface is used to configure selected dual mode pcie controller
>> + as device and then program its various registers to configure it
>> + as a particular device type.
>> + This interfaces can be used to show spear's pcie device capability.
>> +
>> + Nodes are only visible when configfs is mounted. To mount configfs
>> + in /config directory use:
>> + # mount -t configfs none /config/
>> +
>> + /config/pcie-gadget/
>> + link ... used to enable ltssm and read its status.
>> + int_type ...used to configure and read type of supported
>> + interrupt
>> + no_of_msi ... used to configure number of MSI vector needed and
>> + to read no of MSI granted.
>> + inta ... write 1 to assert INTA and 0 to de-assert.
>> + send_msi ... write MSI vector to be sent.
>> + vendor_id ... used to write and read vendor id (hex)
>> + device_id ... used to write and read device id (hex)
>> + bar0_size ... used to write and read bar0_size
>> + bar0_address ... used to write and read bar0 mapped area in hex.
>> + bar0_rw_offset ... used to write and read offset of bar0 where
>> + bar0_data will be written or read.
>> + bar0_data ... used to write and read data at bar0_rw_offset.
>
> This interface implies that there will only ever be one device in the
> machine, yes? Seems a bit short-sighted?
>
This device supports only one BAR in EP mode.
>>
>> ...
>>
>> +Node programming example
>> +===========================
>> +Program all PCIE registers in such a way that when this device is connected
>> +to the pcie host, then host sees this device as 1MB RAM.
>> +#mount -t configfs none /Config
>> +# cd /config/pcie_gadget/
>> +Now you have all the nodes in this directory.
>> +program vendor id as 0x104a
>> +# echo 104A >> vendor_id
>> +
>> +program device id as 0xCD80
>> +# echo CD80 >> device_id
>> +
>> +program BAR0 size as 1MB
>> +# echo 100000 >> bar0_size
>
> I'd be more comfortable if all the hex inputs and outputs had a leading
> 0x.
>
It works with both with and without 0x.
>>
>> ...
>>
>> +static void spear_dbi_read_reg(struct spear_pcie_gadget_config *config,
>> + int where, int size, u32 *val)
>> +{
>> + struct pcie_app_reg __iomem *app_reg
>> + = (struct pcie_app_reg __iomem *) config->va_app_base;
>> + u32 va_address;
>> +
>> + /* Enable DBI access */
>> + enable_dbi_access(app_reg);
>> +
>> + va_address = (u32)config->va_dbi_base + (where & ~0x3);
>
> This will be buggy on 64-bit machines.
>
>> + *val = readl(va_address);
>
> I guess the code won't be running on 64-bit machines ;)
>
> Still, it would be good to minimise the obvious portability problems.
>
Yes, this is for 32 bit ARM platform. But I will typecast it with long
to minimize portability issue.
>> + if (size == 1)
>> + *val = (*val >> (8 * (where & 3))) & 0xff;
>> + else if (size == 2)
>> + *val = (*val >> (8 * (where & 3))) & 0xffff;
>> +
>> + /* Disable DBI access */
>> + disable_dbi_access(app_reg);
>> +}
>> +
>> +static void spear_dbi_write_reg(struct spear_pcie_gadget_config *config,
>> + int where, int size, u32 val)
>> +{
>> + struct pcie_app_reg __iomem *app_reg
>> + = (struct pcie_app_reg __iomem *) config->va_app_base;
>
> Is the typecast needed? We shouldn't *need* to cast a void **iomem *
> in this manner. If we do need the cast then something is broken.
>
It works without typecast also. I will modify it.
>> + u32 va_address;
>> +
>> + /* Enable DBI access */
>> + enable_dbi_access(app_reg);
>> +
>> + va_address = (u32)config->va_dbi_base + (where & ~0x3);
>> +
>> + if (size == 4)
>> + writel(val, va_address);
>> + else if (size == 2)
>> + writew(val, va_address + (where & 2));
>> + else if (size == 1)
>> + writeb(val, va_address + (where & 3));
>> +
>> + /* Disable DBI access */
>> + disable_dbi_access(app_reg);
>> +}
>> +
>>
>> ...
>>
>> +static ssize_t pcie_gadget_store_link(
>> + struct spear_pcie_gadget_config *config,
>> + const char *buf, size_t count)
>> +{
>> + struct pcie_app_reg __iomem *app_reg =
>> + (struct pcie_app_reg __iomem *) config->va_app_base;
>> + char link[10];
>> +
>> + if (strlen(buf) >= 10)
>> + return -EINVAL;
>> +
>> + if (sscanf(buf, "%s", link) != 1)
>> + return -EINVAL;
>> +
>> + if (!strcmp(link, "UP"))
>> + writel(readl(&app_reg->app_ctrl_0) | (1 << APP_LTSSM_ENABLE_ID),
>> + &app_reg->app_ctrl_0);
>> + else
>> + writel(readl(&app_reg->app_ctrl_0)
>> + & ~(1 << APP_LTSSM_ENABLE_ID),
>> + &app_reg->app_ctrl_0);
>> + return count;
>> +}
>
> This function looks unnecessarily complex. Why not do something like
>
> if (sysfs_streq(buf, "UP"))
> ...
> else if (sysfs_streq(buf, "UP"))
> ...
> else
> fail;
>
> And note that the code at present is sloppily treating all input other
> than "UP" as "DOWN". Don't do that.
>
>
sysfs_streq seems better options. I will use it.
>> +static ssize_t pcie_gadget_show_int_type(
>> + struct spear_pcie_gadget_config *config,
>> + char *buf)
>> +{
>> + return sprintf(buf, "%s", config->int_type);
>> +}
>> +
>> +static ssize_t pcie_gadget_store_int_type(
>> + struct spear_pcie_gadget_config *config,
>> + const char *buf, size_t count)
>> +{
>> + char int_type[10];
>> + u32 cap, vec, flags;
>> + unsigned long vector;
>> +
>> + if (strlen(buf) >= 10)
>> + return -EINVAL;
>> +
>> + if (sscanf(buf, "%s", int_type) != 1)
>> + return -EINVAL;
>
> Similarly, the local copy of the string isn't needed.
>
Ok.
>> + if (!strcmp(int_type, "INTA"))
>> + spear_dbi_write_reg(config, PCI_INTERRUPT_LINE, 1, 1);
>> +
>> + else if (!strcmp(int_type, "MSI")) {
>> + vector = config->requested_msi;
>> + vec = 0;
>> + while (vector > 1) {
>> + vector /= 2;
>> + vec++;
>> + }
>> + spear_dbi_write_reg(config, PCI_INTERRUPT_LINE, 1, 0);
>> + cap = pci_find_own_capability(config, PCI_CAP_ID_MSI);
>> + spear_dbi_read_reg(config, cap + PCI_MSI_FLAGS, 1, &flags);
>> + flags &= ~PCI_MSI_FLAGS_QMASK;
>> + flags |= vec << 1;
>> + spear_dbi_write_reg(config, cap + PCI_MSI_FLAGS, 1, flags);
>> + } else
>> + return -EINVAL;
>> +
>> + strcpy(config->int_type, int_type);
>> +
>> + return count;
>> +}
>> +
>> +static ssize_t pcie_gadget_show_no_of_msi(
>> + struct spear_pcie_gadget_config *config,
>> + char *buf)
>> +{
>> + struct pcie_app_reg __iomem *app_reg =
>> + (struct pcie_app_reg __iomem *)config->va_app_base;
>> + u32 cap, vector, vec, flags;
>> +
>> + if ((readl(&app_reg->msg_status) & (1 << CFG_MSI_EN_ID))
>> + != (1 << CFG_MSI_EN_ID))
>> + vector = 0;
>> + else {
>> + cap = pci_find_own_capability(config, PCI_CAP_ID_MSI);
>> + spear_dbi_read_reg(config, cap + PCI_MSI_FLAGS, 1, &flags);
>> + flags &= ~PCI_MSI_FLAGS_QSIZE;
>> + vec = flags >> 4;
>> + vector = 1;
>> + while (vec--)
>> + vector *= 2;
>> + }
>> + config->configured_msi = vector;
>
> Wait. A "show" function is modifying kernel state?!?!?
>
this show is a must call part of MSI vector negotiation.
A device must read first configured number of MSI, before
sending any MSI. Here value of vector is read from HW
and stored in a SW variable. So, it is not programmed
by any application input.
>> +
>> + return sprintf(buf, "%u", vector);
>> +}
>> +
>>
>> ...
>>
>> +static ssize_t pcie_gadget_store_send_msi(
>> + struct spear_pcie_gadget_config *config,
>> + const char *buf, size_t count)
>> +{
>> + struct pcie_app_reg __iomem *app_reg =
>> + (struct pcie_app_reg __iomem *)config->va_app_base;
>> + unsigned long vector;
>> + u32 ven_msi;
>> +
>> + if (strict_strtoul(buf, 0, &vector))
>> + return -EINVAL;
>> +
>> + if (!config->configured_msi)
>> + return -EINVAL;
>
> This is racy, isn't it? Some other thread could be concurrently
> modifying ->configured_msi? (It's a minor issue IMO).
>
configured_msi is programmmed through show_no_of_msi function. It does
not store a value from user interface. rather it stores value from
a HW register.
Normally this function will be called only once , just after link UP.
Even if some other thread calls it again., it will read same value from HW.
>> + if (vector >= config->configured_msi)
>> + return -EINVAL;
>> +
>> + ven_msi = readl(&app_reg->ven_msi_1);
>> + ven_msi &= ~VEN_MSI_FUN_NUM_MASK;
>> + ven_msi |= 0 << VEN_MSI_FUN_NUM_ID;
>> + ven_msi &= ~VEN_MSI_TC_MASK;
>> + ven_msi |= 0 << VEN_MSI_TC_ID;
>> + ven_msi &= ~VEN_MSI_VECTOR_MASK;
>> + ven_msi |= vector << VEN_MSI_VECTOR_ID;
>> +
>> + /*generating interrupt for msi vector*/
>> + ven_msi |= VEN_MSI_REQ_EN;
>> + writel(ven_msi, &app_reg->ven_msi_1);
>> + /*need to wait till this bit is cleared, it is not cleared
>> + * autometically[Bug RTL] TBD*/
>> + udelay(1);
>> + ven_msi &= ~VEN_MSI_REQ_EN;
>> + writel(ven_msi, &app_reg->ven_msi_1);
>> +
>> + return count;
>> +}
>> +
>>
>> ...
>>
>> +static ssize_t pcie_gadget_store_bar0_address(
>> + struct spear_pcie_gadget_config *config,
>> + const char *buf, size_t count)
>> +{
>> + struct pcie_app_reg __iomem *app_reg =
>> + (struct pcie_app_reg __iomem *)config->va_app_base;
>> + unsigned long address;
>> +
>> + if (strict_strtoul(buf, 0, &address))
>> + return -EINVAL;
>> +
>> + address &= ~(config->bar0_size - 1);
>> + if (config->va_bar0_address)
>> + iounmap((void *)config->va_bar0_address);
>
> `void __iomem *' would be a more accurate cast and might avoid sparse
> warnings.
>
> Even better would be to avoid the cast all together. Does
> va_bar0_address have the correct type?
>
OK, i ll do it.
>> + config->va_bar0_address = (u32)ioremap(address, config->bar0_size);
>> + if (!config->va_bar0_address)
>> + return -ENOMEM;
>> +
>> + writel(address, &app_reg->pim0_mem_addr_start);
>> +
>> + return count;
>> +}
>> +
>>
>> ...
>>
>
> .
>
^ permalink raw reply
* [PATCH 1/2] video: Add i.MX23/28 framebuffer driver
From: Juergen Beisert @ 2011-02-10 9:52 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <09EC74FE2C9E8444BF2FF67BD36E1D691678C9@039-SN1MPN1-003.039d.mgd.msft.net>
Li Frank-B20596 wrote:
> > > > +#define VDCTRL1 0x80
> > > > +#define VDCTRL2 0x90
> > > > +#define VDCTRL3 0xa0
> > > > +#define VDCTRL4 0xb0
> > >
> > > Why you give up mx23/mx28 register define role, which generate from SOC
> > > xml.
> >
> > Your macros prevent me from writing short and compact code. If you need
> > more than one of these macros you always have to split each line to follow
> > the 80 columns rule. Unreadable.
> >
> > > There is a set header files for each mx23/mx28 module, which generate
> > > from xml. I know original header files affect run time one Image.
> > > But I think we can copy common part of such register definition because
> > > That keep consistent with mx23/mx28 data sheet. Data sheet and header
> > > file
> >
> > > generate from one source xml.
> > >
> > > HW_<Module name>_<Register name>.
> > > BM_<Module name>_<Register name>_Bit name.
> >
> > IMHO when I define the macros where they belong to, there is not need for
> > this redundant HW_<Module name> or BW__<Module name> prefixes. They are
> > just needless.
>
> At first, someone complain name is longer. But during mx23/mx28 developing,
> Everyone start enjoy such definition because there are not error happen
> about register and bit position definition and identical map to silicon
> spec.
This kind of macro encryption _may_ help when you are coding the driver the
first time. But after reading and reading it again (while testing and
debugging) all these prefixes and suffixes do not add any valuable
information. They only fill up your lines, enlarges your source code and make
you blind for the real bug...
Everyone who wants to see how source code looks that uses these longs macros I
can recommend reading the so called 'bootlets' source code. :-))
> Developer needn't look up register header file when coding, just
That's why I add these macros into the source file instead into a header file.
> write down Register name or bit name according to mx23/mx28 spec.
And sometimes the spec is incomplete or just wrong and so on. Independent of
any macro naming policy.
> If you still think it is too long, I suggest keep HW_ and BM_ prefix to
> distinguish Which one is register name, which one is bit mask.
The used macro in the address part of the writel() must be an offset, while
the macro used in the value part must be a bit definition. Anything else is
redundant.
Regards,
Juergen
--
Pengutronix e.K. | Juergen Beisert |
Linux Solutions for Science and Industry | Phone: +49-8766-939 228 |
Vertretung Sued/Muenchen, Germany | Fax: +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de/ |
^ permalink raw reply
* [PATCH] ARM: mx3/mx31_3ds: fix compiler warning without CONFIG_USB_ULPI
From: Uwe Kleine-König @ 2011-02-10 9:56 UTC (permalink / raw)
To: linux-arm-kernel
This fixes:
arch/arm/mach-mx3/mach-mx31_3ds.c:249: warning: 'mx31_3ds_host2_init' defined but not used
Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
---
arch/arm/mach-mx3/mach-mx31_3ds.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/arch/arm/mach-mx3/mach-mx31_3ds.c b/arch/arm/mach-mx3/mach-mx31_3ds.c
index 63b314c..6d55c62 100644
--- a/arch/arm/mach-mx3/mach-mx31_3ds.c
+++ b/arch/arm/mach-mx3/mach-mx31_3ds.c
@@ -245,7 +245,7 @@ usbotg_free_reset:
return err;
}
-static int mx31_3ds_host2_init(struct platform_device *pdev)
+static int __maybe_unused mx31_3ds_host2_init(struct platform_device *pdev)
{
int err;
--
1.7.2.3
^ permalink raw reply related
* [PATCH] ARM: imx+mx3: convert to mc13xxx MFD
From: Uwe Kleine-König @ 2011-02-10 9:59 UTC (permalink / raw)
To: linux-arm-kernel
From: David Jander <david@protonic.nl>
Signed-off-by: David Jander <david@protonic.nl>
Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
---
arch/arm/mach-imx/mach-mx27_3ds.c | 6 +++---
arch/arm/mach-imx/mach-pcm038.c | 8 ++++----
arch/arm/mach-mx3/mach-mx31_3ds.c | 6 +++---
arch/arm/mach-mx3/mach-mx31lilly.c | 4 ++--
arch/arm/mach-mx3/mach-mx31lite.c | 6 +++---
arch/arm/mach-mx3/mach-mx31moboard.c | 8 ++++----
6 files changed, 19 insertions(+), 19 deletions(-)
diff --git a/arch/arm/mach-imx/mach-mx27_3ds.c b/arch/arm/mach-imx/mach-mx27_3ds.c
index 1643315..49e6a75 100644
--- a/arch/arm/mach-imx/mach-mx27_3ds.c
+++ b/arch/arm/mach-imx/mach-mx27_3ds.c
@@ -216,7 +216,7 @@ static struct regulator_init_data vgen_init = {
.consumer_supplies = vgen_consumers,
};
-static struct mc13783_regulator_init_data mx27_3ds_regulators[] = {
+static struct mc13xxx_regulator_init_data mx27_3ds_regulators[] = {
{
.id = MC13783_REG_VMMC1,
.init_data = &vmmc1_init,
@@ -227,10 +227,10 @@ static struct mc13783_regulator_init_data mx27_3ds_regulators[] = {
};
/* MC13783 */
-static struct mc13783_platform_data mc13783_pdata __initdata = {
+static struct mc13xxx_platform_data mc13783_pdata __initdata = {
.regulators = mx27_3ds_regulators,
.num_regulators = ARRAY_SIZE(mx27_3ds_regulators),
- .flags = MC13783_USE_REGULATOR,
+ .flags = MC13XXX_USE_REGULATOR,
};
/* SPI */
diff --git a/arch/arm/mach-imx/mach-pcm038.c b/arch/arm/mach-imx/mach-pcm038.c
index 5056148..ca20117 100644
--- a/arch/arm/mach-imx/mach-pcm038.c
+++ b/arch/arm/mach-imx/mach-pcm038.c
@@ -252,7 +252,7 @@ static struct regulator_init_data cam_data = {
.consumer_supplies = cam_consumers,
};
-static struct mc13783_regulator_init_data pcm038_regulators[] = {
+static struct mc13xxx_regulator_init_data pcm038_regulators[] = {
{
.id = MC13783_REG_VCAM,
.init_data = &cam_data,
@@ -262,11 +262,11 @@ static struct mc13783_regulator_init_data pcm038_regulators[] = {
},
};
-static struct mc13783_platform_data pcm038_pmic = {
+static struct mc13xxx_platform_data pcm038_pmic = {
.regulators = pcm038_regulators,
.num_regulators = ARRAY_SIZE(pcm038_regulators),
- .flags = MC13783_USE_ADC | MC13783_USE_REGULATOR |
- MC13783_USE_TOUCHSCREEN,
+ .flags = MC13XXX_USE_ADC | MC13XXX_USE_REGULATOR |
+ MC13XXX_USE_TOUCHSCREEN,
};
static struct spi_board_info pcm038_spi_board_info[] __initdata = {
diff --git a/arch/arm/mach-mx3/mach-mx31_3ds.c b/arch/arm/mach-mx3/mach-mx31_3ds.c
index 0d65db8..63b314c 100644
--- a/arch/arm/mach-mx3/mach-mx31_3ds.c
+++ b/arch/arm/mach-mx3/mach-mx31_3ds.c
@@ -138,7 +138,7 @@ static struct regulator_init_data gpo_init = {
}
};
-static struct mc13783_regulator_init_data mx31_3ds_regulators[] = {
+static struct mc13xxx_regulator_init_data mx31_3ds_regulators[] = {
{
.id = MC13783_REG_PWGT1SPI, /* Power Gate for ARM core. */
.init_data = &pwgtx_init,
@@ -156,10 +156,10 @@ static struct mc13783_regulator_init_data mx31_3ds_regulators[] = {
};
/* MC13783 */
-static struct mc13783_platform_data mc13783_pdata __initdata = {
+static struct mc13xxx_platform_data mc13783_pdata __initdata = {
.regulators = mx31_3ds_regulators,
.num_regulators = ARRAY_SIZE(mx31_3ds_regulators),
- .flags = MC13783_USE_REGULATOR | MC13783_USE_TOUCHSCREEN,
+ .flags = MC13XXX_USE_REGULATOR | MC13XXX_USE_TOUCHSCREEN
};
/* SPI */
diff --git a/arch/arm/mach-mx3/mach-mx31lilly.c b/arch/arm/mach-mx3/mach-mx31lilly.c
index 2c59548..6d0e6c9 100644
--- a/arch/arm/mach-mx3/mach-mx31lilly.c
+++ b/arch/arm/mach-mx3/mach-mx31lilly.c
@@ -274,8 +274,8 @@ static const struct spi_imx_master spi1_pdata __initconst = {
.num_chipselect = ARRAY_SIZE(spi_internal_chipselect),
};
-static struct mc13783_platform_data mc13783_pdata __initdata = {
- .flags = MC13783_USE_RTC | MC13783_USE_TOUCHSCREEN,
+static struct mc13xxx_platform_data mc13783_pdata __initdata = {
+ .flags = MC13XXX_USE_RTC | MC13XXX_USE_TOUCHSCREEN,
};
static struct spi_board_info mc13783_dev __initdata = {
diff --git a/arch/arm/mach-mx3/mach-mx31lite.c b/arch/arm/mach-mx3/mach-mx31lite.c
index 9e64c66..864aa4f 100644
--- a/arch/arm/mach-mx3/mach-mx31lite.c
+++ b/arch/arm/mach-mx3/mach-mx31lite.c
@@ -111,9 +111,9 @@ static const struct spi_imx_master spi1_pdata __initconst = {
.num_chipselect = ARRAY_SIZE(spi_internal_chipselect),
};
-static struct mc13783_platform_data mc13783_pdata __initdata = {
- .flags = MC13783_USE_RTC |
- MC13783_USE_REGULATOR,
+static struct mc13xxx_platform_data mc13783_pdata __initdata = {
+ .flags = MC13XXX_USE_RTC |
+ MC13XXX_USE_REGULATOR,
};
static struct spi_board_info mc13783_spi_dev __initdata = {
diff --git a/arch/arm/mach-mx3/mach-mx31moboard.c b/arch/arm/mach-mx3/mach-mx31moboard.c
index 1aa8d65..8fcf991 100644
--- a/arch/arm/mach-mx3/mach-mx31moboard.c
+++ b/arch/arm/mach-mx3/mach-mx31moboard.c
@@ -214,7 +214,7 @@ static struct regulator_init_data cam_vreg_data = {
.consumer_supplies = cam_consumers,
};
-static struct mc13783_regulator_init_data moboard_regulators[] = {
+static struct mc13xxx_regulator_init_data moboard_regulators[] = {
{
.id = MC13783_REG_VMMC1,
.init_data = &sdhc_vreg_data,
@@ -267,12 +267,12 @@ static struct mc13783_leds_platform_data moboard_leds = {
.tc2_period = MC13783_LED_PERIOD_10MS,
};
-static struct mc13783_platform_data moboard_pmic = {
+static struct mc13xxx_platform_data moboard_pmic = {
.regulators = moboard_regulators,
.num_regulators = ARRAY_SIZE(moboard_regulators),
.leds = &moboard_leds,
- .flags = MC13783_USE_REGULATOR | MC13783_USE_RTC |
- MC13783_USE_ADC | MC13783_USE_LED,
+ .flags = MC13XXX_USE_REGULATOR | MC13XXX_USE_RTC |
+ MC13XXX_USE_ADC | MC13XXX_USE_LED,
};
static struct spi_board_info moboard_spi_board_info[] __initdata = {
--
1.7.2.3
^ permalink raw reply related
* [PATCH]ARM: mmp: add Trizeps6 board support
From: Yupeng Schneider @ 2011-02-10 10:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <AANLkTin1q=KP5xmj5mzEwOfHsMf=Mz4Ts1EbpGzJPcQX@mail.gmail.com>
Hello Eric,
2011/2/10 Eric Miao <eric.y.miao@gmail.com>
> Corrected the linux-arm-kernel ML address.
>
> On Thu, Feb 10, 2011 at 10:24 AM, Eric Miao <eric.y.miao@gmail.com> wrote:
> > On Thu, Feb 10, 2011 at 7:53 AM, Yupeng Schneider
> > <yupeng.schneider@ipms.fraunhofer.de> wrote:
> >> Hi all,
> >>
> >> the following patch add the BSP for the Trizeps6 board with pxa168
> Processor.
> >>
> >> Signed-off-by: Yupeng Schneider <yupeng.schneider@googlemail.com>
> >
> > Hi Yupeng,
> >
> > This is really a nice patch. I would be better if this can be separated
> into
> > some smaller patches further:
>
thank u
>
> > 1. some of the MFP macros in trizeps6.h, they are generic and can be
> > placed into mfp-pxa168.h, or is there any reason that the macros in
> > mfp-pxa168.h do not work on your board?
>
ok, i will place them into mfp-pxa168.h. I just thought it is not prefered
to change the mfp-pxa168 file.
>
> > 2. individual patches for adding uart3, audio, and cpld
>
i would very glad to make them in small patchs. i am just now on travel,
and will do that in several days when i am back.
>
> > 3. then the patch for the board
> >
> > Sounds OK? Let me know your ideas.
>
AC97+UCB1400: Sound and Touchscreen is ok. The related pxa2xx-ac97 files
have to be modified, the changes are not in this patch. If u want, i can
patch them later too.
yours,
Yupeng
> >
> > Thanks
> > - eric
> >
> >> ---
> >> arch/arm/mach-mmp/Kconfig | 29 ++
> >> arch/arm/mach-mmp/Makefile | 1 +
> >> arch/arm/mach-mmp/include/mach/audio.h | 29 ++
> >> arch/arm/mach-mmp/include/mach/pxa168.h | 21 +
> >> arch/arm/mach-mmp/include/mach/regs-apmu.h | 1 +
> >> arch/arm/mach-mmp/include/mach/trizeps6.h | 122 ++++++
> >> arch/arm/mach-mmp/include/mach/trizeps6_cpld.h | 87 +++++
> >> arch/arm/mach-mmp/pxa168.c | 10 +
> >> arch/arm/mach-mmp/trizeps6.c | 469
> >> ++++++++++++++++++++++++
> >> arch/arm/mach-mmp/trizeps6_cpld.c | 145 ++++++++
> >> 10 files changed, 914 insertions(+), 0 deletions(-)
> >> create mode 100755 arch/arm/mach-mmp/include/mach/audio.h
> >> create mode 100755 arch/arm/mach-mmp/include/mach/trizeps6.h
> >> create mode 100755 arch/arm/mach-mmp/include/mach/trizeps6_cpld.h
> create
> >> mode 100755 arch/arm/mach-mmp/trizeps6.c
> >> create mode 100755 arch/arm/mach-mmp/trizeps6_cpld.c
> >>
> >> diff --git a/arch/arm/mach-mmp/Kconfig b/arch/arm/mach-mmp/Kconfig index
> >> 0711d3b..8c6be81 100644
> >> --- a/arch/arm/mach-mmp/Kconfig
> >> +++ b/arch/arm/mach-mmp/Kconfig
> >> @@ -64,6 +64,35 @@ config MACH_TETON_BGA
> >> Say 'Y' here if you want to support the Marvell PXA168-based
> >> Teton BGA Development Board.
> >>
> >> +comment "Third Party Dev Platforms (sorted by vendor name)"
> >> +
> >> +config MACH_TRIZEPS6
> >> + bool "Keith und Koep Trizeps6 DIMM-Module"
> >> + select TRIZEPS6_PCMCIA
> >> + select CPU_PXA168
> >> + help
> >> + Say 'Y' here if you want to support TRIZEPS VI board
> Development Board.
> >> +
> >> +choice
> >> + prompt "Select base board for Trizeps module"
> >> + depends on MACH_TRIZEPS6
> >> +
> >> +config MACH_TRIZEPS6_CONXS
> >> + bool "ConXS Eval Board"
> >> +
> >> +config MACH_TRIZEPS6_UCONXS
> >> + bool "uConXS Eval Board"
> >> +
> >> +config MACH_TRIZEPS6_ANY
> >> + bool "another Board"
> >> +
> >> +endchoice
> >> +
> >> +config TRIZEPS6_PCMCIA
> >> + bool
> >> + help
> >> + Enable PCMCIA support for Trizeps modules
> >> +
> >> endmenu
> >>
> >> config CPU_PXA168
> >> diff --git a/arch/arm/mach-mmp/Makefile b/arch/arm/mach-mmp/Makefile
> index
> >> 751cdbf..1b8744f 100644
> >> --- a/arch/arm/mach-mmp/Makefile
> >> +++ b/arch/arm/mach-mmp/Makefile
> >> @@ -18,3 +18,4 @@ obj-$(CONFIG_MACH_TTC_DKB) += ttc_dkb.o
> >> obj-$(CONFIG_MACH_FLINT) += flint.o
> >> obj-$(CONFIG_MACH_MARVELL_JASPER) += jasper.o
> >> obj-$(CONFIG_MACH_TETON_BGA) += teton_bga.o
> >> +obj-$(CONFIG_MACH_TRIZEPS6) += trizeps6.o trizeps6_cpld.o
> >> diff --git a/arch/arm/mach-mmp/include/mach/audio.h
> >> b/arch/arm/mach-mmp/include/mach/audio.h
> >> index 0000000..6ef474f
> >> --- /dev/null
> >> +++ b/arch/arm/mach-mmp/include/mach/audio.h
> >> @@ -0,0 +1,29 @@
> >> +#ifndef __ASM_ARCH_AUDIO_H__
> >> +#define __ASM_ARCH_AUDIO_H__
> >> +
> >> +#include <sound/core.h>
> >> +#include <sound/pcm.h>
> >> +#include <sound/ac97_codec.h>
> >> +
> >> +/*
> >> + * @reset_gpio: AC97 reset gpio (normally gpio113 or gpio95)
> >> + * a -1 value means no gpio will be used for reset
> >> + * @codec_pdata: AC97 codec platform_data
> >> +
> >> + * reset_gpio should only be specified for pxa27x CPUs where a silicon
> +
> >> * bug prevents correct operation of the reset line. If not specified, +
> *
> >> the default behaviour on these CPUs is to consider gpio 113 as the + *
> >> AC97 reset line, which is the default on most boards.
> >> + */
> >> +struct pxa2xx_audio_ops_t {
> >> + int (*startup)(struct snd_pcm_substream *, void *);
> >> + void (*shutdown)(struct snd_pcm_substream *, void *);
> >> + void (*suspend)(void *);
> >> + void (*resume)(void *);
> >> + void *priv;
> >> + int reset_gpio;
> >> + void *codec_pdata[AC97_BUS_MAX_DEVICES];
> >> +};
> >> +
> >> +
> >> +#endif
> >> diff --git a/arch/arm/mach-mmp/include/mach/pxa168.h
> >> b/arch/arm/mach-mmp/include/mach/pxa168.h
> >> index 1801e42..c4a9977 100644
> >> --- a/arch/arm/mach-mmp/include/mach/pxa168.h
> >> +++ b/arch/arm/mach-mmp/include/mach/pxa168.h
> >> @@ -14,9 +14,12 @@ extern void pxa168_clear_keypad_wakeup(void);
> >> #include <video/pxa168fb.h>
> >> #include <plat/pxa27x_keypad.h>
> >> #include <mach/cputype.h>
> >> +#include <linux/pxa168_eth.h>
> >> +#include <mach/audio.h>
> >>
> >> extern struct pxa_device_desc pxa168_device_uart1;
> >> extern struct pxa_device_desc pxa168_device_uart2;
> >> +extern struct pxa_device_desc pxa168_device_uart3;
> >> extern struct pxa_device_desc pxa168_device_twsi0;
> >> extern struct pxa_device_desc pxa168_device_twsi1;
> >> extern struct pxa_device_desc pxa168_device_pwm1;
> >> @@ -31,6 +34,9 @@ extern struct pxa_device_desc pxa168_device_ssp5;
> >> extern struct pxa_device_desc pxa168_device_nand;
> >> extern struct pxa_device_desc pxa168_device_fb;
> >> extern struct pxa_device_desc pxa168_device_keypad;
> >> +extern struct pxa_device_desc pxa168_device_mfu;
> >> +extern struct pxa_device_desc pxa168_device_ac97;
> >> +
> >>
> >> static inline int pxa168_add_uart(int id)
> >> {
> >> @@ -39,6 +45,7 @@ static inline int pxa168_add_uart(int id)
> >> switch (id) {
> >> case 1: d = &pxa168_device_uart1; break;
> >> case 2: d = &pxa168_device_uart2; break;
> >> + case 3: d = &pxa168_device_uart3; break;
> >> }
> >>
> >> if (d == NULL)
> >> @@ -117,4 +124,18 @@ static inline int pxa168_add_keypad(struct
> >> pxa27x_keypad_platform_data *data)
> >> return pxa_register_device(&pxa168_device_keypad, data,
> sizeof(*data));
> >> }
> >>
> >> +static inline int pxa168_add_mfu(struct pxa168_eth_platform_data *data)
> +{
> >> +#if defined(CONFIG_PXA168_ETH)
> >> + return pxa_register_device(&pxa168_device_mfu, data,
> sizeof(*data)); +#else
> >> + return 0;
> >> +#endif
> >> +}
> >> +
> >> +static inline int pxa168_add_ac97(struct pxa2xx_audio_ops_t *ops) +{
> >> + return pxa_register_device(&pxa168_device_ac97, ops ,
> sizeof(*ops)); +}
> >> +
> >> #endif /* __ASM_MACH_PXA168_H */
> >> diff --git a/arch/arm/mach-mmp/include/mach/regs-apmu.h
> >> b/arch/arm/mach-mmp/include/mach/regs-apmu.h
> >> index ac47023..68d39bc 100644
> >> --- a/arch/arm/mach-mmp/include/mach/regs-apmu.h
> >> +++ b/arch/arm/mach-mmp/include/mach/regs-apmu.h
> >> @@ -27,6 +27,7 @@
> >> #define APMU_DMA APMU_REG(0x064)
> >> #define APMU_GEU APMU_REG(0x068)
> >> #define APMU_BUS APMU_REG(0x06c)
> >> +#define APMU_MFU APMU_REG(0x0fc)
> >>
> >> #define APMU_FNCLK_EN (1 << 4)
> >> #define APMU_AXICLK_EN (1 << 3)
> >> diff --git a/arch/arm/mach-mmp/include/mach/trizeps6.h
> >> b/arch/arm/mach-mmp/include/mach/trizeps6.h
> >> index 0000000..40b526a
> >> --- /dev/null
> >> +++ b/arch/arm/mach-mmp/include/mach/trizeps6.h
> >> @@ -0,0 +1,122 @@
> >>
> +/************************************************************************
> >> + * Include file for TRIZEPS6 SoM and ConXS eval-board
> >> + * Copyright (c) Yupeng Schneider
> >> + * 2010
> >> +
> >>
> ************************************************************************/ +
> >> +/*
> >> + * Includes/Defines
> >> + */
> >> +#ifndef _TRIPEPS6_H_
> >> +#define _TRIPEPS6_H_
> >> +
> >> +#define STUART_SODIMM 1
> >> +
> >> +/* UART */
> >> +#define GPIO104_UART1_DSR MFP_CFG(GPIO104, AF2)
> >> +#define GPIO105_UART1_DCD MFP_CFG(GPIO105, AF2)
> >> +#define GPIO107_UART2_TXD MFP_CFG_DRV(GPIO126, AF2, FAST)
> >> +#define GPIO107_UART2_RXD MFP_CFG_DRV(GPIO36, AF2, FAST)
> >> +#define GPIO109_UART2_CTS MFP_CFG(GPIO123, AF2)
> >> +#define GPIO109_UART2_RTS MFP_CFG(GPIO124, AF2)
> >> +#define GPIO30_UART3_TXD MFP_CFG_DRV(GPIO30, AF2, FAST)
> >> +#define GPIO31_UART3_RXD MFP_CFG_DRV(GPIO31, AF2, FAST)
> >> +#define GPIO32_UART3_CTS MFP_CFG(GPIO32, AF2)
> >> +#define GPIO33_UART3_RTS MFP_CFG(GPIO33, AF2)
> >> +
> >> +/* MMC2 */
> >> +#define GPIO122_MMC2_DAT3 MFP_CFG_DRV(GPIO122, AF4, FAST)
> >> +#define GPIO121_MMC2_DAT2 MFP_CFG_DRV(GPIO121, AF4, FAST)
> >> +#define GPIO120_MMC2_DAT1 MFP_CFG_DRV(GPIO120, AF4, FAST)
> >> +#define GPIO119_MMC2_DAT0 MFP_CFG_DRV(GPIO119, AF4, FAST)
> >> +#define GPIO28_MMC2_CMD MFP_CFG_DRV(GPIO28, AF6, FAST)
> >> +#define GPIO29_MMC2_CLK MFP_CFG_DRV(GPIO29, AF6, FAST)
> >> +#define GPIO53_MMC2_CD MFP_CFG(GPIO53, AF0)
> >> +
> >> +/*MMC4*/
> >> +#define GPIO78_MMC4_DAT3 MFP_CFG_DRV(GPIO78, AF5, FAST)
> >> +#define GPIO79_MMC4_DAT2 MFP_CFG_DRV(GPIO79, AF5, FAST)
> >> +#define GPIO80_MMC4_DAT1 MFP_CFG_DRV(GPIO80, AF5, FAST)
> >> +#define GPIO81_MMC4_DAT0 MFP_CFG_DRV(GPIO81, AF5, FAST)
> >> +#define GPIO82_MMC4_CMD MFP_CFG_DRV(GPIO82, AF5, FAST)
> >> +#define GPIO83_MMC4_CLK MFP_CFG_DRV(GPIO83, AF5, FAST)
> >> +
> >> +/* I2C */
> >> +#define GPIO102_CI2C_SDA MFP_CFG(GPIO102, AF1)
> >> +
> >> +/* MFU */
> >> +#define GPIO86_TX_CLK MFP_CFG(GPIO86, AF5)
> >> +#define GPIO87_TX_EN MFP_CFG(GPIO87, AF5)
> >> +#define GPIO88_TX_DQ3 MFP_CFG(GPIO88, AF5)
> >> +#define GPIO89_TX_DQ2 MFP_CFG(GPIO89, AF5)
> >> +#define GPIO90_TX_DQ1 MFP_CFG(GPIO90, AF5)
> >> +#define GPIO91_TX_DQ0 MFP_CFG(GPIO91, AF5)
> >> +#define GPIO92_MII_CRS MFP_CFG(GPIO92, AF5)
> >> +#define GPIO93_MII_COL MFP_CFG(GPIO93, AF5)
> >> +#define GPIO94_RX_CLK MFP_CFG(GPIO94, AF5)
> >> +#define GPIO95_RX_ER MFP_CFG(GPIO95, AF5)
> >> +#define GPIO96_RX_DQ3 MFP_CFG(GPIO96, AF5)
> >> +#define GPIO97_RX_DQ2 MFP_CFG(GPIO97, AF5)
> >> +#define GPIO98_RX_DQ1 MFP_CFG(GPIO98, AF5)
> >> +#define GPIO99_RX_DQ0 MFP_CFG(GPIO99, AF5)
> >> +#define GPIO100_MII_MDC MFP_CFG(GPIO100, AF5)
> >> +#define GPIO101_MII_MDIO MFP_CFG(GPIO101, AF5)
> >> +#define GPIO103_RX_DV MFP_CFG(GPIO103, AF5)
> >> +
> >> +/* AC97 */
> >> +#define GPIO115_AC97_BITCLK MFP_CFG(GPIO115, AF6)
> >> +#define GPIO114_AC97_SDATA_IN_0 MFP_CFG(GPIO114, AF6)
> >> +#define GPIO116_AC97_SDATA_IN_1 MFP_CFG(GPIO116, AF6)
> >> +#define GPIO117_AC97_SDATA_OUT MFP_CFG(GPIO117, AF6)
> >> +#define GPIO118_AC97_SYNC MFP_CFG(GPIO118, AF6)
> >> +
> >> +
> >> +
> >> +#define TRIZEPS6_PHYS_BASE 0xd4000000
> >> +
> >> +
> >> +#define TRIZEPS6_PIC_PHYS (0x88000000) /* CS0-3 Logic chip on
> ConXS */
> >> + /* Logic on ConXS-board CSFR register*/
> >> +#define TRIZEPS6_CFSR_PHYS (TRIZEPS6_PIC_PHYS)
> >> + /* Logic on ConXS-board BOCR register*/
> >> +#define TRIZEPS6_BOCR_PHYS (TRIZEPS6_PIC_PHYS+0x00200000)
> >> + /* Logic on ConXS-board IRCR register*/
> >> +#define TRIZEPS6_IRCR_PHYS (TRIZEPS6_PIC_PHYS+0x00300000)
> >> + /* Logic on ConXS-board UPSR register*/
> >> +#define TRIZEPS6_UPSR_PHYS (TRIZEPS6_PIC_PHYS+0x00280000)
> >> + /* Logic on ConXS-board DICR register*/
> >> +#define TRIZEPS6_DICR_PHYS (TRIZEPS6_PIC_PHYS+0x00380000)
> >> +
> >> +
> >> +#define TRIZEPS6_CPLD_PHYS (0x8e000000) /* CPLD on Trizeps6 module */
> +
> >> +#define TRIZEPS6_CPLD_CTRL_PHYS (TRIZEPS6_CPLD_PHYS)
> >> +#define TRIZEPS6_CPLD_FTUR_PHYS (TRIZEPS6_CPLD_PHYS+0x4)
> >> +#define TRIZEPS6_CPLD_HIBE_PHYS (TRIZEPS6_CPLD_PHYS+0x8)
> >> +#define TRIZEPS6_CPLD_PWM_PHYS (TRIZEPS6_CPLD_PHYS+0xc)
> >> +#define TRIZEPS6_CPLD_PLDR_PHYS (TRIZEPS6_CPLD_PHYS+0x10)
> >> +#define TRIZEPS6_CPLD_PSET_PHYS (TRIZEPS6_CPLD_PHYS+0x14)
> >> +#define TRIZEPS6_CPLD_TTLO_PHYS (TRIZEPS6_CPLD_PHYS+0x18)
> >> +
> >> +
> >> +/* MMC socket */
> >> +#define GPIO_MMC2_DET 53
> >> +#define TRIZEPS6_MMC2_IRQ IRQ_GPIO(mfp_to_gpio(MFP_PIN_GPIO53))
> >> +#define GPIO_MMC4_DET 41
> >> +#define TRIZEPS6_MMC4_IRQ IRQ_GPIO(mfp_to_gpio(MFP_PIN_GPIO41)
> >> +
> >> +/* Off-module PIC on ConXS board */
> >> +#define GPIO_PIC 51
> >> +#define TRIZEPS6_PIC_IRQ IRQ_GPIO(mfp_to_gpio(MFP_PIN_GPIO51)
> >> +
> >> +/* PCMCIA socket Compact Flash */
> >> +#define GPIO_PCD 43 /* PCMCIA Card Detect */
> >> +#define TRIZEPS6_CD_IRQ
> IRQ_GPIO(mfp_to_gpio(MFP_PIN_GPIO43)
> >> +#define GPIO_PRDY 113 /* READY / nINT */
> >> +#define TRIZEPS6_READY_NINT IRQ_GPIO(mfp_to_gpio(MFP_PIN_GPIO113) +
> >> +#define trizeps6_GPIO_CODEC_IRQ 116
> >> +
> >> +extern void trizeps6_ac97_acreset(int i);
> >> +
> >> +#endif /* _TRIPEPS6_H_ */
> >> diff --git a/arch/arm/mach-mmp/include/mach/trizeps6_cpld.h
> >> b/arch/arm/mach-mmp/include/mach/trizeps6_cpld.h
> >> index 0000000..8538a6b
> >> --- /dev/null
> >> +++ b/arch/arm/mach-mmp/include/mach/trizeps6_cpld.h
> >> @@ -0,0 +1,87 @@
> >> +#ifndef _TRIPEPS6_CPLD_H_
> >> +#define _TRIPEPS6_CPLD_H_
> >> +
> >> +/* index of resource */
> >> +#define CTRL_S 0
> >> +#define CTRL_R 1
> >> +#define FTUR_S 2
> >> +#define FTUR_R 3
> >> +#define HIBE_S 4
> >> +#define HIBE_R 5
> >> +#define PWM 6
> >> +#define PLDR_S 7
> >> +#define PLDR_R 8
> >> +#define PSET_S 9
> >> +#define PSET_R 10
> >> +#define TTLO_S 11
> >> +#define TTLO_R 12
> >> +
> >> +#define CPLD_CTRL_S cpld.addr[CTRL_S].val
> >> +#define CPLD_CTRL_R cpld.addr[CTRL_R].val
> >> +#define CPLD_CONTROL_GR (1 << 0)
> >> +#define CPLD_CONTROL_CODEC (1 << 2)
> >> +#define CPLD_CONTROL_ETHPHY (1 << 3)
> >> +#define CPLD_CONTROL_RWL (1 << 4)
> >> +#define CPLD_CONTROL_RBT (1 << 5)
> >> +
> >> +#define CPLD_FTUR_S cpld.addr[FTUR_S].val
> >> +#define CPLD_FTUR_R cpld.addr[FTUR_R].val
> >> +#define CPLD_FEATURE_UART3_SODIMM (1 << 0)
> >> +#define CPLD_FEATURE_UART3_BT (1 << 1)
> >> +#define CPLD_FEATURE_CF_MODE (1 << 2)
> >> +#define CPLD_FEATURE_TTLIO (1 << 3)
> >> +#define CPLD_PWM_SODIMM_P69 (1 << 4)
> >> +#define CPLD_PWM_SODIMM_P77 (1 << 5)
> >> +#define CPLD_PWM_SODIMM_P106 (1 << 6)
> >> +#define CPLD_BT_PWM_SODIMM (1 << 7)
> >> +
> >> +#define CPLD_HIBE_S cpld.addr[HIBE_S].val
> >> +#define CPLD_HIBE_R cpld.addr[HIBE_R].val
> >> +#define CPLD_HIBERNATE_MODE (1 << 0)
> >> +#define CPLD_HIBERNATE_WAKE_TOUCH (1 << 1)
> >> +#define CPLD_HIBERNATE_WAKE_PMIC (1 << 2)
> >> +#define CPLD_HIBERNATE_WAKE_IRQ_P43 (1 << 3)
> >> +
> >> +#define CPLD_PWM cpld.addr[PWM].val
> >> +
> >> +#define CPLD_PINLDR cpld.addr[PINLDR].val
> >> +#define CPLD_PINLDR_P69 (1 << 0)
> >> +#define CPLD_PINLDR_P100_PSKTSEL (1 << 1)
> >> +#define CPLD_PINLDR_P98_CFNREG (1 << 2)
> >> +#define CPLD_PINLDR_P104_CFNIOIS16 (1 << 3)
> >> +#define CPLD_PINLDR_P93_RDNWR (1 << 4)
> >> +#define CPLD_PINLDR_P104_IRQ_P43 (1 << 5)
> >> +
> >> +#define CPLD_PSET_S cpld.addr[PSET_S].val
> >> +#define CPLD_PSET_R cpld.addr[PSET_R].val
> >> +#define CPLD_PINSET_P69 (1 << 0)
> >> +#define CPLD_PINSET_P100_PSKTSEL (1 << 1)
> >> +#define CPLD_PINSET_P98_CFNREG (1 << 2)
> >> +#define CPLD_PINSET_P104_CFNIOIS16 (1 << 3)
> >> +#define CPLD_PINSET_P93_RDnWR (1 << 4)
> >> +
> >> +#define CPLD_TTLO_S cpld.addr[TTLO_S].val
> >> +#define CPLD_TTLO_R cpld.addr[TTLO_R].val
> >> +#define CPLD_TTLIO_W_A8 (1 << 0)
> >> +#define CPLD_TTLIO_W_A9 (1 << 1)
> >> +#define CPLD_TTLIO_W_A10 (1 << 2)
> >> +#define CPLD_TTLIO_W_A11 (1 << 3)
> >> +#define CPLD_TTLIO_W_A12 (1 << 4)
> >> +#define CPLD_TTLIO_W_A13 (1 << 5)
> >> +#define CPLD_TTLIO_W_A14 (1 << 6)
> >> +#define CPLD_TTLIO_W_A15 (1 << 7)
> >> +#define CPLD_TTLIO_r_A0 (1 << 0)
> >> +#define CPLD_TTLIO_r_A1 (1 << 1)
> >> +#define CPLD_TTLIO_r_A2 (1 << 2)
> >> +#define CPLD_TTLIO_r_A3 (1 << 3)
> >> +#define CPLD_TTLIO_r_A4 (1 << 4)
> >> +#define CPLD_TTLIO_r_A5 (1 << 5)
> >> +#define CPLD_TTLIO_r_A6 (1 << 6)
> >> +#define CPLD_TTLIO_r_A7 (1 << 7)
> >> +
> >> +
> >> +
> >> +extern unsigned short trizeps6_cpld_readw(unsigned int reg);
> >> +extern inline void trizeps6_cpld_writew(unsigned int reg, unsigned
> short
> >> value);
> >> +
> >> +#endif /* _TRIPEPS6_CPLD_H_ */
> >> diff --git a/arch/arm/mach-mmp/pxa168.c b/arch/arm/mach-mmp/pxa168.c
> index
> >> 72b4e76..9c2396e 100644
> >> --- a/arch/arm/mach-mmp/pxa168.c
> >> +++ b/arch/arm/mach-mmp/pxa168.c
> >> @@ -66,6 +66,7 @@ void __init pxa168_init_irq(void)
> >> /* APB peripheral clocks */
> >> static APBC_CLK(uart1, PXA168_UART1, 1, 14745600);
> >> static APBC_CLK(uart2, PXA168_UART2, 1, 14745600);
> >> +static APBC_CLK(uart3, PXA168_UART3, 1, 14745600);
> >> static APBC_CLK(twsi0, PXA168_TWSI0, 1, 33000000);
> >> static APBC_CLK(twsi1, PXA168_TWSI1, 1, 33000000);
> >> static APBC_CLK(pwm1, PXA168_PWM1, 1, 13000000);
> >> @@ -78,14 +79,18 @@ static APBC_CLK(ssp3, PXA168_SSP3, 4, 0);
> >> static APBC_CLK(ssp4, PXA168_SSP4, 4, 0);
> >> static APBC_CLK(ssp5, PXA168_SSP5, 4, 0);
> >> static APBC_CLK(keypad, PXA168_KPC, 0, 32000);
> >> +static APBC_CLK(ac97, PXA168_AC97, 0, 24576000);
> >> +
> >>
> >> static APMU_CLK(nand, NAND, 0x01db, 208000000);
> >> static APMU_CLK(lcd, LCD, 0x7f, 312000000);
> >> +static APMU_CLK(mfu, MFU, 0x9, 0);
> >>
> >> /* device and clock bindings */
> >> static struct clk_lookup pxa168_clkregs[] = {
> >> INIT_CLKREG(&clk_uart1, "pxa2xx-uart.0", NULL),
> >> INIT_CLKREG(&clk_uart2, "pxa2xx-uart.1", NULL),
> >> + INIT_CLKREG(&clk_uart3, "pxa2xx-uart.2", NULL),
> >> INIT_CLKREG(&clk_twsi0, "pxa2xx-i2c.0", NULL),
> >> INIT_CLKREG(&clk_twsi1, "pxa2xx-i2c.1", NULL),
> >> INIT_CLKREG(&clk_pwm1, "pxa168-pwm.0", NULL),
> >> @@ -100,6 +105,8 @@ static struct clk_lookup pxa168_clkregs[] = {
> >> INIT_CLKREG(&clk_nand, "pxa3xx-nand", NULL),
> >> INIT_CLKREG(&clk_lcd, "pxa168-fb", NULL),
> >> INIT_CLKREG(&clk_keypad, "pxa27x-keypad", NULL),
> >> + INIT_CLKREG(&clk_mfu, "pxa168-eth", "MFUCLK"),
> >> + INIT_CLKREG(&clk_ac97, "pxa2xx-ac97", "AC97CLK"),
> >> };
> >>
> >> static int __init pxa168_init(void)
> >> @@ -149,6 +156,7 @@ void pxa168_clear_keypad_wakeup(void)
> >> /* on-chip devices */
> >> PXA168_DEVICE(uart1, "pxa2xx-uart", 0, UART1, 0xd4017000, 0x30, 21,
> 22);
> >> PXA168_DEVICE(uart2, "pxa2xx-uart", 1, UART2, 0xd4018000, 0x30, 23, 24);
> >> +PXA168_DEVICE(uart3, "pxa2xx-uart", 2, UART3, 0xd4026000, 0x30, 23,
> 24);
> >> PXA168_DEVICE(twsi0, "pxa2xx-i2c", 0, TWSI0, 0xd4011000, 0x28);
> >> PXA168_DEVICE(twsi1, "pxa2xx-i2c", 1, TWSI1, 0xd4025000, 0x28);
> >> PXA168_DEVICE(pwm1, "pxa168-pwm", 0, NONE, 0xd401a000, 0x10);
> >> @@ -163,3 +171,5 @@ PXA168_DEVICE(ssp4, "pxa168-ssp", 3, SSP4,
> 0xd4020000,
> >> 0x40, 58, 59);
> >> PXA168_DEVICE(ssp5, "pxa168-ssp", 4, SSP5, 0xd4021000, 0x40, 60, 61);
> >> PXA168_DEVICE(fb, "pxa168-fb", -1, LCD, 0xd420b000, 0x1c8);
> >> PXA168_DEVICE(keypad, "pxa27x-keypad", -1, KEYPAD, 0xd4012000, 0x4c);
> >> +PXA168_DEVICE(mfu, "pxa168-eth", -1, MFU, 0xc0800000, 0x0FFF);
> >> +PXA168_DEVICE(ac97, "pxa2xx-ac97", -1, AC97, 0xd402B000, 0x0fff); diff
> >> --git a/arch/arm/mach-mmp/trizeps6.c b/arch/arm/mach-mmp/trizeps6.c
> index
> >> 0000000..a935f14
> >> --- /dev/null
> >> +++ b/arch/arm/mach-mmp/trizeps6.c
> >> @@ -0,0 +1,469 @@
> >> +/*
> >> + * linux/arch/arm/mach-mmp/trizeps6.c
> >> + *
> >> + * Support for the Keith und Koep Trizeps6 Modul Platform
> >> + * based on Marvell PXA168-CPU
> >> + *
> >> + * Author: Yupeng Schneider
> >> + *
> >> + * This program is free software; you can redistribute it and/or
> modify
> >> + * it under the terms of the GNU General Public License version 2 as +
> *
> >> publishhed by the Free Software Foundation.
> >> + */
> >> +
> >> +#include <linux/init.h>
> >> +#include <linux/kernel.h>
> >> +#include <linux/platform_device.h>
> >> +#include <linux/mtd/mtd.h>
> >> +#include <linux/mtd/partitions.h>
> >> +#include <linux/mtd/nand.h>
> >> +#include <linux/delay.h>
> >> +#include <asm/mach-types.h>
> >> +#include <asm/mach/arch.h>
> >> +#include <mach/addr-map.h>
> >> +#include <mach/mfp-pxa168.h>
> >> +#include <mach/pxa168.h>
> >> +#include <mach/gpio.h>
> >> +#include <linux/pxa168_eth.h>
> >> +#include <mach/irqs.h>
> >> +#include <mach/trizeps6.h>
> >> +#include <mach/trizeps6_cpld.h>
> >> +#include "common.h"
> >> +#include <linux/mmc/sdhci.h>
> >> +#include <linux/ucb1400.h>
> >> +#include <mach/audio.h>
> >> +
> >> +
> >> +static unsigned long trizeps6_pin_config[] __initdata = {
> >> + /* Data Flash Interface */
> >> + GPIO0_DFI_D15,
> >> + GPIO1_DFI_D14,
> >> + GPIO2_DFI_D13,
> >> + GPIO3_DFI_D12,
> >> + GPIO4_DFI_D11,
> >> + GPIO5_DFI_D10,
> >> + GPIO6_DFI_D9,
> >> + GPIO7_DFI_D8,
> >> + GPIO8_DFI_D7,
> >> + GPIO9_DFI_D6,
> >> + GPIO10_DFI_D5,
> >> + GPIO11_DFI_D4,
> >> + GPIO12_DFI_D3,
> >> + GPIO13_DFI_D2,
> >> + GPIO14_DFI_D1,
> >> + GPIO15_DFI_D0,
> >> +
> >> + /* Static Memory Controller */
> >> + GPIO18_SMC_nCS0,
> >> + GPIO34_SMC_nCS1,
> >> + GPIO23_SMC_nLUA,
> >> + GPIO25_SMC_nLLA,
> >> + GPIO28_SMC_RDY,
> >> + GPIO29_SMC_SCLK,
> >> + GPIO35_SMC_BE1,
> >> + GPIO36_SMC_BE2,
> >> +
> >> +
> >> + /* UART1 */
> >> + GPIO107_UART1_RXD,
> >> + GPIO108_UART1_TXD,
> >> + GPIO107_UART1_RXD,
> >> + GPIO108_UART1_TXD,
> >> + GPIO109_UART1_RTS,
> >> + GPIO110_UART1_CTS,
> >> + GPIO111_UART1_RI,
> >> + GPIO104_UART1_DSR,
> >> + GPIO112_UART1_DTR,
> >> + GPIO105_UART1_DCD,
> >> +
> >> + /* UART2 */
> >> + GPIO107_UART2_TXD,
> >> + GPIO107_UART2_RXD,
> >> + GPIO109_UART2_CTS,
> >> + GPIO109_UART2_RTS,
> >> +
> >> + /* UART3 */
> >> + GPIO30_UART3_TXD,
> >> + GPIO31_UART3_RXD,
> >> + GPIO32_UART3_CTS,
> >> + GPIO33_UART3_RTS,
> >> +
> >> +
> >> + /* MFU */
> >> + GPIO86_TX_CLK,
> >> + GPIO87_TX_EN,
> >> + GPIO88_TX_DQ3,
> >> + GPIO89_TX_DQ2,
> >> + GPIO90_TX_DQ1,
> >> + GPIO91_TX_DQ0,
> >> + GPIO92_MII_CRS,
> >> + GPIO93_MII_COL,
> >> + GPIO94_RX_CLK,
> >> + GPIO95_RX_ER,
> >> + GPIO96_RX_DQ3,
> >> + GPIO97_RX_DQ2,
> >> + GPIO98_RX_DQ1,
> >> + GPIO99_RX_DQ0,
> >> + GPIO100_MII_MDC,
> >> + GPIO101_MII_MDIO,
> >> + GPIO103_RX_DV,
> >> +
> >> + /* USB OTG */
> >> + GPIO85_GPIO,
> >> + GPIO47_GPIO,
> >> +
> >> + /* i2c bus */
> >> + GPIO102_CI2C_SDA,
> >> + GPIO106_CI2C_SCL,
> >> +
> >> +
> >> + /* MMC2 */
> >> + GPIO122_MMC2_DAT3 | MFP_PULL_HIGH,
> >> + GPIO121_MMC2_DAT2 | MFP_PULL_HIGH,
> >> + GPIO120_MMC2_DAT1 | MFP_PULL_HIGH,
> >> + GPIO119_MMC2_DAT0 | MFP_PULL_HIGH,
> >> + GPIO28_MMC2_CMD | MFP_PULL_HIGH,
> >> + GPIO29_MMC2_CLK,
> >> + GPIO53_MMC2_CD | MFP_PULL_LOW, /*
> TRIZEPS6_MMC2_IRQ */
> >> +
> >> + /* MMC4 */
> >> + GPIO78_MMC4_DAT3 | MFP_PULL_HIGH,
> >> + GPIO79_MMC4_DAT2 | MFP_PULL_HIGH,
> >> + GPIO80_MMC4_DAT1 | MFP_PULL_HIGH,
> >> + GPIO81_MMC4_DAT0 | MFP_PULL_HIGH,
> >> + GPIO82_MMC4_CMD | MFP_PULL_HIGH,
> >> + GPIO83_MMC4_CLK,
> >> +
> >> + /* LCD */
> >> + GPIO56_LCD_FCLK_RD,
> >> + GPIO57_LCD_LCLK_A0,
> >> + GPIO58_LCD_PCLK_WR,
> >> + GPIO59_LCD_DENA_BIAS,
> >> + GPIO60_LCD_DD0,
> >> + GPIO61_LCD_DD1,
> >> + GPIO62_LCD_DD2,
> >> + GPIO63_LCD_DD3,
> >> + GPIO64_LCD_DD4,
> >> + GPIO65_LCD_DD5,
> >> + GPIO66_LCD_DD6,
> >> + GPIO67_LCD_DD7,
> >> + GPIO68_LCD_DD8,
> >> + GPIO69_LCD_DD9,
> >> + GPIO70_LCD_DD10,
> >> + GPIO71_LCD_DD11,
> >> + GPIO72_LCD_DD12,
> >> + GPIO73_LCD_DD13,
> >> + GPIO74_LCD_DD14,
> >> + GPIO75_LCD_DD15,
> >> +
> >> +
> >> + /* AC97 */
> >> + GPIO115_AC97_BITCLK,
> >> + GPIO114_AC97_SDATA_IN_0,
> >> + GPIO117_AC97_SDATA_OUT,
> >> + GPIO118_AC97_SYNC,
> >> + GPIO116_GPIO,
> >> +
> >> +
> >> + GPIO51_GPIO, /* TRIZEPS6_PIC_IRQ */
> >> + GPIO27_GPIO, /* Ethernet IRQ */
> >> +};
> >> +
> >> +
> >> +
> >>
> +/****************************************************************************
> >> + * CPLD
> >> +
> >>
> ****************************************************************************/
> >> +
> >> +static struct resource tri6_cpld_resources[] = {
> >> + [CTRL_S] = {
> >> + .start = TRIZEPS6_CPLD_CTRL_PHYS,
> >> + .end = TRIZEPS6_CPLD_CTRL_PHYS+1,
> >> + .flags = IORESOURCE_MEM,
> >> + },
> >> + [CTRL_R] = {
> >> + .start = TRIZEPS6_CPLD_CTRL_PHYS+2,
> >> + .end = TRIZEPS6_CPLD_CTRL_PHYS+3,
> >> + .flags = IORESOURCE_MEM,
> >> + },
> >> + [FTUR_S] = {
> >> + .start = TRIZEPS6_CPLD_FTUR_PHYS,
> >> + .end = TRIZEPS6_CPLD_FTUR_PHYS+1,
> >> + .flags = IORESOURCE_MEM,
> >> + },
> >> + [FTUR_R] = {
> >> + .start = TRIZEPS6_CPLD_FTUR_PHYS+2,
> >> + .end = TRIZEPS6_CPLD_FTUR_PHYS+3,
> >> + .flags = IORESOURCE_MEM,
> >> + },
> >> + [HIBE_S] = {
> >> + .start = TRIZEPS6_CPLD_HIBE_PHYS,
> >> + .end = TRIZEPS6_CPLD_HIBE_PHYS+1,
> >> + .flags = IORESOURCE_MEM,
> >> + },
> >> + [HIBE_R] = {
> >> + .start = TRIZEPS6_CPLD_HIBE_PHYS+2,
> >> + .end = TRIZEPS6_CPLD_HIBE_PHYS+3,
> >> + .flags = IORESOURCE_MEM,
> >> + },
> >> + [PWM] = {
> >> + .start = TRIZEPS6_CPLD_PWM_PHYS,
> >> + .end = TRIZEPS6_CPLD_PWM_PHYS+1,
> >> + .flags = IORESOURCE_MEM,
> >> + },
> >> + [PLDR_S] = {
> >> + .start = TRIZEPS6_CPLD_PLDR_PHYS,
> >> + .end = TRIZEPS6_CPLD_PLDR_PHYS+1,
> >> + .flags = IORESOURCE_MEM,
> >> + },
> >> + [PLDR_R] = {
> >> + .start = TRIZEPS6_CPLD_PLDR_PHYS+2,
> >> + .end = TRIZEPS6_CPLD_PLDR_PHYS+3,
> >> + .flags = IORESOURCE_MEM,
> >> + },
> >> + [PSET_S] = {
> >> + .start = TRIZEPS6_CPLD_PSET_PHYS,
> >> + .end = TRIZEPS6_CPLD_PSET_PHYS+1,
> >> + .flags = IORESOURCE_MEM,
> >> + },
> >> + [PSET_R] = {
> >> + .start = TRIZEPS6_CPLD_PSET_PHYS+2,
> >> + .end = TRIZEPS6_CPLD_PSET_PHYS+3,
> >> + .flags = IORESOURCE_MEM,
> >> + },
> >> + [TTLO_S] = {
> >> + .start = TRIZEPS6_CPLD_TTLO_PHYS,
> >> + .end = TRIZEPS6_CPLD_TTLO_PHYS+1,
> >> + .flags = IORESOURCE_MEM,
> >> + },
> >> + [TTLO_R] = {
> >> + .start = TRIZEPS6_CPLD_TTLO_PHYS+2,
> >> + .end = TRIZEPS6_CPLD_TTLO_PHYS+3,
> >> + .flags = IORESOURCE_MEM,
> >> + },
> >> +};
> >> +
> >> +static int tri6_cpld_platdata = 1;
> >> +
> >> +static struct platform_device cpld_device = {
> >> + .name = "trizeps6-cpld",
> >> + .id = -1,
> >> + .num_resources = ARRAY_SIZE(tri6_cpld_resources),
> >> + .resource = tri6_cpld_resources,
> >> + .dev = {
> >> + .platform_data = &tri6_cpld_platdata,
> >> + }
> >> +};
> >> +
> >> +
> >>
> +/******************************************************************************
> >> + * Audio and Touchscreen
> >> +
> >>
> ******************************************************************************/
> >> +
> >> +static struct ucb1400_pdata trizeps6_ucb1400_pdata = {
> >> + .irq = gpio_to_irq(trizeps6_GPIO_CODEC_IRQ),
> >> +};
> >> +
> >> +static struct pxa2xx_audio_ops_t trizeps6_ac97_pdata = {
> >> + .codec_pdata = { &trizeps6_ucb1400_pdata, },
> >> +};
> >> +
> >> +static struct platform_device trizeps6_ucb1400_device = {
> >> + .name = "ucb1400_core",
> >> + .id = -1,
> >> + .dev = {
> >> + .platform_data = &trizeps6_ucb1400_pdata,
> >> + },
> >> +};
> >> +
> >> +static void __init trizeps6_ts_init(void)
> >> +{
> >> + pxa168_add_ac97(&trizeps6_ac97_pdata);
> >> + platform_device_register(&trizeps6_ucb1400_device);
> >> +}
> >> +
> >> +void trizeps6_ac97_acreset(int i)
> >> +{ unsigned short value;
> >> +
> >> + if (i == 1) {
> >> +
> >> + value = trizeps6_cpld_readw(CTRL_S);
> >> + trizeps6_cpld_writew(CTRL_S, value |
> CPLD_CONTROL_CODEC);
> >> + }
> >> + if (!i) {
> >> + value = trizeps6_cpld_readw(CTRL_R);
> >> + trizeps6_cpld_writew(CTRL_R, value |
> CPLD_CONTROL_CODEC);
> >> + }
> >> +}
> >> +
> >>
> +/******************************************************************************
> >> + * Ethernet
> >> +
> >>
> ******************************************************************************/
> >> +static int trizeps6_eth_init(void)
> >> +{
> >> + unsigned short value;
> >> +
> >> + value = trizeps6_cpld_readw(CTRL_R);
> >> + trizeps6_cpld_writew(CTRL_R, value | CPLD_CONTROL_ETHPHY);
> >> + return 0;
> >> +
> >> +}
> >> +
> >> +static struct pxa168_eth_platform_data trizeps6_eth_data = {
> >> + .phy_addr = 0x1f,
> >> + .port_number = 0,
> >> + .init = trizeps6_eth_init,
> >> +};
> >> +
> >>
> +/******************************************************************************
> >> + * NAND
> >> +
> >>
> ******************************************************************************/
> >> +static struct pxa3xx_nand_timing stnand02gw3b2d_timing = {
> >> + .tCH = 10,
> >> + .tCS = 40,
> >> + .tWH = 20,
> >> + .tWP = 24,
> >> + .tRH = 20,
> >> + .tRP = 24,
> >> + .tR = 50000,
> >> + .tWHR = 120,
> >> + .tAR = 20,
> >> +
> >> +};
> >> +
> >> +static struct pxa3xx_nand_cmdset largepage_cmdset = {
> >> + .read1 = 0x3000,
> >> + .read2 = 0x0050,
> >> + .program = 0x1080,
> >> + .read_status = 0x0070,
> >> + .read_id = 0x0090,
> >> + .erase = 0xD060,
> >> + .reset = 0x00FF,
> >> + .lock = 0x002A,
> >> + .unlock = 0x2423,
> >> + .lock_status = 0x007A,
> >> +};
> >> +
> >> +static struct pxa3xx_nand_flash trizeps6_flashes[] = {
> >> + {
> >> + .timing = &stnand02gw3b2d_timing,
> >> + .cmdset = &largepage_cmdset,
> >> + .page_per_block = 64,
> >> + .page_size = 2048,
> >> + .flash_width = 8,
> >> + .dfc_width = 8,
> >> + .num_blocks = 2048,
> >> + .chip_id = 0xda20,
> >> + },
> >> +};
> >> +
> >> +
> >> +static struct mtd_partition trizeps6_nand_partitions[] = {
> >> + {
> >> + .name = "bootloader",
> >> + .offset = 0,
> >> + .size = SZ_16M,
> >> + .mask_flags = MTD_WRITEABLE,
> >> + }, {
> >> + .name = "reserved",
> >> + .offset = MTDPART_OFS_APPEND,
> >> + .size = SZ_128K,
> >> + .mask_flags = MTD_WRITEABLE,
> >> + }, {
> >> + .name = "kernel",
> >> + .offset = MTDPART_OFS_APPEND,
> >> + .size = (2*SZ_2M + SZ_1M),
> >> + .mask_flags = 0,
> >> + }, {
> >> + .name = "filesystem",
> >> + .offset = MTDPART_OFS_APPEND,
> >> + .size = (SZ_256M - 3*SZ_8M),
> >> + .mask_flags = 0,
> >> + }
> >> +};
> >> +
> >> +static struct pxa3xx_nand_platform_data trizeps6_nand_info = {
> >> + .enable_arbiter = 1,
> >> + .parts = trizeps6_nand_partitions,
> >> + .nr_parts = ARRAY_SIZE(trizeps6_nand_partitions),
> >> + .flash = trizeps6_flashes,
> >> + .num_flash = ARRAY_SIZE(trizeps6_flashes),
> >> + .keep_config = 0
> >> +};
> >> +
> >> +
> >> +
> >> +static struct i2c_board_info trizeps6_i2c_devices[] = {
> >> + { I2C_BOARD_INFO("pcf8593", 0x51), },
> >> +};
> >> +
> >> +
> >>
> +/******************************************************************************
> >> + * LCD
> >> +
> >>
> ******************************************************************************/
> >> +static struct fb_videomode trizeps6_video_modes[] = {
> >> + [0] = {
> >> + .pixclock = 39720,
> >> + .refresh = 60,
> >> + .xres = 640,
> >> + .yres = 480,
> >> + .hsync_len = 63,
> >> + .left_margin = 12,
> >> + .right_margin = 12,
> >> + .vsync_len = 4,
> >> + .upper_margin = 32,
> >> + .lower_margin = 10,
> >> + .sync = FB_SYNC_VERT_HIGH_ACT |
> FB_SYNC_HOR_HIGH_ACT,
> >> + },
> >> +};
> >> +
> >> +static struct pxa168fb_mach_info trizeps6_lcd_info = {
> >> + .id = "Base-trizeps6",
> >> + .modes = trizeps6_video_modes,
> >> + .num_modes = ARRAY_SIZE(trizeps6_video_modes),
> >> + .pix_fmt = PIX_FMT_RGB565,
> >> + .io_pin_allocation_mode = PIN_MODE_DUMB_16_GPIO,
> >> + .dumb_mode = DUMB_MODE_RGB565,
> >> + .active = 1,
> >> + .panel_rbswap = 1,
> >> + .invert_pixclock = 0,
> >> +};
> >> +
> >> +
> >> +static struct platform_device *trizeps6_devices[] __initdata = {
> >> + &cpld_device,
> >> +};
> >> +
> >> +static void __init trizeps6_init(void)
> >> +{
> >> + mfp_config(ARRAY_AND_SIZE(trizeps6_pin_config));
> >> +
> >> + pxa168_add_uart(1);
> >> + pxa168_add_uart(2);
> >> +#ifdef STUART_SODIMM
> >> + pxa168_add_uart(3);
> >> +#endif
> >> + pxa168_add_nand(&trizeps6_nand_info);
> >> + platform_add_devices(trizeps6_devices,
> >> + ARRAY_SIZE(trizeps6_devices));
> >> +
> >> + pxa168_add_fb(&trizeps6_lcd_info);
> >> + pxa168_add_mfu(&trizeps6_eth_data);
> >> + pxa168_add_twsi(0, NULL, ARRAY_AND_SIZE(trizeps6_i2c_devices));
> >> + trizeps6_ts_init();
> >> +}
> >> +
> >> +static void __init trizeps6_map_io(void)
> >> +{
> >> + mmp_map_io();
> >> +}
> >> +
> >> +MACHINE_START(TRIZEPS6, "PXA168-based Keith & Koep Trizeps VI
> Development
> >> Module")
> >> + /* MAINTAINER("Yupeng Schneider" <
> yupeng.schneider at googlemail.com>) */
> >> + .map_io = trizeps6_map_io,
> >> + .init_irq = pxa168_init_irq,
> >> + .timer = &pxa168_timer,
> >> + .init_machine = trizeps6_init,
> >> +MACHINE_END
> >> +
> >> +
> >> diff --git a/arch/arm/mach-mmp/trizeps6_cpld.c
> >> b/arch/arm/mach-mmp/trizeps6_cpld.c
> >> index 0000000..2577b0f
> >> --- /dev/null
> >> +++ b/arch/arm/mach-mmp/trizeps6_cpld.c
> >> @@ -0,0 +1,145 @@
> >> +/*
> >> + * linux/arch/arm/mach-mmp/trizeps6_cpld.c
> >> + *
> >> + *
> >> + * Author: Yupeng Schneider
> >> + * Created: 27 10, 2010
> >> + * Copyright: Yupeng Schneider
> >> + *
> >> + * This program is free software; you can redistribute it and/or
> modify
> >> + * it under the terms of the GNU General Public License version 2 as +
> *
> >> published by the Free Software Foundation.*/
> >> +
> >> +#include <linux/kernel.h>
> >> +#include <linux/ioport.h>
> >> +#include <linux/platform_device.h>
> >> +#include <linux/device.h>
> >> +#include <linux/module.h>
> >> +
> >> +#include <asm/io.h>
> >> +#include <asm/delay.h>
> >> +#include <mach/trizeps6.h>
> >> +#include <mach/trizeps6_cpld.h>
> >> +
> >> +struct cpld_info {
> >> + struct region {
> >> + struct resource *res;
> >> + struct resource *req;
> >> + void __iomem *iom;
> >> + unsigned short val;
> >> + } addr[7];
> >> +} cpld_info;
> >> +
> >> +static struct cpld_info cpld = { { { 0 } } };
> >> +
> >> +inline void trizeps6_cpld_writew(unsigned int reg, unsigned short
> value) +{
> >> + if ((cpld.addr[reg].iom != NULL))
> >> + writew(value, cpld.addr[reg].iom);
> >> +
> >> +}
> >> +
> >> +unsigned short trizeps6_cpld_readw(unsigned int reg)
> >> +{
> >> + short value = 0;
> >> + if (reg != HIBE_S || reg != HIBE_R || reg != PWM || reg !=
> PSET_S || reg
> >> != PSET_R) {
> >> +
> >> + if ((cpld.addr[reg].iom != NULL))
> >> + value = readw(cpld.addr[reg].iom);
> >> + }
> >> + return value;
> >> +}
> >> +EXPORT_SYMBOL(trizeps6_cpld_readw);
> >> +
> >> +static int trizeps6_cpld_probe(struct platform_device *pdev)
> >> +{
> >> + int i;
> >> +
> >> + CPLD_CTRL_R = CPLD_CONTROL_ETHPHY | CPLD_CONTROL_GR;
> >> +#ifdef STUART_SODIMM
> >> + CPLD_FTUR_S = CPLD_FEATURE_UART3_SODIMM;
> >> +#endif
> >> + for (i = CTRL_S; i <= TTLO_R; i++) {
> >> + cpld.addr[i].res = platform_get_resource(pdev,
> IORESOURCE_MEM, i);
> >> + if (cpld.addr[i].res == NULL) {
> >> + dev_err(&pdev->dev, "cannot get resource %d
> area\n", i);
> >> + return -EIO;
> >> + }
> >> + cpld.addr[i].req =
> request_mem_region(cpld.addr[i].res->start,
> >> + 2, pdev->name);
> >> + if (cpld.addr[i].req == NULL) {
> >> + dev_err(&pdev->dev, "cannot claim addr area
> %d\n", i);
> >> + return -EIO;
> >> + }
> >> + cpld.addr[i].iom = ioremap(cpld.addr[i].res->start, 2);
> >> + if (cpld.addr[i].iom == NULL) {
> >> + dev_err(&pdev->dev, "cannot remap addr area
> %d\n", i);
> >> + return -EIO;
> >> + }
> >> + switch (i) {
> >> + case CTRL_R:
> >> + trizeps6_cpld_writew(CTRL_R, CPLD_CTRL_R);
> >> + break;
> >> + case FTUR_S:
> >> + trizeps6_cpld_writew(FTUR_S, CPLD_FTUR_S);
> >> + break;
> >> + default:
> >> + ;
> >> +
> >> + }
> >> + dev_dbg(&pdev->dev, "mapped region [%d] %08x -> %p\n",
> i,
> >> + (int)cpld.addr[i].req->start,
> cpld.addr[i].iom);
> >> + }
> >> +
> >> +
> >> + return 0;
> >> +}
> >> +
> >> +static int trizeps6_cpld_remove(struct platform_device *pdev)
> >> +{
> >> + dev_dbg(&pdev->dev, "trizeps6_cpld_remove()\n");
> >> + return 0;
> >> +}
> >> +
> >> +#ifdef CONFIG_PM
> >> +static int trizeps6_cpld_suspend(struct platform_device *pdev,
> >> pm_message_t state)
> >> +{
> >> + return 0;
> >> +}
> >> +
> >> +static int trizeps6_cpld_resume(struct platform_device *pdev)
> >> +{
> >> + return 0;
> >> +}
> >> +#endif
> >> +
> >> +static struct platform_driver trizeps6_cpld_driver = {
> >> + .probe = trizeps6_cpld_probe,
> >> + .remove = trizeps6_cpld_remove,
> >> +#ifdef CONFIG_PM
> >> + .suspend = trizeps6_cpld_suspend,
> >> + .resume = trizeps6_cpld_resume,
> >> +#endif
> >> + .driver = {
> >> + .name = "trizeps6-cpld",
> >> + },
> >> +};
> >> +
> >> +
> >> +static int __devinit trizeps6_cpld_init(void)
> >> +{
> >> +
> >> + return platform_driver_register(&trizeps6_cpld_driver);
> >> +}
> >> +
> >> +static void trizeps6_cpld_exit(void)
> >> +{
> >> + platform_driver_unregister(&trizeps6_cpld_driver);
> >> +}
> >> +
> >> +arch_initcall(trizeps6_cpld_init);
> >> +module_exit(trizeps6_cpld_exit);
> >> +
> >> +MODULE_AUTHOR("Yupeng Schneider <yupeng.schneider@googlemail.com>");
> >> +MODULE_DESCRIPTION("Trizeps VI CPLD");
> >> +MODULE_LICENSE("GPL");
> >> --
> >> 1.6.3.3
> >>
> >>
> >>
> >>
> >
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20110210/9018d74e/attachment-0001.html>
^ permalink raw reply
* [RFC,PATCH 1/3] Add a common struct clk
From: Richard Zhao @ 2011-02-10 10:03 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <4D52F73A.4010707@bluewatersys.com>
On Thu, Feb 10, 2011 at 09:21:14AM +1300, Ryan Mallon wrote:
> On 02/09/2011 07:41 PM, Jeremy Kerr wrote:
>
> Hi Jeremy,
>
> Couple more comments below.
>
> ~Ryan
>
[...]
> > +int clk_enable(struct clk *clk)
> > +{
> > + unsigned long flags;
> > + int ret = 0;
> > +
> > + spin_lock_irqsave(&clk->enable_lock, flags);
>
> WARN_ON(clk->prepare_count == 0); ?
>
> > + if (clk->enable_count == 0 && clk->ops->enable)
> > + ret = clk->ops->enable(clk);
>
> Does it make sense to have a clock with no enable function which still
> returns success from clk_enable? Do we have any platforms which have
> NULL clk_enable functions?
>
> I think that for enable/disable at least we should require platforms to
> provide functions and oops if they have failed to do so. In the rare
> case that a platform doesn't need to do anything for enable/disable they
> can just supply empty functions.
It's possible to be NULL. So are set_rate/get_rate.
Ideally, if it's NULL:
prepare/unprepare: only call parent's prepare/unprepare
enable/disable: only call parent's enable/disable
set_rate: fail
get_rate: reture parent's get_rate
set_parent: fail
get_parent: fail
Thanks
Richard
>
> > +
> > + if (!ret)
> > + clk->enable_count++;
> > + spin_unlock_irqrestore(&clk->enable_lock, flags);
> > +
> > + return ret;
> > +}
> > +EXPORT_SYMBOL_GPL(clk_enable);
> > +
^ permalink raw reply
* [PATCH 1/5] cpu_pm: Add cpu power management notifiers
From: Colin Cross @ 2011-02-10 10:04 UTC (permalink / raw)
To: linux-arm-kernel
During some CPU power modes entered during idle, hotplug and
suspend, peripherals located in the CPU power domain, such as
the GIC, localtimers, and VFP, may be powered down. Add a
notifier chain that allows drivers for those peripherals to
be notified before and after they may be reset.
Notified drivers can include VFP co-processor, interrupt controller
and it's PM extensions, local CPU timers context save/restore which
shouldn't be interrupted. Hence CPU PM event APIs must be called
with interrupts disabled.
Signed-off-by: Colin Cross <ccross@android.com>
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Reviewed-by: Kevin Hilman <khilman@ti.com>
Tested-and-Acked-by: Shawn Guo <shawn.guo@linaro.org>
Tested-by: Kevin Hilman <khilman@ti.com>
---
include/linux/cpu_pm.h | 109 ++++++++++++++++++++++++++
kernel/Makefile | 1 +
kernel/cpu_pm.c | 200 ++++++++++++++++++++++++++++++++++++++++++++++++
kernel/power/Kconfig | 4 +
4 files changed, 314 insertions(+), 0 deletions(-)
create mode 100644 include/linux/cpu_pm.h
create mode 100644 kernel/cpu_pm.c
diff --git a/include/linux/cpu_pm.h b/include/linux/cpu_pm.h
new file mode 100644
index 0000000..455b233
--- /dev/null
+++ b/include/linux/cpu_pm.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * Author:
+ * Colin Cross <ccross@android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef _LINUX_CPU_PM_H
+#define _LINUX_CPU_PM_H
+
+#include <linux/kernel.h>
+#include <linux/notifier.h>
+
+/*
+ * When a CPU goes to a low power state that turns off power to the CPU's
+ * power domain, the contents of some blocks (floating point coprocessors,
+ * interrupt controllers, caches, timers) in the same power domain can
+ * be lost. The cpm_pm notifiers provide a method for platform idle, suspend,
+ * and hotplug implementations to notify the drivers for these blocks that
+ * they may be reset.
+ *
+ * All cpu_pm notifications must be called with interrupts disabled.
+ *
+ * The notifications are split into two classes: CPU notifications and CPU
+ * cluster notifications.
+ *
+ * CPU notifications apply to a single CPU and must be called on the affected
+ * CPU. They are used to save per-cpu context for affected blocks.
+ *
+ * CPU cluster notifications apply to all CPUs in a single power domain. They
+ * are used to save any global context for affected blocks, and must be called
+ * after all the CPUs in the power domain have been notified of the low power
+ * state.
+ */
+
+/*
+ * Event codes passed as unsigned long val to notifier calls
+ */
+enum cpu_pm_event {
+ /* A single cpu is entering a low power state */
+ CPU_PM_ENTER,
+
+ /* A single cpu failed to enter a low power state */
+ CPU_PM_ENTER_FAILED,
+
+ /* A single cpu is exiting a low power state */
+ CPU_PM_EXIT,
+
+ /* A cpu power domain is entering a low power state */
+ CPU_CLUSTER_PM_ENTER,
+
+ /* A cpu power domain failed to enter a low power state */
+ CPU_CLUSTER_PM_ENTER_FAILED,
+
+ /* A cpu power domain is exiting a low power state */
+ CPU_CLUSTER_PM_EXIT,
+};
+
+#ifdef CONFIG_CPU_PM
+int cpu_pm_register_notifier(struct notifier_block *nb);
+int cpu_pm_unregister_notifier(struct notifier_block *nb);
+int cpu_pm_enter(void);
+int cpu_pm_exit(void);
+int cpu_cluster_pm_enter(void);
+int cpu_cluster_pm_exit(void);
+
+#else
+
+static inline int cpu_pm_register_notifier(struct notifier_block *nb)
+{
+ return 0;
+}
+
+static inline int cpu_pm_unregister_notifier(struct notifier_block *nb)
+{
+ return 0;
+}
+
+static inline int cpu_pm_enter(void)
+{
+ return 0;
+}
+
+static inline int cpu_pm_exit(void)
+{
+ return 0;
+}
+
+static inline int cpu_cluster_pm_enter(void)
+{
+ return 0;
+}
+
+static inline int cpu_cluster_pm_exit(void)
+{
+ return 0;
+}
+#endif
+#endif
diff --git a/kernel/Makefile b/kernel/Makefile
index eca595e..988cb3d 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -101,6 +101,7 @@ obj-$(CONFIG_RING_BUFFER) += trace/
obj-$(CONFIG_TRACEPOINTS) += trace/
obj-$(CONFIG_SMP) += sched_cpupri.o
obj-$(CONFIG_IRQ_WORK) += irq_work.o
+obj-$(CONFIG_CPU_PM) += cpu_pm.o
obj-$(CONFIG_PERF_EVENTS) += events/
diff --git a/kernel/cpu_pm.c b/kernel/cpu_pm.c
new file mode 100644
index 0000000..4d1ff4a
--- /dev/null
+++ b/kernel/cpu_pm.c
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * Author:
+ * Colin Cross <ccross@android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/cpu_pm.h>
+#include <linux/module.h>
+#include <linux/notifier.h>
+#include <linux/spinlock.h>
+
+static DEFINE_RWLOCK(cpu_pm_notifier_lock);
+static RAW_NOTIFIER_HEAD(cpu_pm_notifier_chain);
+
+static int cpu_pm_notify(enum cpu_pm_event event, int nr_to_call, int *nr_calls)
+{
+ int ret;
+
+ ret = __raw_notifier_call_chain(&cpu_pm_notifier_chain, event, NULL,
+ nr_to_call, nr_calls);
+
+ return notifier_to_errno(ret);
+}
+
+/**
+ * cpu_pm_register_notifier - register a driver with cpu_pm
+ * @nb: notifier block to register
+ *
+ * Add a driver to a list of drivers that are notified about
+ * CPU and CPU cluster low power entry and exit.
+ *
+ * This function may sleep, and has the same return conditions as
+ * raw_notifier_chain_register.
+ */
+int cpu_pm_register_notifier(struct notifier_block *nb)
+{
+ unsigned long flags;
+ int ret;
+
+ write_lock_irqsave(&cpu_pm_notifier_lock, flags);
+ ret = raw_notifier_chain_register(&cpu_pm_notifier_chain, nb);
+ write_unlock_irqrestore(&cpu_pm_notifier_lock, flags);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(cpu_pm_register_notifier);
+
+/**
+ * cpu_pm_unregister_notifier - unregister a driver with cpu_pm
+ * @nb: notifier block to be unregistered
+ *
+ * Remove a driver from the CPU PM notifier list.
+ *
+ * This function may sleep, and has the same return conditions as
+ * raw_notifier_chain_unregister.
+ */
+int cpu_pm_unregister_notifier(struct notifier_block *nb)
+{
+ unsigned long flags;
+ int ret;
+
+ write_lock_irqsave(&cpu_pm_notifier_lock, flags);
+ ret = raw_notifier_chain_unregister(&cpu_pm_notifier_chain, nb);
+ write_unlock_irqrestore(&cpu_pm_notifier_lock, flags);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(cpu_pm_unregister_notifier);
+
+/**
+ * cpm_pm_enter - CPU low power entry notifier
+ *
+ * Notifies listeners that a single CPU is entering a low power state that may
+ * cause some blocks in the same power domain as the cpu to reset.
+ *
+ * Must be called on the affected CPU with interrupts disabled. Platform is
+ * responsible for ensuring that cpu_pm_enter is not called twice on the same
+ * CPU before cpu_pm_exit is called. Notified drivers can include VFP
+ * co-processor, interrupt controller and it's PM extensions, local CPU
+ * timers context save/restore which shouldn't be interrupted. Hence it
+ * must be called with interrupts disabled.
+ *
+ * Return conditions are same as __raw_notifier_call_chain.
+ */
+int cpu_pm_enter(void)
+{
+ int nr_calls;
+ int ret = 0;
+
+ read_lock(&cpu_pm_notifier_lock);
+ ret = cpu_pm_notify(CPU_PM_ENTER, -1, &nr_calls);
+ if (ret)
+ /*
+ * Inform listeners (nr_calls - 1) about failure of CPU PM
+ * PM entry who are notified earlier to prepare for it.
+ */
+ cpu_pm_notify(CPU_PM_ENTER_FAILED, nr_calls - 1, NULL);
+ read_unlock(&cpu_pm_notifier_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(cpu_pm_enter);
+
+/**
+ * cpm_pm_exit - CPU low power exit notifier
+ *
+ * Notifies listeners that a single CPU is exiting a low power state that may
+ * have caused some blocks in the same power domain as the cpu to reset.
+ *
+ * Notified drivers can include VFP co-processor, interrupt controller
+ * and it's PM extensions, local CPU timers context save/restore which
+ * shouldn't be interrupted. Hence it must be called with interrupts disabled.
+ *
+ * Return conditions are same as __raw_notifier_call_chain.
+ */
+int cpu_pm_exit(void)
+{
+ int ret;
+
+ read_lock(&cpu_pm_notifier_lock);
+ ret = cpu_pm_notify(CPU_PM_EXIT, -1, NULL);
+ read_unlock(&cpu_pm_notifier_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(cpu_pm_exit);
+
+/**
+ * cpm_cluster_pm_enter - CPU cluster low power entry notifier
+ *
+ * Notifies listeners that all cpus in a power domain are entering a low power
+ * state that may cause some blocks in the same power domain to reset.
+ *
+ * Must be called after cpu_pm_enter has been called on all cpus in the power
+ * domain, and before cpu_pm_exit has been called on any cpu in the power
+ * domain. Notified drivers can include VFP co-processor, interrupt controller
+ * and it's PM extensions, local CPU timers context save/restore which
+ * shouldn't be interrupted. Hence it must be called with interrupts disabled.
+ *
+ * Must be called with interrupts disabled.
+ *
+ * Return conditions are same as __raw_notifier_call_chain.
+ */
+int cpu_cluster_pm_enter(void)
+{
+ int nr_calls;
+ int ret = 0;
+
+ read_lock(&cpu_pm_notifier_lock);
+ ret = cpu_pm_notify(CPU_CLUSTER_PM_ENTER, -1, &nr_calls);
+ if (ret)
+ /*
+ * Inform listeners (nr_calls - 1) about failure of CPU cluster
+ * PM entry who are notified earlier to prepare for it.
+ */
+ cpu_pm_notify(CPU_CLUSTER_PM_ENTER_FAILED, nr_calls - 1, NULL);
+ read_unlock(&cpu_pm_notifier_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(cpu_cluster_pm_enter);
+
+/**
+ * cpm_cluster_pm_exit - CPU cluster low power exit notifier
+ *
+ * Notifies listeners that all cpus in a power domain are exiting form a
+ * low power state that may have caused some blocks in the same power domain
+ * to reset.
+ *
+ * Must be called after cpu_pm_exit has been called on all cpus in the power
+ * domain, and before cpu_pm_exit has been called on any cpu in the power
+ * domain. Notified drivers can include VFP co-processor, interrupt controller
+ * and it's PM extensions, local CPU timers context save/restore which
+ * shouldn't be interrupted. Hence it must be called with interrupts disabled.
+ *
+ * Return conditions are same as __raw_notifier_call_chain.
+ */
+int cpu_cluster_pm_exit(void)
+{
+ int ret;
+
+ read_lock(&cpu_pm_notifier_lock);
+ ret = cpu_pm_notify(CPU_CLUSTER_PM_EXIT, -1, NULL);
+ read_unlock(&cpu_pm_notifier_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(cpu_cluster_pm_exit);
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index 3744c59..80a8597 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -235,3 +235,7 @@ config PM_GENERIC_DOMAINS
config PM_GENERIC_DOMAINS_RUNTIME
def_bool y
depends on PM_RUNTIME && PM_GENERIC_DOMAINS
+
+config CPU_PM
+ bool
+ depends on SUSPEND || CPU_IDLE
--
1.7.4.1
--------------030209040405090402060508--
^ permalink raw reply related
* [PATCH 1/5] cpu_pm: Add cpu power management notifiers
From: Colin Cross @ 2011-02-10 10:04 UTC (permalink / raw)
To: linux-arm-kernel
During some CPU power modes entered during idle, hotplug and
suspend, peripherals located in the CPU power domain, such as
the GIC, localtimers, and VFP, may be powered down. Add a
notifier chain that allows drivers for those peripherals to
be notified before and after they may be reset.
Notified drivers can include VFP co-processor, interrupt controller
and it's PM extensions, local CPU timers context save/restore which
shouldn't be interrupted. Hence CPU PM event APIs must be called
with interrupts disabled.
Signed-off-by: Colin Cross <ccross@android.com>
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Reviewed-by: Kevin Hilman <khilman@ti.com>
Tested-and-Acked-by: Shawn Guo <shawn.guo@linaro.org>
Tested-by: Kevin Hilman <khilman@ti.com>
---
include/linux/cpu_pm.h | 109 ++++++++++++++++++++++++++
kernel/Makefile | 1 +
kernel/cpu_pm.c | 200 ++++++++++++++++++++++++++++++++++++++++++++++++
kernel/power/Kconfig | 4 +
4 files changed, 314 insertions(+), 0 deletions(-)
create mode 100644 include/linux/cpu_pm.h
create mode 100644 kernel/cpu_pm.c
diff --git a/include/linux/cpu_pm.h b/include/linux/cpu_pm.h
new file mode 100644
index 0000000..455b233
--- /dev/null
+++ b/include/linux/cpu_pm.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * Author:
+ * Colin Cross <ccross@android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef _LINUX_CPU_PM_H
+#define _LINUX_CPU_PM_H
+
+#include <linux/kernel.h>
+#include <linux/notifier.h>
+
+/*
+ * When a CPU goes to a low power state that turns off power to the CPU's
+ * power domain, the contents of some blocks (floating point coprocessors,
+ * interrupt controllers, caches, timers) in the same power domain can
+ * be lost. The cpm_pm notifiers provide a method for platform idle, suspend,
+ * and hotplug implementations to notify the drivers for these blocks that
+ * they may be reset.
+ *
+ * All cpu_pm notifications must be called with interrupts disabled.
+ *
+ * The notifications are split into two classes: CPU notifications and CPU
+ * cluster notifications.
+ *
+ * CPU notifications apply to a single CPU and must be called on the affected
+ * CPU. They are used to save per-cpu context for affected blocks.
+ *
+ * CPU cluster notifications apply to all CPUs in a single power domain. They
+ * are used to save any global context for affected blocks, and must be called
+ * after all the CPUs in the power domain have been notified of the low power
+ * state.
+ */
+
+/*
+ * Event codes passed as unsigned long val to notifier calls
+ */
+enum cpu_pm_event {
+ /* A single cpu is entering a low power state */
+ CPU_PM_ENTER,
+
+ /* A single cpu failed to enter a low power state */
+ CPU_PM_ENTER_FAILED,
+
+ /* A single cpu is exiting a low power state */
+ CPU_PM_EXIT,
+
+ /* A cpu power domain is entering a low power state */
+ CPU_CLUSTER_PM_ENTER,
+
+ /* A cpu power domain failed to enter a low power state */
+ CPU_CLUSTER_PM_ENTER_FAILED,
+
+ /* A cpu power domain is exiting a low power state */
+ CPU_CLUSTER_PM_EXIT,
+};
+
+#ifdef CONFIG_CPU_PM
+int cpu_pm_register_notifier(struct notifier_block *nb);
+int cpu_pm_unregister_notifier(struct notifier_block *nb);
+int cpu_pm_enter(void);
+int cpu_pm_exit(void);
+int cpu_cluster_pm_enter(void);
+int cpu_cluster_pm_exit(void);
+
+#else
+
+static inline int cpu_pm_register_notifier(struct notifier_block *nb)
+{
+ return 0;
+}
+
+static inline int cpu_pm_unregister_notifier(struct notifier_block *nb)
+{
+ return 0;
+}
+
+static inline int cpu_pm_enter(void)
+{
+ return 0;
+}
+
+static inline int cpu_pm_exit(void)
+{
+ return 0;
+}
+
+static inline int cpu_cluster_pm_enter(void)
+{
+ return 0;
+}
+
+static inline int cpu_cluster_pm_exit(void)
+{
+ return 0;
+}
+#endif
+#endif
diff --git a/kernel/Makefile b/kernel/Makefile
index eca595e..988cb3d 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -101,6 +101,7 @@ obj-$(CONFIG_RING_BUFFER) += trace/
obj-$(CONFIG_TRACEPOINTS) += trace/
obj-$(CONFIG_SMP) += sched_cpupri.o
obj-$(CONFIG_IRQ_WORK) += irq_work.o
+obj-$(CONFIG_CPU_PM) += cpu_pm.o
obj-$(CONFIG_PERF_EVENTS) += events/
diff --git a/kernel/cpu_pm.c b/kernel/cpu_pm.c
new file mode 100644
index 0000000..4d1ff4a
--- /dev/null
+++ b/kernel/cpu_pm.c
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * Author:
+ * Colin Cross <ccross@android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/cpu_pm.h>
+#include <linux/module.h>
+#include <linux/notifier.h>
+#include <linux/spinlock.h>
+
+static DEFINE_RWLOCK(cpu_pm_notifier_lock);
+static RAW_NOTIFIER_HEAD(cpu_pm_notifier_chain);
+
+static int cpu_pm_notify(enum cpu_pm_event event, int nr_to_call, int *nr_calls)
+{
+ int ret;
+
+ ret = __raw_notifier_call_chain(&cpu_pm_notifier_chain, event, NULL,
+ nr_to_call, nr_calls);
+
+ return notifier_to_errno(ret);
+}
+
+/**
+ * cpu_pm_register_notifier - register a driver with cpu_pm
+ * @nb: notifier block to register
+ *
+ * Add a driver to a list of drivers that are notified about
+ * CPU and CPU cluster low power entry and exit.
+ *
+ * This function may sleep, and has the same return conditions as
+ * raw_notifier_chain_register.
+ */
+int cpu_pm_register_notifier(struct notifier_block *nb)
+{
+ unsigned long flags;
+ int ret;
+
+ write_lock_irqsave(&cpu_pm_notifier_lock, flags);
+ ret = raw_notifier_chain_register(&cpu_pm_notifier_chain, nb);
+ write_unlock_irqrestore(&cpu_pm_notifier_lock, flags);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(cpu_pm_register_notifier);
+
+/**
+ * cpu_pm_unregister_notifier - unregister a driver with cpu_pm
+ * @nb: notifier block to be unregistered
+ *
+ * Remove a driver from the CPU PM notifier list.
+ *
+ * This function may sleep, and has the same return conditions as
+ * raw_notifier_chain_unregister.
+ */
+int cpu_pm_unregister_notifier(struct notifier_block *nb)
+{
+ unsigned long flags;
+ int ret;
+
+ write_lock_irqsave(&cpu_pm_notifier_lock, flags);
+ ret = raw_notifier_chain_unregister(&cpu_pm_notifier_chain, nb);
+ write_unlock_irqrestore(&cpu_pm_notifier_lock, flags);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(cpu_pm_unregister_notifier);
+
+/**
+ * cpm_pm_enter - CPU low power entry notifier
+ *
+ * Notifies listeners that a single CPU is entering a low power state that may
+ * cause some blocks in the same power domain as the cpu to reset.
+ *
+ * Must be called on the affected CPU with interrupts disabled. Platform is
+ * responsible for ensuring that cpu_pm_enter is not called twice on the same
+ * CPU before cpu_pm_exit is called. Notified drivers can include VFP
+ * co-processor, interrupt controller and it's PM extensions, local CPU
+ * timers context save/restore which shouldn't be interrupted. Hence it
+ * must be called with interrupts disabled.
+ *
+ * Return conditions are same as __raw_notifier_call_chain.
+ */
+int cpu_pm_enter(void)
+{
+ int nr_calls;
+ int ret = 0;
+
+ read_lock(&cpu_pm_notifier_lock);
+ ret = cpu_pm_notify(CPU_PM_ENTER, -1, &nr_calls);
+ if (ret)
+ /*
+ * Inform listeners (nr_calls - 1) about failure of CPU PM
+ * PM entry who are notified earlier to prepare for it.
+ */
+ cpu_pm_notify(CPU_PM_ENTER_FAILED, nr_calls - 1, NULL);
+ read_unlock(&cpu_pm_notifier_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(cpu_pm_enter);
+
+/**
+ * cpm_pm_exit - CPU low power exit notifier
+ *
+ * Notifies listeners that a single CPU is exiting a low power state that may
+ * have caused some blocks in the same power domain as the cpu to reset.
+ *
+ * Notified drivers can include VFP co-processor, interrupt controller
+ * and it's PM extensions, local CPU timers context save/restore which
+ * shouldn't be interrupted. Hence it must be called with interrupts disabled.
+ *
+ * Return conditions are same as __raw_notifier_call_chain.
+ */
+int cpu_pm_exit(void)
+{
+ int ret;
+
+ read_lock(&cpu_pm_notifier_lock);
+ ret = cpu_pm_notify(CPU_PM_EXIT, -1, NULL);
+ read_unlock(&cpu_pm_notifier_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(cpu_pm_exit);
+
+/**
+ * cpm_cluster_pm_enter - CPU cluster low power entry notifier
+ *
+ * Notifies listeners that all cpus in a power domain are entering a low power
+ * state that may cause some blocks in the same power domain to reset.
+ *
+ * Must be called after cpu_pm_enter has been called on all cpus in the power
+ * domain, and before cpu_pm_exit has been called on any cpu in the power
+ * domain. Notified drivers can include VFP co-processor, interrupt controller
+ * and it's PM extensions, local CPU timers context save/restore which
+ * shouldn't be interrupted. Hence it must be called with interrupts disabled.
+ *
+ * Must be called with interrupts disabled.
+ *
+ * Return conditions are same as __raw_notifier_call_chain.
+ */
+int cpu_cluster_pm_enter(void)
+{
+ int nr_calls;
+ int ret = 0;
+
+ read_lock(&cpu_pm_notifier_lock);
+ ret = cpu_pm_notify(CPU_CLUSTER_PM_ENTER, -1, &nr_calls);
+ if (ret)
+ /*
+ * Inform listeners (nr_calls - 1) about failure of CPU cluster
+ * PM entry who are notified earlier to prepare for it.
+ */
+ cpu_pm_notify(CPU_CLUSTER_PM_ENTER_FAILED, nr_calls - 1, NULL);
+ read_unlock(&cpu_pm_notifier_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(cpu_cluster_pm_enter);
+
+/**
+ * cpm_cluster_pm_exit - CPU cluster low power exit notifier
+ *
+ * Notifies listeners that all cpus in a power domain are exiting form a
+ * low power state that may have caused some blocks in the same power domain
+ * to reset.
+ *
+ * Must be called after cpu_pm_exit has been called on all cpus in the power
+ * domain, and before cpu_pm_exit has been called on any cpu in the power
+ * domain. Notified drivers can include VFP co-processor, interrupt controller
+ * and it's PM extensions, local CPU timers context save/restore which
+ * shouldn't be interrupted. Hence it must be called with interrupts disabled.
+ *
+ * Return conditions are same as __raw_notifier_call_chain.
+ */
+int cpu_cluster_pm_exit(void)
+{
+ int ret;
+
+ read_lock(&cpu_pm_notifier_lock);
+ ret = cpu_pm_notify(CPU_CLUSTER_PM_EXIT, -1, NULL);
+ read_unlock(&cpu_pm_notifier_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(cpu_cluster_pm_exit);
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index 3744c59..80a8597 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -235,3 +235,7 @@ config PM_GENERIC_DOMAINS
config PM_GENERIC_DOMAINS_RUNTIME
def_bool y
depends on PM_RUNTIME && PM_GENERIC_DOMAINS
+
+config CPU_PM
+ bool
+ depends on SUSPEND || CPU_IDLE
--
1.7.4.1
--------------050304080702050405070807--
^ permalink raw reply related
* [PATCH] ARM: imx/eukrea_mbimx27: fix compile warnings about unused variables
From: Uwe Kleine-König @ 2011-02-10 10:07 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <4D52F566.1070009@ru.mvista.com>
Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
---
Hello,
On Wed, Feb 09, 2011 at 11:13:26PM +0300, Sergei Shtylyov wrote:
> >>>-static struct spi_board_info eukrea_mbimx27_spi_board_info[] __initdata = {
> >>>+static struct spi_board_info __maybe_unused
> >>>+eukrea_mbimx27_spi_board_info[] __initdata = {
>
> >> I think the second line should be somewhat indented.
>
> >I like it as it is. There are no rules for that, no?
>
> Documentation/CodingStyle, chapter 2.
hmm, this is how vim indents and checkpatch doesn't diagnose a style problem.
Though I prefer it unindented, too, I don't care enough. So here's a patch
with the 2nd line having 2 tabs. Up to Sascha which to include ...
Best regards and thanks,
Uwe
arch/arm/mach-imx/eukrea_mbimx27-baseboard.c | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c b/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c
index 275c858..d12815d 100644
--- a/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c
+++ b/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c
@@ -249,7 +249,7 @@ static const struct imxuart_platform_data uart_pdata __initconst = {
#define ADS7846_PENDOWN (GPIO_PORTD | 25)
-static void ads7846_dev_init(void)
+static void __maybe_unused ads7846_dev_init(void)
{
if (gpio_request(ADS7846_PENDOWN, "ADS7846 pendown") < 0) {
printk(KERN_ERR "can't get ads746 pen down GPIO\n");
@@ -268,7 +268,8 @@ static struct ads7846_platform_data ads7846_config __initdata = {
.keep_vref_on = 1,
};
-static struct spi_board_info eukrea_mbimx27_spi_board_info[] __initdata = {
+static struct spi_board_info __maybe_unused
+ eukrea_mbimx27_spi_board_info[] __initdata = {
[0] = {
.modalias = "ads7846",
.bus_num = 0,
--
1.7.2.3
^ permalink raw reply related
* [PATCH]ARM: mmp: add Trizeps6 board support
From: Yupeng Schneider @ 2011-02-10 10:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <AANLkTim54zTKwhTEKF-ppq-nbtPRAYRvxH3YL0RJ4Vuc@mail.gmail.com>
Hello Eric,
>
> 2011/2/10 Eric Miao <eric.y.miao@gmail.com>
>
>> Corrected the linux-arm-kernel ML address.
>>
>> On Thu, Feb 10, 2011 at 10:24 AM, Eric Miao <eric.y.miao@gmail.com>
>> wrote:
>> > On Thu, Feb 10, 2011 at 7:53 AM, Yupeng Schneider
>> > <yupeng.schneider@ipms.fraunhofer.de> wrote:
>> >> Hi all,
>> >>
>> >> the following patch add the BSP for the Trizeps6 board with pxa168
>> Processor.
>> >>
>> >> Signed-off-by: Yupeng Schneider <yupeng.schneider@googlemail.com>
>> >
>> > Hi Yupeng,
>> >
>> > This is really a nice patch. I would be better if this can be
>> separated
>> into
>> > some smaller patches further:
>>
thank u
>>
>> > 1. some of the MFP macros in trizeps6.h, they are generic and can be
>> > placed into mfp-pxa168.h, or is there any reason that the macros in
>> > mfp-pxa168.h do not work on your board?
>>
ok, i will place them into mfp-pxa168.h. I just thought it is not prefered
to change the mfp-pxa168 file.
>>
>> > 2. individual patches for adding uart3, audio, and cpld
>>
i would very glad to make them in small patchs. i am just now on travel,
and will do that in several days when i am back.
>>
>> > 3. then the patch for the board
>> >
>> > Sounds OK? Let me know your ideas.
>>
AC97+UCB1400: Sound and Touchscreen is ok. The related pxa2xx-ac97 files
have to be modified, the changes are not in this patch. If u want, i can
patch them later too.
yours,
Yupeng
>> >
>> > Thanks
>> > - eric
>> >
>> >> ---
>> >> arch/arm/mach-mmp/Kconfig | 29 ++
>> >> arch/arm/mach-mmp/Makefile | 1 +
>> >> arch/arm/mach-mmp/include/mach/audio.h | 29 ++
>> >> arch/arm/mach-mmp/include/mach/pxa168.h | 21 +
>> >> arch/arm/mach-mmp/include/mach/regs-apmu.h | 1 +
>> >> arch/arm/mach-mmp/include/mach/trizeps6.h | 122 ++++++
>> >> arch/arm/mach-mmp/include/mach/trizeps6_cpld.h | 87 +++++
>> >> arch/arm/mach-mmp/pxa168.c | 10 +
>> >> arch/arm/mach-mmp/trizeps6.c | 469
>> >> ++++++++++++++++++++++++
>> >> arch/arm/mach-mmp/trizeps6_cpld.c | 145 ++++++++
>> >> 10 files changed, 914 insertions(+), 0 deletions(-)
>> >> create mode 100755 arch/arm/mach-mmp/include/mach/audio.h
>> >> create mode 100755 arch/arm/mach-mmp/include/mach/trizeps6.h
>> >> create mode 100755 arch/arm/mach-mmp/include/mach/trizeps6_cpld.h
>> create
>> >> mode 100755 arch/arm/mach-mmp/trizeps6.c
>> >> create mode 100755 arch/arm/mach-mmp/trizeps6_cpld.c
>> >>
>> >> diff --git a/arch/arm/mach-mmp/Kconfig b/arch/arm/mach-mmp/Kconfig
>> index
>> >> 0711d3b..8c6be81 100644
>> >> --- a/arch/arm/mach-mmp/Kconfig
>> >> +++ b/arch/arm/mach-mmp/Kconfig
>> >> @@ -64,6 +64,35 @@ config MACH_TETON_BGA
>> >> Say 'Y' here if you want to support the Marvell PXA168-based
>> >> Teton BGA Development Board.
>> >>
>> >> +comment "Third Party Dev Platforms (sorted by vendor name)"
>> >> +
>> >> +config MACH_TRIZEPS6
>> >> + bool "Keith und Koep Trizeps6 DIMM-Module"
>> >> + select TRIZEPS6_PCMCIA
>> >> + select CPU_PXA168
>> >> + help
>> >> + Say 'Y' here if you want to support TRIZEPS VI board
>> Development Board.
>> >> +
>> >> +choice
>> >> + prompt "Select base board for Trizeps module"
>> >> + depends on MACH_TRIZEPS6
>> >> +
>> >> +config MACH_TRIZEPS6_CONXS
>> >> + bool "ConXS Eval Board"
>> >> +
>> >> +config MACH_TRIZEPS6_UCONXS
>> >> + bool "uConXS Eval Board"
>> >> +
>> >> +config MACH_TRIZEPS6_ANY
>> >> + bool "another Board"
>> >> +
>> >> +endchoice
>> >> +
>> >> +config TRIZEPS6_PCMCIA
>> >> + bool
>> >> + help
>> >> + Enable PCMCIA support for Trizeps modules
>> >> +
>> >> endmenu
>> >>
>> >> config CPU_PXA168
>> >> diff --git a/arch/arm/mach-mmp/Makefile b/arch/arm/mach-mmp/Makefile
>> index
>> >> 751cdbf..1b8744f 100644
>> >> --- a/arch/arm/mach-mmp/Makefile
>> >> +++ b/arch/arm/mach-mmp/Makefile
>> >> @@ -18,3 +18,4 @@ obj-$(CONFIG_MACH_TTC_DKB) += ttc_dkb.o
>> >> obj-$(CONFIG_MACH_FLINT) += flint.o
>> >> obj-$(CONFIG_MACH_MARVELL_JASPER) += jasper.o
>> >> obj-$(CONFIG_MACH_TETON_BGA) += teton_bga.o
>> >> +obj-$(CONFIG_MACH_TRIZEPS6) += trizeps6.o trizeps6_cpld.o
>> >> diff --git a/arch/arm/mach-mmp/include/mach/audio.h
>> >> b/arch/arm/mach-mmp/include/mach/audio.h
>> >> index 0000000..6ef474f
>> >> --- /dev/null
>> >> +++ b/arch/arm/mach-mmp/include/mach/audio.h
>> >> @@ -0,0 +1,29 @@
>> >> +#ifndef __ASM_ARCH_AUDIO_H__
>> >> +#define __ASM_ARCH_AUDIO_H__
>> >> +
>> >> +#include <sound/core.h>
>> >> +#include <sound/pcm.h>
>> >> +#include <sound/ac97_codec.h>
>> >> +
>> >> +/*
>> >> + * @reset_gpio: AC97 reset gpio (normally gpio113 or gpio95)
>> >> + * a -1 value means no gpio will be used for reset
>> >> + * @codec_pdata: AC97 codec platform_data
>> >> +
>> >> + * reset_gpio should only be specified for pxa27x CPUs where a
>> silicon
>> +
>> >> * bug prevents correct operation of the reset line. If not specified,
>> +
>> *
>> >> the default behaviour on these CPUs is to consider gpio 113 as the +
>> *
>> >> AC97 reset line, which is the default on most boards.
>> >> + */
>> >> +struct pxa2xx_audio_ops_t {
>> >> + int (*startup)(struct snd_pcm_substream *, void *);
>> >> + void (*shutdown)(struct snd_pcm_substream *, void *);
>> >> + void (*suspend)(void *);
>> >> + void (*resume)(void *);
>> >> + void *priv;
>> >> + int reset_gpio;
>> >> + void *codec_pdata[AC97_BUS_MAX_DEVICES];
>> >> +};
>> >> +
>> >> +
>> >> +#endif
>> >> diff --git a/arch/arm/mach-mmp/include/mach/pxa168.h
>> >> b/arch/arm/mach-mmp/include/mach/pxa168.h
>> >> index 1801e42..c4a9977 100644
>> >> --- a/arch/arm/mach-mmp/include/mach/pxa168.h
>> >> +++ b/arch/arm/mach-mmp/include/mach/pxa168.h
>> >> @@ -14,9 +14,12 @@ extern void pxa168_clear_keypad_wakeup(void);
>> >> #include <video/pxa168fb.h>
>> >> #include <plat/pxa27x_keypad.h>
>> >> #include <mach/cputype.h>
>> >> +#include <linux/pxa168_eth.h>
>> >> +#include <mach/audio.h>
>> >>
>> >> extern struct pxa_device_desc pxa168_device_uart1;
>> >> extern struct pxa_device_desc pxa168_device_uart2;
>> >> +extern struct pxa_device_desc pxa168_device_uart3;
>> >> extern struct pxa_device_desc pxa168_device_twsi0;
>> >> extern struct pxa_device_desc pxa168_device_twsi1;
>> >> extern struct pxa_device_desc pxa168_device_pwm1;
>> >> @@ -31,6 +34,9 @@ extern struct pxa_device_desc pxa168_device_ssp5;
>> >> extern struct pxa_device_desc pxa168_device_nand;
>> >> extern struct pxa_device_desc pxa168_device_fb;
>> >> extern struct pxa_device_desc pxa168_device_keypad;
>> >> +extern struct pxa_device_desc pxa168_device_mfu;
>> >> +extern struct pxa_device_desc pxa168_device_ac97;
>> >> +
>> >>
>> >> static inline int pxa168_add_uart(int id)
>> >> {
>> >> @@ -39,6 +45,7 @@ static inline int pxa168_add_uart(int id)
>> >> switch (id) {
>> >> case 1: d = &pxa168_device_uart1; break;
>> >> case 2: d = &pxa168_device_uart2; break;
>> >> + case 3: d = &pxa168_device_uart3; break;
>> >> }
>> >>
>> >> if (d == NULL)
>> >> @@ -117,4 +124,18 @@ static inline int pxa168_add_keypad(struct
>> >> pxa27x_keypad_platform_data *data)
>> >> return pxa_register_device(&pxa168_device_keypad, data,
>> sizeof(*data));
>> >> }
>> >>
>> >> +static inline int pxa168_add_mfu(struct pxa168_eth_platform_data
>> *data)
>> +{
>> >> +#if defined(CONFIG_PXA168_ETH)
>> >> + return pxa_register_device(&pxa168_device_mfu, data,
>> sizeof(*data)); +#else
>> >> + return 0;
>> >> +#endif
>> >> +}
>> >> +
>> >> +static inline int pxa168_add_ac97(struct pxa2xx_audio_ops_t *ops) +{
>> >> + return pxa_register_device(&pxa168_device_ac97, ops ,
>> sizeof(*ops)); +}
>> >> +
>> >> #endif /* __ASM_MACH_PXA168_H */
>> >> diff --git a/arch/arm/mach-mmp/include/mach/regs-apmu.h
>> >> b/arch/arm/mach-mmp/include/mach/regs-apmu.h
>> >> index ac47023..68d39bc 100644
>> >> --- a/arch/arm/mach-mmp/include/mach/regs-apmu.h
>> >> +++ b/arch/arm/mach-mmp/include/mach/regs-apmu.h
>> >> @@ -27,6 +27,7 @@
>> >> #define APMU_DMA APMU_REG(0x064)
>> >> #define APMU_GEU APMU_REG(0x068)
>> >> #define APMU_BUS APMU_REG(0x06c)
>> >> +#define APMU_MFU APMU_REG(0x0fc)
>> >>
>> >> #define APMU_FNCLK_EN (1 << 4)
>> >> #define APMU_AXICLK_EN (1 << 3)
>> >> diff --git a/arch/arm/mach-mmp/include/mach/trizeps6.h
>> >> b/arch/arm/mach-mmp/include/mach/trizeps6.h
>> >> index 0000000..40b526a
>> >> --- /dev/null
>> >> +++ b/arch/arm/mach-mmp/include/mach/trizeps6.h
>> >> @@ -0,0 +1,122 @@
>> >>
>> +/************************************************************************
>> >> + * Include file for TRIZEPS6 SoM and ConXS eval-board
>> >> + * Copyright (c) Yupeng Schneider
>> >> + * 2010
>> >> +
>> >>
>> ************************************************************************/
>> +
>> >> +/*
>> >> + * Includes/Defines
>> >> + */
>> >> +#ifndef _TRIPEPS6_H_
>> >> +#define _TRIPEPS6_H_
>> >> +
>> >> +#define STUART_SODIMM 1
>> >> +
>> >> +/* UART */
>> >> +#define GPIO104_UART1_DSR MFP_CFG(GPIO104, AF2)
>> >> +#define GPIO105_UART1_DCD MFP_CFG(GPIO105, AF2)
>> >> +#define GPIO107_UART2_TXD MFP_CFG_DRV(GPIO126, AF2, FAST)
>> >> +#define GPIO107_UART2_RXD MFP_CFG_DRV(GPIO36, AF2, FAST)
>> >> +#define GPIO109_UART2_CTS MFP_CFG(GPIO123, AF2)
>> >> +#define GPIO109_UART2_RTS MFP_CFG(GPIO124, AF2)
>> >> +#define GPIO30_UART3_TXD MFP_CFG_DRV(GPIO30, AF2, FAST)
>> >> +#define GPIO31_UART3_RXD MFP_CFG_DRV(GPIO31, AF2, FAST)
>> >> +#define GPIO32_UART3_CTS MFP_CFG(GPIO32, AF2)
>> >> +#define GPIO33_UART3_RTS MFP_CFG(GPIO33, AF2)
>> >> +
>> >> +/* MMC2 */
>> >> +#define GPIO122_MMC2_DAT3 MFP_CFG_DRV(GPIO122, AF4,
>> FAST)
>> >> +#define GPIO121_MMC2_DAT2 MFP_CFG_DRV(GPIO121, AF4,
>> FAST)
>> >> +#define GPIO120_MMC2_DAT1 MFP_CFG_DRV(GPIO120, AF4,
>> FAST)
>> >> +#define GPIO119_MMC2_DAT0 MFP_CFG_DRV(GPIO119, AF4,
>> FAST)
>> >> +#define GPIO28_MMC2_CMD MFP_CFG_DRV(GPIO28, AF6,
>> FAST)
>> >> +#define GPIO29_MMC2_CLK MFP_CFG_DRV(GPIO29, AF6,
>> FAST)
>> >> +#define GPIO53_MMC2_CD MFP_CFG(GPIO53, AF0)
>> >> +
>> >> +/*MMC4*/
>> >> +#define GPIO78_MMC4_DAT3 MFP_CFG_DRV(GPIO78, AF5,
>> FAST)
>> >> +#define GPIO79_MMC4_DAT2 MFP_CFG_DRV(GPIO79, AF5,
>> FAST)
>> >> +#define GPIO80_MMC4_DAT1 MFP_CFG_DRV(GPIO80, AF5,
>> FAST)
>> >> +#define GPIO81_MMC4_DAT0 MFP_CFG_DRV(GPIO81, AF5,
>> FAST)
>> >> +#define GPIO82_MMC4_CMD MFP_CFG_DRV(GPIO82, AF5,
>> FAST)
>> >> +#define GPIO83_MMC4_CLK MFP_CFG_DRV(GPIO83, AF5,
>> FAST)
>> >> +
>> >> +/* I2C */
>> >> +#define GPIO102_CI2C_SDA MFP_CFG(GPIO102, AF1)
>> >> +
>> >> +/* MFU */
>> >> +#define GPIO86_TX_CLK MFP_CFG(GPIO86, AF5)
>> >> +#define GPIO87_TX_EN MFP_CFG(GPIO87, AF5)
>> >> +#define GPIO88_TX_DQ3 MFP_CFG(GPIO88, AF5)
>> >> +#define GPIO89_TX_DQ2 MFP_CFG(GPIO89, AF5)
>> >> +#define GPIO90_TX_DQ1 MFP_CFG(GPIO90, AF5)
>> >> +#define GPIO91_TX_DQ0 MFP_CFG(GPIO91, AF5)
>> >> +#define GPIO92_MII_CRS MFP_CFG(GPIO92, AF5)
>> >> +#define GPIO93_MII_COL MFP_CFG(GPIO93, AF5)
>> >> +#define GPIO94_RX_CLK MFP_CFG(GPIO94, AF5)
>> >> +#define GPIO95_RX_ER MFP_CFG(GPIO95, AF5)
>> >> +#define GPIO96_RX_DQ3 MFP_CFG(GPIO96, AF5)
>> >> +#define GPIO97_RX_DQ2 MFP_CFG(GPIO97, AF5)
>> >> +#define GPIO98_RX_DQ1 MFP_CFG(GPIO98, AF5)
>> >> +#define GPIO99_RX_DQ0 MFP_CFG(GPIO99, AF5)
>> >> +#define GPIO100_MII_MDC MFP_CFG(GPIO100, AF5)
>> >> +#define GPIO101_MII_MDIO MFP_CFG(GPIO101, AF5)
>> >> +#define GPIO103_RX_DV MFP_CFG(GPIO103, AF5)
>> >> +
>> >> +/* AC97 */
>> >> +#define GPIO115_AC97_BITCLK MFP_CFG(GPIO115, AF6)
>> >> +#define GPIO114_AC97_SDATA_IN_0 MFP_CFG(GPIO114, AF6)
>> >> +#define GPIO116_AC97_SDATA_IN_1 MFP_CFG(GPIO116, AF6)
>> >> +#define GPIO117_AC97_SDATA_OUT MFP_CFG(GPIO117, AF6)
>> >> +#define GPIO118_AC97_SYNC MFP_CFG(GPIO118, AF6)
>> >> +
>> >> +
>> >> +
>> >> +#define TRIZEPS6_PHYS_BASE 0xd4000000
>> >> +
>> >> +
>> >> +#define TRIZEPS6_PIC_PHYS (0x88000000) /* CS0-3 Logic chip
>> on
>> ConXS */
>> >> + /* Logic on ConXS-board CSFR
>> register*/
>> >> +#define TRIZEPS6_CFSR_PHYS (TRIZEPS6_PIC_PHYS)
>> >> + /* Logic on ConXS-board BOCR
>> register*/
>> >> +#define TRIZEPS6_BOCR_PHYS (TRIZEPS6_PIC_PHYS+0x00200000)
>> >> + /* Logic on ConXS-board IRCR
>> register*/
>> >> +#define TRIZEPS6_IRCR_PHYS (TRIZEPS6_PIC_PHYS+0x00300000)
>> >> + /* Logic on ConXS-board UPSR
>> register*/
>> >> +#define TRIZEPS6_UPSR_PHYS (TRIZEPS6_PIC_PHYS+0x00280000)
>> >> + /* Logic on ConXS-board DICR
>> register*/
>> >> +#define TRIZEPS6_DICR_PHYS (TRIZEPS6_PIC_PHYS+0x00380000)
>> >> +
>> >> +
>> >> +#define TRIZEPS6_CPLD_PHYS (0x8e000000) /* CPLD on Trizeps6 module
>> */
>> +
>> >> +#define TRIZEPS6_CPLD_CTRL_PHYS (TRIZEPS6_CPLD_PHYS)
>> >> +#define TRIZEPS6_CPLD_FTUR_PHYS (TRIZEPS6_CPLD_PHYS+0x4)
>> >> +#define TRIZEPS6_CPLD_HIBE_PHYS (TRIZEPS6_CPLD_PHYS+0x8)
>> >> +#define TRIZEPS6_CPLD_PWM_PHYS (TRIZEPS6_CPLD_PHYS+0xc)
>> >> +#define TRIZEPS6_CPLD_PLDR_PHYS (TRIZEPS6_CPLD_PHYS+0x10)
>> >> +#define TRIZEPS6_CPLD_PSET_PHYS (TRIZEPS6_CPLD_PHYS+0x14)
>> >> +#define TRIZEPS6_CPLD_TTLO_PHYS (TRIZEPS6_CPLD_PHYS+0x18)
>> >> +
>> >> +
>> >> +/* MMC socket */
>> >> +#define GPIO_MMC2_DET 53
>> >> +#define TRIZEPS6_MMC2_IRQ IRQ_GPIO(mfp_to_gpio(MFP_PIN_GPIO53))
>> >> +#define GPIO_MMC4_DET 41
>> >> +#define TRIZEPS6_MMC4_IRQ IRQ_GPIO(mfp_to_gpio(MFP_PIN_GPIO41)
>> >> +
>> >> +/* Off-module PIC on ConXS board */
>> >> +#define GPIO_PIC 51
>> >> +#define TRIZEPS6_PIC_IRQ IRQ_GPIO(mfp_to_gpio(MFP_PIN_GPIO51)
>> >> +
>> >> +/* PCMCIA socket Compact Flash */
>> >> +#define GPIO_PCD 43 /* PCMCIA Card Detect
>> */
>> >> +#define TRIZEPS6_CD_IRQ
>> IRQ_GPIO(mfp_to_gpio(MFP_PIN_GPIO43)
>> >> +#define GPIO_PRDY 113 /* READY / nINT */
>> >> +#define TRIZEPS6_READY_NINT IRQ_GPIO(mfp_to_gpio(MFP_PIN_GPIO113)
>> +
>> >> +#define trizeps6_GPIO_CODEC_IRQ 116
>> >> +
>> >> +extern void trizeps6_ac97_acreset(int i);
>> >> +
>> >> +#endif /* _TRIPEPS6_H_ */
>> >> diff --git a/arch/arm/mach-mmp/include/mach/trizeps6_cpld.h
>> >> b/arch/arm/mach-mmp/include/mach/trizeps6_cpld.h
>> >> index 0000000..8538a6b
>> >> --- /dev/null
>> >> +++ b/arch/arm/mach-mmp/include/mach/trizeps6_cpld.h
>> >> @@ -0,0 +1,87 @@
>> >> +#ifndef _TRIPEPS6_CPLD_H_
>> >> +#define _TRIPEPS6_CPLD_H_
>> >> +
>> >> +/* index of resource */
>> >> +#define CTRL_S 0
>> >> +#define CTRL_R 1
>> >> +#define FTUR_S 2
>> >> +#define FTUR_R 3
>> >> +#define HIBE_S 4
>> >> +#define HIBE_R 5
>> >> +#define PWM 6
>> >> +#define PLDR_S 7
>> >> +#define PLDR_R 8
>> >> +#define PSET_S 9
>> >> +#define PSET_R 10
>> >> +#define TTLO_S 11
>> >> +#define TTLO_R 12
>> >> +
>> >> +#define CPLD_CTRL_S cpld.addr[CTRL_S].val
>> >> +#define CPLD_CTRL_R cpld.addr[CTRL_R].val
>> >> +#define CPLD_CONTROL_GR (1 << 0)
>> >> +#define CPLD_CONTROL_CODEC (1 << 2)
>> >> +#define CPLD_CONTROL_ETHPHY (1 << 3)
>> >> +#define CPLD_CONTROL_RWL (1 << 4)
>> >> +#define CPLD_CONTROL_RBT (1 << 5)
>> >> +
>> >> +#define CPLD_FTUR_S cpld.addr[FTUR_S].val
>> >> +#define CPLD_FTUR_R cpld.addr[FTUR_R].val
>> >> +#define CPLD_FEATURE_UART3_SODIMM (1 << 0)
>> >> +#define CPLD_FEATURE_UART3_BT (1 << 1)
>> >> +#define CPLD_FEATURE_CF_MODE (1 << 2)
>> >> +#define CPLD_FEATURE_TTLIO (1 << 3)
>> >> +#define CPLD_PWM_SODIMM_P69 (1 << 4)
>> >> +#define CPLD_PWM_SODIMM_P77 (1 << 5)
>> >> +#define CPLD_PWM_SODIMM_P106 (1 << 6)
>> >> +#define CPLD_BT_PWM_SODIMM (1 << 7)
>> >> +
>> >> +#define CPLD_HIBE_S cpld.addr[HIBE_S].val
>> >> +#define CPLD_HIBE_R cpld.addr[HIBE_R].val
>> >> +#define CPLD_HIBERNATE_MODE (1 << 0)
>> >> +#define CPLD_HIBERNATE_WAKE_TOUCH (1 << 1)
>> >> +#define CPLD_HIBERNATE_WAKE_PMIC (1 << 2)
>> >> +#define CPLD_HIBERNATE_WAKE_IRQ_P43 (1 << 3)
>> >> +
>> >> +#define CPLD_PWM cpld.addr[PWM].val
>> >> +
>> >> +#define CPLD_PINLDR cpld.addr[PINLDR].val
>> >> +#define CPLD_PINLDR_P69 (1 <<
>> 0)
>> >> +#define CPLD_PINLDR_P100_PSKTSEL (1 << 1)
>> >> +#define CPLD_PINLDR_P98_CFNREG (1 << 2)
>> >> +#define CPLD_PINLDR_P104_CFNIOIS16 (1 << 3)
>> >> +#define CPLD_PINLDR_P93_RDNWR (1 << 4)
>> >> +#define CPLD_PINLDR_P104_IRQ_P43 (1 << 5)
>> >> +
>> >> +#define CPLD_PSET_S cpld.addr[PSET_S].val
>> >> +#define CPLD_PSET_R cpld.addr[PSET_R].val
>> >> +#define CPLD_PINSET_P69 (1 <<
>> 0)
>> >> +#define CPLD_PINSET_P100_PSKTSEL (1 << 1)
>> >> +#define CPLD_PINSET_P98_CFNREG (1 << 2)
>> >> +#define CPLD_PINSET_P104_CFNIOIS16 (1 << 3)
>> >> +#define CPLD_PINSET_P93_RDnWR (1 << 4)
>> >> +
>> >> +#define CPLD_TTLO_S cpld.addr[TTLO_S].val
>> >> +#define CPLD_TTLO_R cpld.addr[TTLO_R].val
>> >> +#define CPLD_TTLIO_W_A8 (1 << 0)
>> >> +#define CPLD_TTLIO_W_A9 (1 << 1)
>> >> +#define CPLD_TTLIO_W_A10 (1 << 2)
>> >> +#define CPLD_TTLIO_W_A11 (1 << 3)
>> >> +#define CPLD_TTLIO_W_A12 (1 << 4)
>> >> +#define CPLD_TTLIO_W_A13 (1 << 5)
>> >> +#define CPLD_TTLIO_W_A14 (1 << 6)
>> >> +#define CPLD_TTLIO_W_A15 (1 << 7)
>> >> +#define CPLD_TTLIO_r_A0 (1 << 0)
>> >> +#define CPLD_TTLIO_r_A1 (1 << 1)
>> >> +#define CPLD_TTLIO_r_A2 (1 << 2)
>> >> +#define CPLD_TTLIO_r_A3 (1 << 3)
>> >> +#define CPLD_TTLIO_r_A4 (1 << 4)
>> >> +#define CPLD_TTLIO_r_A5 (1 << 5)
>> >> +#define CPLD_TTLIO_r_A6 (1 << 6)
>> >> +#define CPLD_TTLIO_r_A7 (1 << 7)
>> >> +
>> >> +
>> >> +
>> >> +extern unsigned short trizeps6_cpld_readw(unsigned int reg);
>> >> +extern inline void trizeps6_cpld_writew(unsigned int reg, unsigned
>> short
>> >> value);
>> >> +
>> >> +#endif /* _TRIPEPS6_CPLD_H_ */
>> >> diff --git a/arch/arm/mach-mmp/pxa168.c b/arch/arm/mach-mmp/pxa168.c
>> index
>> >> 72b4e76..9c2396e 100644
>> >> --- a/arch/arm/mach-mmp/pxa168.c
>> >> +++ b/arch/arm/mach-mmp/pxa168.c
>> >> @@ -66,6 +66,7 @@ void __init pxa168_init_irq(void)
>> >> /* APB peripheral clocks */
>> >> static APBC_CLK(uart1, PXA168_UART1, 1, 14745600);
>> >> static APBC_CLK(uart2, PXA168_UART2, 1, 14745600);
>> >> +static APBC_CLK(uart3, PXA168_UART3, 1, 14745600);
>> >> static APBC_CLK(twsi0, PXA168_TWSI0, 1, 33000000);
>> >> static APBC_CLK(twsi1, PXA168_TWSI1, 1, 33000000);
>> >> static APBC_CLK(pwm1, PXA168_PWM1, 1, 13000000);
>> >> @@ -78,14 +79,18 @@ static APBC_CLK(ssp3, PXA168_SSP3, 4, 0);
>> >> static APBC_CLK(ssp4, PXA168_SSP4, 4, 0);
>> >> static APBC_CLK(ssp5, PXA168_SSP5, 4, 0);
>> >> static APBC_CLK(keypad, PXA168_KPC, 0, 32000);
>> >> +static APBC_CLK(ac97, PXA168_AC97, 0, 24576000);
>> >> +
>> >>
>> >> static APMU_CLK(nand, NAND, 0x01db, 208000000);
>> >> static APMU_CLK(lcd, LCD, 0x7f, 312000000);
>> >> +static APMU_CLK(mfu, MFU, 0x9, 0);
>> >>
>> >> /* device and clock bindings */
>> >> static struct clk_lookup pxa168_clkregs[] = {
>> >> INIT_CLKREG(&clk_uart1, "pxa2xx-uart.0", NULL),
>> >> INIT_CLKREG(&clk_uart2, "pxa2xx-uart.1", NULL),
>> >> + INIT_CLKREG(&clk_uart3, "pxa2xx-uart.2", NULL),
>> >> INIT_CLKREG(&clk_twsi0, "pxa2xx-i2c.0", NULL),
>> >> INIT_CLKREG(&clk_twsi1, "pxa2xx-i2c.1", NULL),
>> >> INIT_CLKREG(&clk_pwm1, "pxa168-pwm.0", NULL),
>> >> @@ -100,6 +105,8 @@ static struct clk_lookup pxa168_clkregs[] = {
>> >> INIT_CLKREG(&clk_nand, "pxa3xx-nand", NULL),
>> >> INIT_CLKREG(&clk_lcd, "pxa168-fb", NULL),
>> >> INIT_CLKREG(&clk_keypad, "pxa27x-keypad", NULL),
>> >> + INIT_CLKREG(&clk_mfu, "pxa168-eth", "MFUCLK"),
>> >> + INIT_CLKREG(&clk_ac97, "pxa2xx-ac97", "AC97CLK"),
>> >> };
>> >>
>> >> static int __init pxa168_init(void)
>> >> @@ -149,6 +156,7 @@ void pxa168_clear_keypad_wakeup(void)
>> >> /* on-chip devices */
>> >> PXA168_DEVICE(uart1, "pxa2xx-uart", 0, UART1, 0xd4017000, 0x30, 21,
>> 22);
>> >> PXA168_DEVICE(uart2, "pxa2xx-uart", 1, UART2, 0xd4018000, 0x30, 23,
>> 24);
>> >> +PXA168_DEVICE(uart3, "pxa2xx-uart", 2, UART3, 0xd4026000, 0x30, 23,
>> 24);
>> >> PXA168_DEVICE(twsi0, "pxa2xx-i2c", 0, TWSI0, 0xd4011000, 0x28);
>> >> PXA168_DEVICE(twsi1, "pxa2xx-i2c", 1, TWSI1, 0xd4025000, 0x28);
>> >> PXA168_DEVICE(pwm1, "pxa168-pwm", 0, NONE, 0xd401a000, 0x10);
>> >> @@ -163,3 +171,5 @@ PXA168_DEVICE(ssp4, "pxa168-ssp", 3, SSP4,
>> 0xd4020000,
>> >> 0x40, 58, 59);
>> >> PXA168_DEVICE(ssp5, "pxa168-ssp", 4, SSP5, 0xd4021000, 0x40, 60,
>> 61);
>> >> PXA168_DEVICE(fb, "pxa168-fb", -1, LCD, 0xd420b000, 0x1c8);
>> >> PXA168_DEVICE(keypad, "pxa27x-keypad", -1, KEYPAD, 0xd4012000,
>> 0x4c);
>> >> +PXA168_DEVICE(mfu, "pxa168-eth", -1, MFU, 0xc0800000, 0x0FFF);
>> >> +PXA168_DEVICE(ac97, "pxa2xx-ac97", -1, AC97, 0xd402B000, 0x0fff);
>> diff
>> >> --git a/arch/arm/mach-mmp/trizeps6.c b/arch/arm/mach-mmp/trizeps6.c
>> index
>> >> 0000000..a935f14
>> >> --- /dev/null
>> >> +++ b/arch/arm/mach-mmp/trizeps6.c
>> >> @@ -0,0 +1,469 @@
>> >> +/*
>> >> + * linux/arch/arm/mach-mmp/trizeps6.c
>> >> + *
>> >> + * Support for the Keith und Koep Trizeps6 Modul Platform
>> >> + * based on Marvell PXA168-CPU
>> >> + *
>> >> + * Author: Yupeng Schneider
>> >> + *
>> >> + * This program is free software; you can redistribute it and/or
>> modify
>> >> + * it under the terms of the GNU General Public License version 2
>> as +
>> *
>> >> publishhed by the Free Software Foundation.
>> >> + */
>> >> +
>> >> +#include <linux/init.h>
>> >> +#include <linux/kernel.h>
>> >> +#include <linux/platform_device.h>
>> >> +#include <linux/mtd/mtd.h>
>> >> +#include <linux/mtd/partitions.h>
>> >> +#include <linux/mtd/nand.h>
>> >> +#include <linux/delay.h>
>> >> +#include <asm/mach-types.h>
>> >> +#include <asm/mach/arch.h>
>> >> +#include <mach/addr-map.h>
>> >> +#include <mach/mfp-pxa168.h>
>> >> +#include <mach/pxa168.h>
>> >> +#include <mach/gpio.h>
>> >> +#include <linux/pxa168_eth.h>
>> >> +#include <mach/irqs.h>
>> >> +#include <mach/trizeps6.h>
>> >> +#include <mach/trizeps6_cpld.h>
>> >> +#include "common.h"
>> >> +#include <linux/mmc/sdhci.h>
>> >> +#include <linux/ucb1400.h>
>> >> +#include <mach/audio.h>
>> >> +
>> >> +
>> >> +static unsigned long trizeps6_pin_config[] __initdata = {
>> >> + /* Data Flash Interface */
>> >> + GPIO0_DFI_D15,
>> >> + GPIO1_DFI_D14,
>> >> + GPIO2_DFI_D13,
>> >> + GPIO3_DFI_D12,
>> >> + GPIO4_DFI_D11,
>> >> + GPIO5_DFI_D10,
>> >> + GPIO6_DFI_D9,
>> >> + GPIO7_DFI_D8,
>> >> + GPIO8_DFI_D7,
>> >> + GPIO9_DFI_D6,
>> >> + GPIO10_DFI_D5,
>> >> + GPIO11_DFI_D4,
>> >> + GPIO12_DFI_D3,
>> >> + GPIO13_DFI_D2,
>> >> + GPIO14_DFI_D1,
>> >> + GPIO15_DFI_D0,
>> >> +
>> >> + /* Static Memory Controller */
>> >> + GPIO18_SMC_nCS0,
>> >> + GPIO34_SMC_nCS1,
>> >> + GPIO23_SMC_nLUA,
>> >> + GPIO25_SMC_nLLA,
>> >> + GPIO28_SMC_RDY,
>> >> + GPIO29_SMC_SCLK,
>> >> + GPIO35_SMC_BE1,
>> >> + GPIO36_SMC_BE2,
>> >> +
>> >> +
>> >> + /* UART1 */
>> >> + GPIO107_UART1_RXD,
>> >> + GPIO108_UART1_TXD,
>> >> + GPIO107_UART1_RXD,
>> >> + GPIO108_UART1_TXD,
>> >> + GPIO109_UART1_RTS,
>> >> + GPIO110_UART1_CTS,
>> >> + GPIO111_UART1_RI,
>> >> + GPIO104_UART1_DSR,
>> >> + GPIO112_UART1_DTR,
>> >> + GPIO105_UART1_DCD,
>> >> +
>> >> + /* UART2 */
>> >> + GPIO107_UART2_TXD,
>> >> + GPIO107_UART2_RXD,
>> >> + GPIO109_UART2_CTS,
>> >> + GPIO109_UART2_RTS,
>> >> +
>> >> + /* UART3 */
>> >> + GPIO30_UART3_TXD,
>> >> + GPIO31_UART3_RXD,
>> >> + GPIO32_UART3_CTS,
>> >> + GPIO33_UART3_RTS,
>> >> +
>> >> +
>> >> + /* MFU */
>> >> + GPIO86_TX_CLK,
>> >> + GPIO87_TX_EN,
>> >> + GPIO88_TX_DQ3,
>> >> + GPIO89_TX_DQ2,
>> >> + GPIO90_TX_DQ1,
>> >> + GPIO91_TX_DQ0,
>> >> + GPIO92_MII_CRS,
>> >> + GPIO93_MII_COL,
>> >> + GPIO94_RX_CLK,
>> >> + GPIO95_RX_ER,
>> >> + GPIO96_RX_DQ3,
>> >> + GPIO97_RX_DQ2,
>> >> + GPIO98_RX_DQ1,
>> >> + GPIO99_RX_DQ0,
>> >> + GPIO100_MII_MDC,
>> >> + GPIO101_MII_MDIO,
>> >> + GPIO103_RX_DV,
>> >> +
>> >> + /* USB OTG */
>> >> + GPIO85_GPIO,
>> >> + GPIO47_GPIO,
>> >> +
>> >> + /* i2c bus */
>> >> + GPIO102_CI2C_SDA,
>> >> + GPIO106_CI2C_SCL,
>> >> +
>> >> +
>> >> + /* MMC2 */
>> >> + GPIO122_MMC2_DAT3 | MFP_PULL_HIGH,
>> >> + GPIO121_MMC2_DAT2 | MFP_PULL_HIGH,
>> >> + GPIO120_MMC2_DAT1 | MFP_PULL_HIGH,
>> >> + GPIO119_MMC2_DAT0 | MFP_PULL_HIGH,
>> >> + GPIO28_MMC2_CMD | MFP_PULL_HIGH,
>> >> + GPIO29_MMC2_CLK,
>> >> + GPIO53_MMC2_CD | MFP_PULL_LOW, /*
>> TRIZEPS6_MMC2_IRQ */
>> >> +
>> >> + /* MMC4 */
>> >> + GPIO78_MMC4_DAT3 | MFP_PULL_HIGH,
>> >> + GPIO79_MMC4_DAT2 | MFP_PULL_HIGH,
>> >> + GPIO80_MMC4_DAT1 | MFP_PULL_HIGH,
>> >> + GPIO81_MMC4_DAT0 | MFP_PULL_HIGH,
>> >> + GPIO82_MMC4_CMD | MFP_PULL_HIGH,
>> >> + GPIO83_MMC4_CLK,
>> >> +
>> >> + /* LCD */
>> >> + GPIO56_LCD_FCLK_RD,
>> >> + GPIO57_LCD_LCLK_A0,
>> >> + GPIO58_LCD_PCLK_WR,
>> >> + GPIO59_LCD_DENA_BIAS,
>> >> + GPIO60_LCD_DD0,
>> >> + GPIO61_LCD_DD1,
>> >> + GPIO62_LCD_DD2,
>> >> + GPIO63_LCD_DD3,
>> >> + GPIO64_LCD_DD4,
>> >> + GPIO65_LCD_DD5,
>> >> + GPIO66_LCD_DD6,
>> >> + GPIO67_LCD_DD7,
>> >> + GPIO68_LCD_DD8,
>> >> + GPIO69_LCD_DD9,
>> >> + GPIO70_LCD_DD10,
>> >> + GPIO71_LCD_DD11,
>> >> + GPIO72_LCD_DD12,
>> >> + GPIO73_LCD_DD13,
>> >> + GPIO74_LCD_DD14,
>> >> + GPIO75_LCD_DD15,
>> >> +
>> >> +
>> >> + /* AC97 */
>> >> + GPIO115_AC97_BITCLK,
>> >> + GPIO114_AC97_SDATA_IN_0,
>> >> + GPIO117_AC97_SDATA_OUT,
>> >> + GPIO118_AC97_SYNC,
>> >> + GPIO116_GPIO,
>> >> +
>> >> +
>> >> + GPIO51_GPIO, /* TRIZEPS6_PIC_IRQ */
>> >> + GPIO27_GPIO, /* Ethernet IRQ */
>> >> +};
>> >> +
>> >> +
>> >> +
>> >>
>> +/****************************************************************************
>> >> + * CPLD
>> >> +
>> >>
>> ****************************************************************************/
>> >> +
>> >> +static struct resource tri6_cpld_resources[] = {
>> >> + [CTRL_S] = {
>> >> + .start = TRIZEPS6_CPLD_CTRL_PHYS,
>> >> + .end = TRIZEPS6_CPLD_CTRL_PHYS+1,
>> >> + .flags = IORESOURCE_MEM,
>> >> + },
>> >> + [CTRL_R] = {
>> >> + .start = TRIZEPS6_CPLD_CTRL_PHYS+2,
>> >> + .end = TRIZEPS6_CPLD_CTRL_PHYS+3,
>> >> + .flags = IORESOURCE_MEM,
>> >> + },
>> >> + [FTUR_S] = {
>> >> + .start = TRIZEPS6_CPLD_FTUR_PHYS,
>> >> + .end = TRIZEPS6_CPLD_FTUR_PHYS+1,
>> >> + .flags = IORESOURCE_MEM,
>> >> + },
>> >> + [FTUR_R] = {
>> >> + .start = TRIZEPS6_CPLD_FTUR_PHYS+2,
>> >> + .end = TRIZEPS6_CPLD_FTUR_PHYS+3,
>> >> + .flags = IORESOURCE_MEM,
>> >> + },
>> >> + [HIBE_S] = {
>> >> + .start = TRIZEPS6_CPLD_HIBE_PHYS,
>> >> + .end = TRIZEPS6_CPLD_HIBE_PHYS+1,
>> >> + .flags = IORESOURCE_MEM,
>> >> + },
>> >> + [HIBE_R] = {
>> >> + .start = TRIZEPS6_CPLD_HIBE_PHYS+2,
>> >> + .end = TRIZEPS6_CPLD_HIBE_PHYS+3,
>> >> + .flags = IORESOURCE_MEM,
>> >> + },
>> >> + [PWM] = {
>> >> + .start = TRIZEPS6_CPLD_PWM_PHYS,
>> >> + .end = TRIZEPS6_CPLD_PWM_PHYS+1,
>> >> + .flags = IORESOURCE_MEM,
>> >> + },
>> >> + [PLDR_S] = {
>> >> + .start = TRIZEPS6_CPLD_PLDR_PHYS,
>> >> + .end = TRIZEPS6_CPLD_PLDR_PHYS+1,
>> >> + .flags = IORESOURCE_MEM,
>> >> + },
>> >> + [PLDR_R] = {
>> >> + .start = TRIZEPS6_CPLD_PLDR_PHYS+2,
>> >> + .end = TRIZEPS6_CPLD_PLDR_PHYS+3,
>> >> + .flags = IORESOURCE_MEM,
>> >> + },
>> >> + [PSET_S] = {
>> >> + .start = TRIZEPS6_CPLD_PSET_PHYS,
>> >> + .end = TRIZEPS6_CPLD_PSET_PHYS+1,
>> >> + .flags = IORESOURCE_MEM,
>> >> + },
>> >> + [PSET_R] = {
>> >> + .start = TRIZEPS6_CPLD_PSET_PHYS+2,
>> >> + .end = TRIZEPS6_CPLD_PSET_PHYS+3,
>> >> + .flags = IORESOURCE_MEM,
>> >> + },
>> >> + [TTLO_S] = {
>> >> + .start = TRIZEPS6_CPLD_TTLO_PHYS,
>> >> + .end = TRIZEPS6_CPLD_TTLO_PHYS+1,
>> >> + .flags = IORESOURCE_MEM,
>> >> + },
>> >> + [TTLO_R] = {
>> >> + .start = TRIZEPS6_CPLD_TTLO_PHYS+2,
>> >> + .end = TRIZEPS6_CPLD_TTLO_PHYS+3,
>> >> + .flags = IORESOURCE_MEM,
>> >> + },
>> >> +};
>> >> +
>> >> +static int tri6_cpld_platdata = 1;
>> >> +
>> >> +static struct platform_device cpld_device = {
>> >> + .name = "trizeps6-cpld",
>> >> + .id = -1,
>> >> + .num_resources = ARRAY_SIZE(tri6_cpld_resources),
>> >> + .resource = tri6_cpld_resources,
>> >> + .dev = {
>> >> + .platform_data = &tri6_cpld_platdata,
>> >> + }
>> >> +};
>> >> +
>> >> +
>> >>
>> +/******************************************************************************
>> >> + * Audio and Touchscreen
>> >> +
>> >>
>> ******************************************************************************/
>> >> +
>> >> +static struct ucb1400_pdata trizeps6_ucb1400_pdata = {
>> >> + .irq = gpio_to_irq(trizeps6_GPIO_CODEC_IRQ),
>> >> +};
>> >> +
>> >> +static struct pxa2xx_audio_ops_t trizeps6_ac97_pdata = {
>> >> + .codec_pdata = { &trizeps6_ucb1400_pdata, },
>> >> +};
>> >> +
>> >> +static struct platform_device trizeps6_ucb1400_device = {
>> >> + .name = "ucb1400_core",
>> >> + .id = -1,
>> >> + .dev = {
>> >> + .platform_data = &trizeps6_ucb1400_pdata,
>> >> + },
>> >> +};
>> >> +
>> >> +static void __init trizeps6_ts_init(void)
>> >> +{
>> >> + pxa168_add_ac97(&trizeps6_ac97_pdata);
>> >> + platform_device_register(&trizeps6_ucb1400_device);
>> >> +}
>> >> +
>> >> +void trizeps6_ac97_acreset(int i)
>> >> +{ unsigned short value;
>> >> +
>> >> + if (i == 1) {
>> >> +
>> >> + value = trizeps6_cpld_readw(CTRL_S);
>> >> + trizeps6_cpld_writew(CTRL_S, value |
>> CPLD_CONTROL_CODEC);
>> >> + }
>> >> + if (!i) {
>> >> + value = trizeps6_cpld_readw(CTRL_R);
>> >> + trizeps6_cpld_writew(CTRL_R, value |
>> CPLD_CONTROL_CODEC);
>> >> + }
>> >> +}
>> >> +
>> >>
>> +/******************************************************************************
>> >> + * Ethernet
>> >> +
>> >>
>> ******************************************************************************/
>> >> +static int trizeps6_eth_init(void)
>> >> +{
>> >> + unsigned short value;
>> >> +
>> >> + value = trizeps6_cpld_readw(CTRL_R);
>> >> + trizeps6_cpld_writew(CTRL_R, value | CPLD_CONTROL_ETHPHY);
>> >> + return 0;
>> >> +
>> >> +}
>> >> +
>> >> +static struct pxa168_eth_platform_data trizeps6_eth_data = {
>> >> + .phy_addr = 0x1f,
>> >> + .port_number = 0,
>> >> + .init = trizeps6_eth_init,
>> >> +};
>> >> +
>> >>
>> +/******************************************************************************
>> >> + * NAND
>> >> +
>> >>
>> ******************************************************************************/
>> >> +static struct pxa3xx_nand_timing stnand02gw3b2d_timing = {
>> >> + .tCH = 10,
>> >> + .tCS = 40,
>> >> + .tWH = 20,
>> >> + .tWP = 24,
>> >> + .tRH = 20,
>> >> + .tRP = 24,
>> >> + .tR = 50000,
>> >> + .tWHR = 120,
>> >> + .tAR = 20,
>> >> +
>> >> +};
>> >> +
>> >> +static struct pxa3xx_nand_cmdset largepage_cmdset = {
>> >> + .read1 = 0x3000,
>> >> + .read2 = 0x0050,
>> >> + .program = 0x1080,
>> >> + .read_status = 0x0070,
>> >> + .read_id = 0x0090,
>> >> + .erase = 0xD060,
>> >> + .reset = 0x00FF,
>> >> + .lock = 0x002A,
>> >> + .unlock = 0x2423,
>> >> + .lock_status = 0x007A,
>> >> +};
>> >> +
>> >> +static struct pxa3xx_nand_flash trizeps6_flashes[] = {
>> >> + {
>> >> + .timing = &stnand02gw3b2d_timing,
>> >> + .cmdset = &largepage_cmdset,
>> >> + .page_per_block = 64,
>> >> + .page_size = 2048,
>> >> + .flash_width = 8,
>> >> + .dfc_width = 8,
>> >> + .num_blocks = 2048,
>> >> + .chip_id = 0xda20,
>> >> + },
>> >> +};
>> >> +
>> >> +
>> >> +static struct mtd_partition trizeps6_nand_partitions[] = {
>> >> + {
>> >> + .name = "bootloader",
>> >> + .offset = 0,
>> >> + .size = SZ_16M,
>> >> + .mask_flags = MTD_WRITEABLE,
>> >> + }, {
>> >> + .name = "reserved",
>> >> + .offset = MTDPART_OFS_APPEND,
>> >> + .size = SZ_128K,
>> >> + .mask_flags = MTD_WRITEABLE,
>> >> + }, {
>> >> + .name = "kernel",
>> >> + .offset = MTDPART_OFS_APPEND,
>> >> + .size = (2*SZ_2M + SZ_1M),
>> >> + .mask_flags = 0,
>> >> + }, {
>> >> + .name = "filesystem",
>> >> + .offset = MTDPART_OFS_APPEND,
>> >> + .size = (SZ_256M - 3*SZ_8M),
>> >> + .mask_flags = 0,
>> >> + }
>> >> +};
>> >> +
>> >> +static struct pxa3xx_nand_platform_data trizeps6_nand_info = {
>> >> + .enable_arbiter = 1,
>> >> + .parts = trizeps6_nand_partitions,
>> >> + .nr_parts = ARRAY_SIZE(trizeps6_nand_partitions),
>> >> + .flash = trizeps6_flashes,
>> >> + .num_flash = ARRAY_SIZE(trizeps6_flashes),
>> >> + .keep_config = 0
>> >> +};
>> >> +
>> >> +
>> >> +
>> >> +static struct i2c_board_info trizeps6_i2c_devices[] = {
>> >> + { I2C_BOARD_INFO("pcf8593", 0x51), },
>> >> +};
>> >> +
>> >> +
>> >>
>> +/******************************************************************************
>> >> + * LCD
>> >> +
>> >>
>> ******************************************************************************/
>> >> +static struct fb_videomode trizeps6_video_modes[] = {
>> >> + [0] = {
>> >> + .pixclock = 39720,
>> >> + .refresh = 60,
>> >> + .xres = 640,
>> >> + .yres = 480,
>> >> + .hsync_len = 63,
>> >> + .left_margin = 12,
>> >> + .right_margin = 12,
>> >> + .vsync_len = 4,
>> >> + .upper_margin = 32,
>> >> + .lower_margin = 10,
>> >> + .sync = FB_SYNC_VERT_HIGH_ACT |
>> FB_SYNC_HOR_HIGH_ACT,
>> >> + },
>> >> +};
>> >> +
>> >> +static struct pxa168fb_mach_info trizeps6_lcd_info = {
>> >> + .id = "Base-trizeps6",
>> >> + .modes = trizeps6_video_modes,
>> >> + .num_modes = ARRAY_SIZE(trizeps6_video_modes),
>> >> + .pix_fmt = PIX_FMT_RGB565,
>> >> + .io_pin_allocation_mode = PIN_MODE_DUMB_16_GPIO,
>> >> + .dumb_mode = DUMB_MODE_RGB565,
>> >> + .active = 1,
>> >> + .panel_rbswap = 1,
>> >> + .invert_pixclock = 0,
>> >> +};
>> >> +
>> >> +
>> >> +static struct platform_device *trizeps6_devices[] __initdata = {
>> >> + &cpld_device,
>> >> +};
>> >> +
>> >> +static void __init trizeps6_init(void)
>> >> +{
>> >> + mfp_config(ARRAY_AND_SIZE(trizeps6_pin_config));
>> >> +
>> >> + pxa168_add_uart(1);
>> >> + pxa168_add_uart(2);
>> >> +#ifdef STUART_SODIMM
>> >> + pxa168_add_uart(3);
>> >> +#endif
>> >> + pxa168_add_nand(&trizeps6_nand_info);
>> >> + platform_add_devices(trizeps6_devices,
>> >> +
>> ARRAY_SIZE(trizeps6_devices));
>> >> +
>> >> + pxa168_add_fb(&trizeps6_lcd_info);
>> >> + pxa168_add_mfu(&trizeps6_eth_data);
>> >> + pxa168_add_twsi(0, NULL,
>> ARRAY_AND_SIZE(trizeps6_i2c_devices));
>> >> + trizeps6_ts_init();
>> >> +}
>> >> +
>> >> +static void __init trizeps6_map_io(void)
>> >> +{
>> >> + mmp_map_io();
>> >> +}
>> >> +
>> >> +MACHINE_START(TRIZEPS6, "PXA168-based Keith & Koep Trizeps VI
>> Development
>> >> Module")
>> >> + /* MAINTAINER("Yupeng Schneider" <
>> yupeng.schneider at googlemail.com>) */
>> >> + .map_io = trizeps6_map_io,
>> >> + .init_irq = pxa168_init_irq,
>> >> + .timer = &pxa168_timer,
>> >> + .init_machine = trizeps6_init,
>> >> +MACHINE_END
>> >> +
>> >> +
>> >> diff --git a/arch/arm/mach-mmp/trizeps6_cpld.c
>> >> b/arch/arm/mach-mmp/trizeps6_cpld.c
>> >> index 0000000..2577b0f
>> >> --- /dev/null
>> >> +++ b/arch/arm/mach-mmp/trizeps6_cpld.c
>> >> @@ -0,0 +1,145 @@
>> >> +/*
>> >> + * linux/arch/arm/mach-mmp/trizeps6_cpld.c
>> >> + *
>> >> + *
>> >> + * Author: Yupeng Schneider
>> >> + * Created: 27 10, 2010
>> >> + * Copyright: Yupeng Schneider
>> >> + *
>> >> + * This program is free software; you can redistribute it and/or
>> modify
>> >> + * it under the terms of the GNU General Public License version 2
>> as +
>> *
>> >> published by the Free Software Foundation.*/
>> >> +
>> >> +#include <linux/kernel.h>
>> >> +#include <linux/ioport.h>
>> >> +#include <linux/platform_device.h>
>> >> +#include <linux/device.h>
>> >> +#include <linux/module.h>
>> >> +
>> >> +#include <asm/io.h>
>> >> +#include <asm/delay.h>
>> >> +#include <mach/trizeps6.h>
>> >> +#include <mach/trizeps6_cpld.h>
>> >> +
>> >> +struct cpld_info {
>> >> + struct region {
>> >> + struct resource *res;
>> >> + struct resource *req;
>> >> + void __iomem *iom;
>> >> + unsigned short val;
>> >> + } addr[7];
>> >> +} cpld_info;
>> >> +
>> >> +static struct cpld_info cpld = { { { 0 } } };
>> >> +
>> >> +inline void trizeps6_cpld_writew(unsigned int reg, unsigned short
>> value) +{
>> >> + if ((cpld.addr[reg].iom != NULL))
>> >> + writew(value, cpld.addr[reg].iom);
>> >> +
>> >> +}
>> >> +
>> >> +unsigned short trizeps6_cpld_readw(unsigned int reg)
>> >> +{
>> >> + short value = 0;
>> >> + if (reg != HIBE_S || reg != HIBE_R || reg != PWM || reg !=
>> PSET_S || reg
>> >> != PSET_R) {
>> >> +
>> >> + if ((cpld.addr[reg].iom != NULL))
>> >> + value = readw(cpld.addr[reg].iom);
>> >> + }
>> >> + return value;
>> >> +}
>> >> +EXPORT_SYMBOL(trizeps6_cpld_readw);
>> >> +
>> >> +static int trizeps6_cpld_probe(struct platform_device *pdev)
>> >> +{
>> >> + int i;
>> >> +
>> >> + CPLD_CTRL_R = CPLD_CONTROL_ETHPHY | CPLD_CONTROL_GR;
>> >> +#ifdef STUART_SODIMM
>> >> + CPLD_FTUR_S = CPLD_FEATURE_UART3_SODIMM;
>> >> +#endif
>> >> + for (i = CTRL_S; i <= TTLO_R; i++) {
>> >> + cpld.addr[i].res = platform_get_resource(pdev,
>> IORESOURCE_MEM, i);
>> >> + if (cpld.addr[i].res == NULL) {
>> >> + dev_err(&pdev->dev, "cannot get resource %d
>> area\n", i);
>> >> + return -EIO;
>> >> + }
>> >> + cpld.addr[i].req =
>> request_mem_region(cpld.addr[i].res->start,
>> >> + 2,
>> pdev->name);
>> >> + if (cpld.addr[i].req == NULL) {
>> >> + dev_err(&pdev->dev, "cannot claim addr area
>> %d\n", i);
>> >> + return -EIO;
>> >> + }
>> >> + cpld.addr[i].iom = ioremap(cpld.addr[i].res->start,
>> 2);
>> >> + if (cpld.addr[i].iom == NULL) {
>> >> + dev_err(&pdev->dev, "cannot remap addr area
>> %d\n", i);
>> >> + return -EIO;
>> >> + }
>> >> + switch (i) {
>> >> + case CTRL_R:
>> >> + trizeps6_cpld_writew(CTRL_R, CPLD_CTRL_R);
>> >> + break;
>> >> + case FTUR_S:
>> >> + trizeps6_cpld_writew(FTUR_S, CPLD_FTUR_S);
>> >> + break;
>> >> + default:
>> >> + ;
>> >> +
>> >> + }
>> >> + dev_dbg(&pdev->dev, "mapped region [%d] %08x ->
>> %p\n",
>> i,
>> >> + (int)cpld.addr[i].req->start,
>> cpld.addr[i].iom);
>> >> + }
>> >> +
>> >> +
>> >> + return 0;
>> >> +}
>> >> +
>> >> +static int trizeps6_cpld_remove(struct platform_device *pdev)
>> >> +{
>> >> + dev_dbg(&pdev->dev, "trizeps6_cpld_remove()\n");
>> >> + return 0;
>> >> +}
>> >> +
>> >> +#ifdef CONFIG_PM
>> >> +static int trizeps6_cpld_suspend(struct platform_device *pdev,
>> >> pm_message_t state)
>> >> +{
>> >> + return 0;
>> >> +}
>> >> +
>> >> +static int trizeps6_cpld_resume(struct platform_device *pdev)
>> >> +{
>> >> + return 0;
>> >> +}
>> >> +#endif
>> >> +
>> >> +static struct platform_driver trizeps6_cpld_driver = {
>> >> + .probe = trizeps6_cpld_probe,
>> >> + .remove = trizeps6_cpld_remove,
>> >> +#ifdef CONFIG_PM
>> >> + .suspend = trizeps6_cpld_suspend,
>> >> + .resume = trizeps6_cpld_resume,
>> >> +#endif
>> >> + .driver = {
>> >> + .name = "trizeps6-cpld",
>> >> + },
>> >> +};
>> >> +
>> >> +
>> >> +static int __devinit trizeps6_cpld_init(void)
>> >> +{
>> >> +
>> >> + return platform_driver_register(&trizeps6_cpld_driver);
>> >> +}
>> >> +
>> >> +static void trizeps6_cpld_exit(void)
>> >> +{
>> >> + platform_driver_unregister(&trizeps6_cpld_driver);
>> >> +}
>> >> +
>> >> +arch_initcall(trizeps6_cpld_init);
>> >> +module_exit(trizeps6_cpld_exit);
>> >> +
>> >> +MODULE_AUTHOR("Yupeng Schneider <yupeng.schneider@googlemail.com>");
>> >> +MODULE_DESCRIPTION("Trizeps VI CPLD");
>> >> +MODULE_LICENSE("GPL");
>> >> --
>> >> 1.6.3.3
>> >>
>> >>
>> >>
>> >>
>> >
>>
>
^ 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