//void __init msm8974_bt_init(struct device *dev)
void __init msm8974_bt_init(void)
{
    int err = 0;
#ifdef CONFIG_MACH_MONTBLANC
    int rc = 0;
    pr_err("[BT] msm8974_bt_init(%d)\n", system_rev);

    if (system_rev < 2) {
        rc = gpio_request(get_gpio_hwrev(BTWIFI_LDO_EN), "btwifi_ldoen_gpio");
        if (unlikely(rc)) {
            pr_err("[BT] BTWIFI_LDO_EN request failed.\n");
            //return;
        }
        gpio_direction_output(get_gpio_hwrev(BTWIFI_LDO_EN), 0);
        //usleep_range(20000, 20000);
        gpio_set_value(get_gpio_hwrev(BTWIFI_LDO_EN), 1);
    }
#endif
#ifdef BT_LPM_ENABLE
    gpio_rev_init();
    err = platform_device_register(&msm_bluesleep_device);
    if (err) {
        pr_err("[BT] failed to register Bluesleep device.\n");
        return;
    }
#endif

    platform_add_devices(jf_bt_devs, ARRAY_SIZE(jf_bt_devs));
}
static int bcm4339_bluetooth_remove(struct platform_device *pdev)
{
    rfkill_unregister(bt_rfkill);
    rfkill_destroy(bt_rfkill);

    gpio_free(get_gpio_hwrev(BT_EN));
    gpio_free(get_gpio_hwrev(BT_WAKE));
    return 0;
}
static int bcm4335_bluetooth_probe(struct platform_device *pdev)
{
	int rc = 0;

    #ifdef BT_UART_CFG
    int pin = 0;
    #endif

#if defined(CONFIG_BCM4335) || defined(CONFIG_BCM4335_MODULE)
	bt_is_running = 0;
#endif
    /* temporailiy set HOST_WAKE OUT direction until FPGA work finishs */
	/* if setting HOST_WAKE to NO PULL, BT would not be turned on. */
	/* By guideline of BRCM, it is needed to determine pull status */
	#ifndef BT_LPM_ENABLE
	gpio_tlmm_config(GPIO_CFG(get_gpio_hwrev(GPIO_BT_HOST_WAKE), 0, GPIO_CFG_OUTPUT,
		GPIO_CFG_PULL_UP, GPIO_CFG_8MA), GPIO_CFG_ENABLE);
	gpio_set_value(get_gpio_hwrev(GPIO_BT_HOST_WAKE), 1);
	#endif

    #ifdef BT_UART_CFG
    for (pin = 0; pin < ARRAY_SIZE(bt_uart_off_table); pin++) {
        rc = gpio_tlmm_config(bt_uart_off_table[pin], GPIO_CFG_ENABLE);
        if (rc < 0)
            pr_err("%s: gpio_tlmm_config(%#x)=%d\n",
                    __func__, bt_uart_off_table[pin], rc);
    }
    #endif

	bt_rfkill = rfkill_alloc("bcm4335 Bluetooth", &pdev->dev,
				RFKILL_TYPE_BLUETOOTH, &bcm4335_bt_rfkill_ops,
				NULL);

	if (unlikely(!bt_rfkill)) {
		pr_err("[BT] bt_rfkill alloc failed.\n");
		gpio_free(ice_gpiox_get(FPGA_GPIO_BT_EN));
		return -ENOMEM;
	}


	rfkill_init_sw_state(bt_rfkill, 0);

	rc = rfkill_register(bt_rfkill);

	if (unlikely(rc)) {
		pr_err("[BT] bt_rfkill register failed.\n");
		rfkill_destroy(bt_rfkill);
		gpio_free(ice_gpiox_get(FPGA_GPIO_BT_EN));
		return rc;
	}


	rfkill_set_sw_state(bt_rfkill, true);

	return rc;
}
static void gpio_rev_init(void)
{
	bluesleep_resources[0].start = get_gpio_hwrev(GPIO_BT_HOST_WAKE);
	bluesleep_resources[0].end = get_gpio_hwrev(GPIO_BT_HOST_WAKE);
	bluesleep_resources[1].start = FPGA_GPIO_BT_WAKE;
	bluesleep_resources[1].end = FPGA_GPIO_BT_WAKE;
	bluesleep_resources[2].start = \
		MSM_GPIO_TO_INT(get_gpio_hwrev(GPIO_BT_HOST_WAKE));
	bluesleep_resources[2].end = \
		MSM_GPIO_TO_INT(get_gpio_hwrev(GPIO_BT_HOST_WAKE));
}
//static int gpio_rev_init(struct device *dev)
static void gpio_rev_init(void)
{
    bluesleep_resources[0].start = get_gpio_hwrev(GPIO_BT_HOST_WAKE);
    bluesleep_resources[0].end = get_gpio_hwrev(GPIO_BT_HOST_WAKE);

    bluesleep_resources[1].start = get_gpio_hwrev(BT_WAKE);
    bluesleep_resources[1].end = get_gpio_hwrev(BT_WAKE);

    bluesleep_resources[2].start = gpio_to_irq(GPIO_BT_HOST_WAKE);
    bluesleep_resources[2].end = gpio_to_irq(GPIO_BT_HOST_WAKE);
}
static int bcm4339_bt_rfkill_set_power(void *data, bool blocked)
{
    /* rfkill_ops callback. Turn transmitter on when blocked is false */
#ifdef BT_UART_CFG
    int pin, rc = 0;
#endif

    if (!blocked) {
        pr_err("[BT] Bluetooth Power On.\n");

        gpio_set_value(get_gpio_hwrev(BT_WAKE), 1);

        if (gpio_get_value(get_gpio_hwrev(GPIO_BT_HOST_WAKE)) == 0)
            pr_err("[BT] BT_HOST_WAKE is low.\n");

#ifdef BT_UART_CFG
        for (pin = 0; pin < ARRAY_SIZE(bt_uart_on_table); pin++) {
            rc = gpio_tlmm_config(bt_uart_on_table[pin],
                                  GPIO_CFG_ENABLE);
            if (rc < 0)
                pr_err("[BT] %s: gpio_tlmm_config(%#x)=%d\n",
                       __func__, bt_uart_on_table[pin], rc);
        }
#endif

        gpio_set_value(get_gpio_hwrev(BT_EN), 1);
#if defined(CONFIG_BCM4335) || defined(CONFIG_BCM4335_MODULE) || defined(CONFIG_BCM4339) || defined(CONFIG_BCM4339_MODULE)
        bt_is_running = 1;
#endif
    } else {
#ifdef BT_UART_CFG
        for (pin = 0; pin < ARRAY_SIZE(bt_uart_off_table); pin++) {
            rc = gpio_tlmm_config(bt_uart_off_table[pin],
                                  GPIO_CFG_ENABLE);
            if (rc < 0)
                pr_err("%s: gpio_tlmm_config(%#x)=%d\n",
                       __func__, bt_uart_off_table[pin], rc);
        }
#endif
        pr_err("[BT] Bluetooth Power Off.\n");

        gpio_set_value(get_gpio_hwrev(BT_EN), 0);
        gpio_set_value(get_gpio_hwrev(BT_WAKE), 0);
#if defined(CONFIG_BCM4335) || defined(CONFIG_BCM4335_MODULE) || defined(CONFIG_BCM4339) || defined(CONFIG_BCM4339_MODULE)
        bt_is_running = 0;
#endif
    }
    return 0;
}
//static int gpio_rev_init(struct device *dev)
static void gpio_rev_init(void)
{
#if defined(CONFIG_MACH_K3GDUOS_CTC)
    if (system_rev < 6)
        gpio_bt_host_wake = GPIO_BT_HOST_WAKE_REV01;
#endif
    pr_err("[BT] %s, gpio_bt_host_wake = %d", __func__, gpio_bt_host_wake);

    bluesleep_resources[0].start = get_gpio_hwrev(gpio_bt_host_wake);
    bluesleep_resources[0].end = get_gpio_hwrev(gpio_bt_host_wake);

    bluesleep_resources[1].start = get_gpio_hwrev(BT_WAKE);
    bluesleep_resources[1].end = get_gpio_hwrev(BT_WAKE);

    bluesleep_resources[2].start = gpio_to_irq(gpio_bt_host_wake);
    bluesleep_resources[2].end = gpio_to_irq(gpio_bt_host_wake);
}
static int bcm4354_bt_rfkill_set_power(void *data, bool blocked)
{
/* rfkill_ops callback. Turn transmitter on when blocked is false */
#ifdef BT_UART_CFG
    int pin, rc = 0;
#endif
    int ret = -1;

    if(cnt < 1) {
        /* configure host_wake as input */
        gpio_tlmm_config(GPIO_CFG(gpio_bt_host_wake, 0, GPIO_CFG_INPUT,
                                GPIO_CFG_NO_PULL, GPIO_CFG_16MA), GPIO_CFG_ENABLE);
        ret = gpio_direction_input(gpio_bt_host_wake);
        if (ret < 0) {
            pr_err("[BT] %s: failed to configure input direction for GPIO %d, error %d",
                        __func__, gpio_bt_host_wake, ret);
            gpio_free(gpio_bt_host_wake);
        }
        cnt++;
    }
    pr_err("[BT] %s, gpio_bt_host_wake = %d", __func__, gpio_bt_host_wake);

    if (!blocked) {
        pr_err("[BT] Bluetooth Power On.\n");

        gpio_set_value(get_gpio_hwrev(BT_WAKE), 1);

        if (gpio_get_value(get_gpio_hwrev(gpio_bt_host_wake)) == 0)
            pr_err("[BT] BT_HOST_WAKE is low.\n");

#ifdef BT_UART_CFG
        for (pin = 0; pin < ARRAY_SIZE(bt_uart_on_table); pin++) {
            rc = gpio_tlmm_config(bt_uart_on_table[pin],
                GPIO_CFG_ENABLE);
            if (rc < 0)
                pr_err("[BT] %s: gpio_tlmm_config(%#x)=%d\n",
                    __func__, bt_uart_on_table[pin], rc);
        }
#endif

        ret = gpio_direction_output(GPIO_BT_EN, 1);
        if (ret)
            pr_err("[BT] failed to set BT_EN.\n");
    } else {
#ifdef BT_UART_CFG
        for (pin = 0; pin < ARRAY_SIZE(bt_uart_off_table); pin++) {
            rc = gpio_tlmm_config(bt_uart_off_table[pin],
                GPIO_CFG_ENABLE);
            if (rc < 0)
                pr_err("%s: gpio_tlmm_config(%#x)=%d\n",
                    __func__, bt_uart_off_table[pin], rc);
        }
#endif
        pr_err("[BT] Bluetooth Power Off.\n");

        ret = gpio_direction_output(GPIO_BT_EN, 0);
  	    if (ret)
            pr_err("[BT] failed to set BT_EN.\n");

		gpio_set_value(get_gpio_hwrev(BT_WAKE), 0);
    }
    return 0;
}