/* This should be used in function that cannot release clocks */ static void hci_h4p_set_clk(struct hci_h4p_info *info, int *clock, int enable) { unsigned long flags; spin_lock_irqsave(&info->clocks_lock, flags); if (enable && !*clock) { NBT_DBG_POWER("Enabling %p\n", clock); clk_enable(info->uart_fclk); #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) if (cpu_is_omap24xx() || cpu_is_omap34xx()) clk_enable(info->uart_iclk); #endif if (atomic_read(&info->clk_users) == 0) hci_h4p_restore_regs(info); atomic_inc(&info->clk_users); } if (!enable && *clock) { NBT_DBG_POWER("Disabling %p\n", clock); if (atomic_dec_and_test(&info->clk_users)) hci_h4p_store_regs(info); clk_disable(info->uart_fclk); #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) if (cpu_is_omap24xx() || cpu_is_omap34xx()) clk_disable(info->uart_iclk); #endif } *clock = enable; spin_unlock_irqrestore(&info->clocks_lock, flags); }
static irqreturn_t hci_h4p_wakeup_interrupt(int irq, void *dev_inst) { struct hci_h4p_info *info = dev_inst; int should_wakeup; struct hci_dev *hdev; if (!info->hdev) return IRQ_HANDLED; hdev = info->hdev; if (!test_bit(HCI_RUNNING, &hdev->flags)) return IRQ_HANDLED; should_wakeup = gpio_get_value(info->host_wakeup_gpio); NBT_DBG_POWER("gpio interrupt %d\n", should_wakeup); /* Check if wee have missed some interrupts */ if (info->rx_enabled == should_wakeup) return IRQ_HANDLED; if (should_wakeup) { hci_h4p_enable_rx(info); } else { hci_h4p_disable_rx(info); } return IRQ_HANDLED; }
static void hci_h4p_disable_tx(struct hci_h4p_info *info) { NBT_DBG_POWER("\n"); if (!info->pm_enabled) return; /* Re-enable smart-idle */ hci_h4p_smart_idle(info, 1); gpio_set_value(info->bt_wakeup_gpio, 0); mod_timer(&info->lazy_release, jiffies + msecs_to_jiffies(100)); info->tx_enabled = 0; }
void hci_h4p_enable_tx(struct hci_h4p_info *info) { unsigned long flags; NBT_DBG_POWER("\n"); if (!info->pm_enabled) return; spin_lock_irqsave(&info->lock, flags); del_timer(&info->lazy_release); hci_h4p_set_clk(info, &info->tx_clocks_en, 1); info->tx_enabled = 1; gpio_set_value(info->bt_wakeup_gpio, 1); hci_h4p_outb(info, UART_IER, hci_h4p_inb(info, UART_IER) | UART_IER_THRI); /* * Disable smart-idle as UART TX interrupts * are not wake-up capable */ hci_h4p_smart_idle(info, 0); spin_unlock_irqrestore(&info->lock, flags); }
static irqreturn_t brf6150_wakeup_interrupt(int irq, void *dev_inst) { struct brf6150_info *info = dev_inst; int should_wakeup; unsigned long flags; spin_lock_irqsave(&info->lock, flags); should_wakeup = omap_get_gpio_datain(info->btinfo->host_wakeup_gpio); NBT_DBG_POWER("gpio interrupt %d\n", should_wakeup); if (should_wakeup) { clk_enable(info->uart_ck); brf6150_set_auto_ctsrts(info, 1); brf6150_rx(info); tasklet_schedule(&info->tx_task); } else { brf6150_set_auto_ctsrts(info, 0); brf6150_set_rts(info, 0); clk_disable(info->uart_ck); } spin_unlock_irqrestore(&info->lock, flags); return IRQ_HANDLED; }