diff options
author | eric miao <eric.miao@marvell.com> | 2008-01-02 22:25:56 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2008-01-26 10:07:56 -0500 |
commit | 7f7c8a619253c83cf3b1071df3b001811d0c1a6c (patch) | |
tree | b4a80e57ef93e3d669e1cadb561ba975e2ce2228 /arch/arm/mach-pxa/mfp.c | |
parent | 0ad1fbc86045c2a27ff082c02344131be072699f (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.c | 97 |
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 @@ | |||
28 | static DEFINE_SPINLOCK(mfp_spin_lock); | 29 | static DEFINE_SPINLOCK(mfp_spin_lock); |
29 | 30 | ||
30 | static void __iomem *mfpr_mmio_base = (void __iomem *)&__REG(MFPR_BASE); | 31 | static void __iomem *mfpr_mmio_base = (void __iomem *)&__REG(MFPR_BASE); |
32 | |||
33 | struct 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 | |||
31 | static struct pxa3xx_mfp_pin mfp_table[MFP_PIN_MAX]; | 40 | static struct pxa3xx_mfp_pin mfp_table[MFP_PIN_MAX]; |
32 | 41 | ||
42 | /* mapping of MFP_LPM_* definitions to MFPR_LPM_* register bits */ | ||
43 | const 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 */ | ||
53 | const 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 */ | ||
61 | const 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 | ||
45 | static inline void __mfp_config(int pin, unsigned long val) | 82 | static 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; | 88 | static 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 | ||
53 | void pxa3xx_mfp_config(mfp_cfg_t *mfp_cfgs, int num) | 94 | void 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 | ||
121 | void __init pxa3xx_init_mfp(void) | 185 | void __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 | } |