Example #1
0
void __init kingdom_audio_init(void)
{
	struct pm8058_gpio tpa2051_pwr = {
		.direction      = PM_GPIO_DIR_OUT,
		.output_buffer  = PM_GPIO_OUT_BUF_CMOS,
		.output_value   = 0,
		.pull           = PM_GPIO_PULL_NO,
		.vin_sel        = 6,      /* S3 1.8 V */
		.out_strength   = PM_GPIO_STRENGTH_HIGH,
		.function       = PM_GPIO_FUNC_NORMAL,
	};

	mutex_init(&bt_sco_lock);
#ifdef CONFIG_MSM7KV2_AUDIO
	htc_7x30_register_analog_ops(&ops);
	htc_7x30_register_icodec_ops(&iops);
	htc_7x30_register_ecodec_ops(&eops);
	htc_7x30_register_voice_ops(&vops);
	acoustic_register_ops(&acoustic);
	acdb_register_ops(&acdb);
#endif
	aic3254_register_ctl_ops(&cops);

	pm8058_gpio_config(KINGDOM_AUD_SPK_EN, &tpa2051_pwr);
	pm8058_gpio_config(KINGDOM_AUD_HP_EN, &tpa2051_pwr);

	gpio_request(KINGDOM_AUD_MICPATH_SEL, "aud_mic_sel");
	gpio_direction_output(KINGDOM_AUD_MICPATH_SEL, 1);
	pm8058_gpio_config(KINGDOM_AUD_MICPATH_SEL, &tpa2051_pwr);
	mutex_lock(&bt_sco_lock);
	config_gpio_table(aux_pcm_gpio_off, ARRAY_SIZE(aux_pcm_gpio_off));
	gpio_set_value(KINGDOM_GPIO_BT_PCM_OUT, 0);
	gpio_set_value(KINGDOM_GPIO_BT_PCM_SYNC, 0);
	gpio_set_value(KINGDOM_GPIO_BT_PCM_CLK, 0);
	mutex_unlock(&bt_sco_lock);
}
static void shooter_u_3Dpanel_off(void)
{
	int rc;
	pwm_gpio_config.output_value = 0;

	if (mipi_novatek_panel_data.mipi_send_cmds) {
		mipi_novatek_panel_data.mipi_send_cmds(novatek_2vci_cmds, ARRAY_SIZE(novatek_2vci_cmds));
	}

	rc = pm8058_gpio_config(SHOOTER_U_3DLCM_PD, &pwm_gpio_config);
	if (rc < 0)
		pr_err("%s pmic gpio config gpio %d failed\n", __func__, SHOOTER_U_3DLCM_PD);
	mdp_color_enhancement(mdp_sharp_barrier_off, ARRAY_SIZE(mdp_sharp_barrier_off));
	pwm_disable(pwm_3d);

	rc = pm8058_gpio_config(SHOOTER_U_3DCLK, &clk_gpio_config_off);
	if (rc < 0)
		pr_err("%s pmic gpio config gpio %d failed\n", __func__, SHOOTER_U_3DCLK);
	gpio_set_value(SHOOTER_U_CTL_3D_1, 0);
	gpio_set_value(SHOOTER_U_CTL_3D_2, 0);
	gpio_set_value(SHOOTER_U_CTL_3D_3, 0);
	gpio_set_value(SHOOTER_U_CTL_3D_4, 0);
	led_brightness_switch("lcd-backlight", last_br_2d);
}
Example #3
0
static int msm_uart_aux_chg_uart( void )
{
	int rc = 0;

	// TX -> Low
	uart_tx2_en_22.function = PM_GPIO_FUNC_NORMAL;
/* FUJITSU:2011-10-21 gpio chg start  */
#if defined(CONFIG_MACH_F11APO) || defined(CONFIG_MACH_F12APON)
	if((system_rev != 0x08) || (system_rev != 0x0F))
	{
		uart_tx2_en_22.out_strength = PM_GPIO_STRENGTH_MED;
	}
#elif defined(CONFIG_MACH_FJI12)
	if((system_rev != 0x00) || (system_rev != 0x07))
	{
		uart_tx2_en_22.out_strength = PM_GPIO_STRENGTH_MED;
	}
#endif
/* FUJITSU:2011-10-21 gpio chg end  */
/* FUJITSU:2011-12-01 mod irda start  */
#if 0
	rc = pm8058_gpio_config( PM8058_UART_TX2_22, &uart_tx2_en_22 );
#else
	rc = pm8xxx_gpio_config( PM8058_UART_TX2_22, &uart_tx2_en_22 );
#endif
/* FUJITSU:2011-12-01 mod irda end  */
	if ( rc )
	{
		printk( KERN_ERR "%s: PM8058_UART_TX config failed\n", __func__ );
		return -EIO;
	}
/* FUJITSU:2011-12-01 mod irda start  */
#if 0
	gpio_set_value_cansleep( PM8058_GPIO_PM_TO_SYS( PM8058_UART_TX2_22 ), 0 );
#else
	gpio_set_value_cansleep( PM8058_UART_TX2_22, 0 );
#endif
/* FUJITSU:2011-12-01 mod irda end  */
	printk( KERN_INFO DEV_NAME " %s: IRDA GPIO TX -> Low\n", __func__ );
	return 0;
}
int set_wifi_bt_sleep_clk(int on)
{
	int err = 0;

	if (on) {
		printk(KERN_DEBUG "EN SLEEP CLK\n");
		pmic_gpio_sleep_clk_output.function = PM_GPIO_FUNC_2;
	} else {
		printk(KERN_DEBUG "DIS SLEEP CLK\n");
		pmic_gpio_sleep_clk_output.function = PM_GPIO_FUNC_NORMAL;
	}

	err = pm8058_gpio_config(htc_sleep_clk_pin,
					&pmic_gpio_sleep_clk_output);

	if (err) {
		if (on)
			printk(KERN_DEBUG "ERR EN SLEEP CLK, ERR=%d\n", err);
		else
			printk(KERN_DEBUG "ERR DIS SLEEP CLK, ERR=%d\n", err);
	}

	return err;
}
Example #5
0
static int pm8058_kp_config_drv(int gpio_start, int num_gpios)
{
	int	rc;
	struct pm8058_gpio kypd_drv = {
		.direction	= PM_GPIO_DIR_OUT,
		.output_buffer	= PM_GPIO_OUT_BUF_OPEN_DRAIN,
		.output_value	= 0,
		.pull		= PM_GPIO_PULL_NO,
		.vin_sel	= 2,
		.out_strength	= PM_GPIO_STRENGTH_LOW,
		.function	= PM_GPIO_FUNC_1,
		.inv_int_pol	= 1,
	};

	if (gpio_start < 0 || num_gpios < 0 || num_gpios > PM8058_GPIOS)
		return -EINVAL;

	while (num_gpios--) {
		rc = pm8058_gpio_config(gpio_start++, &kypd_drv);
		if (rc) {
			pr_err("%s: FAIL pm8058_gpio_config(): rc=%d.\n",
				__func__, rc);
			return rc;
		}
	}

	return 0;
}

static int pm8058_kp_config_sns(int gpio_start, int num_gpios)
{
	int	rc;
	struct pm8058_gpio kypd_sns = {
		.direction	= PM_GPIO_DIR_IN,
		.pull		= PM_GPIO_PULL_UP_31P5,
		.vin_sel	= 2,
		.out_strength	= PM_GPIO_STRENGTH_NO,
		.function	= PM_GPIO_FUNC_NORMAL,
		.inv_int_pol	= 1,
	};

	if (gpio_start < 0 || num_gpios < 0 || num_gpios > PM8058_GPIOS)
		return -EINVAL;

	while (num_gpios--) {
		rc = pm8058_gpio_config(gpio_start++, &kypd_sns);
		if (rc) {
			pr_err("%s: FAIL pm8058_gpio_config(): rc=%d.\n",
				__func__, rc);
			return rc;
		}
	}

	return 0;
}

/*
 * keypad controller should be initialized in the following sequence
 * only, otherwise it might get into FSM stuck state.
 *
 * - Initialize keypad control parameters, like no. of rows, columns,
 *   timing values etc.,
 * - configure rows and column gpios pull up/down.
 * - set irq edge type.
 * - enable the keypad controller.
 */
static int __devinit pmic8058_kp_probe(struct platform_device *pdev)
{
	struct pmic8058_keypad_data *pdata = pdev->dev.platform_data;
	const struct matrix_keymap_data *keymap_data;
	struct pmic8058_kp *kp;
	int rc;
	unsigned short *keycodes;
	u8 ctrl_val;
	struct pm8058_chip	*pm_chip;

	pm_chip = platform_get_drvdata(pdev);
	if (pm_chip == NULL) {
		dev_err(&pdev->dev, "no parent data passed in\n");
		return -EFAULT;
	}

	if (!pdata || !pdata->num_cols || !pdata->num_rows ||
		pdata->num_cols > PM8058_MAX_COLS ||
		pdata->num_rows > PM8058_MAX_ROWS ||
		pdata->num_cols < PM8058_MIN_COLS
#if 0
 	||	pdata->num_rows < PM8058_MIN_ROWS
#endif
	) {
		dev_err(&pdev->dev, "invalid platform data\n");
		return -EINVAL;
	}

	if (pdata->rows_gpio_start < 0 || pdata->cols_gpio_start < 0) {
		dev_err(&pdev->dev, "invalid gpio_start platform data\n");
		return -EINVAL;
	}

	if (!pdata->scan_delay_ms || pdata->scan_delay_ms > MAX_SCAN_DELAY
		|| pdata->scan_delay_ms < MIN_SCAN_DELAY ||
		!is_power_of_2(pdata->scan_delay_ms)) {
		dev_err(&pdev->dev, "invalid keypad scan time supplied\n");
		return -EINVAL;
	}

	if (!pdata->row_hold_ns || pdata->row_hold_ns > MAX_ROW_HOLD_DELAY
		|| pdata->row_hold_ns < MIN_ROW_HOLD_DELAY ||
		((pdata->row_hold_ns % MIN_ROW_HOLD_DELAY) != 0)) {
		dev_err(&pdev->dev, "invalid keypad row hold time supplied\n");
		return -EINVAL;
	}

	if (pm8058_rev(pm_chip) == PM_8058_REV_1p0) {
		if (!pdata->debounce_ms
			|| !is_power_of_2(pdata->debounce_ms[0])
			|| pdata->debounce_ms[0] > MAX_DEBOUNCE_A0_TIME
			|| pdata->debounce_ms[0] < MIN_DEBOUNCE_A0_TIME) {
			dev_err(&pdev->dev, "invalid debounce time supplied\n");
			return -EINVAL;
		}
	} else {
		if (!pdata->debounce_ms
			|| ((pdata->debounce_ms[1] % 5) != 0)
			|| pdata->debounce_ms[1] > MAX_DEBOUNCE_B0_TIME
			|| pdata->debounce_ms[1] < MIN_DEBOUNCE_B0_TIME) {
			dev_err(&pdev->dev, "invalid debounce time supplied\n");
			return -EINVAL;
		}
	}

	keymap_data = pdata->keymap_data;
	if (!keymap_data) {
		dev_err(&pdev->dev, "no keymap data supplied\n");
		return -EINVAL;
	}

	kp = kzalloc(sizeof(*kp), GFP_KERNEL);
	if (!kp)
		return -ENOMEM;

	keycodes = kzalloc(PM8058_MATRIX_MAX_SIZE * sizeof(*keycodes),
				 GFP_KERNEL);
	if (!keycodes) {
		rc = -ENOMEM;
		goto err_alloc_mem;
	}

	platform_set_drvdata(pdev, kp);
	mutex_init(&kp->mutex);

	kp->pdata	= pdata;
	kp->dev		= &pdev->dev;
	kp->keycodes	= keycodes;
	kp->pm_chip	= pm_chip;

	if (pm8058_rev(pm_chip) == PM_8058_REV_1p0)
		kp->flags |= KEYF_FIX_LAST_ROW;

	kp->input = input_allocate_device();
	if (!kp->input) {
		dev_err(&pdev->dev, "unable to allocate input device\n");
		rc = -ENOMEM;
		goto err_alloc_device;
	}

	/* Enable runtime PM ops, start in ACTIVE mode */
	rc = pm_runtime_set_active(&pdev->dev);
	if (rc < 0)
		dev_dbg(&pdev->dev, "unable to set runtime pm state\n");
	pm_runtime_enable(&pdev->dev);

	kp->key_sense_irq = platform_get_irq(pdev, 0);
	if (kp->key_sense_irq < 0) {
		dev_err(&pdev->dev, "unable to get keypad sense irq\n");
		rc = -ENXIO;
		goto err_get_irq;
	}

	kp->key_stuck_irq = platform_get_irq(pdev, 1);
	if (kp->key_stuck_irq < 0) {
		dev_err(&pdev->dev, "unable to get keypad stuck irq\n");
		rc = -ENXIO;
		goto err_get_irq;
	}

	if (pdata->input_name)
		kp->input->name = pdata->input_name;
	else
		kp->input->name = "PMIC8058 keypad";

	if (pdata->input_phys_device)
		kp->input->phys = pdata->input_phys_device;
	else
		kp->input->phys = "pmic8058_keypad/input0";

	kp->input->dev.parent	= &pdev->dev;

	kp->input->id.bustype	= BUS_HOST;
	kp->input->id.version	= 0x0001;
	kp->input->id.product	= 0x0001;
	kp->input->id.vendor	= 0x0001;

	kp->input->evbit[0]	= BIT_MASK(EV_KEY);

	if (pdata->rep)
		__set_bit(EV_REP, kp->input->evbit);

	kp->input->keycode	= keycodes;
	kp->input->keycodemax	= PM8058_MATRIX_MAX_SIZE;
	kp->input->keycodesize	= sizeof(*keycodes);

	matrix_keypad_build_keymap(keymap_data, PM8058_ROW_SHIFT,
					kp->input->keycode, kp->input->keybit);

	input_set_capability(kp->input, EV_MSC, MSC_SCAN);
	input_set_drvdata(kp->input, kp);

	rc = input_register_device(kp->input);
	if (rc < 0) {
		dev_err(&pdev->dev, "unable to register keypad input device\n");
		goto err_get_irq;
	}

	/* initialize keypad state */
	memset(kp->keystate, 0xff, sizeof(kp->keystate));
	memset(kp->stuckstate, 0xff, sizeof(kp->stuckstate));

	rc = pmic8058_kpd_init(kp);
	if (rc < 0) {
		dev_err(&pdev->dev, "unable to initialize keypad controller\n");
		goto err_kpd_init;
	}

	rc = pm8058_kp_config_sns(pdata->cols_gpio_start,
			pdata->num_cols);
	if (rc < 0) {
		dev_err(&pdev->dev, "unable to configure keypad sense lines\n");
		goto err_gpio_config;
	}

	rc = pm8058_kp_config_drv(pdata->rows_gpio_start,
			pdata->num_rows);
	if (rc < 0) {
		dev_err(&pdev->dev, "unable to configure keypad drive lines\n");
		goto err_gpio_config;
	}

	rc = request_threaded_irq(kp->key_sense_irq, NULL, pmic8058_kp_irq,
				 IRQF_TRIGGER_RISING, "pmic-keypad", kp);
	if (rc < 0) {
		dev_err(&pdev->dev, "failed to request keypad sense irq\n");
		goto err_req_sense_irq;
	}

	rc = request_threaded_irq(kp->key_stuck_irq, NULL,
				 pmic8058_kp_stuck_irq, IRQF_TRIGGER_RISING,
				 "pmic-keypad-stuck", kp);
	if (rc < 0) {
		dev_err(&pdev->dev, "failed to request keypad stuck irq\n");
		goto err_req_stuck_irq;
	}

	rc = pmic8058_kp_read_u8(kp, &ctrl_val, KEYP_CTRL);
	ctrl_val |= KEYP_CTRL_KEYP_EN;
	rc = pmic8058_kp_write_u8(kp, ctrl_val, KEYP_CTRL);

	kp->ctrl_reg = ctrl_val;

	__dump_kp_regs(kp, "probe");

	rc = device_create_file(&pdev->dev, &dev_attr_key_pressed);
	if (rc < 0)
		goto err_create_file;

	rc = device_create_file(&pdev->dev, &dev_attr_disable_kp);
	if (rc < 0)
		goto err_create_file;

	device_init_wakeup(&pdev->dev, pdata->wakeup);

	return 0;

err_create_file:
	free_irq(kp->key_stuck_irq, kp);
err_req_stuck_irq:
	free_irq(kp->key_sense_irq, kp);
err_req_sense_irq:
err_gpio_config:
err_kpd_init:
	input_unregister_device(kp->input);
	kp->input = NULL;
err_get_irq:
	pm_runtime_set_suspended(&pdev->dev);
	pm_runtime_disable(&pdev->dev);
	input_free_device(kp->input);
err_alloc_device:
	kfree(keycodes);
err_alloc_mem:
	kfree(kp);
	return rc;
}

static int __devexit pmic8058_kp_remove(struct platform_device *pdev)
{
	struct pmic8058_kp *kp = platform_get_drvdata(pdev);

//	sysfs_remove_group(&pdev->dev.kobj, &pmic8058_keys_attr_group);
	pm_runtime_set_suspended(&pdev->dev);
	pm_runtime_disable(&pdev->dev);
	device_remove_file(&pdev->dev, &dev_attr_key_pressed);
	device_remove_file(&pdev->dev, &dev_attr_disable_kp);
	device_init_wakeup(&pdev->dev, 0);
	free_irq(kp->key_stuck_irq, kp);
	free_irq(kp->key_sense_irq, kp);
	input_unregister_device(kp->input);
	platform_set_drvdata(pdev, NULL);
	kfree(kp->input->keycode);
	kfree(kp);

	return 0;
}

#ifdef CONFIG_PM
static int pmic8058_kp_suspend(struct device *dev)
{
	struct pmic8058_kp *kp = dev_get_drvdata(dev);

	if (device_may_wakeup(dev) && !pmic8058_kp_disabled(kp)) {
		enable_irq_wake(kp->key_sense_irq);
	} else {
		mutex_lock(&kp->mutex);
		pmic8058_kp_disable(kp);
		mutex_unlock(&kp->mutex);
	}

	return 0;
}

static int pmic8058_kp_resume(struct device *dev)
{
	struct pmic8058_kp *kp = dev_get_drvdata(dev);

	if (device_may_wakeup(dev) && !pmic8058_kp_disabled(kp)) {
		disable_irq_wake(kp->key_sense_irq);
	} else {
		mutex_lock(&kp->mutex);
		pmic8058_kp_enable(kp);
		mutex_unlock(&kp->mutex);
	}

	return 0;
}

static struct dev_pm_ops pm8058_kp_pm_ops = {
	.suspend	= pmic8058_kp_suspend,
	.resume		= pmic8058_kp_resume,
};
#endif

static struct platform_driver pmic8058_kp_driver = {
	.probe		= pmic8058_kp_probe,
	.remove		= __devexit_p(pmic8058_kp_remove),
	.driver		= {
		.name = "pm8058-keypad",
		.owner = THIS_MODULE,
#ifdef CONFIG_PM
		.pm = &pm8058_kp_pm_ops,
#endif
	},
};

static int __init pmic8058_kp_init(void)
{
	return platform_driver_register(&pmic8058_kp_driver);
}
module_init(pmic8058_kp_init);

static void __exit pmic8058_kp_exit(void)
{
	platform_driver_unregister(&pmic8058_kp_driver);
}
static int gpio_keypad_config(struct pmic8058_kp *kp)
{
	struct pm8058_gpio gpiokpd_configuration = {
		.direction      = PM_GPIO_DIR_IN,
		.pull           = PM_GPIO_PULL_UP_31P5,
		.vin_sel        = 2,
		.out_strength   = PM_GPIO_STRENGTH_NO,
		.function       = PM_GPIO_FUNC_NORMAL,
		.inv_int_pol    = 0,
	};
	int rc = 0;
//-------	
	rc = pm8058_gpio_config(SILENT_KEY_UP_GPIO, &gpiokpd_configuration);	//Div2D5-OwenHung-Silent Key GPIO shift+
	if (rc < 0) {
		printk(KERN_ERR "[KEYPAD] Config GPIO %d fail", SILENT_KEY_UP_GPIO);
		return rc;
	}
	else
	{
        
		rc = gpio_request(PM8058_GPIO_PM_TO_SYS(SILENT_KEY_UP_GPIO), "silent_key_up");		//Div2D5-OwenHung-Silent Key GPIO shift+
        
		if (rc < 0)
		{
			printk(KERN_ERR "[KEYPAD] GPIO request - %d fail", SILENT_KEY_UP_GPIO);
			return rc;
		}
		else
		{
			rc = gpio_direction_input(PM8058_GPIO_PM_TO_SYS(SILENT_KEY_UP_GPIO) );		//Div2D5-OwenHung-Silent Key GPIO shift+
            
			if (rc < 0)
			{
				printk(KERN_ERR "[KEYPAD] GPIO direction - %d fail", SILENT_KEY_UP_GPIO);                
				return rc;
			}
		}
	}

	printk(KERN_INFO "[KEYPAD] Config GPIO %d OK", SILENT_KEY_UP_GPIO);	

	return rc;
}
#endif
//Div2D5-OwenHung-keypad driver porting-

/*
 * NOTE: Last row multi-interrupt issue
 *
 * In PMIC Rev A0, if any key in the last row of the keypad matrix
 * is pressed and held, the H/W keeps on generating interrupts.
 * Software work-arounds it by programming the keypad controller next level
 * up rows (for 8x12 matrix it is 15 rows) so the keypad controller
 * thinks of more-rows than the actual ones, so the actual last-row
 * in the matrix won't generate multiple interrupts.
 */
static int pmic8058_kpd_init(struct pmic8058_kp *kp)
{
	int bits, rc, cycles;
	u8 scan_val = 0, ctrl_val = 0;
	static u8 row_bits[] = {
		0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 7,
	};

	/* Find column bits */
	if (kp->pdata->num_cols < KEYP_CTRL_SCAN_COLS_MIN)
		bits = 0;
	else
		bits = kp->pdata->num_cols - KEYP_CTRL_SCAN_COLS_MIN;
	ctrl_val = (bits & KEYP_CTRL_SCAN_COLS_BITS) <<
		KEYP_CTRL_SCAN_COLS_SHIFT;

	/* Find row bits */
	if (kp->pdata->num_rows < KEYP_CTRL_SCAN_ROWS_MIN)
		bits = 0;
	else if (kp->pdata->num_rows > PM8058_MAX_ROWS)
		bits = KEYP_CTRL_SCAN_ROWS_BITS;
	else
		bits = row_bits[kp->pdata->num_rows - KEYP_CTRL_SCAN_ROWS_MIN];

	/* Use max rows to fix last row problem if actual rows are less */
	if (kp->flags & KEYF_FIX_LAST_ROW &&
			 (kp->pdata->num_rows != PM8058_MAX_ROWS))
		bits = row_bits[kp->pdata->num_rows - KEYP_CTRL_SCAN_ROWS_MIN
					 + 1];

	ctrl_val |= (bits << KEYP_CTRL_SCAN_ROWS_SHIFT);

	rc = pmic8058_kp_write_u8(kp, ctrl_val, KEYP_CTRL);

	if (pm8058_rev(kp->pm_chip) == PM_8058_REV_1p0)
		bits = fls(kp->pdata->debounce_ms[0]) - 1;
	else
		bits = (kp->pdata->debounce_ms[1] / 5) - 1;

	scan_val |= (bits << KEYP_SCAN_DBOUNCE_SHIFT);

	bits = fls(kp->pdata->scan_delay_ms) - 1;
	scan_val |= (bits << KEYP_SCAN_PAUSE_SHIFT);

	/* Row hold time is a multiple of 32KHz cycles. */
	cycles = (kp->pdata->row_hold_ns * KEYP_CLOCK_FREQ) / NSEC_PER_SEC;

	scan_val |= (cycles << KEYP_SCAN_ROW_HOLD_SHIFT);

	rc = pmic8058_kp_write_u8(kp, scan_val, KEYP_SCAN);

	return rc;
}
int pm8058_gpio_config_kypd_drv(int gpio_start, int num_gpios, unsigned mach_id)
{
	int	rc;
	struct pm8058_gpio kypd_drv = {
		.direction	= PM_GPIO_DIR_OUT,
		.pull		= PM_GPIO_PULL_NO,
		.vin_sel	= 2,
		.out_strength	= PM_GPIO_STRENGTH_LOW,
		.function	= PM_GPIO_FUNC_1,
		.inv_int_pol	= 1,
	};

	if(mach_id == LINUX_MACHTYPE_8660_QT)
		kypd_drv.function = PM_GPIO_FUNC_NORMAL;

	while (num_gpios--) {
		rc = pm8058_gpio_config(gpio_start++, &kypd_drv);
		if (rc) {
		        dprintf(INFO, "FAIL pm8058_gpio_config(): rc=%d.\n", rc);
			return rc;
		}
	}

	return 0;
}

int pm8058_gpio_config_kypd_sns(int gpio_start, int num_gpios)
{
	int	rc;
	struct pm8058_gpio kypd_sns = {
		.direction	= PM_GPIO_DIR_IN,
		.pull		= PM_GPIO_PULL_UP1,
		.vin_sel	= 2,
		.out_strength	= PM_GPIO_STRENGTH_NO,
		.function	= PM_GPIO_FUNC_NORMAL,
		.inv_int_pol	= 1,
	};

	while (num_gpios--) {
		rc = pm8058_gpio_config(gpio_start++, &kypd_sns);
		if (rc) {
		        dprintf(INFO, "FAIL pm8058_gpio_config(): rc=%d.\n", rc);
			return rc;
		}
	}

	return 0;
}

static void ssbi_gpio_init(unsigned int mach_id)
{
    unsigned char kypd_cntl_init;
    unsigned char kypd_scan_init = 0x20;
    int rows = (qwerty_keypad->keypad_info)->rows;
    int columns = (qwerty_keypad->keypad_info)->columns;
    write_func wr_function = (qwerty_keypad->keypad_info)->wr_func;
    unsigned char drv_bits[] = {
	    0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 7 };
    unsigned char sns_bits[] = { 0, 0, 0, 0, 0, 0, 1, 2, 3 };

    kypd_cntl_init = ((drv_bits[rows] << 2) | (sns_bits[columns] << 5) | (1 << 7));

    if ((*wr_function)(&kypd_cntl_init, 1, SSBI_REG_KYPD_CNTL_ADDR))
      dprintf (CRITICAL, "Error in initializing SSBI_REG_KYPD_CNTL register\n");

    if ((*wr_function)(&kypd_scan_init, 1, SSBI_REG_KYPD_SCAN_ADDR))
      dprintf (CRITICAL, "Error in initializing SSBI_REG_KYPD_SCAN register\n");

    if(mach_id == LINUX_MACHTYPE_8660_QT)
    {
        pm8058_gpio_config_kypd_sns(QT_PMIC_GPIO_KYPD_SNS, rows);
        pm8058_gpio_config_kypd_drv(QT_PMIC_GPIO_KYPD_DRV,  columns, mach_id);
    }
    else
    {
        pm8058_gpio_config_kypd_sns(SSBI_OFFSET_ADDR_GPIO_KYPD_SNS, columns);
        pm8058_gpio_config_kypd_drv(SSBI_OFFSET_ADDR_GPIO_KYPD_DRV,  rows, mach_id);
    }
}
Example #8
0
/* 
 * init method:
 */
static int msm_uart_aux_init(void)
{
	int ret = 0;
	void *res;
	dev_t dev = MKDEV( driver_major_no, 0 );

	// register class "MSM_UART_AUX"
	irda_class = class_create( THIS_MODULE, DEV_NAME );
	if( IS_ERR( irda_class ) )
	{
  		printk(KERN_ERR  DEV_NAME ":class create failed\n" );
		ret = PTR_ERR( irda_class );
		goto err_class;
	}
	pr_debug(DEV_NAME ": init_module: %s start\n", DEV_NAME );

	// Register char_dev "MSM_UART_AUX"
	if ( driver_major_no )
	{
		ret = register_chrdev_region( dev, 2, DEV_NAME );
	}
	else
	{
		ret = alloc_chrdev_region( &dev, 0, 2, DEV_NAME );
		driver_major_no = MAJOR(dev);
	}
	if ( ret < 0 )
	{
  		printk(KERN_ERR  DEV_NAME ":can't set major %d\n", driver_major_no );
		goto err_alloc;
	}
	if ( driver_major_no == 0 )
	{ 
		driver_major_no = ret;
		pr_debug(DEV_NAME ": Major no. is assigned to %d.\n", ret);
	}
	dev = MKDEV( driver_major_no, 0 );
  	printk(KERN_INFO  DEV_NAME ": UART Major No = %d\n", driver_major_no );
	cdev_init( &char_dev, &driver_fops );
	char_dev.owner = THIS_MODULE;
	ret = cdev_add( &char_dev, dev, 1 );
	if ( ret < 0 )
	{
  		printk(KERN_ERR  DEV_NAME ": cdev_add failed\n" );
		goto err_cdev;
	}
	irda_device = device_create( irda_class, NULL, dev, NULL, DEV_NAME );
	if( IS_ERR( irda_device ) )
	{
  		printk(KERN_ERR  DEV_NAME ": device create failed\n" );
		ret = PTR_ERR( irda_device );
		goto err_device;
	}

	// register driver "MSM_UART_AUX"
	ret = platform_driver_register( &irda_driver );
	if ( ret < 0 )
	{
  		printk(KERN_ERR  DEV_NAME ": platform driver register failed\n" );
		goto err_platform;
	}

	// Set UART MemBase
	res = request_mem_region(THIS_UART_MEMBASE, THIS_UART_MEMSIZE, "sir_iomem" );
	if (res < 0)
	{
		printk(KERN_ERR  DEV_NAME ":request mem region fail.\n" );
		ret = -EBUSY;
		goto err_mem;
	}
	uart_membase = (unsigned long)ioremap_nocache(THIS_UART_MEMBASE,THIS_UART_MEMSIZE);
	if ( uart_membase == 0 )
	{
		printk(KERN_ERR  DEV_NAME ":ioremap() fail.\n" );
		ret = -EBUSY;
		goto err_iomap;
	}
	pr_debug(DEV_NAME ": ioremap() retuns %x\n", (int)uart_membase);
	printk(KERN_INFO DEV_NAME ": ioremap() retuns %x\n", (int)uart_membase );

	// RX Config
/* FUJITSU:2011-09-28 gpio chg start  */
#if defined(CONFIG_MACH_F11APO) || defined(CONFIG_MACH_F12APON)
	if((system_rev != 0x08) || (system_rev != 0x0F))
	{
		uart_rx2_en_34.pull = PM_GPIO_PULL_UP_1P5;
	}
#elif defined(CONFIG_MACH_FJI12)
	if((system_rev != 0x00) || (system_rev != 0x07))
	{
		uart_rx2_en_34.pull = PM_GPIO_PULL_UP_1P5;
	}
#endif
/* FUJITSU:2011-09-28 gpio chg end  */
/* FUJITSU:2011-12-01 mod irda start  */
#if 0
	ret = pm8058_gpio_config( PM8058_UART_RX2_34, &uart_rx2_en_34 );
#else
	ret = pm8xxx_gpio_config( PM8058_UART_RX2_34, &uart_rx2_en_34 );
#endif
/* FUJITSU:2011-12-01 mod irda end  */
	
	if ( ret )
	{
		printk( KERN_ERR "%s: PM8058_UART_RX config failed[%d]\n", __func__, ret );
	}
	// SD -> High
/* FUJITSU:2011-09-28 gpio chg start  */
#if defined(CONFIG_MACH_F11APO) || defined(CONFIG_MACH_F12APON)
	if((system_rev != 0x08) || (system_rev != 0x0F))
	{
		irda_pwdown_26.output_buffer = PM_GPIO_OUT_BUF_OPEN_DRAIN;
		irda_pwdown_26.out_strength = PM_GPIO_STRENGTH_NO;
	}
#elif defined(CONFIG_MACH_FJI12)
	if((system_rev != 0x00) || (system_rev != 0x07))
	{
		irda_pwdown_26.output_buffer = PM_GPIO_OUT_BUF_OPEN_DRAIN;
		irda_pwdown_26.out_strength = PM_GPIO_STRENGTH_NO;
	}
#endif
/* FUJITSU:2011-09-28 gpio chg end  */
/* FUJITSU:2011-12-01 mod irda start  */
#if 0
	ret = pm8058_gpio_config( PM8058_IRDA_PWD_26, &irda_pwdown_26 );
#else
	ret = pm8xxx_gpio_config( PM8058_IRDA_PWD_26, &irda_pwdown_26 );
#endif
/* FUJITSU:2011-12-01 mod irda end  */
	if( ret < 0 )
	{
		printk( KERN_ERR "%s: PM8058_IRDA_PWD_26 config failed[%d]\n", __func__, ret );
	}
/* FUJITSU:2011-12-01 mod irda start  */
#if 0
	gpio_set_value_cansleep( PM8058_GPIO_PM_TO_SYS( PM8058_IRDA_PWD_26 ), 1 );
#else
	gpio_set_value_cansleep( PM8058_IRDA_PWD_26, 1 );
#endif
/* FUJITSU:2011-12-01 mod irda end  */

	// Init Normally
  	printk(KERN_INFO DEV_NAME ":Load normally\n");

  	return 0;

err_iomap:
	release_mem_region( THIS_UART_MEMBASE, THIS_UART_MEMSIZE );
err_mem:
	platform_driver_unregister( &irda_driver );
err_platform:
	device_destroy( irda_class, MKDEV( driver_major_no, 0 ) );
err_device:
	cdev_del( &char_dev );
err_cdev:
	unregister_chrdev_region( dev, 2 );
err_alloc:
	class_destroy( irda_class );
err_class:
	return ret;
}
Example #9
0
static int msm_uart_aux_chg_irda( void )
{
	int rc = 0;

	// TX
	uart_tx2_en_22.function = PM_GPIO_FUNC_2;
/* FUJITSU:2011-10-21 gpio chg start  */
#if defined(CONFIG_MACH_F11APO) || defined(CONFIG_MACH_F12APON)
	if((system_rev != 0x08) || (system_rev != 0x0F))
	{
		uart_tx2_en_22.out_strength = PM_GPIO_STRENGTH_MED;
	}
#elif defined(CONFIG_MACH_FJI12)
	if((system_rev != 0x00) || (system_rev != 0x07))
	{
		uart_tx2_en_22.out_strength = PM_GPIO_STRENGTH_MED;
	}
#endif
/* FUJITSU:2011-10-21 gpio chg end  */
/* FUJITSU:2011-12-01 mod irda start  */
#if 0
	rc = pm8058_gpio_config( PM8058_UART_TX2_22, &uart_tx2_en_22 );
#else
	rc = pm8xxx_gpio_config( PM8058_UART_TX2_22, &uart_tx2_en_22 );
#endif
/* FUJITSU:2011-12-01 mod irda end  */
	if ( rc )
	{
		printk( KERN_ERR "%s: PM8058_UART_TX config failed\n", __func__ );
		return -EIO;
	}
	// RX
/* FUJITSU:2011-09-28 gpio chg start  */
#if defined(CONFIG_MACH_F11APO) || defined(CONFIG_MACH_F12APON)
	if((system_rev != 0x08) || (system_rev != 0x0F))
	{
		uart_rx2_en_34.pull = PM_GPIO_PULL_UP_1P5;
	}
#elif defined(CONFIG_MACH_FJI12)
	if((system_rev != 0x00) || (system_rev != 0x07))
	{
		uart_rx2_en_34.pull = PM_GPIO_PULL_UP_1P5;
	}
#endif
/* FUJITSU:2011-09-28 gpio chg end  */
/* FUJITSU:2011-12-01 mod irda start  */
#if 0
	rc = pm8058_gpio_config( PM8058_UART_RX2_34, &uart_rx2_en_34 );
#else
	rc = pm8xxx_gpio_config( PM8058_UART_RX2_34, &uart_rx2_en_34 );
#endif
/* FUJITSU:2011-12-01 mod irda end  */
	if ( rc )
	{
		printk( KERN_ERR "%s: PM8058_UART_RX config failed\n", __func__ );
		return -EIO;
	}
	// PMIC
/* FUJITSU:2011-12-01 mod irda start */
#if 0
	rc = pm8058_misc_control( NULL, PM8058_UART_MUX_MASK, PM8058_UART_MUX_2 );
#else
	rc = pm8xxx_uart_gpio_mux_ctrl(UART_TX2_RX2);
#endif
/* FUJITSU:2011-12-01 mod irda end  */
	if ( rc )
	{
/* FUJITSU:2011-12-01 mod irda start */
#if 0
		printk( KERN_ERR "%s:pmM8058_misc_control failed=%d\n", __func__, rc );
#else
		printk( KERN_ERR "%s:pm8xxx_uart_gpio_mux_ctrl failed=%d\n", __func__, rc );
#endif
/* FUJITSU:2011-12-01 mod irda end  */
	}
	printk( KERN_INFO DEV_NAME " %s: UART Change -> IRDA\n", __func__ );
	// TXD
/* FUJITSU:2011-09-28 gpio chg start  */
#if defined(CONFIG_MACH_F11APO) || defined(CONFIG_MACH_F12APON)
	if((system_rev != 0x08) || (system_rev != 0x0F))
	{
		uart_pmic_txd_en_36.pull = PM_GPIO_PULL_UP_1P5;
	}
#elif(defined CONFIG_MACH_FJI12)
	if((system_rev != 0x00) || (system_rev != 0x07))
	{
		uart_pmic_txd_en_36.pull = PM_GPIO_PULL_UP_1P5;
	}
#endif
/* FUJITSU:2011-09-28 gpio chg end  */
/* FUJITSU:2011-12-01 mod irda start  */
#if 0
	rc = pm8058_gpio_config( PM8058_UART_PMIC_TXD_36, &uart_pmic_txd_en_36 );
#else
	rc = pm8xxx_gpio_config( PM8058_UART_PMIC_TXD_36, &uart_pmic_txd_en_36 );
#endif
/* FUJITSU:2011-12-01 mod irda end  */
	if ( rc )
	{
		printk( KERN_ERR "%s: PM8058_UART_PMIC_TXD config failed\n", __func__ );
		return -EIO;
	}
	// RXD
/* FUJITSU:2011-09-28 gpio chg start  */
#if defined(CONFIG_MACH_F11APO) || defined(CONFIG_MACH_F12APON)
	if((system_rev != 0x08) || (system_rev != 0x0F))
	{
		uart_pmic_rxd_en_37.out_strength = PM_GPIO_STRENGTH_MED;
		uart_pmic_rxd_en_37.pull = PM_GPIO_PULL_UP_1P5;
	}
#elif defined(CONFIG_MACH_FJI12)
	if((system_rev != 0x00) || (system_rev != 0x07))
	{
		uart_pmic_rxd_en_37.out_strength = PM_GPIO_STRENGTH_MED;
		uart_pmic_rxd_en_37.pull = PM_GPIO_PULL_UP_1P5;
	}
#endif
/* FUJITSU:2011-09-28 gpio chg end  */
/* FUJITSU:2011-12-01 mod irda start  */
#if 0
	rc = pm8058_gpio_config( PM8058_UART_PMIC_RXD_37, &uart_pmic_rxd_en_37 );
#else
	rc = pm8xxx_gpio_config( PM8058_UART_PMIC_RXD_37, &uart_pmic_rxd_en_37 );
#endif
/* FUJITSU:2011-12-01 mod irda end  */
	if ( rc )
	{
		printk( KERN_ERR "%s: PM8058_UART_PMIC_RXD config failed\n", __func__ );
		return -EIO;
	}

	// MSM
	rc = gpio_tlmm_config( GPIO_CFG( 51, 1, GPIO_CFG_INPUT,  GPIO_CFG_NO_PULL, GPIO_CFG_2MA), GPIO_CFG_ENABLE );
	if ( rc )
	{
		printk( KERN_ERR "%s: MSM8655_UART_RXD_A config failed\n", __func__ );
		return -EIO;
	}
/* FUJITSU:2011-09-28 gpio chg start  */
#if defined(CONFIG_MACH_F11APO) || defined(CONFIG_MACH_F12APON)
	if((system_rev != 0x08) || (system_rev != 0x0F))
	{
		rc = gpio_tlmm_config( GPIO_CFG( 52, 1, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP, GPIO_CFG_2MA), GPIO_CFG_ENABLE );
	}else{
		rc = gpio_tlmm_config( GPIO_CFG( 52, 1, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA), GPIO_CFG_ENABLE );
	}
#elif defined(CONFIG_MACH_FJI12)
	if((system_rev != 0x00) || (system_rev != 0x07))
	{
		rc = gpio_tlmm_config( GPIO_CFG( 52, 1, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP, GPIO_CFG_2MA), GPIO_CFG_ENABLE );
	}else{
		rc = gpio_tlmm_config( GPIO_CFG( 52, 1, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA), GPIO_CFG_ENABLE );
	}
#else
	rc = gpio_tlmm_config( GPIO_CFG( 52, 1, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA), GPIO_CFG_ENABLE );
#endif
/* FUJITSU:2011-09-28 gpio chg end  */
	if ( rc )
	{
		printk( KERN_ERR "%s: MSM8655_UART_TXD_A config failed\n", __func__ );
		return -EIO;
	}

	// SD
/* FUJITSU:2011-09-28 gpio chg start  */
#if defined(CONFIG_MACH_F11APO) || defined(CONFIG_MACH_F12APON)
	if((system_rev != 0x08) || (system_rev != 0x0F))
	{
		irda_pwdown_26.output_buffer = PM_GPIO_OUT_BUF_OPEN_DRAIN;
		irda_pwdown_26.out_strength = PM_GPIO_STRENGTH_NO;
	}
#elif defined(CONFIG_MACH_FJI12)
	if((system_rev != 0x00) || (system_rev != 0x07))
	{
		irda_pwdown_26.output_buffer = PM_GPIO_OUT_BUF_OPEN_DRAIN;
		irda_pwdown_26.out_strength = PM_GPIO_STRENGTH_NO;
	}
#endif
/* FUJITSU:2011-09-28 gpio chg end  */
/* FUJITSU:2011-12-01 mod irda start  */
#if 0
	rc = pm8058_gpio_config( PM8058_IRDA_PWD_26, &irda_pwdown_26 );
#else
	rc = pm8xxx_gpio_config( PM8058_IRDA_PWD_26, &irda_pwdown_26 );
#endif
/* FUJITSU:2011-12-01 mod irda end  */
	if( rc < 0 )
	{
		printk( KERN_ERR "%s: PM8058_IRDA_PWD_26 config failed[%d]\n", __func__, rc );
		return -EIO;
	}
	printk( KERN_INFO DEV_NAME " %s: IRDA GPIO Config Complete\n", __func__ );

	return 0;
}
static int irda_uart_release(struct inode *inode, struct file *file)
{
	down(&irc->sem);
	printk(KERN_INFO DRV_NAME ": %s\n", __func__);

	/* Decrement refcount */
	irc->refcount--;

	/* Check refcount */
	if (irc->refcount == 0) {
		/* do discard flush */
		if (irc->rx_state == IRDA_RX_START) {
			irc->rx_state = IRDA_RX_IDLE;
			msm_dmov_stop_cmd(irc->pfdata->chan_uartdm_rx,
						&irc->rxdmov_cmd, 0);
		}

		/* Deactivate RXLEV IRQ */
		irc->imr_reg &= ~BIT_RXLEV;
		msm_uartdm_write(UARTDM_IMR, irc->imr_reg);
		/* (state change)--> IRDA_UART_OPEN */
		irc->state = IRDA_UART_CLOSE;
		/* Disable the IRDA transceiver */
		msm_uartdm_write(UARTDM_IRDA, IRUART_IRDA_DISABLE);
		/* Disable Transmitter and Receiver */
		msm_uartdm_write(UARTDM_CR, BIT_UART_TX_DISABLE);
		msm_uartdm_write(UARTDM_CR, BIT_UART_RX_DISABLE);

		/* Desable TXDM and RXDM mode */
		msm_uartdm_write(UARTDM_DMEN, IRUART_IRDA_DISABLE);

		/* Wait 1usec */
		udelay(1);
		/* Setting PM power off (Hig) */
		pm8058_gpio_config(irc->pfdata->gpio_pow,
				   irc->pfdata->gpio_pwcfg_hig);

		/* Clear UART SW buffer */
		irda_txbuf_clear(&irc->txbuf);
		irda_rxbuf_clear(&irc->rxbuf);
		/* Reset TX and RX*/
		msm_uartdm_write(UARTDM_CR, CCMD_RESET_RECEIVER);
		msm_uartdm_write(UARTDM_CR, CCMD_RESET_TRANSMITTER);
		msm_uartdm_write(UARTDM_CR, CCMD_RESET_ERROR_STATUS);
		msm_uartdm_write(UARTDM_CR, CCMD_RESET_STALE_INTERRUPT);
		/* Release DMOV data */
		dma_free_coherent(NULL, sizeof(dmov_box),
					irc->txbox, irc->mapped_txbox);
		dma_free_coherent(NULL, sizeof(dmov_box),
					irc->rxbox, irc->mapped_rxbox);
		dma_free_coherent(NULL, sizeof(u32 *),
					irc->txbox_ptr, irc->mapped_txbox_ptr);
		dma_free_coherent(NULL, sizeof(u32 *),
					irc->rxbox_ptr, irc->mapped_rxbox_ptr);
		/* UARTDM clock stop */
		clk_disable(irc->clk_uartdm);
		/* UARTDM iounmap */
		if (irc->iores_uartdm)
			release_mem_region((u32) irc->pfdata->paddr_uartdm,
						UARTDM_SIZE);
		iounmap(irc->vaddr_uartdm);
		/* Remove IRQ for UARTDM */
		free_irq(irc->pfdata->irq_uartdm, irc);
		/* Remove tasklets for UARTDM */
		tasklet_kill(&irc->tasklet_rxfer_s);
		tasklet_kill(&irc->tasklet_rxfer_e);
		tasklet_kill(&irc->tasklet_txfer);
		/* PM8058 UART MUX reset */
		pm8058_misc_control(irc->nfcdev->pm_chip,
				PM8058_UART_MUX_MASK, PM8058_UART_MUX_NO);
		{
			u8 misc = 0x0;
			int ret = pm8058_read(irc->nfcdev->pm_chip,
						SSBI_REG_ADDR_MISC, &misc, 1);
			if (ret)
				printk(KERN_ERR DRV_NAME
					": cannot read pm8058 UART MUX reg.\n");
			else
				printk(KERN_INFO DRV_NAME
					": misc register = %x\n", misc);
		}
	}
	printk(KERN_INFO DRV_NAME ": Closed. Refcount = %d\n", irc->refcount);
	up(&irc->sem);

	return 0;
}
Example #11
0
static int fbx_kybd_config_gpio(void)
{
    struct pm8058_gpio button_configuration = {
        .direction      = PM_GPIO_DIR_IN,
        .pull           = PM_GPIO_PULL_DN,
        .vin_sel        = 2,
        .out_strength   = PM_GPIO_STRENGTH_NO,
        .function       = PM_GPIO_FUNC_NORMAL,
        .inv_int_pol    = 0,
    };
    int rc = 0;

    printk(KERN_INFO "%s\n", __func__);

    rc = pm8058_gpio_config(rd->pmic_gpio_vol_up, &button_configuration);
    if (rc < 0) {
        dev_err(rd->fbx_kybd_pdev, "%s: gpio %d configured failed\n", __func__, rd->pmic_gpio_vol_up);
        return rc;
    } else {
        rc = gpio_request(rd->sys_gpio_vol_up, "vol_up_key");
        if (rc < 0) {
            dev_err(rd->fbx_kybd_pdev, "%s: gpio %d requested failed\n", __func__, rd->sys_gpio_vol_up);
            return rc;
        } else {
            rc = gpio_direction_input(rd->sys_gpio_vol_up);
            if (rc < 0) {
                dev_err(rd->fbx_kybd_pdev, "%s: set gpio %d direction failed\n", __func__, rd->sys_gpio_vol_up);
                return rc;
            }
        }
    }
    
    rc = pm8058_gpio_config(rd->pmic_gpio_vol_dn, &button_configuration);
    if (rc < 0) {
        dev_err(rd->fbx_kybd_pdev, "%s: gpio %d configured failed\n", __func__, rd->pmic_gpio_vol_dn);
        return rc;
    } else {
        rc = gpio_request(rd->sys_gpio_vol_dn, "vol_down_key");
        if (rc < 0) {
            dev_err(rd->fbx_kybd_pdev, "%s: gpio %d requested failed\n", __func__, rd->sys_gpio_vol_dn);
            return rc;
        } else {
            rc = gpio_direction_input(rd->sys_gpio_vol_dn);
            if (rc < 0) {
                dev_err(rd->fbx_kybd_pdev, "%s: set gpio %d direction failed\n", __func__, rd->sys_gpio_vol_dn);
                return rc;
            }
        }
    }
 
    if (rd->product_phase == Product_PR1 || rd->product_phase == Product_EVB) {
        rc = pm8058_gpio_config(rd->pmic_gpio_cam_t, &button_configuration);
        if (rc < 0) {
            dev_err(rd->fbx_kybd_pdev, "%s: gpio %d configured failed\n", __func__, rd->pmic_gpio_cam_t);
            return rc;
        } else {
            rc = gpio_request(rd->sys_gpio_cam_t, "camera_key");
            if (rc < 0) {
                dev_err(rd->fbx_kybd_pdev, "%s: gpio %d requested failed\n", __func__, rd->sys_gpio_cam_t);
                return rc;
            } else {
                rc = gpio_direction_input(rd->sys_gpio_cam_t);
                if (rc < 0) {
                    dev_err(rd->fbx_kybd_pdev, "%s: set gpio %d direction failed\n", __func__, rd->sys_gpio_cam_t);
                    return rc;
                }
            }
        }
        
        rc = pm8058_gpio_config(rd->pmic_gpio_cam_f, &button_configuration);
        if (rc < 0) {
            dev_err(rd->fbx_kybd_pdev, "%s: gpio %d configured failed\n", __func__, rd->pmic_gpio_cam_f);
            return rc;
        } else {
            rc = gpio_request(rd->sys_gpio_cam_f, "camera_focus_key");
            if (rc < 0) {
                dev_err(rd->fbx_kybd_pdev, "%s: gpio %d requested failed\n", __func__, rd->sys_gpio_cam_f);
                return rc;
            } else {
                rc = gpio_direction_input(rd->sys_gpio_cam_f); 
                if (rc < 0) {
                    dev_err(rd->fbx_kybd_pdev, "%s: set gpio %d direction failed\n", __func__, rd->sys_gpio_cam_f);
                    return rc;
                }
            }
        }
    }
    
    /* Div1-FW3-BSP-AUDIO */
    rc = gpio_request(rd->hook_sw_pin, "gpio_hook_sw");
    if (rc) {
        printk("gpio_request failed on pin(rc=%d)\n", rc);
        return rc;
    }
    rc = gpio_direction_input(rd->hook_sw_pin);
    if (rc) {
        printk("gpio_direction_input failed on pin rc=%d\n", rc);
        return rc;
    }
    
    return rc;
}

static void fbx_kybd_volup(struct work_struct *work)
{
    struct fbx_kybd_record *kbdrec  = container_of(work, struct fbx_kybd_record, qkybd_volup);
    struct input_dev *idev          = kbdrec->fbx_kybd_idev;
    bool gpio_val                   = (bool)gpio_get_value_cansleep(kbdrec->sys_gpio_vol_up);
    
    dev_dbg(kbdrec->fbx_kybd_pdev, "%s: Key VOLUMEUP (%d) %s\n", __func__, KEY_VOLUMEUP, !gpio_val ? "was RELEASED" : "is PRESSING");

    if (!gpio_val) {
        input_report_key(idev, KEY_VOLUMEUP, KEYRELEASE); 
    } else {
        input_report_key(idev, KEY_VOLUMEUP, KEYPRESS);
    }
 
    input_sync(idev);
}

static void fbx_kybd_voldn(struct work_struct *work)
{
    struct fbx_kybd_record *kbdrec  = container_of(work, struct fbx_kybd_record, qkybd_voldn);
    struct input_dev *idev          = kbdrec->fbx_kybd_idev;
    bool gpio_val                   = (bool)gpio_get_value_cansleep(kbdrec->sys_gpio_vol_dn);
    
    dev_dbg(kbdrec->fbx_kybd_pdev, "%s: Key VOLUMEDOWN (%d) %s\n", __func__, KEY_VOLUMEDOWN, !gpio_val ? "was RELEASED" : "is PRESSING");

    if (!gpio_val) {
        input_report_key(idev, KEY_VOLUMEDOWN, KEYRELEASE); 
    } else {
        input_report_key(idev, KEY_VOLUMEDOWN, KEYPRESS);
    }
 
    input_sync(idev);
}

static void fbx_kybd_camf(struct work_struct *work)
{
    struct fbx_kybd_record *kbdrec  = container_of(work, struct fbx_kybd_record, qkybd_camf);
    struct input_dev *idev          = kbdrec->fbx_kybd_idev;
    bool gpio_val                   = (bool)gpio_get_value_cansleep(kbdrec->sys_gpio_cam_f);
    
    dev_dbg(kbdrec->fbx_kybd_pdev, "%s: Key FOCUS (%d) %s\n", __func__, KEY_FOCUS, !gpio_val ? "was RELEASED" : "is PRESSING");

    if (!gpio_val) {
        input_report_key(idev, KEY_FOCUS, KEYRELEASE); 
    } else {
        input_report_key(idev, KEY_FOCUS, KEYPRESS);
    }
 
    input_sync(idev);
}

static void fbx_kybd_camt(struct work_struct *work)
{
    struct fbx_kybd_record *kbdrec  = container_of(work, struct fbx_kybd_record, qkybd_camt);
    struct input_dev *idev          = kbdrec->fbx_kybd_idev;
    bool gpio_val                   = (bool)gpio_get_value_cansleep(kbdrec->sys_gpio_cam_t);

    dev_dbg(kbdrec->fbx_kybd_pdev, "%s: Key CAMERA (%d) %s\n", __func__, KEY_CAMERA, !gpio_val ? "was RELEASED" : "is PRESSING");

    if (!gpio_val) {
        input_report_key(idev, KEY_CAMERA, KEYRELEASE); 
    } else {
        input_report_key(idev, KEY_CAMERA, KEYPRESS);
    }
 
    input_sync(idev);
}

/* Div1-FW3-BSP-AUDIO */
static void fbx_kybd_hooksw(struct work_struct *work)
{
    //MM-SL-DisableHookInFTM-oo*{
    #ifndef CONFIG_FIH_FTM  
    struct fbx_kybd_record *kbdrec= container_of(work, struct fbx_kybd_record, hook_switchkey);  
    struct input_dev *idev        = kbdrec->fbx_kybd_idev;  
    bool hook_sw_val              = (bool)gpio_get_value_cansleep(kbdrec->hook_sw_pin);
    bool headset_status           = (bool)gpio_get_value_cansleep(26);


    if((rd->hooksw_irq_enable == true) && (headset_status == 1)){
        disable_irq(MSM_GPIO_TO_INT(kbdrec->hook_sw_pin));
        if(idev)
        {
            if (hook_sw_val) {
                report_hs_key(HS_HEADSET_SWITCH_K, HS_REL_K);
                printk("FIH: keyrelease KEY_HEADSETHOOK\n");
            } else {
                report_hs_key(HS_HEADSET_SWITCH_K, HS_NONE_K);
                printk("FIH: keypress KEY_HEADSETHOOK\n");              
            }
            input_sync(idev);       
        }
        enable_irq(MSM_GPIO_TO_INT(kbdrec->hook_sw_pin));
        enable_irq_wake(MSM_GPIO_TO_INT(kbdrec->hook_sw_pin));
    }
    #endif
    //MM-SL-DisableHookInFTM-oo*} 	
}

static void fbx_kybd_free_irq(void)
{
    free_irq(PM8058_GPIO_IRQ(PMIC8058_IRQ_BASE, rd->pmic_gpio_vol_up), rd);
    free_irq(PM8058_GPIO_IRQ(PMIC8058_IRQ_BASE, rd->pmic_gpio_vol_dn), rd);
    if (rd->product_phase == Product_PR1 || rd->product_phase == Product_EVB) {
        free_irq(PM8058_GPIO_IRQ(PMIC8058_IRQ_BASE, rd->pmic_gpio_cam_f), rd);
        free_irq(PM8058_GPIO_IRQ(PMIC8058_IRQ_BASE, rd->pmic_gpio_cam_t), rd);
    }
    /* Div1-FW3-BSP-AUDIO */
    free_irq(MSM_GPIO_TO_INT(rd->hook_sw_pin), rd);
}
Example #12
0
static int mmc_host_io_ctrl(int cmd)
{
	int rc;

    switch (cmd){
    case SD_CFG_POWER_ON:
/* FUJITSU:2011-05-24 mmc_host start  */
/* FUJITSU:2011-06-08 mmc_host start  */
        rc = msm_gpios_enable(gpio_sdcard_poweron, ARRAY_SIZE(gpio_sdcard_poweron));
        if (rc >= 0){
/* FUJITSU:2011-06-08 mmc_host end  */

            gpio_set_value(SD_GPIONO_SD_RST, 0);    /* SD_RST(GPIO[168])   -> 'L' */

#if 0 /* FUJITSU:2011/07/19 del for Sky-SDCC start */
	        rc = pm8058_gpio_config(SD_GPIONO_SD_CLK_EN, &sdc4_en);
	        if (rc) {
	            pr_err("%s SD_GPIONO_SD_CLK_EN config failed\n",
	                                 __func__);
	        }
	        gpio_set_value_cansleep(
	            PM8058_GPIO_PM_TO_SYS(SD_GPIONO_SD_CLK_EN), 0);
#endif/* FUJITSU:2011/07/19 mod for Sky-SDCC end */

        }else{
            pr_err("%s: GPIO_POWER_ON failed\n",
                                 __func__);
            return -1;
        }
/* FUJITSU:2011-05-24 mmc_host end  */
        break;

    case SD_CFG_POWER_OFF:
/* FUJITSU:2011-05-24 mmc_host start  */
/* FUJITSU:2011-06-08 mmc_host start  */
        rc = msm_gpios_enable(gpio_sdcard_poweroff, ARRAY_SIZE(gpio_sdcard_poweroff));
        if (rc >= 0){
/* FUJITSU:2011-06-08 mmc_host end  */
            gpio_set_value(SD_GPIONO_SD_RST, 0);    /* SD_RST(GPIO[168])   -> 'L' */
#if 0 /* FUJITSU:2011/08/04 del for Sky-SDCC start */
            gpio_set_value(SD_GPIONO_SD_CLK, 0);    /* SD_CLK(GPIO[98])    -> 'L' */
#endif/* FUJITSU:2011/08/04 del for Sky-SDCC end */

#if 0 /* FUJITSU:2011/07/19 del for Sky-SDCC start */
	        rc = pm8058_gpio_config(SD_GPIONO_SD_CLK_EN, &sdc4_en);
	        if (rc) {
	            pr_err("%s SD_GPIONO_SD_CLK_EN config failed\n",
	                                 __func__);
	        }
	        gpio_set_value_cansleep(
	            PM8058_GPIO_PM_TO_SYS(SD_GPIONO_SD_CLK_EN), 0);
#endif/* FUJITSU:2011/07/19 del for Sky-SDCC end */
        
        }else{
            printk(KERN_ERR "%s: GPIO_POWER_OFF\n",
                   __func__);
            return -1;
        }
/* FUJITSU:2011-05-24 mmc_host end  */

        break;

    case SD_RST_ON:
        XYZ("SD_RST is '%c' +", gpio_get_value(SD_GPIONO_SD_RST) ? 'H' : 'L');
/* FUJITSU:2011-05-24 mmc_host start */
        gpio_set_value(SD_GPIONO_SD_RST, 1);
/* FUJITSU:2011-05-24 mmc_host end  */
        XYZ("SD_RST is '%c' +", gpio_get_value(SD_GPIONO_SD_RST) ? 'H' : 'L');
        break;
#if 0
    case SD_RST_OFF:
        XYZ("SD_RST is '%c' +", gpio_get_value(SD_GPIONO_SD_RST) ? 'H' : 'L');
        gpio_set_value(SD_GPIONO_SD_RST, 0);
        XYZ("SD_RST is '%c' +", gpio_get_value(SD_GPIONO_SD_RST) ? 'H' : 'L');
        break;
#endif

    case SD_VDD_ON:
/* FUJITSU:2011-05-24 mmc_host start  */
        vreg_sdc = vreg_get(NULL, "gp6"/*"mmc"*/);
        if (IS_ERR(vreg_sdc)) {
            printk(KERN_ERR "%s: vreg get failed (%ld)\n",
                   __func__, PTR_ERR(vreg_sdc));
            break;
        }
        rc = vreg_set_level(vreg_sdc, 2900);
        if (rc)
            printk(KERN_ERR "%s: vreg_set_level() = %d \n",	__func__, rc);
        rc = vreg_enable(vreg_sdc);
        if (rc)
            printk(KERN_ERR "%s: vreg_enable() = %d \n",	__func__, rc);
/* FUJITSU:2011-05-24 mmc_host end  */
        break;

    case SD_VDD_OFF:
/* FUJITSU:2011-05-24 mmc_host start  */
        vreg_sdc = vreg_get(NULL, "gp6"/*"mmc"*/);
        if (IS_ERR(vreg_sdc)) {
            printk(KERN_ERR "%s: vreg get failed (%ld)\n",
                   __func__, PTR_ERR(vreg_sdc));
            break;
        }
        vreg_disable(vreg_sdc);
/* FUJITSU:2011-05-24 mmc_host end  */
        break;

    case SDC_CLK_ON:
#if 1 /* FUJITSU:2011/07/19 mod for Sky-SDCC start */
        XYZ("SD_CLK_EN is '%c' +", gpio_get_value(SD_GPIONO_SD_CLK_EN) ? 'H' : 'L');
        gpio_set_value(SD_GPIONO_SD_CLK_EN, 1);
        XYZ("SD_CLK_EN is '%c' +", gpio_get_value(SD_GPIONO_SD_CLK_EN) ? 'H' : 'L');
#else
        XYZ("SD_CLK_EN is '%c' +", gpio_get_value_cansleep(PM8058_GPIO_PM_TO_SYS(SD_GPIONO_SD_CLK_EN)) ? 'H' : 'L');
/* FUJITSU:2011-05-24 mmc_host start */
//        gpio_set_value(SD_GPIONO_SD_CLK_EN, 1);
//        gpio_set_value_cansleep(PM8058_GPIO_PM_TO_SYS(SD_GPIONO_SD_CLK_EN), 1);
        if( ((system_rev & 0x0f) >= PRODUCT_F11SKY_2_0) && ((system_rev & 0x0f) != PRODUCT_F11SKY_EVM) ) {
        	XYZ("SD_CLK_ON is set L MODEL = %Xh ",system_rev);
            gpio_set_value_cansleep(PM8058_GPIO_PM_TO_SYS(SD_GPIONO_SD_CLK_EN), 0);
        }else{
        	XYZ("SD_CLK_ON is set H MODEL = %Xh ",system_rev);
            gpio_set_value_cansleep(PM8058_GPIO_PM_TO_SYS(SD_GPIONO_SD_CLK_EN), 1);
        }
/* FUJITSU:2011-05-24 mmc_host end  */
        XYZ("SD_CLK_EN is '%c' +", gpio_get_value_cansleep(PM8058_GPIO_PM_TO_SYS(SD_GPIONO_SD_CLK_EN)) ? 'H' : 'L');
#endif/* FUJITSU:2011/07/19 mod for Sky-SDCC end */
        break;

    case SDC_CLK_OFF:
#if 1 /* FUJITSU:2011/07/19 mod for Sky-SDCC start */
        XYZ("SD_CLK_EN is '%c' +", gpio_get_value(SD_GPIONO_SD_CLK_EN) ? 'H' : 'L');
        gpio_set_value(SD_GPIONO_SD_CLK_EN, 0);
        XYZ("SD_CLK_EN is '%c' +", gpio_get_value(SD_GPIONO_SD_CLK_EN) ? 'H' : 'L');
#else
        XYZ("SD_CLK_EN is '%c' +", gpio_get_value_cansleep(PM8058_GPIO_PM_TO_SYS(SD_GPIONO_SD_CLK_EN)) ? 'H' : 'L');
/* FUJITSU:2011-05-24 mmc_host start  */
//        gpio_set_value(SD_GPIONO_SD_CLK_EN, 0);
        gpio_set_value_cansleep(PM8058_GPIO_PM_TO_SYS(SD_GPIONO_SD_CLK_EN), 0);
/* FUJITSU:2011-05-24 mmc_host end  */
        XYZ("SD_CLK_EN is '%c' +", gpio_get_value_cansleep(PM8058_GPIO_PM_TO_SYS(SD_GPIONO_SD_CLK_EN)) ? 'H' : 'L');
#endif/* FUJITSU:2011/07/19 mod for Sky-SDCC end */
        break;

    default:
        return -1;
    }
    return 0;
}
Example #13
0
int backlight_pwm_gpio_config(void)
{
    int rc;
	struct pm8058_gpio backlight_drv = 
	{
		.direction      = PM_GPIO_DIR_OUT,
		.output_buffer  = PM_GPIO_OUT_BUF_CMOS,
		.output_value   = 0,
		.pull           = PM_GPIO_PULL_NO,
		.vin_sel        = 0,
		.out_strength   = PM_GPIO_STRENGTH_HIGH,
		.function       = PM_GPIO_FUNC_2,
		.inv_int_pol 	= 1,
	};
	/* U8800 use PM_GPIO25 as backlight's PWM,but U8820 use PM_GPIO26 */
    if(machine_is_msm7x30_u8800() || machine_is_msm7x30_u8800_51() || machine_is_msm8255_u8800_pro())
	{
        rc = pm8058_gpio_config( 24, &backlight_drv);
    }
    else if(machine_is_msm7x30_u8820()) 
    {
    	rc = pm8058_gpio_config( 25, &backlight_drv);
    }
	else
	{
    	rc = -1;
	}
	
    if (rc) 
	{
		pr_err("%s LCD backlight GPIO config failed\n", __func__);
		return rc;
	}
    return 0;
}
#ifndef CONFIG_HUAWEI_LEDS_PMIC
void touchkey_setbacklight(int level)
{
    if(machine_is_msm7x30_u8800() || machine_is_msm7x30_u8800_51() || machine_is_msm8255_u8800_pro()) 
	{
		pmic_set_led_intensity(LED_KEYPAD, level);
	}

    if(machine_is_msm7x30_u8820())
    {   
		/*if the machine is U8820 use the mpp6 for touchkey backlight*/
        pmic_set_mpp6_led_intensity(level);
    }

}
#endif
void pwm_set_backlight (struct msm_fb_data_type * mfd)
{
	int bl_level = mfd->bl_level;
	/*config PM GPIO25 as PWM and request PWM*/
	if(TRUE == first_set_bl)
	{
	    backlight_pwm_gpio_config();
		/* U8800 use PM_GPIO25 as backlight's PWM,but U8820 use PM_GPIO26 */
		if(machine_is_msm7x30_u8800() || machine_is_msm7x30_u8800_51() || machine_is_msm8255_u8800_pro())
		{
			bl_pwm = pwm_request(PM_GPIO25_PWM_ID, "backlight");
		}
		else if(machine_is_msm7x30_u8820())
		{
			bl_pwm = pwm_request(PM_GPIO26_PWM_ID, "backlight");
		}
		else
		{
			bl_pwm = NULL;
		}
		
	    if (NULL == bl_pwm || IS_ERR(bl_pwm)) 
		{
	    	pr_err("%s: pwm_request() failed\n", __func__);
	    	bl_pwm = NULL;
	    }
	    first_set_bl = FALSE;

	}
	if (bl_pwm) 
	{
		/* keep duty 10% < level < 90% */
		if (bl_level)
		{
			bl_level = ((bl_level * PWM_LEVEL_ADJUST) / PWM_LEVEL + ADD_VALUE); 
			if (bl_level < BL_MIN_LEVEL)
			{
				bl_level = BL_MIN_LEVEL;
			}
		}
		pwm_config(bl_pwm, PWM_DUTY_LEVEL*bl_level/NSEC_PER_USEC, PWM_PERIOD/NSEC_PER_USEC);
		pwm_enable(bl_pwm);
	}
#ifndef CONFIG_HUAWEI_LEDS_PMIC
	touchkey_setbacklight(!!bl_level);
#endif

}
Example #14
0
static int pm8058_kp_config_drv(int gpio_start, int num_gpios)
{
	int	rc;
	struct pm8058_gpio kypd_drv = {
		.direction	= PM_GPIO_DIR_OUT,
		.output_buffer	= PM_GPIO_OUT_BUF_OPEN_DRAIN,
		.output_value	= 0,
		.pull		= PM_GPIO_PULL_NO,
		.vin_sel	= 2,
		.out_strength	= PM_GPIO_STRENGTH_LOW,
		.function	= PM_GPIO_FUNC_1,
		.inv_int_pol	= 1,
	};

	if (gpio_start < 0 || num_gpios < 0 || num_gpios > PM8058_GPIOS)
		return -EINVAL;

	while (num_gpios--) {
		rc = pm8058_gpio_config(gpio_start++, &kypd_drv);
		if (rc) {
			pr_err("%s: FAIL pm8058_gpio_config(): rc=%d.\n",
				__func__, rc);
			return rc;
		}
	}

	return 0;
}

static int pm8058_kp_config_sns(int gpio_start, int num_gpios)
{
	int	rc;
	struct pm8058_gpio kypd_sns = {
		.direction	= PM_GPIO_DIR_IN,
		.pull		= PM_GPIO_PULL_UP_31P5,
		.vin_sel	= 2,
		.out_strength	= PM_GPIO_STRENGTH_NO,
		.function	= PM_GPIO_FUNC_NORMAL,
		.inv_int_pol	= 1,
	};

	if (gpio_start < 0 || num_gpios < 0 || num_gpios > PM8058_GPIOS)
		return -EINVAL;

	while (num_gpios--) {
		rc = pm8058_gpio_config(gpio_start++, &kypd_sns);
		if (rc) {
			pr_err("%s: FAIL pm8058_gpio_config(): rc=%d.\n",
				__func__, rc);
			return rc;
		}
	}

	return 0;
}


static int __devinit pmic8058_kp_probe(struct platform_device *pdev)
{
	struct pmic8058_keypad_data *pdata = pdev->dev.platform_data;
	struct pmic8058_kp *kp;
	int rc, i;
	unsigned short *keycodes;
	u8 ctrl_val;
	struct pm8058_chip	*pm_chip;

	pm_chip = platform_get_drvdata(pdev);
	if (pm_chip == NULL) {
		dev_err(&pdev->dev, "no parent data passed in\n");
		return -EFAULT;
	}

	if (!pdata || !pdata->num_cols || !pdata->num_rows ||
		pdata->num_cols > MATRIX_MAX_COLS ||
		pdata->num_rows > MATRIX_MAX_ROWS ||
		pdata->num_cols < MATRIX_MIN_COLS ||
		pdata->num_rows < MATRIX_MIN_ROWS ||
		!pdata->keymap) {
		dev_err(&pdev->dev, "invalid platform data\n");
		return -EINVAL;
	}

	if (pdata->rows_gpio_start < 0 || pdata->cols_gpio_start < 0) {
		dev_err(&pdev->dev, "invalid gpio_start platform data\n");
		return -EINVAL;
	}

	if (!pdata->scan_delay_ms || pdata->scan_delay_ms > MAX_SCAN_DELAY
		|| pdata->scan_delay_ms < MIN_SCAN_DELAY ||
		!is_power_of_2(pdata->scan_delay_ms)) {
		dev_err(&pdev->dev, "invalid keypad scan time supplied\n");
		return -EINVAL;
	}

	if (!pdata->row_hold_ns || pdata->row_hold_ns > MAX_ROW_HOLD_DELAY
		|| pdata->row_hold_ns < MIN_ROW_HOLD_DELAY ||
		((pdata->row_hold_ns % MIN_ROW_HOLD_DELAY) != 0)) {
		dev_err(&pdev->dev, "invalid keypad row hold time supplied\n");
		return -EINVAL;
	}

	if (pm8058_rev(pm_chip) == PM_8058_REV_1p0) {
		if (!pdata->debounce_ms
			|| !is_power_of_2(pdata->debounce_ms[0])
			|| pdata->debounce_ms[0] > MAX_DEBOUNCE_A0_TIME
			|| pdata->debounce_ms[0] < MIN_DEBOUNCE_A0_TIME) {
			dev_err(&pdev->dev, "invalid debounce time supplied\n");
			return -EINVAL;
		}
	} else {
		if (!pdata->debounce_ms
			|| ((pdata->debounce_ms[1] % 5) != 0)
			|| pdata->debounce_ms[1] > MAX_DEBOUNCE_B0_TIME
			|| pdata->debounce_ms[1] < MIN_DEBOUNCE_B0_TIME) {
			dev_err(&pdev->dev, "invalid debounce time supplied\n");
			return -EINVAL;
		}
	}

	kp = kzalloc(sizeof(*kp), GFP_KERNEL);
	if (!kp)
		return -ENOMEM;

	keycodes = kzalloc(MATRIX_MAX_SIZE * sizeof(keycodes), GFP_KERNEL);
	if (!keycodes) {
		rc = -ENOMEM;
		goto err_alloc_mem;
	}

	platform_set_drvdata(pdev, kp);

	kp->pdata	= pdata;
	kp->dev		= &pdev->dev;
	kp->keycodes	= keycodes;
	kp->pm_chip	= pm_chip;

	if (pm8058_rev(pm_chip) == PM_8058_REV_1p0)
		kp->flags |= KEYF_FIX_LAST_ROW;

	kp->input = input_allocate_device();
	if (!kp->input) {
		dev_err(&pdev->dev, "unable to allocate input device\n");
		rc = -ENOMEM;
		goto err_alloc_device;
	}

	kp->key_sense_irq = platform_get_irq(pdev, 0);
	if (kp->key_sense_irq < 0) {
		dev_err(&pdev->dev, "unable to get keypad sense irq\n");
		rc = -ENXIO;
		goto err_get_irq;
	}

	kp->key_stuck_irq = platform_get_irq(pdev, 1);
	if (kp->key_stuck_irq < 0) {
		dev_err(&pdev->dev, "unable to get keypad stuck irq\n");
		rc = -ENXIO;
		goto err_get_irq;
	}

	if (pdata->input_name)
		kp->input->name = pdata->input_name;
	else
		kp->input->name = "PMIC8058 keypad";

	if (pdata->input_phys_device)
		kp->input->phys = pdata->input_phys_device;
	else
		kp->input->phys = "pmic8058_keypad/input0";

	kp->input->dev.parent	= &pdev->dev;

	kp->input->id.bustype	= BUS_HOST;
	kp->input->id.version	= 0x0001;
	kp->input->id.product	= 0x0001;
	kp->input->id.vendor	= 0x0001;

	kp->input->evbit[0]	= BIT_MASK(EV_KEY);

	if (pdata->rep)
		__set_bit(EV_REP, kp->input->evbit);

	kp->input->keycode	= keycodes;
	kp->input->keycodemax	= MATRIX_MAX_SIZE;
	kp->input->keycodesize	= sizeof(*keycodes);

	
	for (i = 0; i < pdata->keymap_size; i++) {
		unsigned int row = KEY_ROW(pdata->keymap[i]);
		unsigned int col = KEY_COL(pdata->keymap[i]);
		unsigned short keycode = KEY_VAL(pdata->keymap[i]);

		keycodes[(row << 3) + col] = keycode;
		__set_bit(keycode, kp->input->keybit);
	}
	__clear_bit(KEY_RESERVED, kp->input->keybit);

	input_set_capability(kp->input, EV_MSC, MSC_SCAN);
	input_set_drvdata(kp->input, kp);

	rc = input_register_device(kp->input);
	if (rc < 0) {
		dev_err(&pdev->dev, "unable to register keypad input device\n");
		goto err_get_irq;
	}

	
	memset(kp->keystate, 0xff, sizeof(kp->keystate));
	memset(kp->stuckstate, 0xff, sizeof(kp->stuckstate));

	rc = pmic8058_kpd_init(kp);
	if (rc < 0) {
		dev_err(&pdev->dev, "unable to initialize keypad controller\n");
		goto err_kpd_init;
	}

	rc = pm8058_kp_config_sns(pdata->cols_gpio_start,
			pdata->num_cols);
	if (rc < 0) {
		dev_err(&pdev->dev, "unable to configure keypad sense lines\n");
		goto err_gpio_config;
	}

	rc = pm8058_kp_config_drv(pdata->rows_gpio_start,
			pdata->num_rows);
	if (rc < 0) {
		dev_err(&pdev->dev, "unable to configure keypad drive lines\n");
		goto err_gpio_config;
	}

	rc = request_irq(kp->key_sense_irq, pmic8058_kp_irq,
				 IRQF_TRIGGER_RISING, "pmic-keypad", kp);
	if (rc < 0) {
		dev_err(&pdev->dev, "failed to request keypad sense irq\n");
		goto err_req_sense_irq;
	}

	rc = request_irq(kp->key_stuck_irq, pmic8058_kp_stuck_irq,
				 IRQF_TRIGGER_RISING, "pmic-keypad-stuck", kp);
	if (rc < 0) {
		dev_err(&pdev->dev, "failed to request keypad stuck irq\n");
		goto err_req_stuck_irq;
	}

	rc = pmic8058_kp_read(kp, &ctrl_val, KEYP_CTRL, 1);
	ctrl_val |= KEYP_CTRL_KEYP_EN;
	rc = pmic8058_kp_write_u8(kp, ctrl_val, KEYP_CTRL);

	__dump_kp_regs(kp, "probe");

	device_init_wakeup(&pdev->dev, pdata->wakeup);

	return 0;

err_req_stuck_irq:
	free_irq(kp->key_sense_irq, NULL);
err_req_sense_irq:
err_gpio_config:
err_kpd_init:
	input_unregister_device(kp->input);
	kp->input = NULL;
err_get_irq:
	input_free_device(kp->input);
err_alloc_device:
	kfree(keycodes);
err_alloc_mem:
	kfree(kp);
	return rc;
}

static int __devexit pmic8058_kp_remove(struct platform_device *pdev)
{
	struct pmic8058_kp *kp = platform_get_drvdata(pdev);

	device_init_wakeup(&pdev->dev, 0);
	free_irq(kp->key_stuck_irq, NULL);
	free_irq(kp->key_sense_irq, NULL);
	input_unregister_device(kp->input);
	platform_set_drvdata(pdev, NULL);
	kfree(kp->input->keycode);
	kfree(kp);

	return 0;
}

static struct platform_driver pmic8058_kp_driver = {
	.probe		= pmic8058_kp_probe,
	.remove		= __devexit_p(pmic8058_kp_remove),
	.driver		= {
		.name = "pm8058-keypad",
		.owner = THIS_MODULE,
#ifdef CONFIG_PM
		.pm = &pm8058_kp_pm_ops,
#endif
	},
};

static int __init pmic8058_kp_init(void)
{
	return platform_driver_register(&pmic8058_kp_driver);
}
module_init(pmic8058_kp_init);

static void __exit pmic8058_kp_exit(void)
{
	platform_driver_unregister(&pmic8058_kp_driver);
}
Example #15
0
static int fbx_kybd_suspend(struct platform_device *pdev, pm_message_t state)
{
    struct pm8058_gpio button_configuration = {
        .direction      = PM_GPIO_DIR_OUT,
        .pull           = PM_GPIO_PULL_DN,
        .vin_sel        = 2,
        .out_strength   = PM_GPIO_STRENGTH_NO,
        .function       = PM_GPIO_FUNC_NORMAL,
        .inv_int_pol    = 0,
    };
    int rc = 0;

    printk(KERN_INFO "%s\n", __func__);

    rc = pm8058_gpio_config(rd->pmic_gpio_vol_up, &button_configuration);
    if (rc < 0) {
        dev_err(rd->fbx_kybd_pdev, "%s: gpio %d configured failed\n", __func__, rd->pmic_gpio_vol_up);
        return rc;
    } else {
        rc = gpio_direction_output(rd->sys_gpio_vol_up, 0);
        if (rc < 0) {
            dev_err(rd->fbx_kybd_pdev, "%s: set gpio %d direction failed\n", __func__, rd->sys_gpio_vol_up);
            return rc;
        }
    }
    
    rc = pm8058_gpio_config(rd->pmic_gpio_vol_dn, &button_configuration);
    if (rc < 0) {
        dev_err(rd->fbx_kybd_pdev, "%s: gpio %d configured failed\n", __func__, rd->pmic_gpio_vol_dn);
        return rc;
    } else {
        rc = gpio_direction_output(rd->sys_gpio_vol_dn, 0);
        if (rc < 0) {
            dev_err(rd->fbx_kybd_pdev, "%s: set gpio %d direction failed\n", __func__, rd->sys_gpio_vol_dn);
            return rc;
        }
    }
 
    if (rd->product_phase == Product_PR1 || rd->product_phase == Product_EVB) {
        rc = pm8058_gpio_config(rd->pmic_gpio_cam_t, &button_configuration);
        if (rc < 0) {
            dev_err(rd->fbx_kybd_pdev, "%s: gpio %d configured failed\n", __func__, rd->pmic_gpio_cam_t);
            return rc;
        } else {
            rc = gpio_direction_output(rd->sys_gpio_cam_t, 0);
            if (rc < 0) {
                dev_err(rd->fbx_kybd_pdev, "%s: set gpio %d direction failed\n", __func__, rd->sys_gpio_cam_t);
                return rc;
            }
        }
        
        rc = pm8058_gpio_config(rd->pmic_gpio_cam_f, &button_configuration);
        if (rc < 0) {
            dev_err(rd->fbx_kybd_pdev, "%s: gpio %d configured failed\n", __func__, rd->pmic_gpio_cam_f);
            return rc;
        } else {
            rc = gpio_direction_output(rd->sys_gpio_cam_f, 0); 
            if (rc < 0) {
                dev_err(rd->fbx_kybd_pdev, "%s: set gpio %d direction failed\n", __func__, rd->sys_gpio_cam_f);
                return rc;
            }
        }
    }
 
    return 0;
}

static int fbx_kybd_resume(struct platform_device *pdev)
{
    struct pm8058_gpio button_configuration = {
        .direction      = PM_GPIO_DIR_IN,
        .pull           = PM_GPIO_PULL_DN,
        .vin_sel        = 2,
        .out_strength   = PM_GPIO_STRENGTH_NO,
        .function       = PM_GPIO_FUNC_NORMAL,
        .inv_int_pol    = 0,
    };
    int rc = 0;

    printk(KERN_INFO "%s\n", __func__);

    rc = pm8058_gpio_config(rd->pmic_gpio_vol_up, &button_configuration);
    if (rc < 0) {
        dev_err(rd->fbx_kybd_pdev, "%s: gpio %d configured failed\n", __func__, rd->pmic_gpio_vol_up);
        return rc;
    } else {
        rc = gpio_direction_input(rd->sys_gpio_vol_up);
        if (rc < 0) {
            dev_err(rd->fbx_kybd_pdev, "%s: set gpio %d direction failed\n", __func__, rd->sys_gpio_vol_up);
            return rc;
        }
    }
    
    rc = pm8058_gpio_config(rd->pmic_gpio_vol_dn, &button_configuration);
    if (rc < 0) {
        dev_err(rd->fbx_kybd_pdev, "%s: gpio %d configured failed\n", __func__, rd->pmic_gpio_vol_dn);
        return rc;
    } else {
        rc = gpio_direction_input(rd->sys_gpio_vol_dn);
        if (rc < 0) {
            dev_err(rd->fbx_kybd_pdev, "%s: set gpio %d direction failed\n", __func__, rd->sys_gpio_vol_dn);
            return rc;
        }
    }

    if (rd->product_phase == Product_PR1 || rd->product_phase == Product_EVB) {
        rc = pm8058_gpio_config(rd->pmic_gpio_cam_t, &button_configuration);
        if (rc < 0) {
            dev_err(rd->fbx_kybd_pdev, "%s: gpio %d configured failed\n", __func__, rd->pmic_gpio_cam_t);
            return rc;
        } else {
            rc = gpio_direction_input(rd->sys_gpio_cam_t);
            if (rc < 0) {
                dev_err(rd->fbx_kybd_pdev, "%s: set gpio %d direction failed\n", __func__, rd->sys_gpio_cam_t);
                return rc;
            }
        }
        
        rc = pm8058_gpio_config(rd->pmic_gpio_cam_f, &button_configuration);
        if (rc < 0) {
            dev_err(rd->fbx_kybd_pdev, "%s: gpio %d configured failed\n", __func__, rd->pmic_gpio_cam_f);
            return rc;
        } else {
            rc = gpio_direction_input(rd->sys_gpio_cam_f); 
            if (rc < 0) {
                dev_err(rd->fbx_kybd_pdev, "%s: set gpio %d direction failed\n", __func__, rd->sys_gpio_cam_f);
                return rc;
            }
        }
    }
    
    return 0;
}

static ssize_t fbx_kybd_gpio_status_show(struct device *dev,
                    struct device_attribute *attr, char *buf)
{
    
    return sprintf(buf, "%u\n", 0);
}

static ssize_t fbx_kybd_gpio_status_store(struct device *dev, 
        struct device_attribute *attr, const char *buf, size_t count)
{
    return count;
}

static DEVICE_ATTR(gpio_status, 0644, fbx_kybd_gpio_status_show, fbx_kybd_gpio_status_store);

static int fbx_kybd_probe(struct platform_device *pdev)
{
    struct fbx_kybd_platform_data *setup_data = pdev->dev.platform_data;
    int rc = -ENOMEM;

    rd = kzalloc(sizeof(struct fbx_kybd_record), GFP_KERNEL);
    if (!rd) {
        dev_err(&pdev->dev, "record memory allocation failed!!\n");
        return rc;
    }
    
    rd->product_phase           = fih_get_product_phase();
    rd->fbx_kybd_pdev           = &pdev->dev;
    rd->pmic_gpio_vol_up        = setup_data->pmic_gpio_vol_up;
    rd->pmic_gpio_vol_dn        = setup_data->pmic_gpio_vol_dn;
    rd->sys_gpio_vol_up         = setup_data->sys_gpio_vol_up;
    rd->sys_gpio_vol_dn         = setup_data->sys_gpio_vol_dn;
    if (rd->product_phase == Product_PR1 || rd->product_phase == Product_EVB) {
        rd->pmic_gpio_cam_f = setup_data->pmic_gpio_cam_f;
        rd->pmic_gpio_cam_t = setup_data->pmic_gpio_cam_t;
        rd->sys_gpio_cam_f  = setup_data->sys_gpio_cam_f;
        rd->sys_gpio_cam_t  = setup_data->sys_gpio_cam_t;
    }
    /* Div1-FW3-BSP-AUDIO */
    rd->hook_sw_pin             = setup_data->hook_sw_pin;
    rd->hooksw_irq_enable = false;
    headset_hook_wq = create_singlethread_workqueue("headset_hook");
    if (!headset_hook_wq) {
        printk("%s: create workque failed \n", __func__);       
        return -EBUSY;
    }
    
    //Request GPIOs
    rc = fbx_kybd_config_gpio();
    if (rc) {
        goto failexit1;
    } else {
        dev_info(&pdev->dev,
               "%s: GPIOs configured SUCCESSFULLY!!\n", __func__);
    }

    //Initialize WORKs
    INIT_WORK(&rd->qkybd_volup, fbx_kybd_volup);
    INIT_WORK(&rd->qkybd_voldn, fbx_kybd_voldn);
    if (rd->product_phase == Product_PR1 || rd->product_phase == Product_EVB) {
        INIT_WORK(&rd->qkybd_camf, fbx_kybd_camf);
        INIT_WORK(&rd->qkybd_camt, fbx_kybd_camt);
    }
    /* Div1-FW3-BSP-AUDIO */
    INIT_WORK(&rd->hook_switchkey, fbx_kybd_hooksw);
    
    //Request IRQs
    rc = fbx_kybd_irqsetup();
    if (rc)  
        goto failexit2;

    //Register Input Device to Input Subsystem
    fbx_kybd_connect2inputsys();
    if (rd->fbx_kybd_idev == NULL)
        goto failexit2;
        
    rc = device_create_file(&pdev->dev, &dev_attr_gpio_status);
    if (rc) {
        dev_err(&pdev->dev,
               "%s: dev_attr_gpio_status failed\n", __func__);
    }
    
    return 0;

failexit2:
    fbx_kybd_free_irq();
    fbx_kybd_flush_work();
    
failexit1:
    fbx_kybd_release_gpio();
    kfree(rd);

    return rc;
}

static struct platform_driver fbx_kybd_driver = {
    .driver = {
        .owner = THIS_MODULE,
        .name  = fbx_kybd_name,
    },
    .probe    = fbx_kybd_probe,
    .remove   = __devexit_p(fbx_kybd_remove),
    .suspend  = fbx_kybd_suspend,
    .resume   = fbx_kybd_resume,
};

static int __init fbx_kybd_init(void)
{
    return platform_driver_register(&fbx_kybd_driver);
}

static void __exit fbx_kybd_exit(void)
{
    platform_driver_unregister(&fbx_kybd_driver);
}
static int msm_hsusb_pmic_id_notif_init(void (*callback)(int online), int init)
{
	unsigned ret = -ENODEV;

	struct pm8058_gpio pmic_id_cfg = {
		.direction	= PM_GPIO_DIR_IN,
		.pull		= PM_GPIO_PULL_UP_1P5,
		.function	= PM_GPIO_FUNC_NORMAL,
		.vin_sel	= 2,
		.inv_int_pol	= 0,
	};
	struct pm8058_gpio pmic_id_uncfg = {
		.direction	= PM_GPIO_DIR_IN,
		.pull		= PM_GPIO_PULL_NO,
		.function	= PM_GPIO_FUNC_NORMAL,
		.vin_sel	= 2,
		.inv_int_pol	= 0,
	};
	if (!callback)
		return -EINVAL;

	usb_phy_susp_dig_vol = 500000;

	if (init) {
		notify_id_state_func_ptr = callback;
		INIT_DELAYED_WORK(&pmic_id_det, pmic_id_detect);
		ret = pm8058_gpio_config(PMIC_USB_HS_ID_DET, &pmic_id_cfg);
		if (ret)
			pr_err("%s:return val of pm8058_gpio_config: %d\n",
						__func__,  ret);
		ret = request_threaded_irq(PMICID_INT, NULL, pmic_id_on_irq,
			(IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING),
						"msm_otg_id", NULL);
		if (ret) {
			pr_err("%s:pmic_usb_id interrupt registration failed",
					__func__);
			return ret;
		}
		semc_fuji_otg_pdata.pmic_id_irq = PMICID_INT;
	} else {
		usb_phy_susp_dig_vol = 750000;
		free_irq(PMICID_INT, 0);
		ret = pm8058_gpio_config(PMIC_USB_HS_ID_DET, &pmic_id_uncfg);
		if (ret)
			pr_err("%s: return val of pm8058_gpio_config: %d\n",
						__func__,  ret);
		semc_fuji_otg_pdata.pmic_id_irq = 0;
		cancel_delayed_work_sync(&pmic_id_det);
		notify_id_state_func_ptr = NULL;
	}
	return 0;
}
#endif

#define PMIC_CBLPWR0_N		10
#define PMICVBUS_INT		PM8058_MPP_IRQ(PM8058_IRQ_BASE, PMIC_CBLPWR0_N)
#define PMICVBUS_GPIO		PM8058_MPP_PM_TO_SYS(PMIC_CBLPWR0_N)
#define USB_PMIC_VBUS_DET_DELAY	msecs_to_jiffies(100)
struct delayed_work pmic_vbus_det;
notify_vbus_state notify_vbus_state_func_ptr;

static void pmic_vbus_detect(struct work_struct *w)
{
	int val = !gpio_get_value_cansleep(PMICVBUS_GPIO);
	pr_debug("%s(): gpio_read_value = %d\n", __func__, val);

	if (notify_vbus_state_func_ptr)
		(*notify_vbus_state_func_ptr) (val);
}

static irqreturn_t pmic_vbus_on_irq(int irq, void *data)
{
	schedule_delayed_work(&pmic_vbus_det, USB_PMIC_VBUS_DET_DELAY);

	return IRQ_HANDLED;
}
static int irda_uart_open(struct inode *inode, struct file *file)
{
	int ret;
	u8 misc = 0x0;

	down(&irc->sem);
	printk(KERN_INFO DRV_NAME ": %s\n", __func__);

	/* Check refcount */
	if (irc->refcount > 0) {
		irc->refcount++;
		printk(KERN_INFO DRV_NAME
			": refirence counter count up(%d).\n", irc->refcount);
		up(&irc->sem);
		return 0;
	}
	/* PM8058-NFC Request */
	irc->nfcdev = pm8058_nfc_request();
	if (irc->nfcdev == NULL) {
		printk(KERN_ERR DRV_NAME ": pm8058 nfc not found.\n");
		ret = -ENODEV;
		goto error_pm_nfc_request;
	}

	/* PM8058 UART MUX setting */
	ret = pm8058_read(irc->nfcdev->pm_chip, SSBI_REG_ADDR_MISC, &misc, 1);
	if (ret)
		printk(KERN_ERR DRV_NAME
			": cannot read pm8058 UART MUX reg.\n");
	else
		printk(KERN_INFO DRV_NAME ": misc register = %x\n", misc);
	misc &= PM8058_UART_MUX_MASK;
	switch (misc) {
	case PM8058_UART_MUX_NO:
		pm8058_misc_control(irc->nfcdev->pm_chip,
				PM8058_UART_MUX_MASK, PM8058_UART_MUX_3);
		printk(KERN_INFO DRV_NAME
			": OK. UART MUX = neutral --> IrDA.\n");
		break;
	case PM8058_UART_MUX_1:
		printk(KERN_ERR DRV_NAME ": Now, uart_mux = 1 (FeliCa)\n");
		ret = -EBUSY;
		goto err_set_uart_mux;
	case PM8058_UART_MUX_2:
		printk(KERN_ERR DRV_NAME ": Now, uart_mux = 2 (unknown)\n");
		ret = -EBUSY;
		goto err_set_uart_mux;
	default:
		printk(KERN_ERR DRV_NAME ": UART MUX unavaible.\n");
		ret = -EIO;
		goto err_set_uart_mux;
	}

	/* init IMR value */
	irc->imr_reg = 0x0;

	/* init wait queue */
	init_waitqueue_head(&irc->wait_tx);
	init_waitqueue_head(&irc->wait_rx);

	/* init tasklet */
	tasklet_init(&irc->tasklet_rxfer_s, irda_uart_rxfer_start, 0);
	tasklet_init(&irc->tasklet_rxfer_e, irda_uart_rxfer_end,   0);
	tasklet_init(&irc->tasklet_txfer,   irda_uart_txfer_exec,  0);

	/* Register UARTDM IRQ */
	ret = request_irq(irc->pfdata->irq_uartdm, irda_uart_irq_handler,
				IRQF_TRIGGER_HIGH,  "irda_uart", irc);
	if (ret) {
		printk(KERN_ERR DRV_NAME ": request IRQ failed. (UARTDM)\n");
		goto err_request_irq_uart;
	}

	/* UARTDM ioremap */
	/* memory protection */
	irc->iores_uartdm = request_mem_region((u32) irc->pfdata->paddr_uartdm,
						UARTDM_SIZE, "irda_uart");
	if (!irc->iores_uartdm) {
		printk(KERN_ERR DRV_NAME
			": UARTDM request_mem_region failed.\n");
		ret = -EBUSY;
		goto err_request_mem_region;
	}
	irc->vaddr_uartdm = ioremap_nocache((u32) irc->pfdata->paddr_uartdm,
						UARTDM_SIZE);
	if (!irc->vaddr_uartdm) {
		printk(KERN_ERR DRV_NAME ": UARTDM ioremap failed.\n");
		ret = -ENOMEM;
		goto err_ioremap_uartdm;
	}

	/* UARTDM clock set and start */
	/* default 9600 bps */
	irc->bps = 9600;
	clk_set_rate(irc->clk_uartdm, IRUART_UARTDM_CLK(9600));
	clk_enable(irc->clk_uartdm);
	msm_uartdm_write(UARTDM_CSR, IRUART_DEF_BAUDRATE_CSR);

	/* UARTDM register setting */
	/* Data-stop-parity setting (MR2) */
	msm_uartdm_write(UARTDM_MR2, IRUART_DATA_STOP_PARITY);

	/* RX&TX wartermark setting */
	msm_uartdm_write(UARTDM_TFWR, 0x0);
	msm_uartdm_write(UARTDM_RFWR, 0x0);

	/* Stale time-out setting */
	msm_uartdm_write(UARTDM_IPR,
			(IRUART_DEF_RXSTALE & BIT_STALE_TIMEOUT_LSB)
			| ((IRUART_DEF_RXSTALE << 2) & BIT_STALE_TIMEOUT_MSB));

	/* Enable TXDM and RXDM mode */
	msm_uartdm_write(UARTDM_DMEN, BIT_RX_DM_EN|BIT_TX_DM_EN);

	/* Enable the IRDA transceiver */
	msm_uartdm_write(UARTDM_IRDA, IRUART_IRDA_EN);

	/* TX DMOV mapping */
	irc->txbox = dma_alloc_coherent(NULL, sizeof(dmov_box),
					&irc->mapped_txbox, GFP_KERNEL);
	if (!irc->txbox) {
		printk(KERN_ERR DRV_NAME ": no enough mem for TX DMOV(1).\n");
		ret = -ENOMEM;
		goto err_alloc_txbox;
	}
	irc->txbox_ptr = dma_alloc_coherent(NULL, sizeof(u32 *),
					&irc->mapped_txbox_ptr, GFP_KERNEL);
	if (!irc->txbox_ptr) {
		printk(KERN_ERR DRV_NAME ": no enough mem for TX DMOV(2).\n");
		ret = -ENOMEM;
		goto err_alloc_txbox_ptr;
	}
	*irc->txbox_ptr = CMD_PTR_LP | DMOV_CMD_ADDR(irc->mapped_txbox);
	irc->txdmov_cmd.cmdptr = DMOV_CMD_ADDR(irc->mapped_txbox_ptr);
	irc->txdmov_cmd.complete_func = irda_txdmov_callback;
	irc->txdmov_cmd.cmdptr = DMOV_CMD_ADDR(irc->mapped_txbox_ptr);
	irc->txbox->cmd =
		CMD_LC
		| CMD_DST_CRCI(irc->pfdata->crci_uartdm_tx) | CMD_MODE_BOX;
	/* TX DMOV BOX command */
	irc->txbox->src_row_addr = 0x0;
	irc->txbox->dst_row_addr = (u32)irc->pfdata->paddr_uartdm + UARTDM_TF;
	irc->txbox->src_dst_len = (UARTDM_BURST_SIZE<<16)|UARTDM_BURST_SIZE;
	irc->txbox->num_rows = 0x0;
	irc->txbox->row_offset = (UARTDM_BURST_SIZE<<16);

	/* RX DMOV mapping */
	irc->rxbox = dma_alloc_coherent(NULL, sizeof(dmov_box),
					&irc->mapped_rxbox, GFP_KERNEL);
	if (!irc->rxbox) {
		printk(KERN_ERR DRV_NAME ": no enough mem for RX DMOV(1).\n");
		ret = -ENOMEM;
		goto err_alloc_rxbox;
	}
	irc->rxbox_ptr = dma_alloc_coherent(NULL, sizeof(u32 *),
					&irc->mapped_rxbox_ptr, GFP_KERNEL);
	if (!irc->rxbox_ptr) {
		printk(KERN_ERR DRV_NAME ": no enough mem for RX DMOV(2).\n");
		ret = -ENOMEM;
		goto err_alloc_rxbox_ptr;
	}
	*irc->rxbox_ptr = CMD_PTR_LP | DMOV_CMD_ADDR(irc->mapped_rxbox);
	irc->rxdmov_cmd.cmdptr = DMOV_CMD_ADDR(irc->mapped_rxbox_ptr);
	irc->rxdmov_cmd.complete_func = irda_rxdmov_callback;
	irc->rxdmov_cmd.cmdptr = DMOV_CMD_ADDR(irc->mapped_rxbox_ptr);
	irc->rxbox->cmd =
		CMD_LC
		| CMD_SRC_CRCI(irc->pfdata->crci_uartdm_rx)
		| CMD_MODE_BOX;
	/* RX DMOV BOX command */
	irc->rxbox->src_row_addr =
		(u32)irc->pfdata->paddr_uartdm + UARTDM_RF;
	irc->rxbox->dst_row_addr = 0x0;
	irc->rxbox->src_dst_len = (UARTDM_BURST_SIZE<<16)|UARTDM_BURST_SIZE;
	irc->rxbox->num_rows =
		(IRUART_SW_RXBUF_SIZE >> 4 << 16) | IRUART_SW_RXBUF_SIZE >> 4;
	irc->rxbox->row_offset = UARTDM_BURST_SIZE;

	/* Enable Command Register Protection */
	msm_uartdm_write(UARTDM_CR, GCMD_CR_PROTECTION_ENABLE);

	/* Reset TX and RX */
	msm_uartdm_write(UARTDM_CR, CCMD_RESET_RECEIVER);
	msm_uartdm_write(UARTDM_CR, CCMD_RESET_TRANSMITTER);
	msm_uartdm_write(UARTDM_CR, CCMD_RESET_ERROR_STATUS);
	msm_uartdm_write(UARTDM_CR, CCMD_RESET_STALE_INTERRUPT);

	/* Setting PM power on (Low) */
	ret = pm8058_gpio_config(irc->pfdata->gpio_pow,
				 irc->pfdata->gpio_pwcfg_low);
	if (ret) {
		printk(KERN_ERR DRV_NAME ": pmic gpio write failed\n");
		goto err_gpio_config;
	}
	/* Wait 200usec */
	udelay(200);

	/* Enable Transmitter and Receiver */
	msm_uartdm_write(UARTDM_CR, BIT_UART_TX_EN);
	msm_uartdm_write(UARTDM_CR, BIT_UART_RX_EN);

	/* Clear UART SW buffer */
	irda_txbuf_clear(&irc->txbuf);
	irda_rxbuf_clear(&irc->rxbuf);

	/* init Overflow flag */
	irc->rx_overflow = IRDA_NORMAL;

	/* Increment refcount */
	irc->refcount++;

	/* (state change)--> IRDA_UART_OPEN */
	irc->state = IRDA_UART_OPEN;
	irc->rx_state = IRDA_RX_IDLE;

	printk(KERN_INFO DRV_NAME
		": succecssfly opened, refcount = %d\n", irc->refcount);

	/* Activate RXLEV IRQ */
	irc->imr_reg |= BIT_RXLEV;
	msm_uartdm_write(UARTDM_IMR, irc->imr_reg);

	up(&irc->sem);
	return 0;

/* Error handling */
err_gpio_config:
	dma_free_coherent(NULL,
			sizeof(u32 *), irc->rxbox_ptr, irc->mapped_txbox_ptr);
err_alloc_rxbox_ptr:
	dma_free_coherent(NULL,
			sizeof(dmov_box), irc->rxbox, irc->mapped_rxbox);
err_alloc_rxbox:
	dma_free_coherent(NULL,
			sizeof(u32 *), irc->txbox_ptr, irc->mapped_txbox_ptr);
err_alloc_txbox_ptr:
	dma_free_coherent(NULL,
			sizeof(dmov_box), irc->txbox, irc->mapped_txbox);
err_alloc_txbox:
	msm_uartdm_write(UARTDM_IRDA, IRUART_IRDA_DISABLE);
	clk_disable(irc->clk_uartdm);
	iounmap(irc->vaddr_uartdm);
err_ioremap_uartdm:
	release_mem_region((u32) irc->pfdata->paddr_uartdm, UARTDM_SIZE);
err_request_mem_region:
	free_irq(irc->pfdata->irq_uartdm, irc);
err_request_irq_uart:
	tasklet_kill(&irc->tasklet_rxfer_s);
	tasklet_kill(&irc->tasklet_rxfer_e);
	tasklet_kill(&irc->tasklet_txfer);
	pm8058_misc_control(irc->nfcdev->pm_chip,
				PM8058_UART_MUX_MASK, PM8058_UART_MUX_NO);
err_set_uart_mux:
error_pm_nfc_request:
	up(&irc->sem);
	return ret;
}