diff options
author | Daniel Hillenbrand <codeworkx@cyanogenmod.org> | 2013-06-04 01:33:22 +0200 |
---|---|---|
committer | Daniel Hillenbrand <codeworkx@cyanogenmod.org> | 2013-06-04 12:54:26 +0200 |
commit | 55bb2048feb59f2190f704c2a4df81b557b55c7a (patch) | |
tree | cbb680a60770fb762e5b27c502ad71c2366bf604 | |
parent | 3d8b293a4f5042cd9fdc4009a40f6483371cd489 (diff) | |
download | kernel_samsung_smdk4412-55bb2048feb59f2190f704c2a4df81b557b55c7a.zip kernel_samsung_smdk4412-55bb2048feb59f2190f704c2a4df81b557b55c7a.tar.gz kernel_samsung_smdk4412-55bb2048feb59f2190f704c2a4df81b557b55c7a.tar.bz2 |
smdk4412: bulk update from i9300 update 9
Change-Id: Icd3e7b601f3f4c8b3dcf053fed5819fb7caf5296
-rw-r--r-- | arch/arm/mach-exynos/mach-midas.c | 22 | ||||
-rw-r--r-- | arch/arm/mach-exynos/midas-sound.c | 7 | ||||
-rw-r--r-- | drivers/battery/max77693_charger.c | 31 | ||||
-rw-r--r-- | drivers/battery/samsung_battery.c | 14 | ||||
-rw-r--r-- | drivers/gpu/ion/ion.c | 4 | ||||
-rw-r--r-- | drivers/misc/max77693-muic.c | 555 | ||||
-rw-r--r-- | drivers/mmc/card/Kconfig | 7 | ||||
-rw-r--r-- | drivers/mmc/card/Makefile | 4 | ||||
-rw-r--r-- | drivers/mmc/card/block.c | 118 | ||||
-rw-r--r-- | drivers/mmc/card/cprmdrv_samsung.c | 35 | ||||
-rw-r--r-- | drivers/mmc/card/cprmdrv_samsung.h | 14 | ||||
-rw-r--r-- | drivers/mmc/core/mmc.c | 74 | ||||
-rw-r--r-- | drivers/mmc/core/mmc_ops.c | 60 | ||||
-rw-r--r-- | drivers/usb/core/sec-dock.h | 4 | ||||
-rw-r--r-- | include/linux/battery/samsung_battery.h | 11 | ||||
-rw-r--r-- | include/linux/mfd/max77693-private.h | 2 | ||||
-rw-r--r-- | include/linux/mfd/max77693.h | 4 | ||||
-rw-r--r-- | include/linux/mmc/card.h | 5 | ||||
-rw-r--r-- | include/linux/mmc/ioctl.h | 2 | ||||
-rw-r--r-- | include/linux/mmc/mmc.h | 2 | ||||
-rw-r--r-- | mm/cma.c | 8 | ||||
-rw-r--r-- | mm/page_alloc-cma.c | 2 | ||||
-rw-r--r-- | sound/soc/codecs/wm8994.c | 2 |
23 files changed, 780 insertions, 207 deletions
diff --git a/arch/arm/mach-exynos/mach-midas.c b/arch/arm/mach-exynos/mach-midas.c index f462c8a..c2de56b 100644 --- a/arch/arm/mach-exynos/mach-midas.c +++ b/arch/arm/mach-exynos/mach-midas.c @@ -835,9 +835,10 @@ static struct s3c_mshci_platdata exynos4_mshc_pdata __initdata = { MMC_CAP_UHS_DDR50 | MMC_CAP_CMD23, #ifdef CONFIG_MMC_MSHCI_ENABLE_CACHE .host_caps2 = MMC_CAP2_ADAPT_PACKED | MMC_CAP2_PACKED_CMD | - MMC_CAP2_CACHE_CTRL, + MMC_CAP2_CACHE_CTRL | MMC_CAP2_POWEROFF_NOTIFY, #else - .host_caps2 = MMC_CAP2_ADAPT_PACKED | MMC_CAP2_PACKED_CMD, + .host_caps2 = MMC_CAP2_ADAPT_PACKED | MMC_CAP2_PACKED_CMD | + MMC_CAP2_POWEROFF_NOTIFY, #endif #elif defined(CONFIG_EXYNOS4_MSHC_8BIT) .max_width = 8, @@ -3430,29 +3431,16 @@ static void __init exynos4_reserve(void) .start = 0x65800000, .reserved = 1, }; - + if (cma_early_region_register(&fimc_reg)) pr_err("S5P/CMA: Failed to register '%s'\n", - fimc_reg.name); + fimc_reg.name); } #endif #if defined(CONFIG_USE_MFC_CMA) && defined(CONFIG_MACH_M0) ret = dma_declare_contiguous(&s5p_device_mfc.dev, 0x02800000, 0x5C800000, 0); - - if (ret == 0) { - static struct cma_region mfc_reg = { - .name = "mfc", - .size = 0x02800000, - .start = 0x5C800000, - .reserved = 1, - }; - - if (cma_early_region_register(&mfc_reg)) - pr_err("S5P/CMA: Failed to register '%s'\n", - mfc_reg.name); - } #endif if (ret != 0) printk(KERN_ERR "%s Fail\n", __func__); diff --git a/arch/arm/mach-exynos/midas-sound.c b/arch/arm/mach-exynos/midas-sound.c index 28c7cbd..32ab866 100644 --- a/arch/arm/mach-exynos/midas-sound.c +++ b/arch/arm/mach-exynos/midas-sound.c @@ -331,11 +331,16 @@ struct platform_device s3c_device_fm34 = { defined(CONFIG_FM_SI4705_MODULE) static void fmradio_power(int on) { + int err; #if defined(CONFIG_MACH_M0) || defined(CONFIG_MACH_M0_CTC) gpio_set_value(si47xx_data.gpio_sw, GPIO_LEVEL_HIGH); #endif if (on) { - gpio_request(GPIO_FM_INT, "GPC1"); + err = gpio_request(GPIO_FM_INT, "GPC1"); + if (err) { + pr_err(KERN_ERR "GPIO_FM_INT GPIO set error!\n"); + return; + } gpio_direction_output(GPIO_FM_INT, 1); gpio_set_value(si47xx_data.gpio_rst, GPIO_LEVEL_LOW); gpio_set_value(GPIO_FM_INT, GPIO_LEVEL_LOW); diff --git a/drivers/battery/max77693_charger.c b/drivers/battery/max77693_charger.c index 4a147ee..35289a6 100644 --- a/drivers/battery/max77693_charger.c +++ b/drivers/battery/max77693_charger.c @@ -463,7 +463,8 @@ void max77693_set_input_current(struct max77693_charger_data *chg_data, #endif if (set_current == OFF_CURR) { - max77693_write_reg(i2c, MAX77693_CHG_REG_CHG_CNFG_09, set_current); + max77693_write_reg(i2c, MAX77693_CHG_REG_CHG_CNFG_09, + set_current); if (chg_data->soft_reg_state == true) { pr_info("%s: exit soft regulation loop\n", __func__); @@ -676,11 +677,12 @@ static int max77693_get_cable_type(struct max77693_charger_data *chg_data) int state; u8 reg_data, mu_adc, mu_adc1k, otg; u8 dtls_00, chgin_dtls; + u8 dtls_01, chg_dtls; u8 mu_st2, chgdetrun, vbvolt, chgtyp, dxovp; - int muic_cb_typ; +#ifdef CONFIG_BATTERY_WPC_CHARGER bool wc_state; - bool retry_det; - bool chg_det_erred = false; /* TEMP: set as true for logging */ +#endif + bool retry_det, chg_det_erred; bool otg_detected = false; int retry_cnt = 0; pr_debug("%s\n", __func__); @@ -719,10 +721,8 @@ static int max77693_get_cable_type(struct max77693_charger_data *chg_data) } #endif - muic_cb_typ = max77693_muic_get_charging_type(); /* if type detection by otg, do not otg check */ - if ((muic_cb_typ != CABLE_TYPE_AUDIODOCK_MUIC) && - (((otg || (mu_adc == 0x00 && !mu_adc1k))))) { + if (otg || (mu_adc == 0x00 && !mu_adc1k)) { pr_info("%s: otg enabled(otg(0x%x), adc(0x%x))\n", __func__, otg, mu_adc); state = POWER_SUPPLY_TYPE_BATTERY; @@ -737,15 +737,20 @@ static int max77693_get_cable_type(struct max77693_charger_data *chg_data) goto chg_det_finish; } + chg_det_erred = false; /* TEMP: set as true for logging */ do { retry_det = false; max77693_read_reg(chg_data->max77693->i2c, MAX77693_CHG_REG_CHG_DTLS_00, &dtls_00); + max77693_read_reg(chg_data->max77693->i2c, + MAX77693_CHG_REG_CHG_DTLS_01, &dtls_01); max77693_read_reg(chg_data->max77693->muic, MAX77693_MUIC_REG_STATUS2, &mu_st2); chgin_dtls = ((dtls_00 & MAX77693_CHGIN_DTLS) >> MAX77693_CHGIN_DTLS_SHIFT); + chg_dtls = ((dtls_01 & MAX77693_CHG_DTLS) >> + MAX77693_CHG_DTLS_SHIFT); chgdetrun = ((mu_st2 & MAX77693_CHGDETRUN) >> MAX77693_CHGDETRUN_SHIFT); vbvolt = ((mu_st2 & MAX77693_VBVOLT) >> @@ -753,9 +758,9 @@ static int max77693_get_cable_type(struct max77693_charger_data *chg_data) chgtyp = ((mu_st2 & MAX77693_CHGTYPE) >> MAX77693_CHGTYPE_SHIFT); if (chg_det_erred) - pr_err("%s: CHGIN(0x%x). MU_ST2(0x%x), " + pr_err("%s: CHGIN(0x%x). CHG(0x%x), MU_ST2(0x%x), " "CDR(0x%x), VB(0x%x), CHGTYP(0x%x)\n", __func__, - chgin_dtls, mu_st2, + chgin_dtls, chg_dtls, mu_st2, chgdetrun, vbvolt, chgtyp); /* input power state */ @@ -772,9 +777,7 @@ static int max77693_get_cable_type(struct max77693_charger_data *chg_data) chg_det_erred = true; /* check chargable input power */ - if ((chgin_dtls == 0x0) && - (chg_data->cable_type == - POWER_SUPPLY_TYPE_BATTERY)) { + if ((chgin_dtls == 0x0) && (chg_dtls == 0x8)) { pr_err("%s: unchargable power\n", __func__); state = POWER_SUPPLY_TYPE_BATTERY; goto chg_det_finish; @@ -974,10 +977,6 @@ static int max77693_get_online_type(struct max77693_charger_data *chg_data) m_typ = max77693_get_cable_type(chg_data); - pr_info("%s: main(%d), sub(%d), pwr(%d)\n", __func__, m_typ, - chg_data->cable_sub_type, - chg_data->cable_pwr_type); - state = ((m_typ << ONLINE_TYPE_MAIN_SHIFT) | (chg_data->cable_sub_type << ONLINE_TYPE_SUB_SHIFT) | (chg_data->cable_pwr_type << ONLINE_TYPE_PWR_SHIFT)); diff --git a/drivers/battery/samsung_battery.c b/drivers/battery/samsung_battery.c index c63430b..ffe10e9 100644 --- a/drivers/battery/samsung_battery.c +++ b/drivers/battery/samsung_battery.c @@ -637,7 +637,7 @@ static void battery_notify_full_state(struct battery_info *info) info->battery_raw_soc, info->battery_full_soc, info->battery_soc); - if ((info->recharge_phase && info->full_charged_state) || + if (info->full_charged_state || ((info->charge_real_state != POWER_SUPPLY_STATUS_DISCHARGING) && (info->battery_raw_soc > info->battery_full_soc) && (info->battery_soc == 100))) { @@ -808,7 +808,7 @@ static bool battery_fullcharged_cond(struct battery_info *info) if (info->charge_real_state == POWER_SUPPLY_STATUS_FULL) { if ((info->battery_vcell > f_cond_vcell) && (info->battery_soc > f_cond_soc)) { - pr_info("%s: real full charged, v(%d), s(%d)\n", + pr_debug("%s: real full charged, v(%d), s(%d)\n", __func__, info->battery_vcell, info->battery_soc); #if defined(USE_2STEP_TERM) @@ -1606,6 +1606,8 @@ charge_ok: case POWER_SUPPLY_TYPE_DOCK: if (!info->pdata->suspend_chging) wake_lock(&info->charge_wake_lock); + /* default dock prop is AC */ + info->online_prop = ONLINE_PROP_AC; muic_cb_typ = max77693_muic_get_charging_type(); switch (muic_cb_typ) { case CABLE_TYPE_AUDIODOCK_MUIC: @@ -1633,6 +1635,7 @@ charge_ok: case CABLE_TYPE_SMARTDOCK_USB_MUIC: pr_info("%s: smart dock usb(low), %d\n", __func__, DOCK_TYPE_LOW_CURR); + info->online_prop = ONLINE_PROP_USB; battery_charge_control(info, DOCK_TYPE_LOW_CURR, DOCK_TYPE_LOW_CURR); @@ -2037,7 +2040,9 @@ static int samsung_usb_get_property(struct power_supply *ps, val->intval = ((info->charge_virt_state != POWER_SUPPLY_STATUS_DISCHARGING) && ((info->cable_type == POWER_SUPPLY_TYPE_USB) || - (info->cable_type == POWER_SUPPLY_TYPE_USB_CDP))); + (info->cable_type == POWER_SUPPLY_TYPE_USB_CDP) || + ((info->cable_type == POWER_SUPPLY_TYPE_DOCK) && + (info->online_prop == ONLINE_PROP_USB)))); return 0; } @@ -2057,7 +2062,8 @@ static int samsung_ac_get_property(struct power_supply *ps, POWER_SUPPLY_STATUS_DISCHARGING) && ((info->cable_type == POWER_SUPPLY_TYPE_MAINS) || (info->cable_type == POWER_SUPPLY_TYPE_MISC) || - (info->cable_type == POWER_SUPPLY_TYPE_DOCK) || + ((info->cable_type == POWER_SUPPLY_TYPE_DOCK) && + (info->online_prop != ONLINE_PROP_USB)) || (info->cable_type == POWER_SUPPLY_TYPE_WIRELESS))); return 0; diff --git a/drivers/gpu/ion/ion.c b/drivers/gpu/ion/ion.c index eb81503..14dbefc 100644 --- a/drivers/gpu/ion/ion.c +++ b/drivers/gpu/ion/ion.c @@ -1034,8 +1034,8 @@ static int ion_share_mmap(struct file *file, struct vm_area_struct *vma) return -EINVAL; } - if ((size > buffer->size) || (size + (vma->vm_pgoff << PAGE_SHIFT) > - buffer->size)) { + if (((vma->vm_pgoff << PAGE_SHIFT) >= buffer->size) || + (size > (buffer->size - (vma->vm_pgoff << PAGE_SHIFT)))) { pr_err("%s: trying to map larger area than handle has available" "\n", __func__); ret = -EINVAL; diff --git a/drivers/misc/max77693-muic.c b/drivers/misc/max77693-muic.c index 41008a0..9a78d76 100644 --- a/drivers/misc/max77693-muic.c +++ b/drivers/misc/max77693-muic.c @@ -92,6 +92,7 @@ enum { ADC_DOCK_VOL_UP = 0x0b, /* 0x01011 17.26K ohm */ ADC_DOCK_PLAY_PAUSE_KEY = 0x0d, ADC_SMARTDOCK = 0x10, /* 0x10000 40.2K ohm */ + ADC_AUDIODOCK = 0x12, /* 0x10010 64.9K ohm */ ADC_CEA936ATYPE1_CHG = 0x17, /* 0x10111 200K ohm */ ADC_JIG_USB_OFF = 0x18, /* 0x11000 255K ohm */ ADC_JIG_USB_ON = 0x19, /* 0x11001 301K ohm */ @@ -135,6 +136,11 @@ struct max77693_muic_info { struct wake_lock muic_wake_lock; enum cable_type_muic cable_type; +#if defined(CONFIG_MUIC_MAX77693_SUPPORT_SMART_DOCK) ||\ + defined(CONFIG_MUIC_MAX77693_SUPPORT_OTG_AUDIO_DOCK) + struct delayed_work dock_work; +#endif /* CONFIG_MUIC_MAX77693_SUPPORT_SMART_DOCK || + CONFIG_MUIC_MAX77693_SUPPORT_OTG_AUDIO_DOCK */ struct delayed_work init_work; struct delayed_work usb_work; struct delayed_work mhl_work; @@ -151,6 +157,10 @@ struct max77693_muic_info { bool is_otg_attach_blocked; #endif /* CONFIG_MACH_GC1 */ +#if !defined(CONFIG_MUIC_MAX77693_SUPPORT_CAR_DOCK) + bool is_factory_start; +#endif /* !CONFIG_MUIC_MAX77693_SUPPORT_CAR_DOCK */ + #if defined(CONFIG_MUIC_DET_JACK) int earkeypressed; int previous_earkey; @@ -175,8 +185,8 @@ static int get_if_pmic_inifo(char *str) get_option(&str, &if_muic_info); switch_sel = if_muic_info & 0x0f; if_pmic_rev = (if_muic_info & 0xf0) >> 4; - pr_info("%s: switch_sel: %x if_pmic_rev:%x\n", - __func__, switch_sel, if_pmic_rev); + pr_info("%s %s: switch_sel: %x if_pmic_rev:%x\n", + __FILE__, __func__, switch_sel, if_pmic_rev); return if_muic_info; } __setup("pmic_info=", get_if_pmic_inifo); @@ -441,6 +451,14 @@ static ssize_t max77693_muic_show_device(struct device *dev, return sprintf(buf, "mHL\n"); case CABLE_TYPE_MHL_VB_MUIC: return sprintf(buf, "mHL charging\n"); + case CABLE_TYPE_SMARTDOCK_MUIC: + return sprintf(buf, "Smart Dock\n"); + case CABLE_TYPE_SMARTDOCK_TA_MUIC: + return sprintf(buf, "Smart Dock+TA\n"); + case CABLE_TYPE_SMARTDOCK_USB_MUIC: + return sprintf(buf, "Smart Dock+USB\n"); + case CABLE_TYPE_AUDIODOCK_MUIC: + return sprintf(buf, "Audio Dock\n"); default: break; } @@ -934,6 +952,49 @@ static ssize_t max77693_muic_set_otg_block(struct device *dev, } #endif /* CONFIG_MACH_GC1 */ +#if !defined(CONFIG_MUIC_MAX77693_SUPPORT_CAR_DOCK) +static ssize_t max77693_muic_show_apo_factory(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct max77693_muic_info *info = dev_get_drvdata(dev); + const char *mode; + + /* true: Factory mode, false: not Factory mode */ + if (info->is_factory_start) + mode = "FACTORY_MODE"; + else + mode = "NOT_FACTORY_MODE"; + + pr_info("%s:%s apo factory=%s\n", DEV_NAME, __func__, mode); + + return sprintf(buf, "%s\n", mode); +} + +static ssize_t max77693_muic_set_apo_factory(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct max77693_muic_info *info = dev_get_drvdata(dev); + const char *mode; + + pr_info("%s:%s buf:%s\n", DEV_NAME, __func__, buf); + + /* "FACTORY_START": factory mode */ + if (!strncmp(buf, "FACTORY_START", 13)) { + info->is_factory_start = true; + mode = "FACTORY_MODE"; + } else { + pr_warn("%s:%s Wrong command\n", DEV_NAME, __func__); + return count; + } + + pr_info("%s:%s apo factory=%s\n", DEV_NAME, __func__, mode); + + return count; +} +#endif /* !CONFIG_MUIC_MAX77693_SUPPORT_CAR_DOCK */ + #ifdef CONFIG_LTE_VIA_SWITCH static ssize_t max77693_muic_show_check_cpboot(struct device *dev, struct device_attribute *attr, char *buf) @@ -1002,6 +1063,11 @@ static DEVICE_ATTR(otg_block, 0664, max77693_muic_show_otg_block, max77693_muic_set_otg_block); #endif /* CONFIG_MACH_GC1 */ +#if !defined(CONFIG_MUIC_MAX77693_SUPPORT_CAR_DOCK) +static DEVICE_ATTR(apo_factory, 0664, + max77693_muic_show_apo_factory, + max77693_muic_set_apo_factory); +#endif /* !CONFIG_MUIC_MAX77693_SUPPORT_CAR_DOCK */ #ifdef CONFIG_LTE_VIA_SWITCH static DEVICE_ATTR(check_cpboot, 0664, max77693_muic_show_check_cpboot, @@ -1020,6 +1086,9 @@ static struct attribute *max77693_muic_attributes[] = { #if defined(CONFIG_MACH_GC1) &dev_attr_otg_block.attr, #endif /* CONFIG_MACH_GC1 */ +#if !defined(CONFIG_MUIC_MAX77693_SUPPORT_CAR_DOCK) + &dev_attr_apo_factory.attr, +#endif /* !CONFIG_MUIC_MAX77693_SUPPORT_CAR_DOCK */ #ifdef CONFIG_LTE_VIA_SWITCH &dev_attr_check_cpboot.attr, #endif @@ -1085,6 +1154,13 @@ static int max77693_muic_set_usb_path(struct max77693_muic_info *info, int path) (0 << MICEN_SHIFT); cntl1_msk = COMN1SW_MASK | COMP2SW_MASK | MICEN_MASK; break; + case OPEN_USB_MODE: + dev_info(info->dev, "%s: OPEN_USB_MODE\n", __func__); + gpio_val = 0; + val = MAX77693_MUIC_CTRL1_BIN_0_000; + cntl1_val = (val << COMN1SW_SHIFT) | (val << COMP2SW_SHIFT); + cntl1_msk = COMN1SW_MASK | COMP2SW_MASK; + break; default: dev_warn(info->dev, "%s: invalid path(%d)\n", __func__, path); return -EINVAL; @@ -1415,6 +1491,7 @@ static int max77693_muic_attach_dock_type(struct max77693_muic_info *info, if (mdata->dock_cb) mdata->dock_cb(MAX77693_MUIC_DOCK_CARDOCK); break; +#if defined(CONFIG_MUIC_MAX77693_SUPPORT_SMART_DOCK) case ADC_SMARTDOCK: if (info->cable_type == CABLE_TYPE_SMARTDOCK_MUIC) { dev_info(info->dev, "%s: duplicated(SmartDock)\n", @@ -1423,7 +1500,17 @@ static int max77693_muic_attach_dock_type(struct max77693_muic_info *info, } dev_info(info->dev, "%s:SmartDock\n", __func__); info->cable_type = CABLE_TYPE_SMARTDOCK_MUIC; - path = AP_USB_MODE; + + if (info->is_usb_ready) { + pr_info("%s:%s usb is ready, D+,D- line(AP_USB)\n", + DEV_NAME, __func__); + path = AP_USB_MODE; + } else { + pr_info("%s:%s usb not ready yet, D+,D- line(Open)\n", + DEV_NAME, __func__); + path = OPEN_USB_MODE; + } + max77693_muic_set_charging_type(info, false); msleep(40); #ifdef CONFIG_EXTCON @@ -1436,6 +1523,36 @@ static int max77693_muic_attach_dock_type(struct max77693_muic_info *info, if (mdata->dock_cb) mdata->dock_cb(MAX77693_MUIC_DOCK_SMARTDOCK); break; +#endif /* CONFIG_MUIC_MAX77693_SUPPORT_SMART_DOCK */ +#if defined(CONFIG_MUIC_MAX77693_SUPPORT_OTG_AUDIO_DOCK) + case ADC_AUDIODOCK: + if (info->cable_type == CABLE_TYPE_AUDIODOCK_MUIC) { + pr_info("%s:%s duplicated(AudioDock)\n", DEV_NAME, + __func__); + return 0; + } + pr_info("%s:%s AudioDock\n", DEV_NAME, __func__); + info->cable_type = CABLE_TYPE_AUDIODOCK_MUIC; + + if (info->is_usb_ready) { + pr_info("%s:%s usb is ready, D+,D- line(AP_USB)\n", + DEV_NAME, __func__); + path = AP_USB_MODE; + } else { + pr_info("%s:%s usb not ready yet, D+,D- line(Open)\n", + DEV_NAME, __func__); + path = OPEN_USB_MODE; + } + + max77693_muic_set_charging_type(info, false); + + if (mdata->usb_cb && info->is_usb_ready) + mdata->usb_cb(USB_POWERED_HOST_ATTACHED); + + if (mdata->dock_cb) + mdata->dock_cb(MAX77693_MUIC_DOCK_AUDIODOCK); + break; +#endif /* CONFIG_MUIC_MAX77693_SUPPORT_OTG_AUDIO_DOCK */ default: dev_info(info->dev, "%s: should not reach here(0x%x)\n", __func__, adc); @@ -1802,54 +1919,89 @@ void powered_otg_control(int enable) max77693_powered_otg_control(gInfo, enable); } -#if defined(CONFIG_MUIC_MAX77693_SUPPORT_OTG_AUDIO_DOCK) -#define BAT_PSY_NAME "battery" -void max77693_muic_attach_audio_dock(void) +#if defined(CONFIG_MUIC_MAX77693_SUPPORT_SMART_DOCK) +static void max77693_muic_set_cddelay(struct max77693_muic_info *info) { - struct max77693_muic_info *info = gInfo; - struct max77693_muic_data *mdata = info->muic_data; - struct power_supply *psy = power_supply_get_by_name(BAT_PSY_NAME); - union power_supply_propval value; + u8 cdetctrl1; + int ret = 0; - switch (info->cable_type) { -#if defined(CONFIG_MUIC_MAX77693_SUPPORT_SMART_DOCK) - case CABLE_TYPE_SMARTDOCK_MUIC: - case CABLE_TYPE_SMARTDOCK_TA_MUIC: - case CABLE_TYPE_SMARTDOCK_USB_MUIC: - pr_info("%s:%s= SmartDock connected, ignore.\n", __FILE__, + ret = max77693_read_reg(info->max77693->muic, + MAX77693_MUIC_REG_CDETCTRL1, &cdetctrl1); + + pr_info("%s:%s read CDETCTRL1=0x%x, ret=%d\n", DEV_NAME, __func__, + cdetctrl1, ret); + + if ((cdetctrl1 & 0x10) == 0x10) { + pr_info("%s:%s CDDelay already setted, return\n", DEV_NAME, __func__); return; -#endif /* CONFIG_MUIC_MAX77693_SUPPORT_SMART_DOCK */ - default: - break; } - dev_info(info->dev, "%s:AudioDock\n", __func__); + cdetctrl1 |= 0x10; - info->cable_type = CABLE_TYPE_AUDIODOCK_MUIC; + ret = max77693_write_reg(info->max77693->muic, + MAX77693_MUIC_REG_CDETCTRL1, cdetctrl1); - max77693_otg_control(info, 0); + pr_info("%s:%s write CDETCTRL1=0x%x, ret=%d\n", DEV_NAME, + __func__, cdetctrl1, ret); +} - if (mdata->dock_cb) - mdata->dock_cb(MAX77693_MUIC_DOCK_AUDIODOCK); +static void max77693_muic_clear_cddelay(struct max77693_muic_info *info) +{ + u8 cdetctrl1; + int ret = 0; + + ret = max77693_read_reg(info->max77693->muic, + MAX77693_MUIC_REG_CDETCTRL1, &cdetctrl1); + + pr_info("%s:%s read CDETCTRL1=0x%x, ret=%d\n", DEV_NAME, __func__, + cdetctrl1, ret); - if (!psy || !psy->set_property) { - pr_err("%s: fail to get %s psy\n", __func__, BAT_PSY_NAME); + if ((cdetctrl1 & 0x10) == 0x0) { + pr_info("%s:%s CDDelay already cleared, return\n", DEV_NAME, + __func__); return; } - psy->set_property(psy, POWER_SUPPLY_PROP_STATUS, &value); + cdetctrl1 &= ~(0x10); + + ret = max77693_write_reg(info->max77693->muic, + MAX77693_MUIC_REG_CDETCTRL1, cdetctrl1); + + pr_info("%s:%s write CDETCTRL1=0x%x, ret=%d\n", DEV_NAME, + __func__, cdetctrl1, ret); } -#endif /* CONFIG_MUIC_MAX77693_SUPPORT_OTG_AUDIO_DOCK */ -#if defined(CONFIG_MUIC_MAX77693_SUPPORT_SMART_DOCK) static void max77693_muic_detach_smart_dock(struct max77693_muic_info *info) { struct max77693_muic_data *mdata = info->muic_data; + enum cable_type_muic tmp_cable_type = info->cable_type; pr_info("%s:%s\n", DEV_NAME, __func__); - switch (info->cable_type) { + if (info->cable_type != CABLE_TYPE_SMARTDOCK_MUIC && + info->cable_type != CABLE_TYPE_SMARTDOCK_TA_MUIC && + info->cable_type != CABLE_TYPE_SMARTDOCK_USB_MUIC) { + pr_info("%s:%s cable_type is not SMARTDOCK\n", DEV_NAME, + __func__); + return; + } + + if (mdata->dock_cb) + mdata->dock_cb(MAX77693_MUIC_DOCK_DETACHED); + + info->cable_type = CABLE_TYPE_NONE_MUIC; + + max77693_muic_set_charging_type(info, false); +#ifdef CONFIG_EXTCON + if (info->edev && info->is_mhl_ready) + extcon_set_cable_state(info->edev, "MHL", false); +#else + if (mdata->mhl_cb && info->is_mhl_ready) + mdata->mhl_cb(MAX77693_MUIC_DETACHED); +#endif + + switch (tmp_cable_type) { case CABLE_TYPE_SMARTDOCK_TA_MUIC: pr_info("%s:%s SMARTDOCK+TA\n", DEV_NAME, __func__); @@ -1863,29 +2015,16 @@ static void max77693_muic_detach_smart_dock(struct max77693_muic_info *info) mdata->usb_cb(USB_CABLE_DETACHED); break; case CABLE_TYPE_SMARTDOCK_MUIC: + /* clear CDDelay 500ms */ + max77693_muic_clear_cddelay(info); pr_info("%s:%s SMARTDOCK\n", DEV_NAME, __func__); break; default: - pr_info("%s:%s cable_type is not SMARTDOCK\n", DEV_NAME, + pr_warn("%s:%s should not reach here!\n", DEV_NAME, __func__); return; break; } - - info->cable_type = CABLE_TYPE_NONE_MUIC; - - if (mdata->dock_cb) { - mdata->dock_cb(MAX77693_MUIC_DOCK_DETACHED); - msleep(20); - } - max77693_muic_set_charging_type(info, false); -#ifdef CONFIG_EXTCON - if (info->edev && info->is_mhl_ready) - extcon_set_cable_state(info->edev, "MHL", false); -#else - if (mdata->mhl_cb && info->is_mhl_ready) - mdata->mhl_cb(MAX77693_MUIC_DETACHED); -#endif } static void max77693_muic_attach_smart_dock(struct max77693_muic_info *info, @@ -1896,6 +2035,8 @@ static void max77693_muic_attach_smart_dock(struct max77693_muic_info *info, switch (info->cable_type) { case CABLE_TYPE_SMARTDOCK_MUIC: if (chgtyp == CHGTYP_DEDICATED_CHGR) { + /* clear CDDelay 500ms */ + max77693_muic_clear_cddelay(info); pr_info("%s:%s SMART_DOCK+TA=OTG Enable\n", DEV_NAME, __func__); @@ -1904,6 +2045,8 @@ static void max77693_muic_attach_smart_dock(struct max77693_muic_info *info, info->cable_type = CABLE_TYPE_SMARTDOCK_TA_MUIC; } else if (chgtyp == CHGTYP_USB) { + /* clear CDDelay 500ms */ + max77693_muic_clear_cddelay(info); pr_info("%s:%s SMART_DOCK+USB=USB Enable\n", DEV_NAME, __func__); @@ -1940,7 +2083,17 @@ static void max77693_muic_attach_smart_dock(struct max77693_muic_info *info, pr_info("%s:%s SMART_DOCK+vbvolt=chgdetrun\n", DEV_NAME, __func__); max77693_muic_attach_dock_type(info, adc); + if (chgtyp == CHGTYP_DEDICATED_CHGR || + chgtyp == CHGTYP_USB) { + pr_info("%s:%s SMART_DOCK+(TA or USB)="\ + "Recursive call to attach oneshot\n", + DEV_NAME, __func__); + max77693_muic_attach_smart_dock(info, adc, + vbvolt, chgtyp); + } } else { + /* set CDDelay 500ms */ + max77693_muic_set_cddelay(info); dev_warn(info->dev, "no vbus in SAMRTDOCK\n"); } break; @@ -1948,14 +2101,34 @@ static void max77693_muic_attach_smart_dock(struct max77693_muic_info *info, } #endif /* CONFIG_MUIC_MAX77693_SUPPORT_SMART_DOCK */ +#if defined(CONFIG_MUIC_MAX77693_SUPPORT_OTG_AUDIO_DOCK) +static void max77693_muic_detach_audio_dock(struct max77693_muic_info *info) +{ + struct max77693_muic_data *mdata = info->muic_data; + + pr_info("%s:%s AUDIODOCK\n", DEV_NAME, __func__); + + info->cable_type = CABLE_TYPE_NONE_MUIC; + + max77693_muic_set_charging_type(info, false); + + if (mdata->dock_cb) + mdata->dock_cb(MAX77693_MUIC_DOCK_DETACHED); + + if (mdata->usb_cb && info->is_usb_ready) + mdata->usb_cb(USB_POWERED_HOST_DETACHED); +} +#endif /* CONFIG_MUIC_MAX77693_SUPPORT_OTG_AUDIO_DOCK */ + static int max77693_muic_handle_attach(struct max77693_muic_info *info, u8 status1, u8 status2, int irq) { struct max77693_muic_data *mdata = info->muic_data; - u8 adc, vbvolt, chgtyp, chgdetrun, adc1k, dxovp; + u8 adc, adclow, vbvolt, chgtyp, chgdetrun, adc1k, dxovp; int ret = 0; adc = status1 & STATUS1_ADC_MASK; + adclow = status1 & STATUS1_ADCLOW_MASK; adc1k = status1 & STATUS1_ADC1K_MASK; chgtyp = status2 & STATUS2_CHGTYP_MASK; vbvolt = status2 & STATUS2_VBVOLT_MASK; @@ -1966,6 +2139,18 @@ static int max77693_muic_handle_attach(struct max77693_muic_info *info, __func__, status1, status2, info->cable_type); switch (info->cable_type) { + case CABLE_TYPE_OTG_MUIC: + if (!!adclow) { + pr_warn("%s:%s assume OTG detach\n", DEV_NAME, + __func__); + info->cable_type = CABLE_TYPE_NONE_MUIC; + + max77693_muic_set_charging_type(info, false); + + if (mdata->usb_cb && info->is_usb_ready) + mdata->usb_cb(USB_OTGHOST_DETACHED); + } + break; case CABLE_TYPE_JIG_UART_OFF_MUIC: case CABLE_TYPE_JIG_UART_OFF_VB_MUIC: /* Workaround for Factory mode. @@ -1984,6 +2169,13 @@ static int max77693_muic_handle_attach(struct max77693_muic_info *info, && info->max77693->pmic_rev >= MAX77693_REV_PASS2) max77693_muic_handle_jig_uart(info, vbvolt); +#if !defined(CONFIG_MUIC_MAX77693_SUPPORT_CAR_DOCK) + if (info->is_factory_start) { + pr_info("%s:%s factory start, keep attach\n", + DEV_NAME, __func__); + break; + } +#endif /* !CONFIG_MUIC_MAX77693_SUPPORT_CAR_DOCK */ dev_warn(info->dev, "%s: abandon ADC\n", __func__); return 0; } @@ -1994,7 +2186,6 @@ static int max77693_muic_handle_attach(struct max77693_muic_info *info, info->cable_type = CABLE_TYPE_NONE_MUIC; } break; - case CABLE_TYPE_DESKDOCK_MUIC: if (adc != ADC_DESKDOCK) { dev_warn(info->dev, "%s: assume deskdock detach\n", @@ -2007,7 +2198,6 @@ static int max77693_muic_handle_attach(struct max77693_muic_info *info, mdata->dock_cb(MAX77693_MUIC_DOCK_DETACHED); } break; - case CABLE_TYPE_CARDOCK_MUIC: if (adc != ADC_CARDOCK) { dev_warn(info->dev, "%s: assume cardock detach\n", @@ -2020,6 +2210,19 @@ static int max77693_muic_handle_attach(struct max77693_muic_info *info, mdata->dock_cb(MAX77693_MUIC_DOCK_DETACHED); } break; +#if !defined(CONFIG_MUIC_MAX77693_SUPPORT_CAR_DOCK) + case CABLE_TYPE_JIG_UART_ON_MUIC: + if ((adc != ADC_JIG_UART_ON) && + info->is_factory_start) { + pr_warn("%s:%s assume jig uart on detach\n", + DEV_NAME, __func__); + info->cable_type = CABLE_TYPE_NONE_MUIC; + + if (mdata->dock_cb) + mdata->dock_cb(MAX77693_MUIC_DOCK_DETACHED); + } + break; +#endif /* !CONFIG_MUIC_MAX77693_SUPPORT_CAR_DOCK */ #if defined(CONFIG_MUIC_MAX77693_SUPPORT_SMART_DOCK) case CABLE_TYPE_SMARTDOCK_MUIC: case CABLE_TYPE_SMARTDOCK_TA_MUIC: @@ -2029,26 +2232,21 @@ static int max77693_muic_handle_attach(struct max77693_muic_info *info, __func__); max77693_muic_detach_smart_dock(info); + + info->is_adc_open_prev = false; } break; #endif /* CONFIG_MUIC_MAX77693_SUPPORT_SMART_DOCK */ +#if defined(CONFIG_MUIC_MAX77693_SUPPORT_OTG_AUDIO_DOCK) case CABLE_TYPE_AUDIODOCK_MUIC: - if (adc != ADC_GND) { + if ((adc != ADC_AUDIODOCK) || (!vbvolt)) { dev_warn(info->dev, "%s: assume audiodock detach\n", __func__); - info->cable_type = CABLE_TYPE_NONE_MUIC; - - max77693_muic_set_charging_type(info, false); - info->is_adc_open_prev = false; - if (mdata->usb_cb && info->is_usb_ready) - mdata->usb_cb(USB_OTGHOST_DETACHED); - - if (mdata->dock_cb) - mdata->dock_cb(MAX77693_MUIC_DOCK_DETACHED); + max77693_muic_detach_audio_dock(info); } break; - +#endif /* CONFIG_MUIC_MAX77693_SUPPORT_OTG_AUDIO_DOCK */ default: break; } @@ -2065,6 +2263,10 @@ static int max77693_muic_handle_attach(struct max77693_muic_info *info, "%s: Ignore irq:%d at MHL detection\n", __func__, irq); if (vbvolt) { + if (info->cable_type == CABLE_TYPE_MHL_MUIC + && chgtyp == CHGTYP_USB) + info->cable_type = CABLE_TYPE_MHL_VB_MUIC; + dev_info(info->dev, "%s: call charger_cb(%d)" , __func__, vbvolt); max77693_muic_set_charging_type(info, false); @@ -2084,13 +2286,6 @@ static int max77693_muic_handle_attach(struct max77693_muic_info *info, switch (adc) { case ADC_GND: if (chgtyp == CHGTYP_NO_VOLTAGE) { -#if defined(CONFIG_MUIC_MAX77693_SUPPORT_OTG_AUDIO_DOCK) - if (info->cable_type == CABLE_TYPE_AUDIODOCK_MUIC) { - pr_info("%s:%s audio_dock attached, ignore\n", - DEV_NAME, __func__); - break; - } -#endif /* CONFIG_MUIC_MAX77693_SUPPORT_OTG_AUDIO_DOCK */ if (info->cable_type == CABLE_TYPE_OTG_MUIC) { dev_info(info->dev, "%s: duplicated(OTG)\n", __func__); @@ -2116,6 +2311,12 @@ static int max77693_muic_handle_attach(struct max77693_muic_info *info, max77693_muic_attach_smart_dock(info, adc, vbvolt, chgtyp); break; #endif /* CONFIG_MUIC_MAX77693_SUPPORT_SMART_DOCK */ +#if defined(CONFIG_MUIC_MAX77693_SUPPORT_OTG_AUDIO_DOCK) + case ADC_AUDIODOCK: + if (!!vbvolt) + max77693_muic_attach_dock_type(info, adc); + break; +#endif /* CONFIG_MUIC_MAX77693_SUPPORT_OTG_AUDIO_DOCK */ case ADC_JIG_UART_OFF: max77693_muic_handle_jig_uart(info, vbvolt); #if defined(CONFIG_MACH_T0_CHN_CMCC) @@ -2135,7 +2336,23 @@ static int max77693_muic_handle_attach(struct max77693_muic_info *info, mdata->jig_state(true); break; case ADC_DESKDOCK: + max77693_muic_attach_dock_type(info, adc); + if (chgtyp == CHGTYP_USB || + chgtyp == CHGTYP_DOWNSTREAM_PORT || + chgtyp == CHGTYP_DEDICATED_CHGR || + chgtyp == CHGTYP_500MA || chgtyp == CHGTYP_1A) + ret = max77693_muic_set_charging_type(info, false); + else if (chgtyp == CHGTYP_NO_VOLTAGE && !chgdetrun) + ret = max77693_muic_set_charging_type(info, !vbvolt); + /* For MAX77693 IC doesn`t occur chgtyp IRQ + * because of audio noise prevention. + * So, If below condition is set, + * we do charging at CARDOCK. + */ + break; + /* ADC_CARDOCK == ADC_JIG_UART_ON */ case ADC_CARDOCK: +#if defined(CONFIG_MUIC_MAX77693_SUPPORT_CAR_DOCK) max77693_muic_attach_dock_type(info, adc); if (chgtyp == CHGTYP_USB || chgtyp == CHGTYP_DOWNSTREAM_PORT || @@ -2149,7 +2366,29 @@ static int max77693_muic_handle_attach(struct max77693_muic_info *info, * So, If below condition is set, * we do charging at CARDOCK. */ - break; +#else + /* because of change FACTORY CPOriented to APOriented, + * at manufacture need AP wake-up method. write apo_factory + * "FACTORY_START" is set is_factory_start true + * and write apo_factory "FACTORY_END" is set + * is_factory_start false. + */ + if (info->is_factory_start) { + if (info->cable_type == CABLE_TYPE_JIG_UART_ON_MUIC) { + pr_info("%s:%s duplicated(JIG_UART_ON)\n", + DEV_NAME, __func__); + return 0; + } + pr_info("%s:%s JIG_UART_ON\n", DEV_NAME, __func__); + info->cable_type = CABLE_TYPE_JIG_UART_ON_MUIC; + + if (mdata->dock_cb) + mdata->dock_cb(MAX77693_MUIC_DOCK_DESKDOCK); + + return 0; + } +#endif /* CONFIG_MUIC_MAX77693_SUPPORT_CAR_DOCK */ + break; #if defined(CONFIG_MUIC_DET_JACK) case ADC_MHL_OR_SENDEND: case ADC_DOCK_VOL_UP: @@ -2229,14 +2468,6 @@ static int max77693_muic_handle_attach(struct max77693_muic_info *info, break; } -#ifdef CONFIG_FAST_BOOT - if ((info->cable_type == CABLE_TYPE_TA_MUIC) && (fake_shut_down)) { - pr_info("%s: Resetting the device in fake shutdown mode"\ - "(TA inserted !!!)\n", __func__); - kernel_power_off(); - } -#endif - return ret; } @@ -2288,6 +2519,11 @@ static int max77693_muic_handle_detach(struct max77693_muic_info *info, int irq) #endif /* CONFIG_USBHUB_USB3803 */ info->previous_key = DOCK_KEY_NONE; +#if defined(CONFIG_MUIC_MAX77693_SUPPORT_SMART_DOCK) + /* clear CDDelay 500ms */ + max77693_muic_clear_cddelay(info); +#endif /* CONFIG_MUIC_MAX77693_SUPPORT_SMART_DOCK */ + if (info->cable_type == CABLE_TYPE_NONE_MUIC) { dev_info(info->dev, "%s: duplicated(NONE)\n", __func__); return 0; @@ -2305,18 +2541,6 @@ static int max77693_muic_handle_detach(struct max77693_muic_info *info, int irq) if (mdata->usb_cb && info->is_usb_ready) mdata->usb_cb(USB_OTGHOST_DETACHED); break; - - case CABLE_TYPE_AUDIODOCK_MUIC: - dev_info(info->dev, "%s: AUDIO\n", __func__); - info->cable_type = CABLE_TYPE_NONE_MUIC; - - if (mdata->usb_cb && info->is_usb_ready) - mdata->usb_cb(USB_OTGHOST_DETACHED); - - if (mdata->dock_cb) - mdata->dock_cb(MAX77693_MUIC_DOCK_DETACHED); - break; - case CABLE_TYPE_USB_MUIC: case CABLE_TYPE_JIG_USB_OFF_MUIC: case CABLE_TYPE_JIG_USB_ON_MUIC: @@ -2377,8 +2601,18 @@ static int max77693_muic_handle_detach(struct max77693_muic_info *info, int irq) info->cable_type = CABLE_TYPE_TA_MUIC; break; case CABLE_TYPE_JIG_UART_ON_MUIC: +#if defined(CONFIG_MUIC_MAX77693_SUPPORT_CAR_DOCK) dev_info(info->dev, "%s: JIG UART/BOOTON\n", __func__); info->cable_type = CABLE_TYPE_NONE_MUIC; +#else + if (info->is_factory_start) { + pr_info("%s:%s JIG_UART_ON\n", DEV_NAME, __func__); + info->cable_type = CABLE_TYPE_NONE_MUIC; + + if (mdata->dock_cb) + mdata->dock_cb(MAX77693_MUIC_DOCK_DETACHED); + } +#endif /* CONFIG_MUIC_MAX77693_SUPPORT_CAR_DOCK */ break; case CABLE_TYPE_JIG_UART_OFF_MUIC: dev_info(info->dev, "%s: JIG UART/BOOTOFF\n", __func__); @@ -2391,6 +2625,11 @@ static int max77693_muic_handle_detach(struct max77693_muic_info *info, int irq) max77693_muic_detach_smart_dock(info); break; #endif /* CONFIG_MUIC_MAX77693_SUPPORT_SMART_DOCK */ +#if defined(CONFIG_MUIC_MAX77693_SUPPORT_OTG_AUDIO_DOCK) + case CABLE_TYPE_AUDIODOCK_MUIC: + max77693_muic_detach_audio_dock(info); + break; +#endif /* CONFIG_MUIC_MAX77693_SUPPORT_OTG_AUDIO_DOCK */ case CABLE_TYPE_JIG_UART_OFF_VB_MUIC: dev_info(info->dev, "%s: JIG UART/OFF/VB\n", __func__); info->cable_type = CABLE_TYPE_NONE_MUIC; @@ -2478,7 +2717,7 @@ static int max77693_muic_filter_dev(struct max77693_muic_info *info, vbvolt = status2 & STATUS2_VBVOLT_MASK; dxovp = status2 & STATUS2_DXOVP_MASK; - dev_info(info->dev, "adc:%x adcerr:%x chgtyp:%x vb:%x dxovp:%x cable_type:%x\n", + dev_info(info->dev, "adc:%x adcerr:%x chgtyp:%x vb:%x dxovp:%x cable_type:%d\n", adc, adcerr, chgtyp, vbvolt, dxovp, info->cable_type); #if !defined(CONFIG_MUIC_MAX77693_SEPARATE_MHL_PORT) @@ -2513,10 +2752,11 @@ static int max77693_muic_filter_dev(struct max77693_muic_info *info, case ADC_MHL ... (ADC_SMARTDOCK - 1): case (ADC_OPEN - 1): #endif /* !CONFIG_MUIC_DET_JACK */ - case (ADC_SMARTDOCK + 1) ... (ADC_CEA936ATYPE1_CHG - 1): -#if !defined(CONFIG_MUIC_MAX77693_SUPPORT_CAR_DOCK) - case ADC_CARDOCK: -#endif /* CONFIG_MUIC_MAX77693_SUPPORT_CAR_DOCK */ + case (ADC_SMARTDOCK + 1): +#if !defined(CONFIG_MUIC_MAX77693_SUPPORT_OTG_AUDIO_DOCK) + case ADC_AUDIODOCK: +#endif /* !CONFIG_MUIC_MAX77693_SUPPORT_OTG_AUDIO_DOCK */ + case (ADC_AUDIODOCK + 1) ... (ADC_CEA936ATYPE1_CHG - 1): #endif /* CONFIG_MACH_GC1 */ dev_warn(info->dev, "%s: unsupported ADC(0x%02x)\n", __func__, adc); @@ -2682,6 +2922,87 @@ do { \ } \ } while (0) +#if defined(CONFIG_MUIC_MAX77693_SUPPORT_SMART_DOCK) ||\ + defined(CONFIG_MUIC_MAX77693_SUPPORT_OTG_AUDIO_DOCK) +static void max77693_muic_dock_detect(struct work_struct *work) +{ + struct max77693_muic_info *info = + container_of(work, struct max77693_muic_info, dock_work.work); + struct i2c_client *client = info->muic; + u8 status[2]; + int ret; + u8 cntl1_val; + u8 adc, adclow, adcerr, adc1k, chgtyp, vbvolt, dxovp; + + mutex_lock(&info->mutex); + ret = max77693_read_reg(client, MAX77693_MUIC_REG_CTRL1, &cntl1_val); + pr_info("%s:%s CONTROL1:%x\n", DEV_NAME, __func__, cntl1_val); + + ret = max77693_bulk_read(client, MAX77693_MUIC_REG_STATUS1, 2, status); + if (ret) { + pr_err("%s:%s fail to read muic reg(%d)\n", DEV_NAME, __func__, + ret); + goto end; + } + + pr_info("%s:%s STATUS1:0x%x, 2:0x%x\n", DEV_NAME, __func__, status[0], + status[1]); + + adc = status[0] & STATUS1_ADC_MASK; + adclow = status[0] & STATUS1_ADCLOW_MASK; + adcerr = status[0] & STATUS1_ADCERR_MASK; + adc1k = status[0] & STATUS1_ADC1K_MASK; + chgtyp = status[1] & STATUS2_CHGTYP_MASK; + vbvolt = status[1] & STATUS2_VBVOLT_MASK; + dxovp = status[1] & STATUS2_DXOVP_MASK; + + pr_info("%s:%s adc:%x adcerr:%x chgtyp:%x vb:%x dxovp:%x"\ + " cable_type:%d\n", DEV_NAME, __func__, adc, adcerr, chgtyp, + vbvolt, dxovp, info->cable_type); + + if (adc1k) { + pr_info("%s:%s MHL attached, goto end\n", DEV_NAME, __func__); + goto end; + } + + if (adcerr) { + pr_info("%s:%s ADC error, goto end\n", DEV_NAME, __func__); + goto end; + } + + switch (adc) { +#if defined(CONFIG_MUIC_MAX77693_SUPPORT_SMART_DOCK) + case ADC_SMARTDOCK: + pr_info("%s:%s Smart Dock\n", DEV_NAME, __func__); + + if (vbvolt && !info->is_usb_ready) { + pr_info("%s:%s usb not ready yet, D+,D- line(Open)\n", + DEV_NAME, __func__); + max77693_muic_set_usb_path(info, OPEN_USB_MODE); + } + break; +#endif /* CONFIG_MUIC_MAX77693_SUPPORT_SMART_DOCK */ +#if defined(CONFIG_MUIC_MAX77693_SUPPORT_OTG_AUDIO_DOCK) + case ADC_AUDIODOCK: + pr_info("%s:%s Audio Dock\n", DEV_NAME, __func__); + + if (vbvolt && !info->is_usb_ready) { + pr_info("%s:%s usb not ready yet, D+,D- line(Open)\n", + DEV_NAME, __func__); + max77693_muic_set_usb_path(info, OPEN_USB_MODE); + } + break; +#endif /* CONFIG_MUIC_MAX77693_SUPPORT_OTG_AUDIO_DOCK */ + default: + break; + } + +end: + mutex_unlock(&info->mutex); +} +#endif /* CONFIG_MUIC_MAX77693_SUPPORT_SMART_DOCK || + CONFIG_MUIC_MAX77693_SUPPORT_OTG_AUDIO_DOCK */ + static void max77693_muic_init_detect(struct work_struct *work) { struct max77693_muic_info *info = @@ -2720,6 +3041,34 @@ static void max77693_muic_usb_detect(struct work_struct *work) mdata->usb_cb(USB_OTGHOST_ATTACHED); break; case CABLE_TYPE_SMARTDOCK_MUIC: + pr_info("%s:%s now usb ready, turn "\ + "D+,D- line to AP_USB\n", DEV_NAME, + __func__); + max77693_muic_set_usb_path(info, AP_USB_MODE); + break; + case CABLE_TYPE_SMARTDOCK_TA_MUIC: + pr_info("%s:%s now usb ready, turn "\ + "D+,D- line to AP_USB\n", DEV_NAME, + __func__); + max77693_muic_set_usb_path(info, AP_USB_MODE); + + mdata->usb_cb(USB_POWERED_HOST_ATTACHED); + break; + case CABLE_TYPE_SMARTDOCK_USB_MUIC: + pr_info("%s:%s now usb ready, turn "\ + "D+,D- line to AP_USB\n", DEV_NAME, + __func__); + max77693_muic_set_usb_path(info, AP_USB_MODE); + + mdata->usb_cb(USB_CABLE_ATTACHED); + break; + case CABLE_TYPE_AUDIODOCK_MUIC: + pr_info("%s:%s now usb ready, turn "\ + "D+,D- line to AP_USB\n", DEV_NAME, + __func__); + max77693_muic_set_usb_path(info, AP_USB_MODE); + + mdata->usb_cb(USB_POWERED_HOST_ATTACHED); break; default: break; @@ -2742,7 +3091,10 @@ static void max77693_muic_mhl_detect(struct work_struct *work) info->is_mhl_ready = true; if (info->cable_type == CABLE_TYPE_MHL_MUIC || - info->cable_type == CABLE_TYPE_MHL_VB_MUIC) { + info->cable_type == CABLE_TYPE_MHL_VB_MUIC || + info->cable_type == CABLE_TYPE_SMARTDOCK_MUIC || + info->cable_type == CABLE_TYPE_SMARTDOCK_TA_MUIC || + info->cable_type == CABLE_TYPE_SMARTDOCK_USB_MUIC) { #ifdef CONFIG_EXTCON if (info->edev) extcon_set_cable_state(info->edev, "MHL", true); @@ -2945,6 +3297,9 @@ static int __devinit max77693_muic_probe(struct platform_device *pdev) #if defined(CONFIG_MACH_GC1) info->is_otg_attach_blocked = false; #endif /* CONFIG_MACH_GC1 */ +#if !defined(CONFIG_MUIC_MAX77693_SUPPORT_CAR_DOCK) + info->is_factory_start = false; +#endif /* !CONFIG_MUIC_MAX77693_SUPPORT_CAR_DOCK */ wake_lock_init(&info->muic_wake_lock, WAKE_LOCK_SUSPEND, "muic wake lock"); @@ -3102,6 +3457,13 @@ static int __devinit max77693_muic_probe(struct platform_device *pdev) max77693_update_jig_state(info); /* initial cable detection */ +#if defined(CONFIG_MUIC_MAX77693_SUPPORT_SMART_DOCK) ||\ + defined(CONFIG_MUIC_MAX77693_SUPPORT_OTG_AUDIO_DOCK) + INIT_DELAYED_WORK(&info->dock_work, max77693_muic_dock_detect); + schedule_delayed_work(&info->dock_work, msecs_to_jiffies(50)); +#endif /* CONFIG_MUIC_MAX77693_SUPPORT_SMART_DOCK || + CONFIG_MUIC_MAX77693_SUPPORT_OTG_AUDIO_DOCK */ + INIT_DELAYED_WORK(&info->init_work, max77693_muic_init_detect); schedule_delayed_work(&info->init_work, msecs_to_jiffies(3000)); @@ -3143,6 +3505,11 @@ static int __devexit max77693_muic_remove(struct platform_device *pdev) if (info) { dev_info(info->dev, "func:%s\n", __func__); input_unregister_device(info->input); +#if defined(CONFIG_MUIC_MAX77693_SUPPORT_SMART_DOCK) ||\ + defined(CONFIG_MUIC_MAX77693_SUPPORT_OTG_AUDIO_DOCK) + cancel_delayed_work(&info->dock_work); +#endif /* CONFIG_MUIC_MAX77693_SUPPORT_SMART_DOCK || + CONFIG_MUIC_MAX77693_SUPPORT_OTG_AUDIO_DOCK */ cancel_delayed_work(&info->init_work); cancel_delayed_work(&info->usb_work); cancel_delayed_work(&info->mhl_work); diff --git a/drivers/mmc/card/Kconfig b/drivers/mmc/card/Kconfig index 4283bc2..2320c98 100644 --- a/drivers/mmc/card/Kconfig +++ b/drivers/mmc/card/Kconfig @@ -81,3 +81,10 @@ config MMC_SELECTIVE_PACKED_CMD_POLICY tristate "Change the condition of Pakced command" help Say Y here to change packed_cmd policy + +config MMC_CPRM + bool "Japan only CPRM MMC driver" + depends on MMC_BLOCK + default n + help + Japan only feature of CPRM MMC driver.
\ No newline at end of file diff --git a/drivers/mmc/card/Makefile b/drivers/mmc/card/Makefile index a6efd4d..fad6e00 100644 --- a/drivers/mmc/card/Makefile +++ b/drivers/mmc/card/Makefile @@ -1,10 +1,6 @@ # # Makefile for MMC/SD card drivers # -ifeq ($(CONFIG_MMC_CPRM),y) -EXTRA_CFLAGS += -I$(src)/cprm/softcprm -EXTRA_CFLAGS += -I$(src)/cprm/include -endif obj-$(CONFIG_MMC_BLOCK) += mmc_block.o mmc_block-objs := block.o queue.o diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 7027962..f49e92c 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -60,6 +60,9 @@ MODULE_ALIAS("mmc:block"); #define MMC_IOCTL_GET_SECTOR_COUNT _IOR(MMC_IOCTL_BASE, 100, int) #define MMC_IOCTL_GET_SECTOR_SIZE _IOR(MMC_IOCTL_BASE, 101, int) #define MMC_IOCTL_GET_BLOCK_SIZE _IOR(MMC_IOCTL_BASE, 102, int) +#define MMC_IOCTL_SET_RETRY_AKE_PROCESS _IOR(MMC_IOCTL_BASE, 104, int) + +static int cprm_ake_retry_flag; #endif #ifdef MOVI_DEBUG @@ -329,6 +332,47 @@ out: return ERR_PTR(err); } +struct scatterlist *mmc_blk_get_sg(struct mmc_card *card, + unsigned char *buf, int *sg_len, int size) +{ + struct scatterlist *sg; + struct scatterlist *sl; + int total_sec_cnt, sec_cnt; + int max_seg_size, len; + + sl = kmalloc(sizeof(struct scatterlist) * card->host->max_segs, GFP_KERNEL); + if (!sl) { + return NULL; + } + + sg = (struct scatterlist *)sl; + sg_init_table(sg, card->host->max_segs); + + total_sec_cnt = size; + max_seg_size = card->host->max_seg_size; + + len = 0; + while (total_sec_cnt) { + if (total_sec_cnt < max_seg_size) + sec_cnt = total_sec_cnt; + else + sec_cnt = max_seg_size; + sg_set_page(sg, virt_to_page(buf), sec_cnt, offset_in_page(buf)); + buf = buf + sec_cnt; + total_sec_cnt = total_sec_cnt - sec_cnt; + len++; + if (total_sec_cnt == 0) + break; + sg = sg_next(sg); + } + + if (sg) + sg_mark_end(sg); + + *sg_len = len; + + return sl; +} static int mmc_blk_ioctl_cmd(struct block_device *bdev, struct mmc_ioc_cmd __user *ic_ptr) { @@ -338,7 +382,7 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev, struct mmc_command cmd = {0}; struct mmc_data data = {0}; struct mmc_request mrq = {0}; - struct scatterlist sg; + struct scatterlist *sg = 0; int err = 0; /* @@ -369,13 +413,22 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev, cmd.arg = idata->ic.arg; cmd.flags = idata->ic.flags; + if( cmd.opcode == MMC_IOC_CLOCK ) + { + mmc_set_clock(card->host, cmd.arg); + err = 0; + goto cmd_done; + } + if (idata->buf_bytes) { - data.sg = &sg; - data.sg_len = 1; + int len; data.blksz = idata->ic.blksz; data.blocks = idata->ic.blocks; - sg_init_one(data.sg, idata->buf, idata->buf_bytes); + sg = mmc_blk_get_sg(card, idata->buf, &len, idata->buf_bytes); + + data.sg = sg; + data.sg_len = len; if (idata->ic.write_flag) data.flags = MMC_DATA_WRITE; @@ -456,6 +509,9 @@ cmd_rel_host: cmd_done: if (md) mmc_blk_put(md); + if (sg) + kfree(sg); + kfree(idata->buf); kfree(idata); return err; @@ -467,6 +523,8 @@ static int mmc_blk_ioctl(struct block_device *bdev, fmode_t mode, #ifdef MMC_ENABLE_CPRM struct mmc_blk_data *md = bdev->bd_disk->private_data; struct mmc_card *card = md->queue.card; + static int i; + static unsigned long temp_arg[16] = {0}; #endif int ret = -EINVAL; if (cmd == MMC_IOC_CMD) @@ -476,6 +534,10 @@ static int mmc_blk_ioctl(struct block_device *bdev, fmode_t mode, printk(KERN_DEBUG " %s ], %x ", __func__, cmd); switch (cmd) { + case MMC_IOCTL_SET_RETRY_AKE_PROCESS: + cprm_ake_retry_flag = 1; + ret = 0; + break; case MMC_IOCTL_GET_SECTOR_COUNT: { int size = 0; @@ -498,9 +560,54 @@ static int mmc_blk_ioctl(struct block_device *bdev, fmode_t mode, struct cprm_request *req = (struct cprm_request *)arg; printk(KERN_DEBUG "[%s]: cmd [%x]\n", __func__, cmd); + if (cmd == ACMD43) { + printk(KERN_DEBUG"storing acmd43 arg[%d] = %ul\n" + , i, (unsigned int)req->arg); + temp_arg[i] = req->arg; + i++; + if(i >= 16){ + printk(KERN_DEBUG"reset acmd43 i = %d\n", + i); + i = 0; + } + } + + + if (cmd == ACMD45 && cprm_ake_retry_flag == 1) { + cprm_ake_retry_flag = 0; + printk(KERN_DEBUG"ACMD45.. I'll call ACMD43 and ACMD44 first\n"); + + for (i = 0; i < 16; i++) { + printk(KERN_DEBUG"calling ACMD43 with arg[%d] = %ul\n", + i, (unsigned int)temp_arg[i]); + if (stub_sendcmd(card, + ACMD43, temp_arg[i], + 512, NULL) < 0) { + + printk(KERN_DEBUG"error ACMD43 %d\n", i); + return -EINVAL; + } + } + + + printk(KERN_DEBUG"calling ACMD44\n"); + if (stub_sendcmd(card, ACMD44, 0, 8, NULL) < 0) + { + + printk(KERN_DEBUG"error in ACMD44 %d\n", + i); + return -EINVAL; + } + + } return stub_sendcmd(card, req->cmd, req->arg, \ req->len, req->buff); } + break; + + default: + printk(KERN_DEBUG"%s: Invalid ioctl command\n", __func__); + break; } #endif return ret; @@ -2372,9 +2479,6 @@ static int mmc_blk_probe(struct mmc_card *card) md->disk->disk_name, mmc_card_id(card), mmc_card_name(card), cap_str, md->read_only ? "(ro)" : ""); - if (mmc_blk_alloc_parts(card, md)) - goto out; - mmc_set_drvdata(card, md); mmc_fixup_device(card, blk_fixups); diff --git a/drivers/mmc/card/cprmdrv_samsung.c b/drivers/mmc/card/cprmdrv_samsung.c index 6f64a7f..81b430c 100644 --- a/drivers/mmc/card/cprmdrv_samsung.c +++ b/drivers/mmc/card/cprmdrv_samsung.c @@ -1,4 +1,17 @@ - +/* drivers/mmc/cprmdrv_samsung.c + * + * Copyright 2010 Samsung Electronics Co.Ltd + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ #include <linux/mmc/core.h> #include <linux/mmc/card.h> #include <linux/mmc/host.h> @@ -54,7 +67,6 @@ static int CPRM_CMD_SecureRW(struct mmc_card *card, struct mmc_command cmd; struct mmc_command stop; struct mmc_data data; - unsigned int timeout_us; struct scatterlist sg; @@ -91,17 +103,8 @@ static int CPRM_CMD_SecureRW(struct mmc_card *card, memset(&data, 0, sizeof(struct mmc_data)); - data.timeout_ns = card->csd.tacc_ns * 100; - data.timeout_clks = card->csd.tacc_clks * 100; - - timeout_us = data.timeout_ns / 1000; - timeout_us += data.timeout_clks * 1000 / - (card->host->ios.clock / 1000); - - if (timeout_us > 100000) { data.timeout_ns = 100000000; data.timeout_clks = 0; - } #if defined(CONFIG_TARGET_LOCALE_NTT) data.timeout_ns = 100000000; @@ -178,7 +181,6 @@ static int CPRM_CMD_SecureMultiRW(struct mmc_card *card, struct mmc_command cmd; struct mmc_command stop; struct mmc_data data; - unsigned int timeout_us; unsigned long flags; struct scatterlist sg; @@ -212,17 +214,8 @@ static int CPRM_CMD_SecureMultiRW(struct mmc_card *card, memset(&data, 0, sizeof(struct mmc_data)); - data.timeout_ns = card->csd.tacc_ns * 100; - data.timeout_clks = card->csd.tacc_clks * 100; - - timeout_us = data.timeout_ns / 1000; - timeout_us += data.timeout_clks * 1000 / - (card->host->ios.clock / 1000); - - if (timeout_us > 100000) { data.timeout_ns = 100000000; data.timeout_clks = 0; - } #if defined(CONFIG_TARGET_LOCALE_NTT) data.timeout_ns = 100000000; diff --git a/drivers/mmc/card/cprmdrv_samsung.h b/drivers/mmc/card/cprmdrv_samsung.h index b07dd6e..68fc7cb 100644 --- a/drivers/mmc/card/cprmdrv_samsung.h +++ b/drivers/mmc/card/cprmdrv_samsung.h @@ -1,3 +1,17 @@ +/* drivers/mmc/cprmdrv_samsung.h + * + * Copyright 2010 Samsung Electronics Co.Ltd + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ #ifndef __CPRM_API_SAMSUNG #define __CPRM_API_SAMSUNG diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 3403f53..506a4e3 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -35,6 +35,27 @@ #endif #endif +/* + * If moviNAND VHX 4.41 device + * enable PON to force. + */ +#define CHECK_MOVI_VHX4_41 \ + (card->ext_csd.rev == 5 && card->movi_fwver >= 0x1C) + +/* + * If moviNAND VHX 4.5 device + * enable PON to force. + */ +#define CHECK_MOVI_VHX4_5 \ + (card->ext_csd.rev == 6 && card->movi_fwver >= 0x0A) + +#define CHECK_MOVI_PON_SUPPORT \ + (card->cid.manfid == 0x15 && \ + ext_csd[EXT_CSD_VENDOR_SPECIFIC_FIELD] & 0x2) + +#define CHECK_PON_ENABLE \ + (card->ext_csd.feature_support & MMC_POWEROFF_NOTIFY_FEATURE) + static const unsigned int tran_exp[] = { 10000, 100000, 1000000, 10000000, 0, 0, 0, 0 @@ -333,6 +354,7 @@ static int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd) static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) { int err = 0; + int movi_ver_check = 0; BUG_ON(!card); @@ -581,11 +603,49 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) } if (card->ext_csd.rev >= 5) { - /* enable discard feature if emmc is 4.41+ */ + /* If moviNAND, run smart report */ + if (card->cid.manfid == 0x15) { + card->host->card = card; + movi_ver_check = mmc_start_movi_smart(card); + } + + /* enable discard feature if emmc is 4.41+ moviNand */ if ((ext_csd[EXT_CSD_VENDOR_SPECIFIC_FIELD + 0] & 0x1) && (card->cid.manfid == 0x15)) card->ext_csd.feature_support |= MMC_DISCARD_FEATURE; + /* enable PON feature if moviNAND VHX/VMX devices */ + if (CHECK_MOVI_PON_SUPPORT) { + if ((movi_ver_check & MMC_MOVI_VER_VHX0) && + (CHECK_MOVI_VHX4_41 || + CHECK_MOVI_VHX4_5)) { + card->ext_csd.feature_support |= + MMC_POWEROFF_NOTIFY_FEATURE; + card->ext_csd.generic_cmd6_time = 100; + card->ext_csd.power_off_longtime = 600; + } + if (movi_ver_check & MMC_MOVI_VER_VMX0) { + card->ext_csd.feature_support |= + MMC_POWEROFF_NOTIFY_FEATURE; + } + pr_info("%s : %s PON feature : " + "%02x : %02x(%02x) : %08x\n", + mmc_hostname(card->host), + card->ext_csd.feature_support & MMC_POWEROFF_NOTIFY_FEATURE ? + "enable" : "disable", + movi_ver_check, + card->movi_fwver, ext_csd[82], + card->movi_fwdate); + } + + /* + * enable discard feature if emmc is 4.41+ Toshiba eMMC 19nm + * Normally, emmc 4.5 use EXT_CSD[501] + */ + if ((ext_csd[EXT_CSD_MAX_PACKED_READS] & 0x3F) && + (card->cid.manfid == 0x11)) + card->ext_csd.feature_support |= MMC_DISCARD_FEATURE; + /* check whether the eMMC card supports HPI */ if (ext_csd[EXT_CSD_HPI_FEATURES] & 0x1) { card->ext_csd.hpi = 1; @@ -717,6 +777,7 @@ MMC_DEV_ATTR(serial, "0x%08x\n", card->cid.serial); MMC_DEV_ATTR(enhanced_area_offset, "%llu\n", card->ext_csd.enhanced_area_offset); MMC_DEV_ATTR(enhanced_area_size, "%u\n", card->ext_csd.enhanced_area_size); +MMC_DEV_ATTR(fwver, "%02x : %x\n", card->movi_fwver, card->movi_fwdate); static struct attribute *mmc_std_attrs[] = { &dev_attr_cid.attr, @@ -732,6 +793,7 @@ static struct attribute *mmc_std_attrs[] = { &dev_attr_serial.attr, &dev_attr_enhanced_area_offset.attr, &dev_attr_enhanced_area_size.attr, + &dev_attr_fwver.attr, NULL, }; @@ -1111,22 +1173,20 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, * set the notification byte in the ext_csd register of device */ if ((host->caps2 & MMC_CAP2_POWEROFF_NOTIFY) && - (card->ext_csd.rev >= 6)) { + ((card->ext_csd.rev >= 5) && CHECK_PON_ENABLE)) { err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_POWER_OFF_NOTIFICATION, EXT_CSD_POWER_ON, card->ext_csd.generic_cmd6_time); if (err && err != -EBADMSG) goto free_card; - } - - if (!err && (host->caps2 & MMC_CAP2_POWEROFF_NOTIFY)) /* * The err can be -EBADMSG or 0, * so check for success and update the flag */ if (!err) card->poweroff_notify_state = MMC_POWERED_ON; + } /* * Activate high speed (if supported) @@ -1656,10 +1716,10 @@ int mmc_attach_mmc(struct mmc_host *host) if (!strncmp(host->card->cid.prod_name, "VTU00M", 6) && (host->card->cid.prod_rev == 0xf1) && - (mmc_start_movi_smart(host->card) == 0x2)) + (host->card->movi_fwdate == 0x20120413)) { + /* It needs host work-around codes */ host->card->movi_ops = 0x2; - if (host->card->movi_ops == 0x2) { err = mmc_start_movi_operation(host->card); if (err) { pr_warning("%s: movi operation is failed\n", diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 90085a3..3cec450 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -677,41 +677,59 @@ static int mmc_movi_read_req(struct mmc_card *card, return 0; } +#define MOVI_CONT_VHX0 0x56485830 +#define MOVI_CONT_VMX0 0x564D5830 + int mmc_start_movi_smart(struct mmc_card *card) { - int err; + int ret; u8 data_buf[512]; u32 date = 0; + u32 old_date = 0; + u32 movi_ver = 0; - err = mmc_movi_cmd(card->host, 0xEFAC62EC); - if (err) - return err; + ret = mmc_movi_cmd(card->host, 0xEFAC62EC); + if (ret) + return ret; - err = mmc_movi_cmd(card->host, 0x0000CCEE); - if (err) - return err; + ret = mmc_movi_cmd(card->host, 0x0000CCEE); + if (ret) + return ret; - err = mmc_movi_read_req(card, (void *)data_buf, 0x1000, 1); - if (err) - return err; + ret = mmc_movi_read_req(card, (void *)data_buf, 0x1000, 1); + if (ret) + return ret; - err = mmc_movi_cmd(card->host, 0xEFAC62EC); - if (err) - return err; + ret = mmc_movi_cmd(card->host, 0xEFAC62EC); + if (ret) + return ret; - err = mmc_movi_cmd(card->host, 0x00DECCEE); - if (err) - return err; + ret = mmc_movi_cmd(card->host, 0x00DECCEE); + if (ret) + return ret; + + movi_ver = ((data_buf[312] << 24) | (data_buf[313] << 16) | + (data_buf[314] << 8) | data_buf[315]); + if (movi_ver == MOVI_CONT_VMX0) + ret = MMC_MOVI_VER_VMX0; + else if (movi_ver == MOVI_CONT_VHX0) + ret = MMC_MOVI_VER_VHX0; + else + ret = 0x0; date = ((data_buf[327] << 24) | (data_buf[326] << 16) | (data_buf[325] << 8) | data_buf[324]); - if (date != 0x20120413) { - err = -1; - return err; - } + card->movi_fwver = data_buf[320]; + card->movi_fwdate = date; + + old_date = ((data_buf[351] << 24) | (data_buf[350] << 16) | + (data_buf[349] << 8) | data_buf[348]); + + pr_info("%s : %02x : %02x : %08x : %x.\n", mmc_hostname(card->host), + ret, card->movi_fwver, card->movi_fwdate, old_date); - return 0x2; + return ret; } EXPORT_SYMBOL_GPL(mmc_start_movi_smart); diff --git a/drivers/usb/core/sec-dock.h b/drivers/usb/core/sec-dock.h index 1521b67..73c4ea6 100644 --- a/drivers/usb/core/sec-dock.h +++ b/drivers/usb/core/sec-dock.h @@ -9,9 +9,6 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. */ -#if defined(CONFIG_MUIC_MAX77693_SUPPORT_OTG_AUDIO_DOCK) -#include <linux/mfd/max77693.h> -#endif /* CONFIG_MUIC_MAX77693_SUPPORT_OTG_AUDIO_DOCK */ #include <linux/power_supply.h> #define PSY_CHG_NAME "max77693-charger" @@ -48,7 +45,6 @@ static void call_audiodock_notify(struct usb_device *dev) id->idVendor == le16_to_cpu(dev->descriptor.idVendor) && id->idProduct == le16_to_cpu(dev->descriptor.idProduct)) { dev_info(&dev->dev, "Audio Dock is connected!\n"); - max77693_muic_attach_audio_dock(); return; } } diff --git a/include/linux/battery/samsung_battery.h b/include/linux/battery/samsung_battery.h index f58c839..2293fce 100644 --- a/include/linux/battery/samsung_battery.h +++ b/include/linux/battery/samsung_battery.h @@ -115,6 +115,7 @@ struct battery_info { unsigned int cable_type; unsigned int cable_sub_type; unsigned int cable_pwr_type; + int online_prop; /* For SAMSUNG charge spec */ unsigned int vf_state; @@ -205,6 +206,12 @@ extern bool is_jig_attached; #undef EXTENDED_ONLINE_TYPE #endif +enum online_property { + ONLINE_PROP_UNKNOWN = 0, + ONLINE_PROP_AC, + ONLINE_PROP_USB, +}; + /* use 2step charge termination */ #if defined(CONFIG_MACH_T0) #define USE_2STEP_TERM @@ -269,7 +276,11 @@ enum status_full_type { /* WORKAROUND: define audio dock current */ #define DOCK_TYPE_AUDIO_CURR 1000 +#if defined(CONFIG_MACH_T0) #define DOCK_TYPE_SMART_NOTG_CURR 1700 +#else +#define DOCK_TYPE_SMART_NOTG_CURR 1000 +#endif #define DOCK_TYPE_SMART_OTG_CURR 1000 #define DOCK_TYPE_LOW_CURR 475 diff --git a/include/linux/mfd/max77693-private.h b/include/linux/mfd/max77693-private.h index 7a2c536..ad0ccf8 100644 --- a/include/linux/mfd/max77693-private.h +++ b/include/linux/mfd/max77693-private.h @@ -413,7 +413,7 @@ enum { #if defined(CONFIG_SWITCH_DUAL_MODEM) CP_ESC_USB_MODE, #endif - + OPEN_USB_MODE }; enum { diff --git a/include/linux/mfd/max77693.h b/include/linux/mfd/max77693.h index 274693a..dc26961 100644 --- a/include/linux/mfd/max77693.h +++ b/include/linux/mfd/max77693.h @@ -150,8 +150,4 @@ struct max77693_muic_data { extern int max7693_muic_cp_usb_state(void); #endif -#if defined(CONFIG_MUIC_MAX77693_SUPPORT_OTG_AUDIO_DOCK) -extern void max77693_muic_attach_audio_dock(void); -#endif /* CONFIG_MUIC_MAX77693_SUPPORT_OTG_AUDIO_DOCK */ - #endif /* __LINUX_MFD_MAX77693_H */ diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 5eb40a9..8cbcc95 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -94,6 +94,7 @@ struct mmc_ext_csd { unsigned int feature_support; #define MMC_DISCARD_FEATURE BIT(0) /* CMD38 feature */ +#define MMC_POWEROFF_NOTIFY_FEATURE BIT(1) /* PON feature */ }; struct sd_scr { @@ -244,8 +245,12 @@ struct mmc_card { struct dentry *debugfs_root; unsigned int movi_ops; + unsigned int movi_fwver; + unsigned int movi_fwdate; }; +#define MMC_MOVI_VER_VHX0 (1<<4) +#define MMC_MOVI_VER_VMX0 (1<<5) /* * The world is not perfect and supplies us with broken mmc/sdio devices. * For at least some of these bugs we need a work-around. diff --git a/include/linux/mmc/ioctl.h b/include/linux/mmc/ioctl.h index 5baf298..8f8204b 100644 --- a/include/linux/mmc/ioctl.h +++ b/include/linux/mmc/ioctl.h @@ -50,5 +50,5 @@ struct mmc_ioc_cmd { * is enforced per ioctl call. For larger data transfers, use the normal * block device operations. */ -#define MMC_IOC_MAX_BYTES (512L * 256) +#define MMC_IOC_MAX_BYTES (512L * 512) #endif /* LINUX_MMC_IOCTL_H */ diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h index bc047b4..ac13431 100644 --- a/include/linux/mmc/mmc.h +++ b/include/linux/mmc/mmc.h @@ -84,6 +84,8 @@ #define MMC_APP_CMD 55 /* ac [31:16] RCA R1 */ #define MMC_GEN_CMD 56 /* adtc [0] RD/WR R1 */ +#define MMC_IOC_CLOCK 120 + static inline bool mmc_op_multi(u32 opcode) { return opcode == MMC_WRITE_MULTIPLE_BLOCK || @@ -284,9 +284,15 @@ bool cma_is_registered_region(phys_addr_t start, size_t size) { struct cma_region *reg; + if (start + size <= start) + return false; + cma_foreach_region(reg) { if ((start >= reg->start) && - ((start + size) <= (reg->start + reg->size))) + ((start + size) <= (reg->start + reg->size)) && + (size <= reg->size) && + (start < (reg->start + reg->size))) + return true; } return false; diff --git a/mm/page_alloc-cma.c b/mm/page_alloc-cma.c index 74cdf7d..fc675bd 100644 --- a/mm/page_alloc-cma.c +++ b/mm/page_alloc-cma.c @@ -6057,7 +6057,7 @@ static int __alloc_contig_migrate_range(unsigned long start, unsigned long end) failed_pages[i][j] = NULL; } - migrate_prep_local(); + migrate_prep(); while (pfn < end || !list_empty(&cc.migratepages)) { if (fatal_signal_pending(current)) { diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index d175153..63d1a5f 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -2766,7 +2766,7 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } - bclk_rate = params_rate(params) * 4; + bclk_rate = params_rate(params) * 2; switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: bclk_rate *= 16; |