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); }
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; }
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); } }
/* * 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; }
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; }
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); }
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; }
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 }
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); }
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; }