aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-pxa/mfp.c
diff options
context:
space:
mode:
authoreric miao <eric.miao@marvell.com>2008-01-02 22:25:56 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2008-01-26 10:07:56 -0500
commit7f7c8a619253c83cf3b1071df3b001811d0c1a6c (patch)
treeb4a80e57ef93e3d669e1cadb561ba975e2ce2228 /arch/arm/mach-pxa/mfp.c
parent0ad1fbc86045c2a27ff082c02344131be072699f (diff)
[ARM] pxa: make MFP configuration processor independent
There are two reasons for making the MFP configuration to be processor independent, i.e. removing the relationship of configuration bits with actual MFPR register settings: 1. power management sometimes requires the MFP to be configured differently when in run mode or in low power mode 2. for future integration of pxa{25x,27x} GPIO configurations The modifications include: 1. introducing of processor independent MFP configuration bits, as defined in [include/asm-arm/arch-pxa/mfp.h]: bit 0.. 9 - MFP Pin Number (1024 Pins Maximum) bit 10..12 - Alternate Function Selection bit 13..15 - Drive Strength bit 16..18 - Low Power Mode State bit 19..20 - Low Power Mode Edge Detection bit 21..22 - Run Mode Pull State and so on, 2. moving the processor dependent code from mfp.h into mfp-pxa3xx.h 3. cleaning up of the MFPR bit definitions 4. mapping of processor independent MFP configuration into processor specific MFPR register settings is now totally encapsulated within pxa3xx_mfp_config() 5. using of "unsigned long" instead of invented type of "mfp_cfg_t" according to Documentation/CodingStyle Chapter 5, usage of this in platform code will be slowly removed in later patches Signed-off-by: eric miao <eric.miao@marvell.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mach-pxa/mfp.c')
-rw-r--r--arch/arm/mach-pxa/mfp.c97
1 files changed, 82 insertions, 15 deletions
diff --git a/arch/arm/mach-pxa/mfp.c b/arch/arm/mach-pxa/mfp.c
index 785ae0ddb84f..c66b1cd7df64 100644
--- a/arch/arm/mach-pxa/mfp.c
+++ b/arch/arm/mach-pxa/mfp.c
@@ -20,6 +20,7 @@
20 20
21#include <asm/hardware.h> 21#include <asm/hardware.h>
22#include <asm/arch/mfp.h> 22#include <asm/arch/mfp.h>
23#include <asm/arch/mfp-pxa3xx.h>
23 24
24/* mfp_spin_lock is used to ensure that MFP register configuration 25/* mfp_spin_lock is used to ensure that MFP register configuration
25 * (most likely a read-modify-write operation) is atomic, and that 26 * (most likely a read-modify-write operation) is atomic, and that
@@ -28,43 +29,105 @@
28static DEFINE_SPINLOCK(mfp_spin_lock); 29static DEFINE_SPINLOCK(mfp_spin_lock);
29 30
30static void __iomem *mfpr_mmio_base = (void __iomem *)&__REG(MFPR_BASE); 31static void __iomem *mfpr_mmio_base = (void __iomem *)&__REG(MFPR_BASE);
32
33struct pxa3xx_mfp_pin {
34 unsigned long config; /* -1 for not configured */
35 unsigned long mfpr_off; /* MFPRxx Register offset */
36 unsigned long mfpr_run; /* Run-Mode Register Value */
37 unsigned long mfpr_lpm; /* Low Power Mode Register Value */
38};
39
31static struct pxa3xx_mfp_pin mfp_table[MFP_PIN_MAX]; 40static struct pxa3xx_mfp_pin mfp_table[MFP_PIN_MAX];
32 41
42/* mapping of MFP_LPM_* definitions to MFPR_LPM_* register bits */
43const static unsigned long mfpr_lpm[] = {
44 MFPR_LPM_INPUT,
45 MFPR_LPM_DRIVE_LOW,
46 MFPR_LPM_DRIVE_HIGH,
47 MFPR_LPM_PULL_LOW,
48 MFPR_LPM_PULL_HIGH,
49 MFPR_LPM_FLOAT,
50};
51
52/* mapping of MFP_PULL_* definitions to MFPR_PULL_* register bits */
53const static unsigned long mfpr_pull[] = {
54 MFPR_PULL_NONE,
55 MFPR_PULL_LOW,
56 MFPR_PULL_HIGH,
57 MFPR_PULL_BOTH,
58};
59
60/* mapping of MFP_LPM_EDGE_* definitions to MFPR_EDGE_* register bits */
61const static unsigned long mfpr_edge[] = {
62 MFPR_EDGE_NONE,
63 MFPR_EDGE_RISE,
64 MFPR_EDGE_FALL,
65 MFPR_EDGE_BOTH,
66};
67
33#define mfpr_readl(off) \ 68#define mfpr_readl(off) \
34 __raw_readl(mfpr_mmio_base + (off)) 69 __raw_readl(mfpr_mmio_base + (off))
35 70
36#define mfpr_writel(off, val) \ 71#define mfpr_writel(off, val) \
37 __raw_writel(val, mfpr_mmio_base + (off)) 72 __raw_writel(val, mfpr_mmio_base + (off))
38 73
74#define mfp_configured(p) ((p)->config != -1)
75
39/* 76/*
40 * perform a read-back of any MFPR register to make sure the 77 * perform a read-back of any MFPR register to make sure the
41 * previous writings are finished 78 * previous writings are finished
42 */ 79 */
43#define mfpr_sync() (void)__raw_readl(mfpr_mmio_base + 0) 80#define mfpr_sync() (void)__raw_readl(mfpr_mmio_base + 0)
44 81
45static inline void __mfp_config(int pin, unsigned long val) 82static inline void __mfp_config_run(struct pxa3xx_mfp_pin *p)
46{ 83{
47 unsigned long off = mfp_table[pin].mfpr_off; 84 if (mfp_configured(p))
85 mfpr_writel(p->mfpr_off, p->mfpr_run);
86}
48 87
49 mfp_table[pin].mfpr_val = val; 88static inline void __mfp_config_lpm(struct pxa3xx_mfp_pin *p)
50 mfpr_writel(off, val); 89{
90 if (mfp_configured(p) && p->mfpr_lpm != p->mfpr_run)
91 mfpr_writel(p->mfpr_off, p->mfpr_lpm);
51} 92}
52 93
53void pxa3xx_mfp_config(mfp_cfg_t *mfp_cfgs, int num) 94void pxa3xx_mfp_config(unsigned long *mfp_cfgs, int num)
54{ 95{
55 int i, pin; 96 unsigned long flags;
56 unsigned long val, flags; 97 int i;
57 mfp_cfg_t *mfp_cfg = mfp_cfgs;
58 98
59 spin_lock_irqsave(&mfp_spin_lock, flags); 99 spin_lock_irqsave(&mfp_spin_lock, flags);
60 100
61 for (i = 0; i < num; i++, mfp_cfg++) { 101 for (i = 0; i < num; i++, mfp_cfgs++) {
62 pin = MFP_CFG_PIN(*mfp_cfg); 102 unsigned long tmp, c = *mfp_cfgs;
63 val = MFP_CFG_VAL(*mfp_cfg); 103 struct pxa3xx_mfp_pin *p;
104 int pin, af, drv, lpm, edge, pull;
64 105
106 pin = MFP_PIN(c);
65 BUG_ON(pin >= MFP_PIN_MAX); 107 BUG_ON(pin >= MFP_PIN_MAX);
66 108 p = &mfp_table[pin];
67 __mfp_config(pin, val); 109
110 af = MFP_AF(c);
111 drv = MFP_DS(c);
112 lpm = MFP_LPM_STATE(c);
113 edge = MFP_LPM_EDGE(c);
114 pull = MFP_PULL(c);
115
116 /* run-mode pull settings will conflict with MFPR bits of
117 * low power mode state, calculate mfpr_run and mfpr_lpm
118 * individually if pull != MFP_PULL_NONE
119 */
120 tmp = MFPR_AF_SEL(af) | MFPR_DRIVE(drv);
121
122 if (likely(pull == MFP_PULL_NONE)) {
123 p->mfpr_run = tmp | mfpr_lpm[lpm] | mfpr_edge[edge];
124 p->mfpr_lpm = p->mfpr_run;
125 } else {
126 p->mfpr_lpm = tmp | mfpr_lpm[lpm] | mfpr_edge[edge];
127 p->mfpr_run = tmp | mfpr_pull[pull];
128 }
129
130 p->config = c; __mfp_config_run(p);
68 } 131 }
69 132
70 mfpr_sync(); 133 mfpr_sync();
@@ -110,7 +173,8 @@ void __init pxa3xx_mfp_init_addr(struct pxa3xx_mfp_addr_map *map)
110 173
111 do { 174 do {
112 mfp_table[i].mfpr_off = offset; 175 mfp_table[i].mfpr_off = offset;
113 mfp_table[i].mfpr_val = 0; 176 mfp_table[i].mfpr_run = 0;
177 mfp_table[i].mfpr_lpm = 0;
114 offset += 4; i++; 178 offset += 4; i++;
115 } while ((i <= p->end) && (p->end != -1)); 179 } while ((i <= p->end) && (p->end != -1));
116 } 180 }
@@ -120,5 +184,8 @@ void __init pxa3xx_mfp_init_addr(struct pxa3xx_mfp_addr_map *map)
120 184
121void __init pxa3xx_init_mfp(void) 185void __init pxa3xx_init_mfp(void)
122{ 186{
123 memset(mfp_table, 0, sizeof(mfp_table)); 187 int i;
188
189 for (i = 0; i < ARRAY_SIZE(mfp_table); i++)
190 mfp_table[i].config = -1;
124} 191}