static int rfkill_rk_pm_prepare(struct device *dev) { struct rfkill_rk_data *rfkill = g_rfkill; struct rfkill_rk_gpio* rts; struct rfkill_rk_irq* wake_host_irq; DBG("Enter %s\n",__FUNCTION__); if (!rfkill) return 0; rts = &rfkill->pdata->rts_gpio; wake_host_irq = &rfkill->pdata->wake_host_irq; //To prevent uart to receive bt data when suspended if (gpio_is_valid(rts->io)) { DBG("Disable UART_RTS\n"); if (rts->iomux.name) { rk_mux_api_set(rts->iomux.name, rts->iomux.fgpio); } gpio_direction_output(rts->io, !rts->enable); } #ifdef CONFIG_BT_AUTOSLEEP // BT进入睡眠状态,不接收主控数据 rfkill_rk_sleep_bt(BT_SLEEP); #endif /* 至此,蓝牙不再送数据到UART,也不再接收主控的UART数据 * 接着调用enable_irq使能 bt_wake_host irq,当远端设备有数据 * 到来时,将通过该IRQ唤醒主控 */ // enable bt wakeup host if (gpio_is_valid(wake_host_irq->gpio.io)) { DBG("enable irq for bt wakeup host\n"); enable_irq(wake_host_irq->irq); } #ifdef CONFIG_RFKILL_RESET rfkill_set_states(rfkill->rfkill_dev, BT_BLOCKED, false); rfkill_rk_set_power(rfkill, BT_BLOCKED); #endif return 0; }
static int rfkill_rk_probe(struct platform_device *pdev) { struct rfkill_rk_data *rfkill; struct rfkill_rk_platform_data *pdata = pdev->dev.platform_data; int ret = 0; struct proc_dir_entry *ent; DBG("Enter %s\n", __func__); if (!pdata) { LOG("%s: No platform data specified\n", __func__); return -EINVAL; } pdata->name = (char*)bt_name; rfkill = kzalloc(sizeof(*rfkill), GFP_KERNEL); if (!rfkill) return -ENOMEM; rfkill->pdata = pdata; g_rfkill = rfkill; bluetooth_dir = proc_mkdir("bluetooth", NULL); if (bluetooth_dir == NULL) { LOG("Unable to create /proc/bluetooth directory"); return -ENOMEM; } sleep_dir = proc_mkdir("sleep", bluetooth_dir); if (sleep_dir == NULL) { LOG("Unable to create /proc/%s directory", PROC_DIR); return -ENOMEM; } /* read/write proc entries */ ent = create_proc_entry("lpm", 0, sleep_dir); if (ent == NULL) { LOG("Unable to create /proc/%s/lpm entry", PROC_DIR); ret = -ENOMEM; goto fail_alloc; } ent->read_proc = bluesleep_read_proc_lpm; ent->write_proc = bluesleep_write_proc_lpm; /* read/write proc entries */ ent = create_proc_entry("btwrite", 0, sleep_dir); if (ent == NULL) { LOG("Unable to create /proc/%s/btwrite entry", PROC_DIR); ret = -ENOMEM; goto fail_alloc; } ent->read_proc = bluesleep_read_proc_btwrite; ent->write_proc = bluesleep_write_proc_btwrite; // 申请GPIO以及IRQ DBG("init gpio\n"); // 对于RK29 BCM4329,它的poweron io与wifi共用,在boad文件中已经request // 此处不用去申请 #if !WIFI_BT_POWER_TOGGLE ret = rfkill_rk_setup_gpio(&pdata->poweron_gpio, IOMUX_FGPIO, pdata->name, "poweron"); if (ret) goto fail_alloc; #endif ret = rfkill_rk_setup_gpio(&pdata->reset_gpio, IOMUX_FGPIO, pdata->name, "reset"); if (ret) goto fail_poweron; ret = rfkill_rk_setup_gpio(&pdata->wake_gpio, IOMUX_FGPIO, pdata->name, "wake"); if (ret) goto fail_reset; ret = rfkill_rk_setup_wake_irq(rfkill); if (ret) goto fail_wake; ret = rfkill_rk_setup_gpio(&pdata->rts_gpio, IOMUX_FMUX, rfkill->pdata->name, "rts"); if (ret) goto fail_wake_host_irq; // 创建并注册RFKILL设备 DBG("setup rfkill\n"); rfkill->rfkill_dev = rfkill_alloc(pdata->name, &pdev->dev, pdata->type, &rfkill_rk_ops, rfkill); if (!rfkill->rfkill_dev) goto fail_rts; // cmy: 设置rfkill初始状态为blocked,在注册时不会调用 set_blocked函数 rfkill_set_states(rfkill->rfkill_dev, BT_BLOCKED, false); ret = rfkill_register(rfkill->rfkill_dev); if (ret < 0) goto fail_rfkill; wake_lock_init(&(rfkill->bt_irq_wl), WAKE_LOCK_SUSPEND, "rfkill_rk_irq_wl"); INIT_DELAYED_WORK(&rfkill->bt_sleep_delay_work, rfkill_rk_delay_sleep_bt); // cmy: 设置蓝牙电源的状态为 blocked rfkill_rk_set_power(rfkill, BT_BLOCKED); platform_set_drvdata(pdev, rfkill); LOG("%s device registered.\n", pdata->name); return 0; fail_rfkill: rfkill_destroy(rfkill->rfkill_dev); fail_rts: if (gpio_is_valid(pdata->rts_gpio.io)) gpio_free(pdata->rts_gpio.io); fail_wake_host_irq: if (gpio_is_valid(pdata->wake_host_irq.gpio.io)){ free_irq(pdata->wake_host_irq.irq, rfkill); gpio_free(pdata->wake_host_irq.gpio.io); } fail_wake: if (gpio_is_valid(pdata->wake_gpio.io)) gpio_free(pdata->wake_gpio.io); fail_reset: if (gpio_is_valid(pdata->reset_gpio.io)) gpio_free(pdata->reset_gpio.io); fail_poweron: #if !WIFI_BT_POWER_TOGGLE if (gpio_is_valid(pdata->poweron_gpio.io)) gpio_free(pdata->poweron_gpio.io); #endif fail_alloc: kfree(rfkill); g_rfkill = NULL; remove_proc_entry("btwrite", sleep_dir); remove_proc_entry("lpm", sleep_dir); return ret; }
static int rfkill_rk_probe(struct platform_device *pdev) { struct rfkill_rk_data *rfkill; struct rfkill_rk_platform_data *pdata = pdev->dev.platform_data; int ret = 0; DBG("Enter %s\n", __func__); if (!pdata) { LOG("%s: No platform data specified\n", __func__); return -EINVAL; } pdata->name = (char*)bt_name; rfkill = kzalloc(sizeof(*rfkill), GFP_KERNEL); if (!rfkill) return -ENOMEM; rfkill->pdata = pdata; g_rfkill = rfkill; // 申请GPIO以及IRQ DBG("init gpio\n"); // 对于RK29 BCM4329,它的poweron io与wifi共用,在boad文件中已经request // 此处不用去申请 #if !WIFI_BT_POWER_TOGGLE ret = rfkill_rk_setup_gpio(&pdata->poweron_gpio, IOMUX_FGPIO, pdata->name, "poweron"); if (ret) goto fail_alloc; #endif ret = rfkill_rk_setup_gpio(&pdata->reset_gpio, IOMUX_FGPIO, pdata->name, "reset"); if (ret) goto fail_poweron; ret = rfkill_rk_setup_gpio(&pdata->wake_gpio, IOMUX_FGPIO, pdata->name, "wake"); if (ret) goto fail_reset; ret = rfkill_rk_setup_wake_irq(rfkill); if (ret) goto fail_wake; ret = rfkill_rk_setup_gpio(&(pdata->rts_gpio), IOMUX_FNORMAL, rfkill->pdata->name, "rts"); if (ret) goto fail_wake_host_irq; // 创建并注册RFKILL设备 DBG("setup rfkill\n"); rfkill->rfkill_dev = rfkill_alloc(pdata->name, &pdev->dev, pdata->type, &rfkill_rk_ops, rfkill); if (!rfkill->rfkill_dev) goto fail_rts; // cmy: 设置rfkill初始状态为blocked,在注册时不会调用 set_blocked函数 rfkill_set_states(rfkill->rfkill_dev, BT_BLOCKED, false); ret = rfkill_register(rfkill->rfkill_dev); if (ret < 0) goto fail_rfkill; wake_lock_init(&(rfkill->bt_irq_wl), WAKE_LOCK_SUSPEND, "rfkill_rk_irq_wl"); INIT_DELAYED_WORK(&rfkill->bt_sleep_delay_work, rfkill_rk_delay_sleep_bt); // cmy: 设置蓝牙电源的状态为 blocked rfkill_rk_set_power(rfkill, BT_BLOCKED); platform_set_drvdata(pdev, rfkill); LOG("%s device registered.\n", pdata->name); return 0; fail_rfkill: rfkill_destroy(rfkill->rfkill_dev); fail_rts: if (gpio_is_valid(pdata->rts_gpio.io)) gpio_free(pdata->rts_gpio.io); fail_wake_host_irq: if (gpio_is_valid(pdata->wake_host_irq.gpio.io)){ free_irq(pdata->wake_host_irq.irq, rfkill); gpio_free(pdata->wake_host_irq.gpio.io); } fail_wake: if (gpio_is_valid(pdata->wake_gpio.io)) gpio_free(pdata->wake_gpio.io); fail_reset: if (gpio_is_valid(pdata->reset_gpio.io)) gpio_free(pdata->reset_gpio.io); fail_poweron: #if !WIFI_BT_POWER_TOGGLE if (gpio_is_valid(pdata->poweron_gpio.io)) gpio_free(pdata->poweron_gpio.io); #endif fail_alloc: kfree(rfkill); g_rfkill = NULL; return ret; }