int gpio_set_wake(unsigned int gpio, unsigned int on) { struct gpio_desc *d; unsigned long c, mux_taken; if (gpio > mfp_to_gpio(MFP_PIN_GPIO127)) return -EINVAL; d = &gpio_desc[gpio]; c = d->config; if (!d->valid) return -EINVAL; /* Allow keypad GPIOs to wakeup system when * configured as generic GPIOs. */ if (d->keypad_gpio && (MFP_AF(d->config) == 0) && (d->config & MFP_LPM_CAN_WAKEUP)) { if (on) PKWR |= d->mask; else PKWR &= ~d->mask; return 0; } mux_taken = (PWER & d->mux_mask) & (~d->mask); if (on && mux_taken) return -EBUSY; if (d->can_wakeup && (c & MFP_LPM_CAN_WAKEUP)) { if (on) { PWER = (PWER & ~d->mux_mask) | d->mask; if (c & MFP_LPM_EDGE_RISE) PRER |= d->mask; else PRER &= ~d->mask; if (c & MFP_LPM_EDGE_FALL) PFER |= d->mask; else PFER &= ~d->mask; } else { PWER &= ~d->mask; PRER &= ~d->mask; PFER &= ~d->mask; } } return 0; }
void mfp_config(unsigned long *mfp_cfgs, int num) { unsigned long flags; int i, drv_b11 = 0, no_lpm = 0; #ifdef CONFIG_ARCH_MMP if (cpu_is_pxa910() || cpu_is_pxa988() || cpu_is_pxa986() || cpu_is_mmp2() || cpu_is_mmp3() || cpu_is_pxa1088()) drv_b11 = 1; if (cpu_is_pxa168() || cpu_is_pxa910()) no_lpm = 1; #elif defined(CONFIG_ARCH_PXA) if (cpu_is_pxa95x()) drv_b11 = 1; #endif spin_lock_irqsave(&mfp_spin_lock, flags); for (i = 0; i < num; i++, mfp_cfgs++) { unsigned long tmp, c = *mfp_cfgs; struct mfp_pin *p; int pin, af, drv, lpm, edge, pull; pin = MFP_PIN(c); BUG_ON(pin >= MFP_PIN_MAX); p = &mfp_table[pin]; af = MFP_AF(c); drv = MFP_DS(c); lpm = MFP_LPM_STATE(c); edge = MFP_LPM_EDGE(c); pull = MFP_PULL(c); if (drv_b11) drv = drv << 1; if (no_lpm) lpm = 0; tmp = MFPR_AF_SEL(af) | MFPR_DRIVE(drv); tmp |= mfpr_pull[pull] | mfpr_lpm[lpm] | mfpr_edge[edge]; p->mfpr_run = tmp; p->mfpr_lpm = p->mfpr_run; p->config = c; __mfp_config_run(p); } mfpr_sync(); spin_unlock_irqrestore(&mfp_spin_lock, flags); }
void pxa3xx_mfp_config(unsigned long *mfp_cfgs, int num) { unsigned long flags; int i; spin_lock_irqsave(&mfp_spin_lock, flags); for (i = 0; i < num; i++, mfp_cfgs++) { unsigned long tmp, c = *mfp_cfgs; struct pxa3xx_mfp_pin *p; int pin, af, drv, lpm, edge, pull; pin = MFP_PIN(c); BUG_ON(pin >= MFP_PIN_MAX); p = &mfp_table[pin]; af = MFP_AF(c); drv = MFP_DS(c); lpm = MFP_LPM_STATE(c); edge = MFP_LPM_EDGE(c); pull = MFP_PULL(c); /* run-mode pull settings will conflict with MFPR bits of * low power mode state, calculate mfpr_run and mfpr_lpm * individually if pull != MFP_PULL_NONE */ tmp = MFPR_AF_SEL(af) | MFPR_DRIVE(drv); if (likely(pull == MFP_PULL_NONE)) { p->mfpr_run = tmp | mfpr_lpm[lpm] | mfpr_edge[edge]; p->mfpr_lpm = p->mfpr_run; } else { p->mfpr_lpm = tmp | mfpr_lpm[lpm] | mfpr_edge[edge]; p->mfpr_run = tmp | mfpr_pull[pull]; } p->config = c; __mfp_config_run(p); } mfpr_sync(); spin_unlock_irqrestore(&mfp_spin_lock, flags); }
static int __mfp_config_gpio(unsigned gpio, unsigned long c) { unsigned long gafr, mask = GPIO_bit(gpio); int fn; fn = MFP_AF(c); if (fn > 3) return -EINVAL; /* alternate function and direction */ gafr = GAFR(gpio) & ~(0x3 << ((gpio & 0xf) * 2)); GAFR(gpio) = gafr | (fn << ((gpio & 0xf) * 2)); if (c & MFP_DIR_OUT) GPDR(gpio) |= mask; else GPDR(gpio) &= ~mask; if (__mfp_config_lpm(gpio, c & MFP_LPM_STATE_MASK)) return -EINVAL; /* give early warning if MFP_LPM_CAN_WAKEUP is set on the * configurations of those pins not able to wakeup */ if ((c & MFP_LPM_CAN_WAKEUP) && !gpio_desc[gpio].can_wakeup) { pr_warning("%s: GPIO%d unable to wakeup\n", __func__, gpio); return -EINVAL; } if ((c & MFP_LPM_CAN_WAKEUP) && (c & MFP_DIR_OUT)) { pr_warning("%s: output GPIO%d unable to wakeup\n", __func__, gpio); return -EINVAL; } return 0; }
int keypad_set_wake(unsigned int on) { unsigned int i, gpio, mask = 0; struct gpio_desc *d; for (i = 0; i < ARRAY_SIZE(pxa27x_pkwr_gpio); i++) { gpio = pxa27x_pkwr_gpio[i]; d = &gpio_desc[gpio]; /* skip if configured as generic GPIO */ if (MFP_AF(d->config) == 0) continue; if (d->config & MFP_LPM_CAN_WAKEUP) mask |= gpio_desc[gpio].mask; } if (on) PKWR |= mask; else PKWR &= ~mask; return 0; }
static int __mfp_config_gpio(unsigned gpio, unsigned long c) { unsigned long gafr, mask = GPIO_bit(gpio); int bank = gpio_to_bank(gpio); int uorl = !!(gpio & 0x10); /* GAFRx_U or GAFRx_L ? */ int shft = (gpio & 0xf) << 1; int fn = MFP_AF(c); int is_out = (c & MFP_DIR_OUT) ? 1 : 0; if (fn > 3) return -EINVAL; /* alternate function and direction at run-time */ gafr = (uorl == 0) ? GAFR_L(bank) : GAFR_U(bank); gafr = (gafr & ~(0x3 << shft)) | (fn << shft); if (uorl == 0) GAFR_L(bank) = gafr; else GAFR_U(bank) = gafr; if (is_out ^ gpio_desc[gpio].dir_inverted) GPDR(gpio) |= mask; else GPDR(gpio) &= ~mask; /* alternate function and direction at low power mode */ switch (c & MFP_LPM_STATE_MASK) { case MFP_LPM_DRIVE_HIGH: PGSR(bank) |= mask; is_out = 1; break; case MFP_LPM_DRIVE_LOW: PGSR(bank) &= ~mask; is_out = 1; break; case MFP_LPM_INPUT: case MFP_LPM_DEFAULT: break; default: /* warning and fall through, treat as MFP_LPM_DEFAULT */ pr_warning("%s: GPIO%d: unsupported low power mode\n", __func__, gpio); break; } if (is_out ^ gpio_desc[gpio].dir_inverted) gpdr_lpm[bank] |= mask; else gpdr_lpm[bank] &= ~mask; /* give early warning if MFP_LPM_CAN_WAKEUP is set on the * configurations of those pins not able to wakeup */ if ((c & MFP_LPM_CAN_WAKEUP) && !gpio_desc[gpio].can_wakeup) { pr_warning("%s: GPIO%d unable to wakeup\n", __func__, gpio); return -EINVAL; } if ((c & MFP_LPM_CAN_WAKEUP) && is_out) { pr_warning("%s: output GPIO%d unable to wakeup\n", __func__, gpio); return -EINVAL; } return 0; }
static int __mfp_config_gpio(unsigned gpio, unsigned long c) { unsigned long gafr, mask = GPIO_bit(gpio); int bank = gpio_to_bank(gpio); int uorl = !!(gpio & 0x10); int shft = (gpio & 0xf) << 1; int fn = MFP_AF(c); int is_out = (c & MFP_DIR_OUT) ? 1 : 0; if (fn > 3) return -EINVAL; gafr = (uorl == 0) ? GAFR_L(bank) : GAFR_U(bank); gafr = (gafr & ~(0x3 << shft)) | (fn << shft); if (uorl == 0) GAFR_L(bank) = gafr; else GAFR_U(bank) = gafr; if (is_out ^ gpio_desc[gpio].dir_inverted) GPDR(gpio) |= mask; else GPDR(gpio) &= ~mask; switch (c & MFP_LPM_STATE_MASK) { case MFP_LPM_DRIVE_HIGH: PGSR(bank) |= mask; is_out = 1; break; case MFP_LPM_DRIVE_LOW: PGSR(bank) &= ~mask; is_out = 1; break; case MFP_LPM_INPUT: case MFP_LPM_DEFAULT: break; default: pr_warning("%s: GPIO%d: unsupported low power mode\n", __func__, gpio); break; } if (is_out ^ gpio_desc[gpio].dir_inverted) gpdr_lpm[bank] |= mask; else gpdr_lpm[bank] &= ~mask; if ((c & MFP_LPM_CAN_WAKEUP) && !gpio_desc[gpio].can_wakeup) { pr_warning("%s: GPIO%d unable to wakeup\n", __func__, gpio); return -EINVAL; } if ((c & MFP_LPM_CAN_WAKEUP) && is_out) { pr_warning("%s: output GPIO%d unable to wakeup\n", __func__, gpio); return -EINVAL; } return 0; }