/* * configures accdet2 input on/off */ static void ab8500_config_accdetect2_hw(struct abx500_ad *dd, int enable) { int ret = 0; if (!dd->accdet2_th_set) { /* Configure accdetect21+22 thresholds */ ret = abx500_set_register_interruptible(&dd->pdev->dev, AB8500_ECI_AV_ACC, AB8500_ACC_DET_DB2_REG, dd->pdata->accdet2122_th); if (ret < 0) { dev_err(&dd->pdev->dev, "%s: Failed to write reg (%d).\n", __func__, ret); goto out; } else { dd->accdet2_th_set = 1; } } /* Enable/Disable accdetect21 comparators + pullup */ ret = abx500_mask_and_set_register_interruptible( &dd->pdev->dev, AB8500_ECI_AV_ACC, AB8500_ACC_DET_CTRL_REG, BITS_ACCDETCTRL2_ENA, enable ? BITS_ACCDETCTRL2_ENA : 0); if (ret < 0) dev_err(&dd->pdev->dev, "%s: Failed to update reg (%d).\n", __func__, ret); out: return; }
/* * configures accdet1 input on/off */ static void ab8500_config_accdetect1_hw(struct abx500_ad *dd, int enable) { int ret; if (!dd->accdet1_th_set) { ret = abx500_set_register_interruptible(&dd->pdev->dev, AB8500_ECI_AV_ACC, AB8500_ACC_DET_DB1_REG, dd->pdata->accdet1_dbth); if (ret < 0) dev_err(&dd->pdev->dev, "%s: Failed to write reg (%d).\n", __func__, ret); else dd->accdet1_th_set = 1; } /* enable accdetect1 comparator */ ret = abx500_mask_and_set_register_interruptible( &dd->pdev->dev, AB8500_ECI_AV_ACC, AB8500_ACC_DET_CTRL_REG, BITS_ACCDETCTRL1_ENA, enable ? BITS_ACCDETCTRL1_ENA : 0); if (ret < 0) dev_err(&dd->pdev->dev, "%s: Failed to update reg (%d).\n", __func__, ret); }
static void enable_adp(void) { if (ab8500_rev == AB8500_REV_20) abx500_set_register_interruptible(device, AB8500_USB, AB8500_USB_ADP_CTRL_REG, AB8500_USB_ADP_ENABLE); }
/** * usb_kick_watchdog() - Kick the watch dog timer * * This function used to Kick the watch dog timer */ static void usb_kick_watchdog(void) { abx500_set_register_interruptible(device, AB8500_SYS_CTRL2_BLOCK, AB8500_MAIN_WDOG_CTRL_REG, AB8500_MAIN_WATCHDOG_ENABLE); udelay(WATCHDOG_DELAY_US); abx500_set_register_interruptible(device, AB8500_SYS_CTRL2_BLOCK, AB8500_MAIN_WDOG_CTRL_REG, (AB8500_MAIN_WATCHDOG_ENABLE | AB8500_MAIN_WATCHDOG_KICK)); udelay(WATCHDOG_DELAY_US); abx500_set_register_interruptible(device, AB8500_SYS_CTRL2_BLOCK, AB8500_MAIN_WDOG_CTRL_REG, AB8500_MAIN_WATCHDOG_DISABLE); udelay(WATCHDOG_DELAY_US); }
static void ab8500_turn_on_accdet_comparator(struct platform_device *pdev) { struct abx500_ad *dd = platform_get_drvdata(pdev); /* Turn on AccDetect comparators and pull-up */ (void) abx500_set_register_interruptible( &dd->pdev->dev, AB8500_ECI_AV_ACC, AB8500_ACC_DET_CTRL_REG, acc_det_ctrl_suspend_val); }
static void set_reg(u8 reg, u8 val) { if (!ab3550_dev) { pr_err("%s: The AB3550 codec driver not initialized.\n", __func__); return; } if (reg < AB3550_FIRST_REG) return; else if (reg <= AB3550_LAST_REG) { abx500_set_register_interruptible( ab3550_dev, I2C_BANK, reg, val); } else if (reg - AB3550_LAST_REG - 1 < ARRAY_SIZE(virtual_regs)) { virtual_regs[reg - AB3550_LAST_REG - 1] = val; } }
void musb_platform_device_en(int enable) { int ret; if ((enable == 1) && (phy_enable_stat == USB_DISABLE)) { stm_musb_curr_state = USB_DEVICE; usb_device_phy_en(USB_ENABLE); return; } if ((enable == 1) && (phy_enable_stat == USB_ENABLE)) { /* Phy already enabled. no need to do anything. */ return; } if ((enable == 0) && (phy_enable_stat == USB_DISABLE)) { /* Phy already disabled. no need to do anything. */ return; } if ((enable == 0) && (phy_enable_stat == USB_ENABLE)) { /* Phy enabled. Disable it */ abx500_set_register_interruptible(device, AB8500_USB, AB8500_USB_PHY_CTRL_REG, AB8500_USB_DEVICE_DISABLE); prcmu_qos_update_requirement(PRCMU_QOS_APE_OPP, DEVICE_NAME, 50); prcmu_release_usb_wakeup_state(); regulator_disable(musb_vape_supply); regulator_disable(musb_vintcore_supply); regulator_set_optimum_mode(musb_vintcore_supply, 0); ret = regulator_set_voltage(musb_vintcore_supply, 0, 1350000); if (ret < 0) printk(KERN_ERR "Failed to set the Vintcore" " to 0 V .. 1.35 V, ret=%d\n", ret); regulator_disable(musb_smps2_supply); clk_disable(sysclock); phy_enable_stat = USB_DISABLE; return; } }
/** * musb_force_detect : detect the USB cable during boot time. * @mode: value for mode. * * This function is used to detect the USB cable during boot time. */ int musb_force_detect(u8 mode) { int ret; u8 usb_status = 0; u8 val = 0; if (!device) return -EINVAL; /* Disabling PHY before selective enable or disable */ abx500_set_register_interruptible(device, AB8500_USB, AB8500_USB_PHY_CTRL_REG, AB8500_USB_DEVICE_ENABLE); udelay(200); abx500_set_register_interruptible(device, AB8500_USB, AB8500_USB_PHY_CTRL_REG, AB8500_USB_DEVICE_DISABLE); abx500_set_register_interruptible(device, AB8500_USB, AB8500_USB_PHY_CTRL_REG, AB8500_USB_HOST_ENABLE); udelay(200); abx500_set_register_interruptible(device, AB8500_USB, AB8500_USB_PHY_CTRL_REG, AB8500_USB_HOST_DISABLE); if (mode == MUSB_HOST || mode == MUSB_OTG) { ret = abx500_get_register_interruptible(device, AB8500_INTERRUPT, AB8500_IT_SOURCE20_REG, &usb_status); if (ret < 0) { dev_err(device, "Read IT 20 failed\n"); return ret; } if (usb_status & AB8500_SRC_INT_USB_HOST) { boot_time_flag = USB_ENABLE; /* Change the current state */ stm_musb_curr_state = USB_HOST; usb_host_phy_en(USB_ENABLE); } } if (mode == MUSB_PERIPHERAL || mode == MUSB_OTG) { ret = abx500_get_register_interruptible(device, AB8500_INTERRUPT, AB8500_IT_SOURCE2_REG, &usb_status); if (ret < 0) { dev_err(device, "Read IT 2 failed\n"); return ret; } if (usb_status & AB8500_SRC_INT_USB_DEVICE) { /* Check if it is a dedicated charger */ (void)abx500_get_register_interruptible(device, AB8500_USB, AB8500_USB_LINE_STAT_REG, &val); val = (val & AB8500_USB_LINK_STATUS) >> 3; if (val == USB_LINK_DEDICATED_CHG) { /* Change the current state */ stm_musb_curr_state = USB_DEDICATED_CHG; } else { boot_time_flag = USB_ENABLE; /* Change the current state */ stm_musb_curr_state = USB_DEVICE; usb_device_phy_en(USB_ENABLE); } }
/** * musb_phy_en : register USB callback handlers for ab8500 * @mode: value for mode. * * This function is used to register USB callback handlers for ab8500. */ int musb_phy_en(u8 mode) { int ret = -1; u8 save_val; if (!device) return -EINVAL; ab8500_rev = abx500_get_chip_id(device); if (ab8500_rev < 0) { dev_err(device, "get chip id failed\n"); return ab8500_rev; } if (!((ab8500_rev == AB8500_REV_20) || (ab8500_rev == AB8500_REV_30) || (ab8500_rev == AB8500_REV_33))) { dev_err(device, "Unknown AB type!\n"); return -ENODEV; } musb_vape_supply = regulator_get(device, "v-ape"); if (IS_ERR(musb_vape_supply)) { dev_err(device, "Could not get %s:v-ape supply\n", dev_name(device)); ret = PTR_ERR(musb_vape_supply); return ret; } musb_vintcore_supply = regulator_get(device, "v-intcore"); if (IS_ERR(musb_vintcore_supply)) { dev_err(device, "Could not get %s:v-intcore12 supply\n", dev_name(device)); ret = PTR_ERR(musb_vintcore_supply); return ret; } musb_smps2_supply = regulator_get(device, "musb_1v8"); if (IS_ERR(musb_smps2_supply)) { dev_err(device, "Could not get %s:v-intcore12 supply\n", dev_name(device)); ret = PTR_ERR(musb_smps2_supply); return ret; } sysclock = clk_get(device, "sysclk"); if (IS_ERR(sysclock)) { ret = PTR_ERR(sysclock); sysclock = NULL; return ret; } /* * When usb cable is not connected,set Qos for VAPE to 50. * This is done to run APE at low OPP when usb is not used. */ prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP, DEVICE_NAME, 50); if (mode == MUSB_HOST || mode == MUSB_OTG) { ret = request_threaded_irq(irq_host_remove, NULL, usb_host_remove_handler, IRQF_NO_SUSPEND | IRQF_SHARED, "usb-host-remove", device); if (ret < 0) { printk(KERN_ERR "failed to set the callback" " handler for usb host" " removal\n"); return ret; } } if ((mode == MUSB_PERIPHERAL) || (mode == MUSB_OTG)) { ret = request_threaded_irq(irq_device_remove, NULL, usb_device_remove_handler, IRQF_NO_SUSPEND | IRQF_SHARED, "usb-device-remove", device); if (ret < 0) { printk(KERN_ERR "failed to set the callback" " handler for usb host" " removal\n"); return ret; } } /* create a thread for work */ usb_cable_wq = create_singlethread_workqueue( "usb_cable_wq"); if (usb_cable_wq == NULL) return -ENOMEM; ret = request_threaded_irq(irq_device_insert, NULL, usb_device_insert_handler, IRQF_NO_SUSPEND | IRQF_SHARED, "usb-device-insert", device); if (ret < 0) { printk(KERN_ERR "failed to set the callback" " handler for usb device" " insert\n"); return ret; } INIT_WORK(&usb_host_remove, usb_host_remove_work); INIT_WORK(&usb_device_remove, usb_device_remove_work); INIT_WORK(&usb_lnk_status_update, usb_link_status_update_work); if (ab8500_rev == AB8500_REV_20) INIT_WORK(&usb_dedicated_charger_remove, usb_dedicated_charger_remove_work); /* Required for Host, Device and OTG mode */ init_completion(&usb_link_status_update); ret = request_threaded_irq(irq_link_status_update, NULL, usb_link_status_update_handler, IRQF_NO_SUSPEND | IRQF_SHARED, "usb-link-status-update", device); if (ret < 0) { printk(KERN_ERR "failed to set the callback" " handler for usb charge" " detect done\n"); return ret; } #ifdef CONFIG_USB_OTG_20 ret = request_threaded_irq(irq_adp_plug, NULL, irq_adp_plug_handler, IRQF_SHARED, "usb-adp-plug", device); if (ret < 0) { printk(KERN_ERR "failed to set the callback" " handler for usb adp" " plug\n"); return ret; } ret = request_threaded_irq(irq_adp_unplug, NULL, irq_adp_unplug_handler, IRQF_SHARED, "usb-adp-unplug", device); if (ret < 0) { printk(KERN_ERR "failed to set the callback" " handler for usb adp" " unplug\n"); return ret; } #endif /* Write Phy tuning values */ if ((ab8500_rev == AB8500_REV_30) || (ab8500_rev == AB8500_REV_33)) { /* Enable the PBT/Bank 0x12 access * Save old bank settings for * later restore */ ret = abx500_get_register_interruptible(device, AB8500_DEVELOPMENT, AB8500_BANK12_ACCESS, &save_val); ret = abx500_set_register_interruptible(device, AB8500_DEVELOPMENT, AB8500_BANK12_ACCESS, 0x01); if (ret < 0) printk(KERN_ERR "Failed to enable bank12" " access ret=%d\n", ret); ret = abx500_set_register_interruptible(device, AB8500_DEBUG, AB8500_USB_PHY_TUNE1, 0xC8); if (ret < 0) printk(KERN_ERR "Failed to set PHY_TUNE1" " register ret=%d\n", ret); ret = abx500_set_register_interruptible(device, AB8500_DEBUG, AB8500_USB_PHY_TUNE2, 0x00); if (ret < 0) printk(KERN_ERR "Failed to set PHY_TUNE2" " register ret=%d\n", ret); ret = abx500_set_register_interruptible(device, AB8500_DEBUG, AB8500_USB_PHY_TUNE3, 0x78); if (ret < 0) printk(KERN_ERR "Failed to set PHY_TUNE3" " regester ret=%d\n", ret); /* Switch back to previous mode/disable Bank 0x12 access */ ret = abx500_set_register_interruptible(device, AB8500_DEVELOPMENT, AB8500_BANK12_ACCESS, save_val); if (ret < 0) printk(KERN_ERR "Failed to switch bank12" " access ret=%d\n", ret); } return 0; }
/** * usb_device_phy_en() - for enabling the 5V to usb gadget * @enable: to enabling the Phy for device. * * This function used to set the voltage for USB gadget mode. */ static void usb_device_phy_en(int enable) { int volt = 0; int ret = -1; if (phy_enable_stat == enable) return; if (enable == USB_ENABLE) { wake_lock(&ab8500_musb_wakelock); ux500_pins_enable(usb_gpio_pins); clk_enable(sysclock); phy_enable_stat = USB_ENABLE; regulator_enable(musb_vape_supply); regulator_enable(musb_smps2_supply); /* Set Vintcore12 LDO to 1.3V */ ret = regulator_set_voltage(musb_vintcore_supply, 1300000, 1350000); if (ret < 0) printk(KERN_ERR "Failed to set the Vintcore" " to 1.3V, ret=%d\n", ret); ret = regulator_set_optimum_mode(musb_vintcore_supply, 28000); if (ret < 0) printk(KERN_ERR "Failed to set optimum mode" " (ret=%d)\n", ret); regulator_enable(musb_vintcore_supply); volt = regulator_get_voltage(musb_vintcore_supply); if ((volt != 1300000) && (volt != 1350000)) printk(KERN_ERR "Vintcore is not" " set to 1.3V" " volt=%d\n", volt); #ifdef CONFIG_PM stm_musb_context(USB_ENABLE); #endif /* Workaround for USB performance issue. */ schedule_delayed_work_on(0, &work_usb_workaround, msecs_to_jiffies(USB_PROBE_DELAY)); prcmu_qos_update_requirement(PRCMU_QOS_APE_OPP, DEVICE_NAME, 100); abx500_set_register_interruptible(device, AB8500_USB, AB8500_USB_PHY_CTRL_REG, AB8500_USB_DEVICE_ENABLE); } else { /* enable == USB_DISABLE */ /* * Workaround: Sometimes the DISCONNECT interrupt is * not generated in musb_core. Force a disconnect if * necessary before we power down the PHY. */ stm_musb_force_disconnect(); if (boot_time_flag) boot_time_flag = USB_DISABLE; /* * Workaround for bug31952 in ABB cut2.0. Write 0x1 * before disabling the PHY. */ abx500_set_register_interruptible(device, AB8500_USB, AB8500_USB_PHY_CTRL_REG, AB8500_USB_DEVICE_ENABLE); udelay(200); abx500_set_register_interruptible(device, AB8500_USB, AB8500_USB_PHY_CTRL_REG, AB8500_USB_DEVICE_DISABLE); prcmu_qos_update_requirement(PRCMU_QOS_APE_OPP, DEVICE_NAME, 50); /* Workaround for USB performance issue. */ cancel_delayed_work_sync(&work_usb_workaround); prcmu_qos_update_requirement(PRCMU_QOS_ARM_OPP, "usb", 25); prcmu_release_usb_wakeup_state(); phy_enable_stat = USB_DISABLE; regulator_disable(musb_vape_supply); regulator_disable(musb_smps2_supply); regulator_disable(musb_vintcore_supply); regulator_set_optimum_mode(musb_vintcore_supply, 0); /* Set Vintcore12 LDO to 0V to 1.35V */ ret = regulator_set_voltage(musb_vintcore_supply, 0000000, 1350000); if (ret < 0) printk(KERN_ERR "Failed to set the Vintcore" " to 0V to 1.35V," " ret=%d\n", ret); clk_disable(sysclock); #ifdef CONFIG_PM stm_musb_context(USB_DISABLE); #endif ux500_pins_disable(usb_gpio_pins); wake_unlock(&ab8500_musb_wakelock); } }
static void usb_charger_det_enable(struct work_struct *work) { int i, ret; u8 val; /* * Until the IT source register is read the UsbLineStatus * register is not updated. */ ret = abx500_get_register_interruptible(device, AB8500_INTERRUPT, AB8500_IT_SOURCE21_REG, &val); if (ret < 0) { dev_err(device, "%s ab8500 read 0x0e14 failed\n", __func__); return; } ret = abx500_get_register_interruptible(device, AB8500_USB, AB8500_USB_LINE_STAT_REG, &val); if (ret < 0) { dev_err(device, "%s ab8500 read 0x580 failed\n", __func__); return; } if (val != 0) return; /* connection type already detected, so we do not need workaround */ dev_info(device, "USB cable detect workaround activated\n"); val = 0; ret = abx500_get_register_interruptible(device, AB8500_INTERRUPT, AB8500_IT_SOURCE2_REG, &val); if (ret < 0) { dev_err(device, "%s ab8500 read 0x0e01 failed\n", __func__); return; } if (!(val & 0x80)) return; /* workaround will not be activated because vbus is not detected */ ret = abx500_set_register_interruptible(device, AB8500_USB, AB8500_USB_PHY_CTRL_REG, 0x00); if (ret < 0) { dev_err(device, "%s ab8500 write 0x58A failed\n", __func__); return; } ret = abx500_set_register_interruptible(device, AB8500_USB, AB8500_USB_LINE_CTRL2_REG, 0x01); if (ret < 0) { dev_err(device, "%s ab8500 write 0x582 failed\n", __func__); return; } for (i = 10; i != 0; i--) { val = 0; ret = abx500_get_register_interruptible(device, AB8500_INTERRUPT, AB8500_IT_LATCH12_REG, &val); if (ret < 0) { dev_err(device, "%s ab8500 read 0x0e2b failed\n", __func__); return; } if (val & 0x80) break; msleep(2); } ret = abx500_set_register_interruptible(device, AB8500_USB, AB8500_USB_LINE_CTRL2_REG, 0x00); if (ret < 0) { dev_err(device, "%s ab8500 write 0x582 failed\n", __func__); return; } ret = abx500_get_register_interruptible(device, AB8500_USB, AB8500_USB_LINE_STAT_REG, &val); if (ret < 0) { dev_err(device, "%s ab8500 read 0x580 failed\n", __func__); return; } }
/** * usb_device_phy_en() - for enabling the 5V to usb gadget * @enable: to enabling the Phy for device. * * This function used to set the voltage for USB gadget mode. */ static void usb_device_phy_en(int enable) { int volt = 0; int ret = -1; if (phy_enable_stat == enable) return; if (enable == USB_ENABLE) { wake_lock(&ab8500_musb_wakelock); clk_enable(sysclock); phy_enable_stat = USB_ENABLE; regulator_enable(musb_vape_supply); regulator_enable(musb_smps2_supply); /* Set Vintcore12 LDO to 1.3V */ ret = regulator_set_voltage(musb_vintcore_supply, 1300000, 1350000); if (ret < 0) printk(KERN_ERR "Failed to set the Vintcore" " to 1.3V, ret=%d\n", ret); ret = regulator_set_optimum_mode(musb_vintcore_supply, 28000); if (ret < 0) printk(KERN_ERR "Failed to set optimum mode" " (ret=%d)\n", ret); regulator_enable(musb_vintcore_supply); volt = regulator_get_voltage(musb_vintcore_supply); if ((volt != 1300000) && (volt != 1350000)) printk(KERN_ERR "Vintcore is not" " set to 1.3V" " volt=%d\n", volt); #ifdef CONFIG_PM stm_musb_context(USB_ENABLE); #endif usb_kick_watchdog(); /* Workaround for USB performance issue. */ cpufreq_usb_connect_notify(true); prcmu_qos_update_requirement(PRCMU_QOS_APE_OPP, DEVICE_NAME, 100); abx500_set_register_interruptible(device, AB8500_USB, AB8500_USB_PHY_CTRL_REG, AB8500_USB_DEVICE_ENABLE); } else { /* enable == USB_DISABLE */ if (boot_time_flag) boot_time_flag = USB_DISABLE; /* * Workaround for bug31952 in ABB cut2.0. Write 0x1 * before disabling the PHY. */ abx500_set_register_interruptible(device, AB8500_USB, AB8500_USB_PHY_CTRL_REG, AB8500_USB_DEVICE_ENABLE); udelay(100); abx500_set_register_interruptible(device, AB8500_USB, AB8500_USB_PHY_CTRL_REG, AB8500_USB_DEVICE_DISABLE); prcmu_qos_update_requirement(PRCMU_QOS_APE_OPP, DEVICE_NAME, 50); /* Workaround for USB performance issue. */ cpufreq_usb_connect_notify(false); prcmu_release_usb_wakeup_state(); phy_enable_stat = USB_DISABLE; regulator_disable(musb_vape_supply); regulator_disable(musb_smps2_supply); regulator_disable(musb_vintcore_supply); regulator_set_optimum_mode(musb_vintcore_supply, 0); /* Set Vintcore12 LDO to 0V to 1.35V */ ret = regulator_set_voltage(musb_vintcore_supply, 0000000, 1350000); if (ret < 0) printk(KERN_ERR "Failed to set the Vintcore" " to 0V to 1.35V," " ret=%d\n", ret); clk_disable(sysclock); #ifdef CONFIG_PM stm_musb_context(USB_DISABLE); #endif wake_unlock(&ab8500_musb_wakelock); } }