Ejemplo n.º 1
0
// 设置 BT_WAKE_HOST IRQ
static int rfkill_rk_setup_wake_irq(struct rfkill_rk_data* rfkill)
{
    int ret=0;
    struct rfkill_rk_irq* irq = &(rfkill->pdata->wake_host_irq);
    
    ret = rfkill_rk_setup_gpio(&irq->gpio, IOMUX_FGPIO, rfkill->pdata->name, "wake_host");
    if (ret) goto fail1;

    if (gpio_is_valid(irq->gpio.io))
    {
        ret = gpio_pull_updown(irq->gpio.io, (irq->gpio.enable==GPIO_LOW)?GPIOPullUp:GPIOPullDown);
        if (ret) goto fail2;
        LOG("Request irq for bt wakeup host\n");
        irq->irq = gpio_to_irq(irq->gpio.io);
        sprintf(irq->name, "%s_irq", irq->gpio.name);
        ret = request_irq(irq->irq,
                    rfkill_rk_wake_host_irq,
                    (irq->gpio.enable==GPIO_LOW)?IRQF_TRIGGER_FALLING:IRQF_TRIGGER_RISING,
                    irq->name,
                    rfkill);
        if (ret) goto fail2;
        LOG("** disable irq\n");
        disable_irq(irq->irq);
        ret = enable_irq_wake(irq->irq);
        if (ret) goto fail3;
    }

    return ret;

fail3:
    free_irq(irq->gpio.io, rfkill);
fail2:
    gpio_free(irq->gpio.io);
fail1:
    return ret;
}
Ejemplo n.º 2
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;
}
Ejemplo n.º 3
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;

    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;
}