bfin_gpio.c
来自「linux 内核源代码」· C语言 代码 · 共 1,197 行 · 第 1/2 页
C
1,197 行
unsigned long flags; \ unsigned short ret; \ local_irq_save(flags); \ ret = (gpio_bankb[gpio_bank(gpio)]->name); \ AWA_DUMMY_READ(name); \ local_irq_restore(flags); \ return ret; \} \EXPORT_SYMBOL(get_gpiop_ ## name);#else#define GET_GPIO_P(name) \unsigned short get_gpiop_ ## name(unsigned short gpio) \{ \ return (gpio_bankb[gpio_bank(gpio)]->name);\} \EXPORT_SYMBOL(get_gpiop_ ## name);#endifGET_GPIO_P(data)GET_GPIO_P(dir)GET_GPIO_P(inen)GET_GPIO_P(polar)GET_GPIO_P(edge)GET_GPIO_P(both)GET_GPIO_P(maska)GET_GPIO_P(maskb)#ifdef CONFIG_PM/************************************************************* FUNCTIONS: Blackfin PM Setup API** INPUTS/OUTPUTS:* gpio - GPIO Number between 0 and MAX_BLACKFIN_GPIOS* type -* PM_WAKE_RISING* PM_WAKE_FALLING* PM_WAKE_HIGH* PM_WAKE_LOW* PM_WAKE_BOTH_EDGES** DESCRIPTION: Blackfin PM Driver API** CAUTION:************************************************************** MODIFICATION HISTORY :**************************************************************/int gpio_pm_wakeup_request(unsigned short gpio, unsigned char type){ unsigned long flags; if ((check_gpio(gpio) < 0) || !type) return -EINVAL; local_irq_save(flags); wakeup_map[gpio_bank(gpio)] |= gpio_bit(gpio); wakeup_flags_map[gpio] = type; local_irq_restore(flags); return 0;}EXPORT_SYMBOL(gpio_pm_wakeup_request);void gpio_pm_wakeup_free(unsigned short gpio){ unsigned long flags; if (check_gpio(gpio) < 0) return; local_irq_save(flags); wakeup_map[gpio_bank(gpio)] &= ~gpio_bit(gpio); local_irq_restore(flags);}EXPORT_SYMBOL(gpio_pm_wakeup_free);static int bfin_gpio_wakeup_type(unsigned short gpio, unsigned char type){ port_setup(gpio, GPIO_USAGE); set_gpio_dir(gpio, 0); set_gpio_inen(gpio, 1); if (type & (PM_WAKE_RISING | PM_WAKE_FALLING)) set_gpio_edge(gpio, 1); else set_gpio_edge(gpio, 0); if ((type & (PM_WAKE_BOTH_EDGES)) == (PM_WAKE_BOTH_EDGES)) set_gpio_both(gpio, 1); else set_gpio_both(gpio, 0); if ((type & (PM_WAKE_FALLING | PM_WAKE_LOW))) set_gpio_polar(gpio, 1); else set_gpio_polar(gpio, 0); SSYNC(); return 0;}u32 gpio_pm_setup(void){ u32 sic_iwr = 0; u16 bank, mask, i, gpio; for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) { mask = wakeup_map[gpio_bank(i)]; bank = gpio_bank(i); gpio_bank_saved[bank].maskb = gpio_bankb[bank]->maskb; gpio_bankb[bank]->maskb = 0; if (mask) {#ifdef BF537_FAMILY gpio_bank_saved[bank].fer = *port_fer[bank];#endif gpio_bank_saved[bank].inen = gpio_bankb[bank]->inen; gpio_bank_saved[bank].polar = gpio_bankb[bank]->polar; gpio_bank_saved[bank].dir = gpio_bankb[bank]->dir; gpio_bank_saved[bank].edge = gpio_bankb[bank]->edge; gpio_bank_saved[bank].both = gpio_bankb[bank]->both; gpio_bank_saved[bank].reserved = reserved_gpio_map[bank]; gpio = i; while (mask) { if (mask & 1) { reserved_gpio_map[gpio_bank(gpio)] |= gpio_bit(gpio); bfin_gpio_wakeup_type(gpio, wakeup_flags_map[gpio]); set_gpio_data(gpio, 0); /*Clear*/ } gpio++; mask >>= 1; } sic_iwr |= 1 << (sic_iwr_irqs[bank] - (IRQ_CORETMR + 1)); gpio_bankb[bank]->maskb_set = wakeup_map[gpio_bank(i)]; } } AWA_DUMMY_READ(maskb_set); if (sic_iwr) return sic_iwr; else return IWR_ENABLE_ALL;}void gpio_pm_restore(void){ u16 bank, mask, i; for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) { mask = wakeup_map[gpio_bank(i)]; bank = gpio_bank(i); if (mask) {#ifdef BF537_FAMILY *port_fer[bank] = gpio_bank_saved[bank].fer;#endif gpio_bankb[bank]->inen = gpio_bank_saved[bank].inen; gpio_bankb[bank]->dir = gpio_bank_saved[bank].dir; gpio_bankb[bank]->polar = gpio_bank_saved[bank].polar; gpio_bankb[bank]->edge = gpio_bank_saved[bank].edge; gpio_bankb[bank]->both = gpio_bank_saved[bank].both; reserved_gpio_map[bank] = gpio_bank_saved[bank].reserved; } gpio_bankb[bank]->maskb = gpio_bank_saved[bank].maskb; } AWA_DUMMY_READ(maskb);}#endif#endif /* BF548_FAMILY *//************************************************************* FUNCTIONS: Blackfin Peripheral Resource Allocation* and PortMux Setup** INPUTS/OUTPUTS:* per Peripheral Identifier* label String** DESCRIPTION: Blackfin Peripheral Resource Allocation and Setup API** CAUTION:************************************************************** MODIFICATION HISTORY :**************************************************************/#ifdef BF548_FAMILYint peripheral_request(unsigned short per, const char *label){ unsigned long flags; unsigned short ident = P_IDENT(per); /* * Don't cares are pins with only one dedicated function */ if (per & P_DONTCARE) return 0; if (!(per & P_DEFINED)) return -ENODEV; if (check_gpio(ident) < 0) return -EINVAL; local_irq_save(flags); if (unlikely(reserved_gpio_map[gpio_bank(ident)] & gpio_bit(ident))) { printk(KERN_ERR "%s: Peripheral %d is already reserved as GPIO by %s !\n", __FUNCTION__, ident, get_label(ident)); dump_stack(); local_irq_restore(flags); return -EBUSY; } if (unlikely(reserved_peri_map[gpio_bank(ident)] & gpio_bit(ident))) { u16 funct = get_portmux(ident); /* * Pin functions like AMC address strobes my * be requested and used by several drivers */ if (!((per & P_MAYSHARE) && (funct == P_FUNCT2MUX(per)))) { /* * Allow that the identical pin function can * be requested from the same driver twice */ if (cmp_label(ident, label) == 0) goto anyway; printk(KERN_ERR "%s: Peripheral %d function %d is already reserved by %s !\n", __FUNCTION__, ident, P_FUNCT2MUX(per), get_label(ident)); dump_stack(); local_irq_restore(flags); return -EBUSY; } }anyway: reserved_peri_map[gpio_bank(ident)] |= gpio_bit(ident); portmux_setup(ident, P_FUNCT2MUX(per)); port_setup(ident, PERIPHERAL_USAGE); local_irq_restore(flags); set_label(ident, label); return 0;}EXPORT_SYMBOL(peripheral_request);#elseint peripheral_request(unsigned short per, const char *label){ unsigned long flags; unsigned short ident = P_IDENT(per); /* * Don't cares are pins with only one dedicated function */ if (per & P_DONTCARE) return 0; if (!(per & P_DEFINED)) return -ENODEV; local_irq_save(flags); if (!check_gpio(ident)) { if (unlikely(reserved_gpio_map[gpio_bank(ident)] & gpio_bit(ident))) { printk(KERN_ERR "%s: Peripheral %d is already reserved as GPIO by %s !\n", __FUNCTION__, ident, get_label(ident)); dump_stack(); local_irq_restore(flags); return -EBUSY; } } if (unlikely(reserved_peri_map[gpio_bank(ident)] & gpio_bit(ident))) { /* * Pin functions like AMC address strobes my * be requested and used by several drivers */ if (!(per & P_MAYSHARE)) { /* * Allow that the identical pin function can * be requested from the same driver twice */ if (cmp_label(ident, label) == 0) goto anyway; printk(KERN_ERR "%s: Peripheral %d function %d is already" " reserved by %s !\n", __FUNCTION__, ident, P_FUNCT2MUX(per), get_label(ident)); dump_stack(); local_irq_restore(flags); return -EBUSY; } }anyway: portmux_setup(per, P_FUNCT2MUX(per)); port_setup(ident, PERIPHERAL_USAGE); reserved_peri_map[gpio_bank(ident)] |= gpio_bit(ident); local_irq_restore(flags); set_label(ident, label); return 0;}EXPORT_SYMBOL(peripheral_request);#endifint peripheral_request_list(unsigned short per[], const char *label){ u16 cnt; int ret; for (cnt = 0; per[cnt] != 0; cnt++) { ret = peripheral_request(per[cnt], label); if (ret < 0) { for ( ; cnt > 0; cnt--) { peripheral_free(per[cnt - 1]); } return ret; } } return 0;}EXPORT_SYMBOL(peripheral_request_list);void peripheral_free(unsigned short per){ unsigned long flags; unsigned short ident = P_IDENT(per); if (per & P_DONTCARE) return; if (!(per & P_DEFINED)) return; if (check_gpio(ident) < 0) return; local_irq_save(flags); if (unlikely(!(reserved_peri_map[gpio_bank(ident)] & gpio_bit(ident)))) { local_irq_restore(flags); return; } if (!(per & P_MAYSHARE)) { port_setup(ident, GPIO_USAGE); } reserved_peri_map[gpio_bank(ident)] &= ~gpio_bit(ident); set_label(ident, "free"); local_irq_restore(flags);}EXPORT_SYMBOL(peripheral_free);void peripheral_free_list(unsigned short per[]){ u16 cnt; for (cnt = 0; per[cnt] != 0; cnt++) { peripheral_free(per[cnt]); }}EXPORT_SYMBOL(peripheral_free_list);/************************************************************* FUNCTIONS: Blackfin GPIO Driver** INPUTS/OUTPUTS:* gpio PIO Number between 0 and MAX_BLACKFIN_GPIOS* label String** DESCRIPTION: Blackfin GPIO Driver API** CAUTION:************************************************************** MODIFICATION HISTORY :**************************************************************/int gpio_request(unsigned short gpio, const char *label){ unsigned long flags; if (check_gpio(gpio) < 0) return -EINVAL; local_irq_save(flags); /* * Allow that the identical GPIO can * be requested from the same driver twice * Do nothing and return - */ if (cmp_label(gpio, label) == 0) { local_irq_restore(flags); return 0; } if (unlikely(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) { printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved by %s !\n", gpio, get_label(gpio)); dump_stack(); local_irq_restore(flags); return -EBUSY; } if (unlikely(reserved_peri_map[gpio_bank(gpio)] & gpio_bit(gpio))) { printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n", gpio, get_label(gpio)); dump_stack(); local_irq_restore(flags); return -EBUSY; } reserved_gpio_map[gpio_bank(gpio)] |= gpio_bit(gpio); local_irq_restore(flags); port_setup(gpio, GPIO_USAGE); set_label(gpio, label); return 0;}EXPORT_SYMBOL(gpio_request);void gpio_free(unsigned short gpio){ unsigned long flags; if (check_gpio(gpio) < 0) return; local_irq_save(flags); if (unlikely(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)))) { printk(KERN_ERR "bfin-gpio: GPIO %d wasn't reserved!\n", gpio); dump_stack(); local_irq_restore(flags); return; } default_gpio(gpio); reserved_gpio_map[gpio_bank(gpio)] &= ~gpio_bit(gpio); set_label(gpio, "free"); local_irq_restore(flags);}EXPORT_SYMBOL(gpio_free);#ifdef BF548_FAMILYvoid gpio_direction_input(unsigned short gpio){ unsigned long flags; BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))); local_irq_save(flags); gpio_array[gpio_bank(gpio)]->port_dir_clear = gpio_bit(gpio); gpio_array[gpio_bank(gpio)]->port_inen |= gpio_bit(gpio); local_irq_restore(flags);}EXPORT_SYMBOL(gpio_direction_input);void gpio_direction_output(unsigned short gpio){ unsigned long flags; BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))); local_irq_save(flags); gpio_array[gpio_bank(gpio)]->port_inen &= ~gpio_bit(gpio); gpio_array[gpio_bank(gpio)]->port_dir_set = gpio_bit(gpio); local_irq_restore(flags);}EXPORT_SYMBOL(gpio_direction_output);void gpio_set_value(unsigned short gpio, unsigned short arg){ if (arg) gpio_array[gpio_bank(gpio)]->port_set = gpio_bit(gpio); else gpio_array[gpio_bank(gpio)]->port_clear = gpio_bit(gpio);}EXPORT_SYMBOL(gpio_set_value);unsigned short gpio_get_value(unsigned short gpio){ return (1 & (gpio_array[gpio_bank(gpio)]->port_data >> gpio_sub_n(gpio)));}EXPORT_SYMBOL(gpio_get_value);#elsevoid gpio_direction_input(unsigned short gpio){ unsigned long flags; BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))); local_irq_save(flags); gpio_bankb[gpio_bank(gpio)]->dir &= ~gpio_bit(gpio); gpio_bankb[gpio_bank(gpio)]->inen |= gpio_bit(gpio); AWA_DUMMY_READ(inen); local_irq_restore(flags);}EXPORT_SYMBOL(gpio_direction_input);void gpio_direction_output(unsigned short gpio){ unsigned long flags; BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))); local_irq_save(flags); gpio_bankb[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio); gpio_bankb[gpio_bank(gpio)]->dir |= gpio_bit(gpio); AWA_DUMMY_READ(dir); local_irq_restore(flags);}EXPORT_SYMBOL(gpio_direction_output);/* If we are booting from SPI and our board lacks a strong enough pull up, * the core can reset and execute the bootrom faster than the resistor can * pull the signal logically high. To work around this (common) error in * board design, we explicitly set the pin back to GPIO mode, force /CS * high, and wait for the electrons to do their thing. * * This function only makes sense to be called from reset code, but it * lives here as we need to force all the GPIO states w/out going through * BUG() checks and such. */void bfin_gpio_reset_spi0_ssel1(void){ u16 gpio = P_IDENT(P_SPI0_SSEL1); port_setup(gpio, GPIO_USAGE); gpio_bankb[gpio_bank(gpio)]->data_set = gpio_bit(gpio); udelay(1);}#endif /*BF548_FAMILY */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?