/** * Get value of the specified gpio */ int gpio_get_value(unsigned gpio) { const struct gpio_bank *bank; void *reg; int input; if (check_gpio(gpio) < 0) return -1; bank = get_gpio_bank(gpio); reg = bank->base; switch (bank->method) { case METHOD_GPIO_24XX: input = _get_gpio_direction(bank, get_gpio_index(gpio)); switch (input) { case OMAP_GPIO_DIR_IN: reg += OMAP_GPIO_DATAIN; break; case OMAP_GPIO_DIR_OUT: reg += OMAP_GPIO_DATAOUT; break; default: return -1; } break; default: return -1; } return (__raw_readl(reg) & (1 << get_gpio_index(gpio))) != 0; }
/** * Set gpio direction as output */ int gpio_direction_output(unsigned gpio, int value) { const struct gpio_bank *bank; if (check_gpio(gpio) < 0) return -1; bank = get_gpio_bank(gpio); _set_gpio_dataout(bank, get_gpio_index(gpio), value); _set_gpio_direction(bank, get_gpio_index(gpio), 0); return 0; }
int pnx_gpio_set_irq_selection(int irq, int selection) { int gpio, index; struct gpio_bank *bank; u32 l = 0; void __iomem *reg; gpio = EXTINT_TO_GPIO(irq); irq -= IRQ_COUNT; if (!check_gpio_irq(irq)) return -EINVAL; bank = get_gpio_bank(gpio); index = get_gpio_index(gpio); if (!check_gpio_requested(bank, index)) return -EINVAL; reg = (void __iomem*) EXTINT_CFGx(irq); l = __raw_readl(reg); if (selection == EXTINT_SEL_ALTERNATE) l |= EXTINT_SEL_ALTERNATE; else l &= ~EXTINT_SEL_ALTERNATE; __raw_writel(l,reg); return 0; }
int pnx_gpio_read_pin(int gpio) { struct gpio_bank *bank; void __iomem *reg; u32 l = 0; int irq, index; if (!check_gpio(gpio)) return -EINVAL; bank = get_gpio_bank(gpio); index = get_gpio_index(gpio); if (!check_gpio_requested(bank, index)) return -EINVAL; /* check if the GPIO is used as extint */ irq = pnx_gpio_to_extint(gpio); if (irq >= 0) { /* and if it's an alternate internal signal */ /* (cf PNX67xx datasheet table 444)*/ reg = (void __iomem*) EXTINT_CFGx(irq); l = __raw_readl(reg); if (l & EXTINT_SEL_ALTERNATE) { reg = (void __iomem*) EXTINT_SIGNAL_REG; return (__raw_readl(reg) & (1 << irq)) !=0; } } reg = bank->gpio_base; reg += PNX_GPIO_PINS_OFFSET; return (__raw_readl(reg) & (1 << index)) != 0; }
void omap_set_gpio_dataout(int gpio, int enable) { struct gpio_bank *bank; if (check_gpio(gpio) < 0) return; bank = get_gpio_bank(gpio); _set_gpio_dataout(bank, get_gpio_index(gpio), enable); }
void omap_set_gpio_direction(int gpio, int is_input) { struct gpio_bank *bank; if (check_gpio(gpio) < 0) return; bank = get_gpio_bank(gpio); _set_gpio_direction(bank, get_gpio_index(gpio), is_input); }
int pnx_gpio_set_mode(int gpio, int mode) { struct gpio_bank *bank; int index; if (!check_gpio(gpio)) return -EINVAL; bank = get_gpio_bank(gpio); index = get_gpio_index(gpio); if (!check_gpio_requested(bank, index)) return -EINVAL; spin_lock(&bank->lock); _set_gpio_mode(bank, get_gpio_index(gpio), mode); spin_unlock(&bank->lock); return 0; }
void pnx_gpio_free(int gpio) { int index; struct gpio_bank *bank; if (!check_gpio(gpio)) return; index = get_gpio_index(gpio); bank = get_gpio_bank(gpio); _pnx_gpio_free(bank, index); }
/** * Set gpio direction as input */ int gpio_direction_input(unsigned gpio) { const struct gpio_bank *bank; if (check_gpio(gpio) < 0) return -1; bank = get_gpio_bank(gpio); _set_gpio_direction(bank, get_gpio_index(gpio), 1); return 0; }
int pnx_gpio_request(int gpio) { int index; struct gpio_bank *bank; if (!check_gpio(gpio)) return -EINVAL; index = get_gpio_index(gpio); bank = get_gpio_bank(gpio); return _pnx_gpio_request(bank, index); }
int omap_get_gpio_datain(int gpio) { struct gpio_bank *bank; void *reg; if (check_gpio(gpio) < 0) return -EINVAL; bank = get_gpio_bank(gpio); reg = bank->base; switch (bank->method) { case METHOD_GPIO_24XX: reg += OMAP24XX_GPIO_DATAIN; break; default: return -EINVAL; } return (__raw_readl(reg) & (1 << get_gpio_index(gpio))) != 0; }
int pnx_gpio_write_pin(int gpio, int gpio_value) { struct gpio_bank *bank; unsigned long index; if (!check_gpio(gpio)) return -EINVAL; bank = get_gpio_bank(gpio); index = get_gpio_index(gpio); if (!check_gpio_requested(bank, index)) return -EINVAL; spin_lock(&bank->lock); _write_gpio_pin(bank, index, gpio_value); spin_unlock(&bank->lock); return 0; }
int pnx_gpio_set_direction(int gpio, int is_input) { unsigned long flags, index; struct gpio_bank *bank; if (!check_gpio(gpio)) return -EINVAL; bank = get_gpio_bank(gpio); index = get_gpio_index(gpio); if (!check_gpio_requested(bank, index)) return -EINVAL; spin_lock_irqsave(&bank->lock, flags); _set_gpio_direction(bank, index, is_input); spin_unlock_irqrestore(&bank->lock, flags); return 0; }
int pnx_gpio_set_irq_debounce(int irq, int cycles) { int gpio; struct gpio_bank *bank; void __iomem *reg; int mode; u32 l = 0; gpio = EXTINT_TO_GPIO(irq); irq -= IRQ_COUNT; if (!check_gpio_irq(irq)) goto err; bank = get_gpio_bank(gpio); if (!check_gpio_requested(bank, get_gpio_index(gpio))) return -EINVAL; reg = (void __iomem*) EXTINT_CFGx(irq); l = __raw_readl(reg); mode=l&(3<<EXTINT_MODE_SHIFT); if ( mode==EXTINT_MODE_BYPASS ) goto err; /* clear mode and set streching to debounce */ if ( mode==EXTINT_MODE_STRETCHING ){ l &= ~(3 << EXTINT_MODE_SHIFT); l |= EXTINT_MODE_DEBOUNCE; } /* clear and set the debounce field */ l &= ~(7<<EXTINT_DEBOUNCE_SHIFT); l |= ((cycles & 0x7) << EXTINT_DEBOUNCE_SHIFT); __raw_writel(l,reg); return 0; err: return -EINVAL; }
static void _reset_gpio(struct gpio_bank *bank, int gpio) { _set_gpio_direction(bank, get_gpio_index(gpio), 1); }
static int __init pnx_gpio_probe(struct platform_device *pdev) { int i,j; int gpio = 0; struct gpio_bank *bank; struct gpio_data *data = pdev->dev.platform_data; unsigned long flags; initialized = 1; printk(KERN_INFO "PNX GPIO\n"); gpio_bank_desc = data->gpio_bank_desc; gpio_bank_count = data->nb_banks; for (i = 0; i < gpio_bank_count; i++) { int gpio_count = 32; /* 32 GPIO per bank */ bank = &gpio_bank_desc[i]; bank->reserved_map = 0; /* must always be initialized */ spin_lock_init(&bank->lock); /* check if bank is managed by PNX GPIO driver */ if ((bank->gpio_base != 0) && (bank->mux_base != 0)) { bank->chip.request = pnx_gpio_acquire; bank->chip.free = pnx_gpio_release; bank->chip.direction_input = gpio_input; bank->chip.get = gpio_get; bank->chip.direction_output = gpio_output; bank->chip.set = gpio_set; bank->chip.to_irq = gpio_2irq; bank->chip.label = "gpio"; bank->chip.base = gpio; bank->chip.ngpio = gpio_count; gpiochip_add(&bank->chip); } gpio += gpio_count; } #ifdef CONFIG_MODEM_BLACK_BOX /* set init value */ printk(KERN_INFO "PNX GPIO initialize SCON\n"); /* configure MUX and PAD settings */ for (i = 0; i< SCON_REGISTER_NB; i++) __raw_writel(pnx_scon_init_config[i].scon_reg_value, pnx_scon_init_config[i].scon_reg_addr); /* configure GPIO direction and value */ for (i=0; i < gpio_to_configure; i++) { int index; bank = get_gpio_bank(pnx_gpio_init_config[i].gpio); index = get_gpio_index(pnx_gpio_init_config[i].gpio); _set_gpio_direction(bank, index, pnx_gpio_init_config[i].dir); _write_gpio_pin(bank, index, pnx_gpio_init_config[i].value); } /* reserve GPIO used by Modem */ for (i = 0; i < pnx_modem_gpio_reserved_nb; i++) { int index; bank = get_gpio_bank(pnx_modem_gpio_reserved[i]); index = get_gpio_index(pnx_modem_gpio_reserved[i]); bank->reserved_map |= (1 << index); } /* configure EXTINT used by modem */ for (i = 0; i< pnx_modem_extint_nb; i++) __raw_writel(pnx_extint_init_config[i].reg_value, pnx_extint_init_config[i].reg_addr); printk(KERN_INFO "PNX GPIO Driver\n"); #endif /* for extint */ for (j = IRQ_COUNT; j < IRQ_COUNT + NR_EXTINT; j++) { set_irq_chip(j, &gpio_irq_chip); set_irq_handler(j, handle_simple_irq); set_irq_flags(j, IRQF_VALID); } hw_raw_local_irq_save ( flags ); /* mask all EXT IRQ sources before registring handler */ /* read status */ j = __raw_readl(EXTINT_STATUS_REG) & __raw_readl(EXTINT_ENABLE3_REG); /* clear IRQ source(s)*/ __raw_writel(j, EXTINT_STATUS_REG); __raw_writel(0, EXTINT_ENABLE3_REG); /* set irq in low level */ set_irq_type(IRQ_EXTINT3, IRQF_TRIGGER_LOW); /* chained GPIO-IRQ on EXTINT3 */ set_irq_chained_handler(IRQ_EXTINT3, gpio_irq_handler); hw_raw_local_irq_restore ( flags ); return 0; }