diff options
| -rw-r--r-- | arch/arm/mach-pxa/include/mach/mfp-pxa25x.h | 1 | ||||
| -rw-r--r-- | arch/arm/mach-pxa/include/mach/mfp-pxa27x.h | 1 | ||||
| -rw-r--r-- | arch/arm/mach-pxa/include/mach/mfp-pxa2xx.h | 2 | ||||
| -rw-r--r-- | arch/arm/mach-pxa/include/mach/mfp-pxa300.h | 1 | ||||
| -rw-r--r-- | arch/arm/mach-pxa/include/mach/mfp-pxa320.h | 1 | ||||
| -rw-r--r-- | arch/arm/mach-pxa/include/mach/mfp-pxa3xx.h | 130 | ||||
| -rw-r--r-- | arch/arm/mach-pxa/include/mach/mfp-pxa930.h | 1 | ||||
| -rw-r--r-- | arch/arm/mach-pxa/mfp-pxa3xx.c | 189 | ||||
| -rw-r--r-- | arch/arm/mach-pxa/pxa300.c | 10 | ||||
| -rw-r--r-- | arch/arm/mach-pxa/pxa320.c | 6 | ||||
| -rw-r--r-- | arch/arm/mach-pxa/pxa930.c | 6 | ||||
| -rw-r--r-- | arch/arm/plat-pxa/Makefile | 2 | ||||
| -rw-r--r-- | arch/arm/plat-pxa/include/plat/mfp.h | 369 | ||||
| -rw-r--r-- | arch/arm/plat-pxa/mfp.c | 278 |
14 files changed, 680 insertions, 317 deletions
diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa25x.h b/arch/arm/mach-pxa/include/mach/mfp-pxa25x.h index a72869b73ee3..b13dc0269a6d 100644 --- a/arch/arm/mach-pxa/include/mach/mfp-pxa25x.h +++ b/arch/arm/mach-pxa/include/mach/mfp-pxa25x.h | |||
| @@ -1,7 +1,6 @@ | |||
| 1 | #ifndef __ASM_ARCH_MFP_PXA25X_H | 1 | #ifndef __ASM_ARCH_MFP_PXA25X_H |
| 2 | #define __ASM_ARCH_MFP_PXA25X_H | 2 | #define __ASM_ARCH_MFP_PXA25X_H |
| 3 | 3 | ||
| 4 | #include <mach/mfp.h> | ||
| 5 | #include <mach/mfp-pxa2xx.h> | 4 | #include <mach/mfp-pxa2xx.h> |
| 6 | 5 | ||
| 7 | /* GPIO */ | 6 | /* GPIO */ |
diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h b/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h index da4f85a4f990..6543c05f47ed 100644 --- a/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h +++ b/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h | |||
| @@ -8,7 +8,6 @@ | |||
| 8 | * specific controller, and this should work in most cases. | 8 | * specific controller, and this should work in most cases. |
| 9 | */ | 9 | */ |
| 10 | 10 | ||
| 11 | #include <mach/mfp.h> | ||
| 12 | #include <mach/mfp-pxa2xx.h> | 11 | #include <mach/mfp-pxa2xx.h> |
| 13 | 12 | ||
| 14 | /* Note: GPIO3/GPIO4 will be driven by Power I2C when PCFR/PI2C_EN | 13 | /* Note: GPIO3/GPIO4 will be driven by Power I2C when PCFR/PI2C_EN |
diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa2xx.h b/arch/arm/mach-pxa/include/mach/mfp-pxa2xx.h index 3e9211591e20..658b28ed129b 100644 --- a/arch/arm/mach-pxa/include/mach/mfp-pxa2xx.h +++ b/arch/arm/mach-pxa/include/mach/mfp-pxa2xx.h | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | #ifndef __ASM_ARCH_MFP_PXA2XX_H | 1 | #ifndef __ASM_ARCH_MFP_PXA2XX_H |
| 2 | #define __ASM_ARCH_MFP_PXA2XX_H | 2 | #define __ASM_ARCH_MFP_PXA2XX_H |
| 3 | 3 | ||
| 4 | #include <mach/mfp.h> | 4 | #include <plat/mfp.h> |
| 5 | 5 | ||
| 6 | /* | 6 | /* |
| 7 | * the following MFP_xxx bit definitions in mfp.h are re-used for pxa2xx: | 7 | * the following MFP_xxx bit definitions in mfp.h are re-used for pxa2xx: |
diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa300.h b/arch/arm/mach-pxa/include/mach/mfp-pxa300.h index 928fbef9cbf3..ae8441192ef0 100644 --- a/arch/arm/mach-pxa/include/mach/mfp-pxa300.h +++ b/arch/arm/mach-pxa/include/mach/mfp-pxa300.h | |||
| @@ -15,7 +15,6 @@ | |||
| 15 | #ifndef __ASM_ARCH_MFP_PXA300_H | 15 | #ifndef __ASM_ARCH_MFP_PXA300_H |
| 16 | #define __ASM_ARCH_MFP_PXA300_H | 16 | #define __ASM_ARCH_MFP_PXA300_H |
| 17 | 17 | ||
| 18 | #include <mach/mfp.h> | ||
| 19 | #include <mach/mfp-pxa3xx.h> | 18 | #include <mach/mfp-pxa3xx.h> |
| 20 | 19 | ||
| 21 | /* GPIO */ | 20 | /* GPIO */ |
diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa320.h b/arch/arm/mach-pxa/include/mach/mfp-pxa320.h index 80a0da9e092d..07897e61d05a 100644 --- a/arch/arm/mach-pxa/include/mach/mfp-pxa320.h +++ b/arch/arm/mach-pxa/include/mach/mfp-pxa320.h | |||
| @@ -15,7 +15,6 @@ | |||
| 15 | #ifndef __ASM_ARCH_MFP_PXA320_H | 15 | #ifndef __ASM_ARCH_MFP_PXA320_H |
| 16 | #define __ASM_ARCH_MFP_PXA320_H | 16 | #define __ASM_ARCH_MFP_PXA320_H |
| 17 | 17 | ||
| 18 | #include <mach/mfp.h> | ||
| 19 | #include <mach/mfp-pxa3xx.h> | 18 | #include <mach/mfp-pxa3xx.h> |
| 20 | 19 | ||
| 21 | /* GPIO */ | 20 | /* GPIO */ |
diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa3xx.h b/arch/arm/mach-pxa/include/mach/mfp-pxa3xx.h index 1f6b35c015d0..d375195d982b 100644 --- a/arch/arm/mach-pxa/include/mach/mfp-pxa3xx.h +++ b/arch/arm/mach-pxa/include/mach/mfp-pxa3xx.h | |||
| @@ -1,68 +1,9 @@ | |||
| 1 | #ifndef __ASM_ARCH_MFP_PXA3XX_H | 1 | #ifndef __ASM_ARCH_MFP_PXA3XX_H |
| 2 | #define __ASM_ARCH_MFP_PXA3XX_H | 2 | #define __ASM_ARCH_MFP_PXA3XX_H |
| 3 | 3 | ||
| 4 | #define MFPR_BASE (0x40e10000) | 4 | #include <plat/mfp.h> |
| 5 | #define MFPR_SIZE (PAGE_SIZE) | ||
| 6 | |||
| 7 | /* MFPR register bit definitions */ | ||
| 8 | #define MFPR_PULL_SEL (0x1 << 15) | ||
| 9 | #define MFPR_PULLUP_EN (0x1 << 14) | ||
| 10 | #define MFPR_PULLDOWN_EN (0x1 << 13) | ||
| 11 | #define MFPR_SLEEP_SEL (0x1 << 9) | ||
| 12 | #define MFPR_SLEEP_OE_N (0x1 << 7) | ||
| 13 | #define MFPR_EDGE_CLEAR (0x1 << 6) | ||
| 14 | #define MFPR_EDGE_FALL_EN (0x1 << 5) | ||
| 15 | #define MFPR_EDGE_RISE_EN (0x1 << 4) | ||
| 16 | |||
| 17 | #define MFPR_SLEEP_DATA(x) ((x) << 8) | ||
| 18 | #define MFPR_DRIVE(x) (((x) & 0x7) << 10) | ||
| 19 | #define MFPR_AF_SEL(x) (((x) & 0x7) << 0) | ||
| 20 | 5 | ||
| 21 | #define MFPR_EDGE_NONE (0) | 6 | #define MFPR_BASE (0x40e10000) |
| 22 | #define MFPR_EDGE_RISE (MFPR_EDGE_RISE_EN) | ||
| 23 | #define MFPR_EDGE_FALL (MFPR_EDGE_FALL_EN) | ||
| 24 | #define MFPR_EDGE_BOTH (MFPR_EDGE_RISE | MFPR_EDGE_FALL) | ||
| 25 | |||
| 26 | /* | ||
| 27 | * Table that determines the low power modes outputs, with actual settings | ||
| 28 | * used in parentheses for don't-care values. Except for the float output, | ||
| 29 | * the configured driven and pulled levels match, so if there is a need for | ||
| 30 | * non-LPM pulled output, the same configuration could probably be used. | ||
| 31 | * | ||
| 32 | * Output value sleep_oe_n sleep_data pullup_en pulldown_en pull_sel | ||
| 33 | * (bit 7) (bit 8) (bit 14) (bit 13) (bit 15) | ||
| 34 | * | ||
| 35 | * Input 0 X(0) X(0) X(0) 0 | ||
| 36 | * Drive 0 0 0 0 X(1) 0 | ||
| 37 | * Drive 1 0 1 X(1) 0 0 | ||
| 38 | * Pull hi (1) 1 X(1) 1 0 0 | ||
| 39 | * Pull lo (0) 1 X(0) 0 1 0 | ||
| 40 | * Z (float) 1 X(0) 0 0 0 | ||
| 41 | */ | ||
| 42 | #define MFPR_LPM_INPUT (0) | ||
| 43 | #define MFPR_LPM_DRIVE_LOW (MFPR_SLEEP_DATA(0) | MFPR_PULLDOWN_EN) | ||
| 44 | #define MFPR_LPM_DRIVE_HIGH (MFPR_SLEEP_DATA(1) | MFPR_PULLUP_EN) | ||
| 45 | #define MFPR_LPM_PULL_LOW (MFPR_LPM_DRIVE_LOW | MFPR_SLEEP_OE_N) | ||
| 46 | #define MFPR_LPM_PULL_HIGH (MFPR_LPM_DRIVE_HIGH | MFPR_SLEEP_OE_N) | ||
| 47 | #define MFPR_LPM_FLOAT (MFPR_SLEEP_OE_N) | ||
| 48 | #define MFPR_LPM_MASK (0xe080) | ||
| 49 | |||
| 50 | /* | ||
| 51 | * The pullup and pulldown state of the MFP pin at run mode is by default | ||
| 52 | * determined by the selected alternate function. In case that some buggy | ||
| 53 | * devices need to override this default behavior, the definitions below | ||
| 54 | * indicates the setting of corresponding MFPR bits | ||
| 55 | * | ||
| 56 | * Definition pull_sel pullup_en pulldown_en | ||
| 57 | * MFPR_PULL_NONE 0 0 0 | ||
| 58 | * MFPR_PULL_LOW 1 0 1 | ||
| 59 | * MFPR_PULL_HIGH 1 1 0 | ||
| 60 | * MFPR_PULL_BOTH 1 1 1 | ||
| 61 | */ | ||
| 62 | #define MFPR_PULL_NONE (0) | ||
| 63 | #define MFPR_PULL_LOW (MFPR_PULL_SEL | MFPR_PULLDOWN_EN) | ||
| 64 | #define MFPR_PULL_BOTH (MFPR_PULL_LOW | MFPR_PULLUP_EN) | ||
| 65 | #define MFPR_PULL_HIGH (MFPR_PULL_SEL | MFPR_PULLUP_EN) | ||
| 66 | 7 | ||
| 67 | /* PXA3xx common MFP configurations - processor specific ones defined | 8 | /* PXA3xx common MFP configurations - processor specific ones defined |
| 68 | * in mfp-pxa300.h and mfp-pxa320.h | 9 | * in mfp-pxa300.h and mfp-pxa320.h |
| @@ -197,56 +138,21 @@ | |||
| 197 | #define GPIO5_2_GPIO MFP_CFG(GPIO5_2, AF0) | 138 | #define GPIO5_2_GPIO MFP_CFG(GPIO5_2, AF0) |
| 198 | #define GPIO6_2_GPIO MFP_CFG(GPIO6_2, AF0) | 139 | #define GPIO6_2_GPIO MFP_CFG(GPIO6_2, AF0) |
| 199 | 140 | ||
| 200 | /* | 141 | /* NOTE: usage of these two functions is not recommended, |
| 201 | * each MFP pin will have a MFPR register, since the offset of the | 142 | * use pxa3xx_mfp_config() instead. |
| 202 | * register varies between processors, the processor specific code | ||
| 203 | * should initialize the pin offsets by pxa3xx_mfp_init_addr() | ||
| 204 | * | ||
| 205 | * pxa3xx_mfp_init_addr - accepts a table of "pxa3xx_mfp_addr_map" | ||
| 206 | * structure, which represents a range of MFP pins from "start" to | ||
| 207 | * "end", with the offset begining at "offset", to define a single | ||
| 208 | * pin, let "end" = -1 | ||
| 209 | * | ||
| 210 | * use | ||
| 211 | * | ||
| 212 | * MFP_ADDR_X() to define a range of pins | ||
| 213 | * MFP_ADDR() to define a single pin | ||
| 214 | * MFP_ADDR_END to signal the end of pin offset definitions | ||
| 215 | */ | ||
| 216 | struct pxa3xx_mfp_addr_map { | ||
| 217 | unsigned int start; | ||
| 218 | unsigned int end; | ||
| 219 | unsigned long offset; | ||
| 220 | }; | ||
| 221 | |||
| 222 | #define MFP_ADDR_X(start, end, offset) \ | ||
| 223 | { MFP_PIN_##start, MFP_PIN_##end, offset } | ||
| 224 | |||
| 225 | #define MFP_ADDR(pin, offset) \ | ||
| 226 | { MFP_PIN_##pin, -1, offset } | ||
| 227 | |||
| 228 | #define MFP_ADDR_END { MFP_PIN_INVALID, 0 } | ||
| 229 | |||
| 230 | /* | ||
| 231 | * pxa3xx_mfp_read()/pxa3xx_mfp_write() - for direct read/write access | ||
| 232 | * to the MFPR register | ||
| 233 | */ | ||
| 234 | unsigned long pxa3xx_mfp_read(int mfp); | ||
| 235 | void pxa3xx_mfp_write(int mfp, unsigned long mfpr_val); | ||
| 236 | |||
| 237 | /* | ||
| 238 | * pxa3xx_mfp_config - configure the MFPR registers | ||
| 239 | * | ||
| 240 | * used by board specific initialization code | ||
| 241 | */ | ||
| 242 | void pxa3xx_mfp_config(unsigned long *mfp_cfgs, int num); | ||
| 243 | |||
| 244 | /* | ||
| 245 | * pxa3xx_mfp_init_addr() - initialize the mapping between mfp pin | ||
| 246 | * index and MFPR register offset | ||
| 247 | * | ||
| 248 | * used by processor specific code | ||
| 249 | */ | 143 | */ |
| 250 | void __init pxa3xx_mfp_init_addr(struct pxa3xx_mfp_addr_map *); | 144 | static inline unsigned long pxa3xx_mfp_read(int mfp) |
| 251 | void __init pxa3xx_init_mfp(void); | 145 | { |
| 146 | return mfp_read(mfp); | ||
| 147 | } | ||
| 148 | |||
| 149 | static inline void pxa3xx_mfp_write(int mfp, unsigned long val) | ||
| 150 | { | ||
| 151 | mfp_write(mfp, val); | ||
| 152 | } | ||
| 153 | |||
| 154 | static inline void pxa3xx_mfp_config(unsigned long *mfp_cfg, int num) | ||
| 155 | { | ||
| 156 | mfp_config(mfp_cfg, num); | ||
| 157 | } | ||
| 252 | #endif /* __ASM_ARCH_MFP_PXA3XX_H */ | 158 | #endif /* __ASM_ARCH_MFP_PXA3XX_H */ |
diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa930.h b/arch/arm/mach-pxa/include/mach/mfp-pxa930.h index fa73f56a1372..0d119d3b9221 100644 --- a/arch/arm/mach-pxa/include/mach/mfp-pxa930.h +++ b/arch/arm/mach-pxa/include/mach/mfp-pxa930.h | |||
| @@ -13,7 +13,6 @@ | |||
| 13 | #ifndef __ASM_ARCH_MFP_PXA9xx_H | 13 | #ifndef __ASM_ARCH_MFP_PXA9xx_H |
| 14 | #define __ASM_ARCH_MFP_PXA9xx_H | 14 | #define __ASM_ARCH_MFP_PXA9xx_H |
| 15 | 15 | ||
| 16 | #include <mach/mfp.h> | ||
| 17 | #include <mach/mfp-pxa3xx.h> | 16 | #include <mach/mfp-pxa3xx.h> |
| 18 | 17 | ||
| 19 | /* GPIO */ | 18 | /* GPIO */ |
diff --git a/arch/arm/mach-pxa/mfp-pxa3xx.c b/arch/arm/mach-pxa/mfp-pxa3xx.c index eb197a6e8e94..7a270eecd480 100644 --- a/arch/arm/mach-pxa/mfp-pxa3xx.c +++ b/arch/arm/mach-pxa/mfp-pxa3xx.c | |||
| @@ -20,183 +20,9 @@ | |||
| 20 | #include <linux/sysdev.h> | 20 | #include <linux/sysdev.h> |
| 21 | 21 | ||
| 22 | #include <mach/hardware.h> | 22 | #include <mach/hardware.h> |
| 23 | #include <mach/mfp.h> | ||
| 24 | #include <mach/mfp-pxa3xx.h> | 23 | #include <mach/mfp-pxa3xx.h> |
| 25 | #include <mach/pxa3xx-regs.h> | 24 | #include <mach/pxa3xx-regs.h> |
| 26 | 25 | ||
| 27 | /* mfp_spin_lock is used to ensure that MFP register configuration | ||
| 28 | * (most likely a read-modify-write operation) is atomic, and that | ||
| 29 | * mfp_table[] is consistent | ||
| 30 | */ | ||
| 31 | static DEFINE_SPINLOCK(mfp_spin_lock); | ||
| 32 | |||
| 33 | static void __iomem *mfpr_mmio_base = (void __iomem *)&__REG(MFPR_BASE); | ||
| 34 | |||
| 35 | struct pxa3xx_mfp_pin { | ||
| 36 | unsigned long config; /* -1 for not configured */ | ||
| 37 | unsigned long mfpr_off; /* MFPRxx Register offset */ | ||
| 38 | unsigned long mfpr_run; /* Run-Mode Register Value */ | ||
| 39 | unsigned long mfpr_lpm; /* Low Power Mode Register Value */ | ||
| 40 | }; | ||
| 41 | |||
| 42 | static struct pxa3xx_mfp_pin mfp_table[MFP_PIN_MAX]; | ||
| 43 | |||
| 44 | /* mapping of MFP_LPM_* definitions to MFPR_LPM_* register bits */ | ||
| 45 | static const unsigned long mfpr_lpm[] = { | ||
| 46 | MFPR_LPM_INPUT, | ||
| 47 | MFPR_LPM_DRIVE_LOW, | ||
| 48 | MFPR_LPM_DRIVE_HIGH, | ||
| 49 | MFPR_LPM_PULL_LOW, | ||
| 50 | MFPR_LPM_PULL_HIGH, | ||
| 51 | MFPR_LPM_FLOAT, | ||
| 52 | }; | ||
| 53 | |||
| 54 | /* mapping of MFP_PULL_* definitions to MFPR_PULL_* register bits */ | ||
| 55 | static const unsigned long mfpr_pull[] = { | ||
| 56 | MFPR_PULL_NONE, | ||
| 57 | MFPR_PULL_LOW, | ||
| 58 | MFPR_PULL_HIGH, | ||
| 59 | MFPR_PULL_BOTH, | ||
| 60 | }; | ||
| 61 | |||
| 62 | /* mapping of MFP_LPM_EDGE_* definitions to MFPR_EDGE_* register bits */ | ||
| 63 | static const unsigned long mfpr_edge[] = { | ||
| 64 | MFPR_EDGE_NONE, | ||
| 65 | MFPR_EDGE_RISE, | ||
| 66 | MFPR_EDGE_FALL, | ||
| 67 | MFPR_EDGE_BOTH, | ||
| 68 | }; | ||
| 69 | |||
| 70 | #define mfpr_readl(off) \ | ||
| 71 | __raw_readl(mfpr_mmio_base + (off)) | ||
| 72 | |||
| 73 | #define mfpr_writel(off, val) \ | ||
| 74 | __raw_writel(val, mfpr_mmio_base + (off)) | ||
| 75 | |||
| 76 | #define mfp_configured(p) ((p)->config != -1) | ||
| 77 | |||
| 78 | /* | ||
| 79 | * perform a read-back of any MFPR register to make sure the | ||
| 80 | * previous writings are finished | ||
| 81 | */ | ||
| 82 | #define mfpr_sync() (void)__raw_readl(mfpr_mmio_base + 0) | ||
| 83 | |||
| 84 | static inline void __mfp_config_run(struct pxa3xx_mfp_pin *p) | ||
| 85 | { | ||
| 86 | if (mfp_configured(p)) | ||
| 87 | mfpr_writel(p->mfpr_off, p->mfpr_run); | ||
| 88 | } | ||
| 89 | |||
| 90 | static inline void __mfp_config_lpm(struct pxa3xx_mfp_pin *p) | ||
| 91 | { | ||
| 92 | if (mfp_configured(p)) { | ||
| 93 | unsigned long mfpr_clr = (p->mfpr_run & ~MFPR_EDGE_BOTH) | MFPR_EDGE_CLEAR; | ||
| 94 | if (mfpr_clr != p->mfpr_run) | ||
| 95 | mfpr_writel(p->mfpr_off, mfpr_clr); | ||
| 96 | if (p->mfpr_lpm != mfpr_clr) | ||
| 97 | mfpr_writel(p->mfpr_off, p->mfpr_lpm); | ||
| 98 | } | ||
| 99 | } | ||
| 100 | |||
| 101 | void pxa3xx_mfp_config(unsigned long *mfp_cfgs, int num) | ||
| 102 | { | ||
| 103 | unsigned long flags; | ||
| 104 | int i; | ||
| 105 | |||
| 106 | spin_lock_irqsave(&mfp_spin_lock, flags); | ||
| 107 | |||
| 108 | for (i = 0; i < num; i++, mfp_cfgs++) { | ||
| 109 | unsigned long tmp, c = *mfp_cfgs; | ||
| 110 | struct pxa3xx_mfp_pin *p; | ||
| 111 | int pin, af, drv, lpm, edge, pull; | ||
| 112 | |||
| 113 | pin = MFP_PIN(c); | ||
| 114 | BUG_ON(pin >= MFP_PIN_MAX); | ||
| 115 | p = &mfp_table[pin]; | ||
| 116 | |||
| 117 | af = MFP_AF(c); | ||
| 118 | drv = MFP_DS(c); | ||
| 119 | lpm = MFP_LPM_STATE(c); | ||
| 120 | edge = MFP_LPM_EDGE(c); | ||
| 121 | pull = MFP_PULL(c); | ||
| 122 | |||
| 123 | /* run-mode pull settings will conflict with MFPR bits of | ||
| 124 | * low power mode state, calculate mfpr_run and mfpr_lpm | ||
| 125 | * individually if pull != MFP_PULL_NONE | ||
| 126 | */ | ||
| 127 | tmp = MFPR_AF_SEL(af) | MFPR_DRIVE(drv); | ||
| 128 | |||
| 129 | if (likely(pull == MFP_PULL_NONE)) { | ||
| 130 | p->mfpr_run = tmp | mfpr_lpm[lpm] | mfpr_edge[edge]; | ||
| 131 | p->mfpr_lpm = p->mfpr_run; | ||
| 132 | } else { | ||
| 133 | p->mfpr_lpm = tmp | mfpr_lpm[lpm] | mfpr_edge[edge]; | ||
| 134 | p->mfpr_run = tmp | mfpr_pull[pull]; | ||
| 135 | } | ||
| 136 | |||
| 137 | p->config = c; __mfp_config_run(p); | ||
| 138 | } | ||
| 139 | |||
| 140 | mfpr_sync(); | ||
| 141 | spin_unlock_irqrestore(&mfp_spin_lock, flags); | ||
| 142 | } | ||
| 143 | |||
| 144 | unsigned long pxa3xx_mfp_read(int mfp) | ||
| 145 | { | ||
| 146 | unsigned long val, flags; | ||
| 147 | |||
| 148 | BUG_ON(mfp >= MFP_PIN_MAX); | ||
| 149 | |||
| 150 | spin_lock_irqsave(&mfp_spin_lock, flags); | ||
| 151 | val = mfpr_readl(mfp_table[mfp].mfpr_off); | ||
| 152 | spin_unlock_irqrestore(&mfp_spin_lock, flags); | ||
| 153 | |||
| 154 | return val; | ||
| 155 | } | ||
| 156 | |||
| 157 | void pxa3xx_mfp_write(int mfp, unsigned long val) | ||
| 158 | { | ||
| 159 | unsigned long flags; | ||
| 160 | |||
| 161 | BUG_ON(mfp >= MFP_PIN_MAX); | ||
| 162 | |||
| 163 | spin_lock_irqsave(&mfp_spin_lock, flags); | ||
| 164 | mfpr_writel(mfp_table[mfp].mfpr_off, val); | ||
| 165 | mfpr_sync(); | ||
| 166 | spin_unlock_irqrestore(&mfp_spin_lock, flags); | ||
| 167 | } | ||
| 168 | |||
| 169 | void __init pxa3xx_mfp_init_addr(struct pxa3xx_mfp_addr_map *map) | ||
| 170 | { | ||
| 171 | struct pxa3xx_mfp_addr_map *p; | ||
| 172 | unsigned long offset, flags; | ||
| 173 | int i; | ||
| 174 | |||
| 175 | spin_lock_irqsave(&mfp_spin_lock, flags); | ||
| 176 | |||
| 177 | for (p = map; p->start != MFP_PIN_INVALID; p++) { | ||
| 178 | offset = p->offset; | ||
| 179 | i = p->start; | ||
| 180 | |||
| 181 | do { | ||
| 182 | mfp_table[i].mfpr_off = offset; | ||
| 183 | mfp_table[i].mfpr_run = 0; | ||
| 184 | mfp_table[i].mfpr_lpm = 0; | ||
| 185 | offset += 4; i++; | ||
| 186 | } while ((i <= p->end) && (p->end != -1)); | ||
| 187 | } | ||
| 188 | |||
| 189 | spin_unlock_irqrestore(&mfp_spin_lock, flags); | ||
| 190 | } | ||
| 191 | |||
| 192 | void __init pxa3xx_init_mfp(void) | ||
| 193 | { | ||
| 194 | int i; | ||
| 195 | |||
| 196 | for (i = 0; i < ARRAY_SIZE(mfp_table); i++) | ||
| 197 | mfp_table[i].config = -1; | ||
| 198 | } | ||
| 199 | |||
| 200 | #ifdef CONFIG_PM | 26 | #ifdef CONFIG_PM |
| 201 | /* | 27 | /* |
| 202 | * Configure the MFPs appropriately for suspend/resume. | 28 | * Configure the MFPs appropriately for suspend/resume. |
| @@ -207,23 +33,13 @@ void __init pxa3xx_init_mfp(void) | |||
| 207 | */ | 33 | */ |
| 208 | static int pxa3xx_mfp_suspend(struct sys_device *d, pm_message_t state) | 34 | static int pxa3xx_mfp_suspend(struct sys_device *d, pm_message_t state) |
| 209 | { | 35 | { |
| 210 | int pin; | 36 | mfp_config_lpm(); |
| 211 | |||
| 212 | for (pin = 0; pin < ARRAY_SIZE(mfp_table); pin++) { | ||
| 213 | struct pxa3xx_mfp_pin *p = &mfp_table[pin]; | ||
| 214 | __mfp_config_lpm(p); | ||
| 215 | } | ||
| 216 | return 0; | 37 | return 0; |
| 217 | } | 38 | } |
| 218 | 39 | ||
| 219 | static int pxa3xx_mfp_resume(struct sys_device *d) | 40 | static int pxa3xx_mfp_resume(struct sys_device *d) |
| 220 | { | 41 | { |
| 221 | int pin; | 42 | mfp_config_run(); |
| 222 | |||
| 223 | for (pin = 0; pin < ARRAY_SIZE(mfp_table); pin++) { | ||
| 224 | struct pxa3xx_mfp_pin *p = &mfp_table[pin]; | ||
| 225 | __mfp_config_run(p); | ||
| 226 | } | ||
| 227 | 43 | ||
| 228 | /* clear RDH bit when MFP settings are restored | 44 | /* clear RDH bit when MFP settings are restored |
| 229 | * | 45 | * |
| @@ -231,7 +47,6 @@ static int pxa3xx_mfp_resume(struct sys_device *d) | |||
| 231 | * preserve them here in case they will be referenced later | 47 | * preserve them here in case they will be referenced later |
| 232 | */ | 48 | */ |
| 233 | ASCR &= ~(ASCR_RDH | ASCR_D1S | ASCR_D2S | ASCR_D3S); | 49 | ASCR &= ~(ASCR_RDH | ASCR_D1S | ASCR_D2S | ASCR_D3S); |
| 234 | |||
| 235 | return 0; | 50 | return 0; |
| 236 | } | 51 | } |
| 237 | #else | 52 | #else |
diff --git a/arch/arm/mach-pxa/pxa300.c b/arch/arm/mach-pxa/pxa300.c index 37bb12d13ca2..4ba6d21f851c 100644 --- a/arch/arm/mach-pxa/pxa300.c +++ b/arch/arm/mach-pxa/pxa300.c | |||
| @@ -23,7 +23,7 @@ | |||
| 23 | #include "devices.h" | 23 | #include "devices.h" |
| 24 | #include "clock.h" | 24 | #include "clock.h" |
| 25 | 25 | ||
| 26 | static struct pxa3xx_mfp_addr_map pxa300_mfp_addr_map[] __initdata = { | 26 | static struct mfp_addr_map pxa300_mfp_addr_map[] __initdata = { |
| 27 | 27 | ||
| 28 | MFP_ADDR_X(GPIO0, GPIO2, 0x00b4), | 28 | MFP_ADDR_X(GPIO0, GPIO2, 0x00b4), |
| 29 | MFP_ADDR_X(GPIO3, GPIO26, 0x027c), | 29 | MFP_ADDR_X(GPIO3, GPIO26, 0x027c), |
| @@ -72,7 +72,7 @@ static struct pxa3xx_mfp_addr_map pxa300_mfp_addr_map[] __initdata = { | |||
| 72 | }; | 72 | }; |
| 73 | 73 | ||
| 74 | /* override pxa300 MFP register addresses */ | 74 | /* override pxa300 MFP register addresses */ |
| 75 | static struct pxa3xx_mfp_addr_map pxa310_mfp_addr_map[] __initdata = { | 75 | static struct mfp_addr_map pxa310_mfp_addr_map[] __initdata = { |
| 76 | MFP_ADDR_X(GPIO30, GPIO98, 0x0418), | 76 | MFP_ADDR_X(GPIO30, GPIO98, 0x0418), |
| 77 | MFP_ADDR_X(GPIO7_2, GPIO12_2, 0x052C), | 77 | MFP_ADDR_X(GPIO7_2, GPIO12_2, 0x052C), |
| 78 | 78 | ||
| @@ -98,13 +98,13 @@ static struct clk_lookup pxa310_clkregs[] = { | |||
| 98 | static int __init pxa300_init(void) | 98 | static int __init pxa300_init(void) |
| 99 | { | 99 | { |
| 100 | if (cpu_is_pxa300() || cpu_is_pxa310()) { | 100 | if (cpu_is_pxa300() || cpu_is_pxa310()) { |
| 101 | pxa3xx_init_mfp(); | 101 | mfp_init_base(io_p2v(MFPR_BASE)); |
| 102 | pxa3xx_mfp_init_addr(pxa300_mfp_addr_map); | 102 | mfp_init_addr(pxa300_mfp_addr_map); |
| 103 | clks_register(ARRAY_AND_SIZE(common_clkregs)); | 103 | clks_register(ARRAY_AND_SIZE(common_clkregs)); |
| 104 | } | 104 | } |
| 105 | 105 | ||
| 106 | if (cpu_is_pxa310()) { | 106 | if (cpu_is_pxa310()) { |
| 107 | pxa3xx_mfp_init_addr(pxa310_mfp_addr_map); | 107 | mfp_init_addr(pxa310_mfp_addr_map); |
| 108 | clks_register(ARRAY_AND_SIZE(pxa310_clkregs)); | 108 | clks_register(ARRAY_AND_SIZE(pxa310_clkregs)); |
| 109 | } | 109 | } |
| 110 | 110 | ||
diff --git a/arch/arm/mach-pxa/pxa320.c b/arch/arm/mach-pxa/pxa320.c index e708f4e0ecaf..8b3d97efadab 100644 --- a/arch/arm/mach-pxa/pxa320.c +++ b/arch/arm/mach-pxa/pxa320.c | |||
| @@ -23,7 +23,7 @@ | |||
| 23 | #include "devices.h" | 23 | #include "devices.h" |
| 24 | #include "clock.h" | 24 | #include "clock.h" |
| 25 | 25 | ||
| 26 | static struct pxa3xx_mfp_addr_map pxa320_mfp_addr_map[] __initdata = { | 26 | static struct mfp_addr_map pxa320_mfp_addr_map[] __initdata = { |
| 27 | 27 | ||
| 28 | MFP_ADDR_X(GPIO0, GPIO4, 0x0124), | 28 | MFP_ADDR_X(GPIO0, GPIO4, 0x0124), |
| 29 | MFP_ADDR_X(GPIO5, GPIO9, 0x028C), | 29 | MFP_ADDR_X(GPIO5, GPIO9, 0x028C), |
| @@ -86,8 +86,8 @@ static struct clk_lookup pxa320_clkregs[] = { | |||
| 86 | static int __init pxa320_init(void) | 86 | static int __init pxa320_init(void) |
| 87 | { | 87 | { |
| 88 | if (cpu_is_pxa320()) { | 88 | if (cpu_is_pxa320()) { |
| 89 | pxa3xx_init_mfp(); | 89 | mfp_init_base(io_p2v(MFPR_BASE)); |
| 90 | pxa3xx_mfp_init_addr(pxa320_mfp_addr_map); | 90 | mfp_init_addr(pxa320_mfp_addr_map); |
| 91 | clks_register(ARRAY_AND_SIZE(pxa320_clkregs)); | 91 | clks_register(ARRAY_AND_SIZE(pxa320_clkregs)); |
| 92 | } | 92 | } |
| 93 | 93 | ||
diff --git a/arch/arm/mach-pxa/pxa930.c b/arch/arm/mach-pxa/pxa930.c index f15dfa55f27f..71131742fffd 100644 --- a/arch/arm/mach-pxa/pxa930.c +++ b/arch/arm/mach-pxa/pxa930.c | |||
| @@ -18,7 +18,7 @@ | |||
| 18 | 18 | ||
| 19 | #include <mach/pxa930.h> | 19 | #include <mach/pxa930.h> |
| 20 | 20 | ||
| 21 | static struct pxa3xx_mfp_addr_map pxa930_mfp_addr_map[] __initdata = { | 21 | static struct mfp_addr_map pxa930_mfp_addr_map[] __initdata = { |
| 22 | 22 | ||
| 23 | MFP_ADDR(GPIO0, 0x02e0), | 23 | MFP_ADDR(GPIO0, 0x02e0), |
| 24 | MFP_ADDR(GPIO1, 0x02dc), | 24 | MFP_ADDR(GPIO1, 0x02dc), |
| @@ -179,8 +179,8 @@ static struct pxa3xx_mfp_addr_map pxa930_mfp_addr_map[] __initdata = { | |||
| 179 | static int __init pxa930_init(void) | 179 | static int __init pxa930_init(void) |
| 180 | { | 180 | { |
| 181 | if (cpu_is_pxa930()) { | 181 | if (cpu_is_pxa930()) { |
| 182 | pxa3xx_init_mfp(); | 182 | mfp_init_base(io_p2v(MFPR_BASE)); |
| 183 | pxa3xx_mfp_init_addr(pxa930_mfp_addr_map); | 183 | mfp_init_addr(pxa930_mfp_addr_map); |
| 184 | } | 184 | } |
| 185 | 185 | ||
| 186 | return 0; | 186 | return 0; |
diff --git a/arch/arm/plat-pxa/Makefile b/arch/arm/plat-pxa/Makefile index b837df440483..4be37235f57b 100644 --- a/arch/arm/plat-pxa/Makefile +++ b/arch/arm/plat-pxa/Makefile | |||
| @@ -2,6 +2,6 @@ | |||
| 2 | # Makefile for code common across different PXA processor families | 2 | # Makefile for code common across different PXA processor families |
| 3 | # | 3 | # |
| 4 | 4 | ||
| 5 | obj-y := dma.o | 5 | obj-y := dma.o mfp.o |
| 6 | 6 | ||
| 7 | obj-$(CONFIG_GENERIC_GPIO) += gpio.o | 7 | obj-$(CONFIG_GENERIC_GPIO) += gpio.o |
diff --git a/arch/arm/plat-pxa/include/plat/mfp.h b/arch/arm/plat-pxa/include/plat/mfp.h new file mode 100644 index 000000000000..a22229cde096 --- /dev/null +++ b/arch/arm/plat-pxa/include/plat/mfp.h | |||
| @@ -0,0 +1,369 @@ | |||
| 1 | /* | ||
| 2 | * arch/arm/plat-pxa/include/plat/mfp.h | ||
| 3 | * | ||
| 4 | * Common Multi-Function Pin Definitions | ||
| 5 | * | ||
| 6 | * Copyright (C) 2007 Marvell International Ltd. | ||
| 7 | * | ||
| 8 | * 2007-8-21: eric miao <eric.miao@marvell.com> | ||
| 9 | * initial version | ||
| 10 | * | ||
| 11 | * This program is free software; you can redistribute it and/or modify | ||
| 12 | * it under the terms of the GNU General Public License version 2 as | ||
| 13 | * published by the Free Software Foundation. | ||
| 14 | */ | ||
| 15 | |||
| 16 | #ifndef __ASM_PLAT_MFP_H | ||
| 17 | #define __ASM_PLAT_MFP_H | ||
| 18 | |||
| 19 | #define mfp_to_gpio(m) ((m) % 128) | ||
| 20 | |||
| 21 | /* list of all the configurable MFP pins */ | ||
| 22 | enum { | ||
| 23 | MFP_PIN_INVALID = -1, | ||
| 24 | |||
| 25 | MFP_PIN_GPIO0 = 0, | ||
| 26 | MFP_PIN_GPIO1, | ||
| 27 | MFP_PIN_GPIO2, | ||
| 28 | MFP_PIN_GPIO3, | ||
| 29 | MFP_PIN_GPIO4, | ||
| 30 | MFP_PIN_GPIO5, | ||
| 31 | MFP_PIN_GPIO6, | ||
| 32 | MFP_PIN_GPIO7, | ||
| 33 | MFP_PIN_GPIO8, | ||
| 34 | MFP_PIN_GPIO9, | ||
| 35 | MFP_PIN_GPIO10, | ||
| 36 | MFP_PIN_GPIO11, | ||
| 37 | MFP_PIN_GPIO12, | ||
| 38 | MFP_PIN_GPIO13, | ||
| 39 | MFP_PIN_GPIO14, | ||
| 40 | MFP_PIN_GPIO15, | ||
| 41 | MFP_PIN_GPIO16, | ||
| 42 | MFP_PIN_GPIO17, | ||
| 43 | MFP_PIN_GPIO18, | ||
| 44 | MFP_PIN_GPIO19, | ||
| 45 | MFP_PIN_GPIO20, | ||
| 46 | MFP_PIN_GPIO21, | ||
| 47 | MFP_PIN_GPIO22, | ||
| 48 | MFP_PIN_GPIO23, | ||
| 49 | MFP_PIN_GPIO24, | ||
| 50 | MFP_PIN_GPIO25, | ||
| 51 | MFP_PIN_GPIO26, | ||
| 52 | MFP_PIN_GPIO27, | ||
| 53 | MFP_PIN_GPIO28, | ||
| 54 | MFP_PIN_GPIO29, | ||
| 55 | MFP_PIN_GPIO30, | ||
| 56 | MFP_PIN_GPIO31, | ||
| 57 | MFP_PIN_GPIO32, | ||
| 58 | MFP_PIN_GPIO33, | ||
| 59 | MFP_PIN_GPIO34, | ||
| 60 | MFP_PIN_GPIO35, | ||
| 61 | MFP_PIN_GPIO36, | ||
| 62 | MFP_PIN_GPIO37, | ||
| 63 | MFP_PIN_GPIO38, | ||
| 64 | MFP_PIN_GPIO39, | ||
| 65 | MFP_PIN_GPIO40, | ||
| 66 | MFP_PIN_GPIO41, | ||
| 67 | MFP_PIN_GPIO42, | ||
| 68 | MFP_PIN_GPIO43, | ||
| 69 | MFP_PIN_GPIO44, | ||
| 70 | MFP_PIN_GPIO45, | ||
| 71 | MFP_PIN_GPIO46, | ||
| 72 | MFP_PIN_GPIO47, | ||
| 73 | MFP_PIN_GPIO48, | ||
| 74 | MFP_PIN_GPIO49, | ||
| 75 | MFP_PIN_GPIO50, | ||
| 76 | MFP_PIN_GPIO51, | ||
| 77 | MFP_PIN_GPIO52, | ||
| 78 | MFP_PIN_GPIO53, | ||
| 79 | MFP_PIN_GPIO54, | ||
| 80 | MFP_PIN_GPIO55, | ||
| 81 | MFP_PIN_GPIO56, | ||
| 82 | MFP_PIN_GPIO57, | ||
| 83 | MFP_PIN_GPIO58, | ||
| 84 | MFP_PIN_GPIO59, | ||
| 85 | MFP_PIN_GPIO60, | ||
| 86 | MFP_PIN_GPIO61, | ||
| 87 | MFP_PIN_GPIO62, | ||
| 88 | MFP_PIN_GPIO63, | ||
| 89 | MFP_PIN_GPIO64, | ||
| 90 | MFP_PIN_GPIO65, | ||
| 91 | MFP_PIN_GPIO66, | ||
| 92 | MFP_PIN_GPIO67, | ||
| 93 | MFP_PIN_GPIO68, | ||
| 94 | MFP_PIN_GPIO69, | ||
| 95 | MFP_PIN_GPIO70, | ||
| 96 | MFP_PIN_GPIO71, | ||
| 97 | MFP_PIN_GPIO72, | ||
| 98 | MFP_PIN_GPIO73, | ||
| 99 | MFP_PIN_GPIO74, | ||
| 100 | MFP_PIN_GPIO75, | ||
| 101 | MFP_PIN_GPIO76, | ||
| 102 | MFP_PIN_GPIO77, | ||
| 103 | MFP_PIN_GPIO78, | ||
| 104 | MFP_PIN_GPIO79, | ||
| 105 | MFP_PIN_GPIO80, | ||
| 106 | MFP_PIN_GPIO81, | ||
| 107 | MFP_PIN_GPIO82, | ||
| 108 | MFP_PIN_GPIO83, | ||
| 109 | MFP_PIN_GPIO84, | ||
| 110 | MFP_PIN_GPIO85, | ||
| 111 | MFP_PIN_GPIO86, | ||
| 112 | MFP_PIN_GPIO87, | ||
| 113 | MFP_PIN_GPIO88, | ||
| 114 | MFP_PIN_GPIO89, | ||
| 115 | MFP_PIN_GPIO90, | ||
| 116 | MFP_PIN_GPIO91, | ||
| 117 | MFP_PIN_GPIO92, | ||
| 118 | MFP_PIN_GPIO93, | ||
| 119 | MFP_PIN_GPIO94, | ||
| 120 | MFP_PIN_GPIO95, | ||
| 121 | MFP_PIN_GPIO96, | ||
| 122 | MFP_PIN_GPIO97, | ||
| 123 | MFP_PIN_GPIO98, | ||
| 124 | MFP_PIN_GPIO99, | ||
| 125 | MFP_PIN_GPIO100, | ||
| 126 | MFP_PIN_GPIO101, | ||
| 127 | MFP_PIN_GPIO102, | ||
| 128 | MFP_PIN_GPIO103, | ||
| 129 | MFP_PIN_GPIO104, | ||
| 130 | MFP_PIN_GPIO105, | ||
| 131 | MFP_PIN_GPIO106, | ||
| 132 | MFP_PIN_GPIO107, | ||
| 133 | MFP_PIN_GPIO108, | ||
| 134 | MFP_PIN_GPIO109, | ||
| 135 | MFP_PIN_GPIO110, | ||
| 136 | MFP_PIN_GPIO111, | ||
| 137 | MFP_PIN_GPIO112, | ||
| 138 | MFP_PIN_GPIO113, | ||
| 139 | MFP_PIN_GPIO114, | ||
| 140 | MFP_PIN_GPIO115, | ||
| 141 | MFP_PIN_GPIO116, | ||
| 142 | MFP_PIN_GPIO117, | ||
| 143 | MFP_PIN_GPIO118, | ||
| 144 | MFP_PIN_GPIO119, | ||
| 145 | MFP_PIN_GPIO120, | ||
| 146 | MFP_PIN_GPIO121, | ||
| 147 | MFP_PIN_GPIO122, | ||
| 148 | MFP_PIN_GPIO123, | ||
| 149 | MFP_PIN_GPIO124, | ||
| 150 | MFP_PIN_GPIO125, | ||
| 151 | MFP_PIN_GPIO126, | ||
| 152 | MFP_PIN_GPIO127, | ||
| 153 | MFP_PIN_GPIO0_2, | ||
| 154 | MFP_PIN_GPIO1_2, | ||
| 155 | MFP_PIN_GPIO2_2, | ||
| 156 | MFP_PIN_GPIO3_2, | ||
| 157 | MFP_PIN_GPIO4_2, | ||
| 158 | MFP_PIN_GPIO5_2, | ||
| 159 | MFP_PIN_GPIO6_2, | ||
| 160 | MFP_PIN_GPIO7_2, | ||
| 161 | MFP_PIN_GPIO8_2, | ||
| 162 | MFP_PIN_GPIO9_2, | ||
| 163 | MFP_PIN_GPIO10_2, | ||
| 164 | MFP_PIN_GPIO11_2, | ||
| 165 | MFP_PIN_GPIO12_2, | ||
| 166 | MFP_PIN_GPIO13_2, | ||
| 167 | MFP_PIN_GPIO14_2, | ||
| 168 | MFP_PIN_GPIO15_2, | ||
| 169 | MFP_PIN_GPIO16_2, | ||
| 170 | MFP_PIN_GPIO17_2, | ||
| 171 | |||
| 172 | MFP_PIN_ULPI_STP, | ||
| 173 | MFP_PIN_ULPI_NXT, | ||
| 174 | MFP_PIN_ULPI_DIR, | ||
| 175 | |||
| 176 | MFP_PIN_nXCVREN, | ||
| 177 | MFP_PIN_DF_CLE_nOE, | ||
| 178 | MFP_PIN_DF_nADV1_ALE, | ||
| 179 | MFP_PIN_DF_SCLK_E, | ||
| 180 | MFP_PIN_DF_SCLK_S, | ||
| 181 | MFP_PIN_nBE0, | ||
| 182 | MFP_PIN_nBE1, | ||
| 183 | MFP_PIN_DF_nADV2_ALE, | ||
| 184 | MFP_PIN_DF_INT_RnB, | ||
| 185 | MFP_PIN_DF_nCS0, | ||
| 186 | MFP_PIN_DF_nCS1, | ||
| 187 | MFP_PIN_nLUA, | ||
| 188 | MFP_PIN_nLLA, | ||
| 189 | MFP_PIN_DF_nWE, | ||
| 190 | MFP_PIN_DF_ALE_nWE, | ||
| 191 | MFP_PIN_DF_nRE_nOE, | ||
| 192 | MFP_PIN_DF_ADDR0, | ||
| 193 | MFP_PIN_DF_ADDR1, | ||
| 194 | MFP_PIN_DF_ADDR2, | ||
| 195 | MFP_PIN_DF_ADDR3, | ||
| 196 | MFP_PIN_DF_IO0, | ||
| 197 | MFP_PIN_DF_IO1, | ||
| 198 | MFP_PIN_DF_IO2, | ||
| 199 | MFP_PIN_DF_IO3, | ||
| 200 | MFP_PIN_DF_IO4, | ||
| 201 | MFP_PIN_DF_IO5, | ||
| 202 | MFP_PIN_DF_IO6, | ||
| 203 | MFP_PIN_DF_IO7, | ||
| 204 | MFP_PIN_DF_IO8, | ||
| 205 | MFP_PIN_DF_IO9, | ||
| 206 | MFP_PIN_DF_IO10, | ||
| 207 | MFP_PIN_DF_IO11, | ||
| 208 | MFP_PIN_DF_IO12, | ||
| 209 | MFP_PIN_DF_IO13, | ||
| 210 | MFP_PIN_DF_IO14, | ||
| 211 | MFP_PIN_DF_IO15, | ||
| 212 | |||
| 213 | /* additional pins on PXA930 */ | ||
| 214 | MFP_PIN_GSIM_UIO, | ||
| 215 | MFP_PIN_GSIM_UCLK, | ||
| 216 | MFP_PIN_GSIM_UDET, | ||
| 217 | MFP_PIN_GSIM_nURST, | ||
| 218 | MFP_PIN_PMIC_INT, | ||
| 219 | MFP_PIN_RDY, | ||
| 220 | |||
| 221 | MFP_PIN_MAX, | ||
| 222 | }; | ||
| 223 | |||
| 224 | /* | ||
| 225 | * a possible MFP configuration is represented by a 32-bit integer | ||
| 226 | * | ||
| 227 | * bit 0.. 9 - MFP Pin Number (1024 Pins Maximum) | ||
| 228 | * bit 10..12 - Alternate Function Selection | ||
| 229 | * bit 13..15 - Drive Strength | ||
| 230 | * bit 16..18 - Low Power Mode State | ||
| 231 | * bit 19..20 - Low Power Mode Edge Detection | ||
| 232 | * bit 21..22 - Run Mode Pull State | ||
| 233 | * | ||
| 234 | * to facilitate the definition, the following macros are provided | ||
| 235 | * | ||
| 236 | * MFP_CFG_DEFAULT - default MFP configuration value, with | ||
| 237 | * alternate function = 0, | ||
| 238 | * drive strength = fast 3mA (MFP_DS03X) | ||
| 239 | * low power mode = default | ||
| 240 | * edge detection = none | ||
| 241 | * | ||
| 242 | * MFP_CFG - default MFPR value with alternate function | ||
| 243 | * MFP_CFG_DRV - default MFPR value with alternate function and | ||
| 244 | * pin drive strength | ||
| 245 | * MFP_CFG_LPM - default MFPR value with alternate function and | ||
| 246 | * low power mode | ||
| 247 | * MFP_CFG_X - default MFPR value with alternate function, | ||
| 248 | * pin drive strength and low power mode | ||
| 249 | */ | ||
| 250 | |||
| 251 | typedef unsigned long mfp_cfg_t; | ||
| 252 | |||
| 253 | #define MFP_PIN(x) ((x) & 0x3ff) | ||
| 254 | |||
| 255 | #define MFP_AF0 (0x0 << 10) | ||
| 256 | #define MFP_AF1 (0x1 << 10) | ||
| 257 | #define MFP_AF2 (0x2 << 10) | ||
| 258 | #define MFP_AF3 (0x3 << 10) | ||
| 259 | #define MFP_AF4 (0x4 << 10) | ||
| 260 | #define MFP_AF5 (0x5 << 10) | ||
| 261 | #define MFP_AF6 (0x6 << 10) | ||
| 262 | #define MFP_AF7 (0x7 << 10) | ||
| 263 | #define MFP_AF_MASK (0x7 << 10) | ||
| 264 | #define MFP_AF(x) (((x) >> 10) & 0x7) | ||
| 265 | |||
| 266 | #define MFP_DS01X (0x0 << 13) | ||
| 267 | #define MFP_DS02X (0x1 << 13) | ||
| 268 | #define MFP_DS03X (0x2 << 13) | ||
| 269 | #define MFP_DS04X (0x3 << 13) | ||
| 270 | #define MFP_DS06X (0x4 << 13) | ||
| 271 | #define MFP_DS08X (0x5 << 13) | ||
| 272 | #define MFP_DS10X (0x6 << 13) | ||
| 273 | #define MFP_DS13X (0x7 << 13) | ||
| 274 | #define MFP_DS_MASK (0x7 << 13) | ||
| 275 | #define MFP_DS(x) (((x) >> 13) & 0x7) | ||
| 276 | |||
| 277 | #define MFP_LPM_DEFAULT (0x0 << 16) | ||
| 278 | #define MFP_LPM_DRIVE_LOW (0x1 << 16) | ||
| 279 | #define MFP_LPM_DRIVE_HIGH (0x2 << 16) | ||
| 280 | #define MFP_LPM_PULL_LOW (0x3 << 16) | ||
| 281 | #define MFP_LPM_PULL_HIGH (0x4 << 16) | ||
| 282 | #define MFP_LPM_FLOAT (0x5 << 16) | ||
| 283 | #define MFP_LPM_INPUT (0x6 << 16) | ||
| 284 | #define MFP_LPM_STATE_MASK (0x7 << 16) | ||
| 285 | #define MFP_LPM_STATE(x) (((x) >> 16) & 0x7) | ||
| 286 | |||
| 287 | #define MFP_LPM_EDGE_NONE (0x0 << 19) | ||
| 288 | #define MFP_LPM_EDGE_RISE (0x1 << 19) | ||
| 289 | #define MFP_LPM_EDGE_FALL (0x2 << 19) | ||
| 290 | #define MFP_LPM_EDGE_BOTH (0x3 << 19) | ||
| 291 | #define MFP_LPM_EDGE_MASK (0x3 << 19) | ||
| 292 | #define MFP_LPM_EDGE(x) (((x) >> 19) & 0x3) | ||
| 293 | |||
| 294 | #define MFP_PULL_NONE (0x0 << 21) | ||
| 295 | #define MFP_PULL_LOW (0x1 << 21) | ||
| 296 | #define MFP_PULL_HIGH (0x2 << 21) | ||
| 297 | #define MFP_PULL_BOTH (0x3 << 21) | ||
| 298 | #define MFP_PULL_MASK (0x3 << 21) | ||
| 299 | #define MFP_PULL(x) (((x) >> 21) & 0x3) | ||
| 300 | |||
| 301 | #define MFP_CFG_DEFAULT (MFP_AF0 | MFP_DS03X | MFP_LPM_DEFAULT |\ | ||
| 302 | MFP_LPM_EDGE_NONE | MFP_PULL_NONE) | ||
| 303 | |||
| 304 | #define MFP_CFG(pin, af) \ | ||
| 305 | ((MFP_CFG_DEFAULT & ~MFP_AF_MASK) |\ | ||
| 306 | (MFP_PIN(MFP_PIN_##pin) | MFP_##af)) | ||
| 307 | |||
| 308 | #define MFP_CFG_DRV(pin, af, drv) \ | ||
| 309 | ((MFP_CFG_DEFAULT & ~(MFP_AF_MASK | MFP_DS_MASK)) |\ | ||
| 310 | (MFP_PIN(MFP_PIN_##pin) | MFP_##af | MFP_##drv)) | ||
| 311 | |||
| 312 | #define MFP_CFG_LPM(pin, af, lpm) \ | ||
| 313 | ((MFP_CFG_DEFAULT & ~(MFP_AF_MASK | MFP_LPM_STATE_MASK)) |\ | ||
| 314 | (MFP_PIN(MFP_PIN_##pin) | MFP_##af | MFP_LPM_##lpm)) | ||
| 315 | |||
| 316 | #define MFP_CFG_X(pin, af, drv, lpm) \ | ||
| 317 | ((MFP_CFG_DEFAULT & ~(MFP_AF_MASK | MFP_DS_MASK | MFP_LPM_STATE_MASK)) |\ | ||
| 318 | (MFP_PIN(MFP_PIN_##pin) | MFP_##af | MFP_##drv | MFP_LPM_##lpm)) | ||
| 319 | |||
| 320 | #if defined(CONFIG_PXA3xx) || defined(CONFIG_ARCH_MMP) | ||
| 321 | /* | ||
| 322 | * each MFP pin will have a MFPR register, since the offset of the | ||
| 323 | * register varies between processors, the processor specific code | ||
| 324 | * should initialize the pin offsets by mfp_init() | ||
| 325 | * | ||
| 326 | * mfp_init_base() - accepts a virtual base for all MFPR registers and | ||
| 327 | * initialize the MFP table to a default state | ||
| 328 | * | ||
| 329 | * mfp_init_addr() - accepts a table of "mfp_addr_map" structure, which | ||
| 330 | * represents a range of MFP pins from "start" to "end", with the offset | ||
| 331 | * begining at "offset", to define a single pin, let "end" = -1. | ||
| 332 | * | ||
| 333 | * use | ||
| 334 | * | ||
| 335 | * MFP_ADDR_X() to define a range of pins | ||
| 336 | * MFP_ADDR() to define a single pin | ||
| 337 | * MFP_ADDR_END to signal the end of pin offset definitions | ||
| 338 | */ | ||
| 339 | struct mfp_addr_map { | ||
| 340 | unsigned int start; | ||
| 341 | unsigned int end; | ||
| 342 | unsigned long offset; | ||
| 343 | }; | ||
| 344 | |||
| 345 | #define MFP_ADDR_X(start, end, offset) \ | ||
| 346 | { MFP_PIN_##start, MFP_PIN_##end, offset } | ||
| 347 | |||
| 348 | #define MFP_ADDR(pin, offset) \ | ||
| 349 | { MFP_PIN_##pin, -1, offset } | ||
| 350 | |||
| 351 | #define MFP_ADDR_END { MFP_PIN_INVALID, 0 } | ||
| 352 | |||
| 353 | void __init mfp_init_base(unsigned long mfpr_base); | ||
| 354 | void __init mfp_init_addr(struct mfp_addr_map *map); | ||
| 355 | |||
| 356 | /* | ||
| 357 | * mfp_{read, write}() - for direct read/write access to the MFPR register | ||
| 358 | * mfp_config() - for configuring a group of MFPR registers | ||
| 359 | * mfp_config_lpm() - configuring all low power MFPR registers for suspend | ||
| 360 | * mfp_config_run() - configuring all run time MFPR registers after resume | ||
| 361 | */ | ||
| 362 | unsigned long mfp_read(int mfp); | ||
| 363 | void mfp_write(int mfp, unsigned long mfpr_val); | ||
| 364 | void mfp_config(unsigned long *mfp_cfgs, int num); | ||
| 365 | void mfp_config_run(void); | ||
| 366 | void mfp_config_lpm(void); | ||
| 367 | #endif /* CONFIG_PXA3xx || CONFIG_ARCH_MMP */ | ||
| 368 | |||
| 369 | #endif /* __ASM_PLAT_MFP_H */ | ||
diff --git a/arch/arm/plat-pxa/mfp.c b/arch/arm/plat-pxa/mfp.c new file mode 100644 index 000000000000..e716c622a17c --- /dev/null +++ b/arch/arm/plat-pxa/mfp.c | |||
| @@ -0,0 +1,278 @@ | |||
| 1 | /* | ||
| 2 | * linux/arch/arm/plat-pxa/mfp.c | ||
| 3 | * | ||
| 4 | * Multi-Function Pin Support | ||
| 5 | * | ||
| 6 | * Copyright (C) 2007 Marvell Internation Ltd. | ||
| 7 | * | ||
| 8 | * 2007-08-21: eric miao <eric.miao@marvell.com> | ||
| 9 | * initial version | ||
| 10 | * | ||
| 11 | * This program is free software; you can redistribute it and/or modify | ||
| 12 | * it under the terms of the GNU General Public License version 2 as | ||
| 13 | * published by the Free Software Foundation. | ||
| 14 | */ | ||
| 15 | |||
| 16 | #include <linux/module.h> | ||
| 17 | #include <linux/kernel.h> | ||
| 18 | #include <linux/init.h> | ||
| 19 | #include <linux/io.h> | ||
| 20 | #include <linux/sysdev.h> | ||
| 21 | |||
| 22 | #include <plat/mfp.h> | ||
| 23 | |||
| 24 | #define MFPR_SIZE (PAGE_SIZE) | ||
| 25 | |||
| 26 | /* MFPR register bit definitions */ | ||
| 27 | #define MFPR_PULL_SEL (0x1 << 15) | ||
| 28 | #define MFPR_PULLUP_EN (0x1 << 14) | ||
| 29 | #define MFPR_PULLDOWN_EN (0x1 << 13) | ||
| 30 | #define MFPR_SLEEP_SEL (0x1 << 9) | ||
| 31 | #define MFPR_SLEEP_OE_N (0x1 << 7) | ||
| 32 | #define MFPR_EDGE_CLEAR (0x1 << 6) | ||
| 33 | #define MFPR_EDGE_FALL_EN (0x1 << 5) | ||
| 34 | #define MFPR_EDGE_RISE_EN (0x1 << 4) | ||
| 35 | |||
| 36 | #define MFPR_SLEEP_DATA(x) ((x) << 8) | ||
| 37 | #define MFPR_DRIVE(x) (((x) & 0x7) << 10) | ||
| 38 | #define MFPR_AF_SEL(x) (((x) & 0x7) << 0) | ||
| 39 | |||
| 40 | #define MFPR_EDGE_NONE (0) | ||
| 41 | #define MFPR_EDGE_RISE (MFPR_EDGE_RISE_EN) | ||
| 42 | #define MFPR_EDGE_FALL (MFPR_EDGE_FALL_EN) | ||
| 43 | #define MFPR_EDGE_BOTH (MFPR_EDGE_RISE | MFPR_EDGE_FALL) | ||
| 44 | |||
| 45 | /* | ||
| 46 | * Table that determines the low power modes outputs, with actual settings | ||
| 47 | * used in parentheses for don't-care values. Except for the float output, | ||
| 48 | * the configured driven and pulled levels match, so if there is a need for | ||
| 49 | * non-LPM pulled output, the same configuration could probably be used. | ||
| 50 | * | ||
| 51 | * Output value sleep_oe_n sleep_data pullup_en pulldown_en pull_sel | ||
| 52 | * (bit 7) (bit 8) (bit 14) (bit 13) (bit 15) | ||
| 53 | * | ||
| 54 | * Input 0 X(0) X(0) X(0) 0 | ||
| 55 | * Drive 0 0 0 0 X(1) 0 | ||
| 56 | * Drive 1 0 1 X(1) 0 0 | ||
| 57 | * Pull hi (1) 1 X(1) 1 0 0 | ||
| 58 | * Pull lo (0) 1 X(0) 0 1 0 | ||
| 59 | * Z (float) 1 X(0) 0 0 0 | ||
| 60 | */ | ||
| 61 | #define MFPR_LPM_INPUT (0) | ||
| 62 | #define MFPR_LPM_DRIVE_LOW (MFPR_SLEEP_DATA(0) | MFPR_PULLDOWN_EN) | ||
| 63 | #define MFPR_LPM_DRIVE_HIGH (MFPR_SLEEP_DATA(1) | MFPR_PULLUP_EN) | ||
| 64 | #define MFPR_LPM_PULL_LOW (MFPR_LPM_DRIVE_LOW | MFPR_SLEEP_OE_N) | ||
| 65 | #define MFPR_LPM_PULL_HIGH (MFPR_LPM_DRIVE_HIGH | MFPR_SLEEP_OE_N) | ||
| 66 | #define MFPR_LPM_FLOAT (MFPR_SLEEP_OE_N) | ||
| 67 | #define MFPR_LPM_MASK (0xe080) | ||
| 68 | |||
| 69 | /* | ||
| 70 | * The pullup and pulldown state of the MFP pin at run mode is by default | ||
| 71 | * determined by the selected alternate function. In case that some buggy | ||
| 72 | * devices need to override this default behavior, the definitions below | ||
| 73 | * indicates the setting of corresponding MFPR bits | ||
| 74 | * | ||
| 75 | * Definition pull_sel pullup_en pulldown_en | ||
| 76 | * MFPR_PULL_NONE 0 0 0 | ||
| 77 | * MFPR_PULL_LOW 1 0 1 | ||
| 78 | * MFPR_PULL_HIGH 1 1 0 | ||
| 79 | * MFPR_PULL_BOTH 1 1 1 | ||
| 80 | */ | ||
| 81 | #define MFPR_PULL_NONE (0) | ||
| 82 | #define MFPR_PULL_LOW (MFPR_PULL_SEL | MFPR_PULLDOWN_EN) | ||
| 83 | #define MFPR_PULL_BOTH (MFPR_PULL_LOW | MFPR_PULLUP_EN) | ||
| 84 | #define MFPR_PULL_HIGH (MFPR_PULL_SEL | MFPR_PULLUP_EN) | ||
| 85 | |||
| 86 | /* mfp_spin_lock is used to ensure that MFP register configuration | ||
| 87 | * (most likely a read-modify-write operation) is atomic, and that | ||
| 88 | * mfp_table[] is consistent | ||
| 89 | */ | ||
| 90 | static DEFINE_SPINLOCK(mfp_spin_lock); | ||
| 91 | |||
| 92 | static void __iomem *mfpr_mmio_base; | ||
| 93 | |||
| 94 | struct mfp_pin { | ||
| 95 | unsigned long config; /* -1 for not configured */ | ||
| 96 | unsigned long mfpr_off; /* MFPRxx Register offset */ | ||
| 97 | unsigned long mfpr_run; /* Run-Mode Register Value */ | ||
| 98 | unsigned long mfpr_lpm; /* Low Power Mode Register Value */ | ||
| 99 | }; | ||
| 100 | |||
| 101 | static struct mfp_pin mfp_table[MFP_PIN_MAX]; | ||
| 102 | |||
| 103 | /* mapping of MFP_LPM_* definitions to MFPR_LPM_* register bits */ | ||
| 104 | static const unsigned long mfpr_lpm[] = { | ||
| 105 | MFPR_LPM_INPUT, | ||
| 106 | MFPR_LPM_DRIVE_LOW, | ||
| 107 | MFPR_LPM_DRIVE_HIGH, | ||
| 108 | MFPR_LPM_PULL_LOW, | ||
| 109 | MFPR_LPM_PULL_HIGH, | ||
| 110 | MFPR_LPM_FLOAT, | ||
| 111 | }; | ||
| 112 | |||
| 113 | /* mapping of MFP_PULL_* definitions to MFPR_PULL_* register bits */ | ||
| 114 | static const unsigned long mfpr_pull[] = { | ||
| 115 | MFPR_PULL_NONE, | ||
| 116 | MFPR_PULL_LOW, | ||
| 117 | MFPR_PULL_HIGH, | ||
| 118 | MFPR_PULL_BOTH, | ||
| 119 | }; | ||
| 120 | |||
| 121 | /* mapping of MFP_LPM_EDGE_* definitions to MFPR_EDGE_* register bits */ | ||
| 122 | static const unsigned long mfpr_edge[] = { | ||
| 123 | MFPR_EDGE_NONE, | ||
| 124 | MFPR_EDGE_RISE, | ||
| 125 | MFPR_EDGE_FALL, | ||
| 126 | MFPR_EDGE_BOTH, | ||
| 127 | }; | ||
| 128 | |||
| 129 | #define mfpr_readl(off) \ | ||
| 130 | __raw_readl(mfpr_mmio_base + (off)) | ||
| 131 | |||
| 132 | #define mfpr_writel(off, val) \ | ||
| 133 | __raw_writel(val, mfpr_mmio_base + (off)) | ||
| 134 | |||
| 135 | #define mfp_configured(p) ((p)->config != -1) | ||
| 136 | |||
| 137 | /* | ||
| 138 | * perform a read-back of any MFPR register to make sure the | ||
| 139 | * previous writings are finished | ||
| 140 | */ | ||
| 141 | #define mfpr_sync() (void)__raw_readl(mfpr_mmio_base + 0) | ||
| 142 | |||
| 143 | static inline void __mfp_config_run(struct mfp_pin *p) | ||
| 144 | { | ||
| 145 | if (mfp_configured(p)) | ||
| 146 | mfpr_writel(p->mfpr_off, p->mfpr_run); | ||
| 147 | } | ||
| 148 | |||
| 149 | static inline void __mfp_config_lpm(struct mfp_pin *p) | ||
| 150 | { | ||
| 151 | if (mfp_configured(p)) { | ||
| 152 | unsigned long mfpr_clr = (p->mfpr_run & ~MFPR_EDGE_BOTH) | MFPR_EDGE_CLEAR; | ||
| 153 | if (mfpr_clr != p->mfpr_run) | ||
| 154 | mfpr_writel(p->mfpr_off, mfpr_clr); | ||
| 155 | if (p->mfpr_lpm != mfpr_clr) | ||
| 156 | mfpr_writel(p->mfpr_off, p->mfpr_lpm); | ||
| 157 | } | ||
| 158 | } | ||
| 159 | |||
| 160 | void mfp_config(unsigned long *mfp_cfgs, int num) | ||
| 161 | { | ||
| 162 | unsigned long flags; | ||
| 163 | int i; | ||
| 164 | |||
| 165 | spin_lock_irqsave(&mfp_spin_lock, flags); | ||
| 166 | |||
| 167 | for (i = 0; i < num; i++, mfp_cfgs++) { | ||
| 168 | unsigned long tmp, c = *mfp_cfgs; | ||
| 169 | struct mfp_pin *p; | ||
| 170 | int pin, af, drv, lpm, edge, pull; | ||
| 171 | |||
| 172 | pin = MFP_PIN(c); | ||
| 173 | BUG_ON(pin >= MFP_PIN_MAX); | ||
| 174 | p = &mfp_table[pin]; | ||
| 175 | |||
| 176 | af = MFP_AF(c); | ||
| 177 | drv = MFP_DS(c); | ||
| 178 | lpm = MFP_LPM_STATE(c); | ||
| 179 | edge = MFP_LPM_EDGE(c); | ||
| 180 | pull = MFP_PULL(c); | ||
| 181 | |||
| 182 | /* run-mode pull settings will conflict with MFPR bits of | ||
| 183 | * low power mode state, calculate mfpr_run and mfpr_lpm | ||
| 184 | * individually if pull != MFP_PULL_NONE | ||
| 185 | */ | ||
| 186 | tmp = MFPR_AF_SEL(af) | MFPR_DRIVE(drv); | ||
| 187 | |||
| 188 | if (likely(pull == MFP_PULL_NONE)) { | ||
| 189 | p->mfpr_run = tmp | mfpr_lpm[lpm] | mfpr_edge[edge]; | ||
| 190 | p->mfpr_lpm = p->mfpr_run; | ||
| 191 | } else { | ||
| 192 | p->mfpr_lpm = tmp | mfpr_lpm[lpm] | mfpr_edge[edge]; | ||
| 193 | p->mfpr_run = tmp | mfpr_pull[pull]; | ||
| 194 | } | ||
| 195 | |||
| 196 | p->config = c; __mfp_config_run(p); | ||
| 197 | } | ||
| 198 | |||
| 199 | mfpr_sync(); | ||
| 200 | spin_unlock_irqrestore(&mfp_spin_lock, flags); | ||
| 201 | } | ||
| 202 | |||
| 203 | unsigned long mfp_read(int mfp) | ||
| 204 | { | ||
| 205 | unsigned long val, flags; | ||
| 206 | |||
| 207 | BUG_ON(mfp >= MFP_PIN_MAX); | ||
| 208 | |||
| 209 | spin_lock_irqsave(&mfp_spin_lock, flags); | ||
| 210 | val = mfpr_readl(mfp_table[mfp].mfpr_off); | ||
| 211 | spin_unlock_irqrestore(&mfp_spin_lock, flags); | ||
| 212 | |||
| 213 | return val; | ||
| 214 | } | ||
| 215 | |||
| 216 | void mfp_write(int mfp, unsigned long val) | ||
| 217 | { | ||
| 218 | unsigned long flags; | ||
| 219 | |||
| 220 | BUG_ON(mfp >= MFP_PIN_MAX); | ||
| 221 | |||
| 222 | spin_lock_irqsave(&mfp_spin_lock, flags); | ||
| 223 | mfpr_writel(mfp_table[mfp].mfpr_off, val); | ||
| 224 | mfpr_sync(); | ||
| 225 | spin_unlock_irqrestore(&mfp_spin_lock, flags); | ||
| 226 | } | ||
| 227 | |||
| 228 | void __init mfp_init_base(unsigned long mfpr_base) | ||
| 229 | { | ||
| 230 | int i; | ||
| 231 | |||
| 232 | /* initialize the table with default - unconfigured */ | ||
| 233 | for (i = 0; i < ARRAY_SIZE(mfp_table); i++) | ||
| 234 | mfp_table[i].config = -1; | ||
| 235 | |||
| 236 | mfpr_mmio_base = (void __iomem *)mfpr_base; | ||
| 237 | } | ||
| 238 | |||
| 239 | void __init mfp_init_addr(struct mfp_addr_map *map) | ||
| 240 | { | ||
| 241 | struct mfp_addr_map *p; | ||
| 242 | unsigned long offset, flags; | ||
| 243 | int i; | ||
| 244 | |||
| 245 | spin_lock_irqsave(&mfp_spin_lock, flags); | ||
| 246 | |||
| 247 | for (p = map; p->start != MFP_PIN_INVALID; p++) { | ||
| 248 | offset = p->offset; | ||
| 249 | i = p->start; | ||
| 250 | |||
| 251 | do { | ||
| 252 | mfp_table[i].mfpr_off = offset; | ||
| 253 | mfp_table[i].mfpr_run = 0; | ||
| 254 | mfp_table[i].mfpr_lpm = 0; | ||
| 255 | offset += 4; i++; | ||
| 256 | } while ((i <= p->end) && (p->end != -1)); | ||
| 257 | } | ||
| 258 | |||
| 259 | spin_unlock_irqrestore(&mfp_spin_lock, flags); | ||
| 260 | } | ||
| 261 | |||
| 262 | void mfp_config_lpm(void) | ||
| 263 | { | ||
| 264 | struct mfp_pin *p = &mfp_table[0]; | ||
| 265 | int pin; | ||
| 266 | |||
| 267 | for (pin = 0; pin < ARRAY_SIZE(mfp_table); pin++, p++) | ||
| 268 | __mfp_config_lpm(p); | ||
| 269 | } | ||
| 270 | |||
| 271 | void mfp_config_run(void) | ||
| 272 | { | ||
| 273 | struct mfp_pin *p = &mfp_table[0]; | ||
| 274 | int pin; | ||
| 275 | |||
| 276 | for (pin = 0; pin < ARRAY_SIZE(mfp_table); pin++, p++) | ||
| 277 | __mfp_config_run(p); | ||
| 278 | } | ||
