static int write_muic_ctrl_reg(struct max14577_muic_data *muic_data, const u8 reg, const u8 val) { struct i2c_client *i2c = muic_data->i2c; int ret = 0; u8 reg_val = 0; ret = max14577_read_reg(i2c, reg, ®_val); if (ret < 0) pr_err("%s:%s err read REG(0x%02x) [%d]\n", MUIC_DEV_NAME, __func__, reg, ret); if (reg_val ^ val) { pr_info("%s:%s overwrite REG(0x%02x) from [0x%x] to [0x%x]\n", MUIC_DEV_NAME, __func__, reg, reg_val, val); ret = max14577_write_reg(i2c, reg, val); if (ret < 0) pr_err("%s:%s err write REG(0x%02x)\n", MUIC_DEV_NAME, __func__, reg); } else { pr_info("%s:%s REG(0x%02x) already [0x%x], just return\n", MUIC_DEV_NAME, __func__, reg, reg_val); } ret = max14577_read_reg(i2c, reg, ®_val); if (ret < 0) pr_err("%s:%s err read REG(0x%02x) [%d]\n", MUIC_DEV_NAME, __func__, reg, ret); else pr_info("%s:%s REG(0x%02x) after change [0x%x]\n", MUIC_DEV_NAME, __func__, reg, reg_val); return ret; }
static void max14577_muic_set_adcdbset(struct max14577_muic_data *muic_data, int value) { int ret; u8 val; u8 cntl3_before, cntl3_after; if (value > 3) { pr_err("%s:%s invalid value(%d)\n", MUIC_DEV_NAME, __func__, value); return; } if (!muic_data->i2c) { pr_err("%s:%s no muic i2c client\n", MUIC_DEV_NAME, __func__); return; } val = (value << CTRL3_ADCDBSET_SHIFT); max14577_read_reg(muic_data->i2c, MAX14577_MUIC_REG_CONTROL3, &cntl3_before); ret = max14577_write_reg(muic_data->i2c, MAX14577_MUIC_REG_CONTROL3, val); if (ret < 0) pr_err("%s: fail to write reg\n", __func__); max14577_read_reg(muic_data->i2c, MAX14577_MUIC_REG_CONTROL3, &cntl3_after); pr_info("%s:%s CNTL3: before(0x%02x), value(0x%02x), after(0x%02x)\n", MUIC_DEV_NAME, __func__, cntl3_before, val, cntl3_after); }
static void max14577_read_regs(struct sec_charger_info *charger, char *str) { u8 data = 0; u32 addr = 0; max14577_read_reg(charger->client, MAX14577_CHG_REG_STATUS3, &data); sprintf(str+strlen(str), "0x%x, ", data); for (addr = MAX14577_CHG_REG_CHG_CTRL1; addr <= MAX14577_CHG_REG_CHG_CTRL7; addr++) { max14577_read_reg(charger->client, addr, &data); sprintf(str+strlen(str), "0x%x, ", data); } }
static ssize_t max14577_muic_show_manual_sw(struct device *dev, struct device_attribute *attr, char *buf) { struct max14577_muic_data *muic_data = dev_get_drvdata(dev); u8 val = 0; ssize_t cnt = 0; max14577_read_reg(muic_data->i2c, MAX14577_MUIC_REG_CONTROL1, &val); switch (val) { case 0x9: cnt = sprintf(buf, "USB\n"); break; case 0x12: cnt = sprintf(buf, "AUDIO\n"); break; case 0x1b: cnt = sprintf(buf, "UART\n"); break; default: cnt = sprintf(buf, "OPEN\n"); break; } return cnt; }
static int max14577_get_charging_status(struct sec_charger_info *charger) { int status = POWER_SUPPLY_STATUS_UNKNOWN; u8 data = 0; max14577_read_reg(charger->client, MAX14577_CHG_REG_STATUS3, &data); dev_info(&charger->client->dev, "%s : charger status (0x%02x)\n", __func__, data); if (data & 0x01) { status = POWER_SUPPLY_STATUS_FULL; data = 0; max14577_set_command(charger, MAX14577_CHG_REG_CHG_CTRL6, data); } else if (data & 0x02) status = POWER_SUPPLY_STATUS_CHARGING; else if (data & 0x04) status = POWER_SUPPLY_STATUS_NOT_CHARGING; else status = POWER_SUPPLY_STATUS_DISCHARGING; #if 0 max14577_test_read_regs(charger); #endif return (int)status; }
static void max14577_test_read_regs(struct sec_charger_info *charger) { u8 data = 0; u32 addr = 0; max14577_read_reg(charger->client, MAX14577_CHG_REG_STATUS3, &data); dev_info(&charger->client->dev, "%s : 0x%02x (0x%02x)\n", __func__, MAX14577_CHG_REG_STATUS3, data); for (addr = MAX14577_CHG_REG_CHG_CTRL1; addr <= MAX14577_CHG_REG_CHG_CTRL7; addr++) { max14577_read_reg(charger->client, addr, &data); dev_info(&charger->client->dev, "%s : 0x%02x (0x%02x)\n", __func__, addr, data); } }
static void max14577_set_command(struct sec_charger_info *charger, int reg, int datum) { int val; u8 data = 0; val = max14577_read_reg(charger->client, (u8)reg, &data); if (val >= 0) { dev_dbg(&charger->client->dev, "%s : reg(0x%02x): 0x%02x", __func__, reg, data); if (data != datum) { data = datum; if (max14577_write_reg(charger->client, (u8)reg, data) < 0) dev_err(&charger->client->dev, "%s : error!\n", __func__); val = max14577_read_reg(charger->client, (u8)reg, &data); if (val >= 0) dev_dbg(&charger->client->dev, " => 0x%02x\n", data); } } }
int max14577_get_control2_reg(struct i2c_client *i2c, u8 *val) { u8 value = 0; int ret = 0; ret = max14577_read_reg(i2c, MAX14577_REG_CONTROL2, &value); if (ret) *val = 0xff; else *val = value; pr_info("%s:%s(0x%02x), ret(%d)\n", MFD_DEV_NAME, __func__, *val, ret); return ret; }
static u8 max14577_muic_get_adc_value(struct max14577_muic_data *muic_data) { u8 status; u8 adc = ADC_ERROR; int ret = 0; ret = max14577_read_reg(muic_data->i2c, MAX14577_MUIC_REG_STATUS1, &status); if (ret) pr_err("%s:%s fail to read muic reg(%d)\n", MUIC_DEV_NAME, __func__, ret); else adc = status & STATUS1_ADC_MASK; return adc; }
static int max14577_get_charging_health(struct sec_charger_info *charger) { int health = POWER_SUPPLY_HEALTH_GOOD; u8 data = 0; max14577_read_reg(charger->client, MAX14577_CHG_REG_STATUS3, &data); dev_info(&charger->client->dev, "%s : charger status (0x%02x)\n", __func__, data); if (data & 0x04) health = POWER_SUPPLY_HEALTH_OVERVOLTAGE; else health = POWER_SUPPLY_HEALTH_GOOD; return (int)health; }
bool sec_hal_chg_get_property(struct sec_charger_info *charger, enum power_supply_property psp, union power_supply_propval *val) { u8 data; switch (psp) { case POWER_SUPPLY_PROP_STATUS: val->intval = max14577_get_charging_status(charger); break; case POWER_SUPPLY_PROP_CHARGE_TYPE: if (charger->is_charging) val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST; else val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE; break; case POWER_SUPPLY_PROP_HEALTH: val->intval = max14577_get_charging_health(charger); break; case POWER_SUPPLY_PROP_ONLINE: val->intval = charger->cable_type; break; case POWER_SUPPLY_PROP_CURRENT_AVG: /* charging current */ /* calculated input current limit value */ case POWER_SUPPLY_PROP_CURRENT_NOW: if (charger->charging_current) { max14577_read_reg(charger->client, MAX14577_CHG_REG_CHG_CTRL4, &data); if (data & 0x10) /* enable fast charge current set */ val->intval = (data & 0x0f) * 50 + 200; else val->intval = 90; } else val->intval = 0; dev_dbg(&charger->client->dev, "%s : set-current(%dmA), current now(%dmA)\n", __func__, charger->charging_current, val->intval); break; default: return false; } return true; }
ssize_t sec_hal_chg_store_attrs(struct device *dev, const ptrdiff_t offset, const char *buf, size_t count) { struct power_supply *psy = dev_get_drvdata(dev); struct sec_charger_info *chg = container_of(psy, struct sec_charger_info, psy_chg); int ret = 0; int x = 0; u8 data = 0; switch (offset) { case CHG_REG: if (sscanf(buf, "%x\n", &x) == 1) { chg->reg_addr = x; max14577_read_reg(chg->client, chg->reg_addr, &data); chg->reg_data = data; dev_dbg(dev, "%s: (read) addr = 0x%x, data = 0x%x\n", __func__, chg->reg_addr, chg->reg_data); ret = count; } break; case CHG_DATA: if (sscanf(buf, "%x\n", &x) == 1) { data = (u8)x; dev_dbg(dev, "%s: (write) addr = 0x%x, data = 0x%x\n", __func__, chg->reg_addr, data); max14577_write_reg(chg->client, chg->reg_addr, data); ret = count; } break; default: ret = -EINVAL; break; } return ret; }
bool sec_hal_chg_get_property(struct sec_charger_info *charger, enum power_supply_property psp, union power_supply_propval *val) { u8 data; switch (psp) { case POWER_SUPPLY_PROP_STATUS: val->intval = max14577_get_charging_status(charger); break; case POWER_SUPPLY_PROP_CHARGE_TYPE: if (charger->is_charging) val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST; else val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE; break; case POWER_SUPPLY_PROP_HEALTH: val->intval = max14577_get_charging_health(charger); break; case POWER_SUPPLY_PROP_ONLINE: val->intval = charger->cable_type; break; case POWER_SUPPLY_PROP_CURRENT_AVG: /* charging current */ /* calculated input current limit value */ case POWER_SUPPLY_PROP_CURRENT_NOW: if (charger->charging_current) { max14577_read_reg(charger->client, MAX14577_CHG_REG_CHG_CTRL4, &data); if (data & 0x10) /* enable fast charge current set */ #if defined(max77836_charger) val->intval = (data & 0x0f) * 25 + 100; #else val->intval = (data & 0x0f) * 50 + 200; #endif else val->intval = 90; } else
void max14577_muic_shutdown(struct device *dev) { struct max14577_muic_data *muic_data = dev_get_drvdata(dev); struct max14577_dev *max14577; int ret; u8 val; u8 ctrl2 = 0; pr_info("%s:%s +\n", MUIC_DEV_NAME, __func__); if (!muic_data->i2c) { pr_err("%s:%s no muic i2c client\n", MUIC_DEV_NAME, __func__); return; } max14577 = i2c_get_clientdata(muic_data->i2c); pr_info("%s:%s max14577->i2c_lock.count.counter=%d\n", MUIC_DEV_NAME, __func__, max14577->i2c_lock.count.counter); pr_info("%s:%s JIGSet: auto detection\n", MUIC_DEV_NAME, __func__); val = (0 << CTRL3_JIGSET_SHIFT) | (0 << CTRL3_BOOTSET_SHIFT); ret = max14577_update_reg(muic_data->i2c, MAX14577_MUIC_REG_CONTROL3, val, CTRL3_JIGSET_MASK | CTRL3_BOOTSET_MASK); if (ret < 0) { pr_err("%s:%s fail to update reg\n", MUIC_DEV_NAME, __func__); return; } ret = max14577_read_reg(muic_data->i2c, MAX14577_REG_CONTROL2, &ctrl2); if (ret) { pr_err("%s:%s fail to read cntl2 reg\n", MUIC_DEV_NAME, __func__); return; } pr_info("%s:%s: ctrl2:0x%x\n", MUIC_DEV_NAME, __func__, ctrl2); pr_info("%s:%s -\n", MUIC_DEV_NAME, __func__); }
int max14577_irq_init(struct max14577_dev *max14577) { struct max14577_platform_data *pdata = max14577->pdata; struct i2c_client *i2c = max14577->i2c; int i; int cur_irq; int ret; u8 val; if (!pdata->irq_gpio) { pr_warn("%s:%s No interrupt specified.\n", MFD_DEV_NAME, __func__); pdata->irq_base = 0; return 0; } if (!pdata->irq_base) { pr_err("%s:%s No interrupt base specified.\n", MFD_DEV_NAME, __func__); return 0; } mutex_init(&max14577->irq_lock); max14577->irq = gpio_to_irq(pdata->irq_gpio); ret = gpio_request(pdata->irq_gpio, "max14577_irq"); if (ret) { pr_err("%s:%s failed requesting gpio(%d)\n", MFD_DEV_NAME, __func__, pdata->irq_gpio); return ret; } gpio_direction_input(pdata->irq_gpio); gpio_free(pdata->irq_gpio); pr_info("%s:%s\n", MFD_DEV_NAME, __func__); max14577_write_reg(max14577->i2c_pmic, MAX77836_PMIC_REG_INTSRC_MASK, 0xF7); max14577_read_reg(max14577->i2c_pmic, MAX77836_PMIC_REG_INTSRC_MASK, &val); pr_info("%s: INTSRC:0x%x\n", __func__, val); /* Mask individual interrupt sources */ for (i = 0; i < MAX14577_IRQ_REGS_NUM; i++) { /* IRQ 0:MASK 1:NOT MASK */ max14577->irq_masks_cur[i] = 0x00; max14577->irq_masks_cache[i] = 0x00; if (IS_ERR_OR_NULL(i2c)) continue; if (max14577_mask_reg[i] == MAX14577_REG_INVALID) continue; max14577_write_reg(i2c, max14577_mask_reg[i], max14577->irq_masks_cur[i]); } /* Register with genirq */ for (i = 0; i < MAX14577_IRQ_NUM; i++) { cur_irq = i + pdata->irq_base; ret = irq_set_chip_data(cur_irq, max14577); if (ret) { pr_err("%s: Failed to set_chip_data (irq:%d, ret:%d)\n", __func__, cur_irq, ret); continue; } irq_set_chip_and_handler(cur_irq, &max14577_irq_chip, handle_edge_irq); irq_set_nested_thread(cur_irq, true); #ifdef CONFIG_ARM set_irq_flags(cur_irq, IRQF_VALID); #else irq_set_noprobe(cur_irq); #endif } ret = request_threaded_irq(max14577->irq, NULL, max14577_irq_thread, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "max14577-irq", max14577); if (ret) { pr_err("%s:%s Failed to request IRQ(%d) ret(%d)\n", MFD_DEV_NAME, __func__, max14577->irq, ret); return ret; } return 0; }
static int __devinit max14577_muic_probe(struct platform_device *pdev) { struct max14577_dev *max14577 = dev_get_drvdata(pdev->dev.parent); struct max14577_platform_data *mfd_pdata = dev_get_platdata(max14577->dev); struct max14577_muic_data *muic_data; u8 ctrl2 = 0; int ret = 0; muic_data = kzalloc(sizeof(struct max14577_muic_data), GFP_KERNEL); if (!muic_data) { pr_err("%s: failed to allocate driver data\n", __func__); ret = -ENOMEM; goto err_return; } if (!mfd_pdata) { pr_err("%s: failed to get max14577 mfd platform data\n", __func__); ret = -ENOMEM; goto err_kfree; } muic_data->dev = &pdev->dev; mutex_init(&muic_data->muic_mutex); muic_data->i2c = max14577->i2c; muic_data->mfd_pdata = mfd_pdata; muic_data->irq_adcerr = mfd_pdata->irq_base + MAX14577_IRQ_INT1_ADCERR; muic_data->irq_adc = mfd_pdata->irq_base + MAX14577_IRQ_INT1_ADC; muic_data->irq_chgtyp = mfd_pdata->irq_base + MAX14577_IRQ_INT2_CHGTYP; muic_data->irq_vbvolt = mfd_pdata->irq_base + MAX14577_IRQ_INT2_VBVOLT; muic_data->switch_data = &sec_switch_data; muic_data->attached_dev = ATTACHED_DEV_UNKNOWN_MUIC; muic_data->is_usb_ready = false; muic_data->is_muic_ready = false; pr_info("%s:%s irq_num: adcerr(%d), adc(%d), chgtyp(%d), vbvolt(%d)\n", MUIC_DEV_NAME, __func__, muic_data->irq_adcerr, muic_data->irq_adc, muic_data->irq_chgtyp, muic_data->irq_vbvolt); platform_set_drvdata(pdev, muic_data); /* Set ADC debounce time: 25ms */ max14577_muic_set_adcdbset(muic_data, 2); /* Set Charger-Detection Check Time: 625ms */ max14577_muic_set_dchktm(muic_data, 1); ret = max14577_read_reg(muic_data->i2c, MAX14577_REG_CONTROL2, &ctrl2); if (ret) { pr_err("%s:%s fail to read CTRL2 (%d)\n", MUIC_DEV_NAME, __func__, ret); goto fail; } pr_info("%s:%s: ctrl2:0x%x\n", MUIC_DEV_NAME, __func__, ctrl2); /* create sysfs group */ ret = sysfs_create_group(&switch_device->kobj, &max14577_muic_group); if (ret) { pr_err("%s: failed to create max14577 muic attribute group\n", __func__); goto fail; } dev_set_drvdata(switch_device, muic_data); if (muic_data->switch_data->init_cb) muic_data->switch_data->init_cb(); ret = max14577_muic_irq_init(muic_data); if (ret < 0) { dev_err(&pdev->dev, "Failed to initialize MUIC irq:%d\n", ret); goto fail_init_irq; } /* initial cable detection */ INIT_DELAYED_WORK(&muic_data->init_work, max14577_muic_init_detect); schedule_delayed_work(&muic_data->init_work, msecs_to_jiffies(3000)); INIT_DELAYED_WORK(&muic_data->usb_work, max14577_muic_usb_detect); schedule_delayed_work(&muic_data->usb_work, msecs_to_jiffies(17000)); return 0; fail_init_irq: if (muic_data->irq_adcerr) free_irq(muic_data->irq_adcerr, NULL); if (muic_data->irq_adc) free_irq(muic_data->irq_adc, NULL); if (muic_data->irq_chgtyp) free_irq(muic_data->irq_chgtyp, NULL); if (muic_data->irq_vbvolt) free_irq(muic_data->irq_vbvolt, NULL); fail: platform_set_drvdata(pdev, NULL); mutex_destroy(&muic_data->muic_mutex); err_kfree: kfree(muic_data); err_return: return ret; }
static void max14577_muic_detect_dev(struct max14577_muic_data *muic_data, int irq) { struct i2c_client *i2c = muic_data->i2c; const struct max14577_muic_vps_data *tmp_vps; enum muic_attached_dev new_dev = ATTACHED_DEV_UNKNOWN_MUIC; int intr = MUIC_INTR_DETACH; u8 status[2], ctrl2, ctrl3; u8 adcerr, adclow, adc, vbvolt, chgdetrun, chgtyp, adcen; int ret; int i; ret = max14577_bulk_read(i2c, MAX14577_MUIC_REG_STATUS1, 2, status); if (ret) { pr_err("%s:%s fail to read STAT (%d)\n", MUIC_DEV_NAME, __func__, ret); return; } ret = max14577_read_reg(muic_data->i2c, MAX14577_REG_CONTROL2, &ctrl2); if (ret) { pr_err("%s:%s fail to read CTRL2 (%d)\n", MUIC_DEV_NAME, __func__, ret); return; } ret = max14577_read_reg(muic_data->i2c, MAX14577_MUIC_REG_CONTROL3, &ctrl3); if (ret) { pr_err("%s:%s fail to read CTRL3 (%d)\n", MUIC_DEV_NAME, __func__, ret); return; } pr_info("%s:%s STATUS1:0x%02x, 2:0x%02x, ctrl2:0x%02x\n", MUIC_DEV_NAME, __func__, status[0], status[1], ctrl2); adcerr = status[0] & STATUS1_ADCERR_MASK; adclow = status[0] & STATUS1_ADCLOW_MASK; adc = status[0] & STATUS1_ADC_MASK; vbvolt = status[1] & STATUS2_VBVOLT_MASK; chgdetrun = status[1] & STATUS2_CHGDETRUN_MASK; chgtyp = status[1] & STATUS2_CHGTYP_MASK; adcen = ctrl2 & CTRL2_ADCEN_MASK; pr_info("%s:%s adcerr:0x%x adclow:0x%x adc:0x%x vb:0x%x chgdetrun:0x%x" " chgtyp:0x%x adcen:0x%x\n", MUIC_DEV_NAME, __func__, adcerr, adclow, adc, vbvolt, chgdetrun, chgtyp, adcen); /* Workaround for Factory mode. * Abandon adc interrupt of approximately +-100K range * if previous cable status was JIG UART BOOT OFF. */ if (muic_data->attached_dev == ATTACHED_DEV_JIG_UART_OFF_MUIC) { if ((adc == (ADC_JIG_UART_OFF + 1)) || (adc == (ADC_JIG_UART_OFF - 1))) { pr_warn("%s:%s abandon ADC\n", MUIC_DEV_NAME, __func__); return; } } for (i = 0; i < ARRAY_SIZE(muic_vps_table); i++) { tmp_vps = &(muic_vps_table[i]); if (tmp_vps->adcerr != adcerr) continue; if (tmp_vps->adclow != adclow) continue; if (tmp_vps->adc != adc) continue; if (tmp_vps->vbvolt != vbvolt) continue; if (tmp_vps->chgdetrun != chgdetrun) continue; if (tmp_vps->chgtyp != chgtyp) continue; pr_info("%s:%s vps table match found at i(%d), %s\n", MUIC_DEV_NAME, __func__, i, tmp_vps->vps_name); new_dev = tmp_vps->attached_dev; intr = MUIC_INTR_ATTACH; break; } if (intr == MUIC_INTR_ATTACH) { pr_info("%s:%s ATTACHED\n", MUIC_DEV_NAME, __func__); max14577_muic_handle_attach(muic_data, new_dev); } else { pr_info("%s:%s DETACHED\n", MUIC_DEV_NAME, __func__); max14577_muic_handle_detach(muic_data); } return; }
static int max14577_muic_probe(struct platform_device *pdev) { struct max14577 *max14577 = dev_get_drvdata(pdev->dev.parent); struct max14577_muic_info *info; int delay_jiffies; int ret; int i; u8 id; info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; info->dev = &pdev->dev; info->max14577 = max14577; platform_set_drvdata(pdev, info); mutex_init(&info->mutex); INIT_WORK(&info->irq_work, max14577_muic_irq_work); switch (max14577->dev_type) { case MAXIM_DEVICE_TYPE_MAX77836: info->muic_irqs = max77836_muic_irqs; info->muic_irqs_num = ARRAY_SIZE(max77836_muic_irqs); break; case MAXIM_DEVICE_TYPE_MAX14577: default: info->muic_irqs = max14577_muic_irqs; info->muic_irqs_num = ARRAY_SIZE(max14577_muic_irqs); } /* Support irq domain for max14577 MUIC device */ for (i = 0; i < info->muic_irqs_num; i++) { struct max14577_muic_irq *muic_irq = &info->muic_irqs[i]; int virq = 0; virq = regmap_irq_get_virq(max14577->irq_data, muic_irq->irq); if (virq <= 0) return -EINVAL; muic_irq->virq = virq; ret = devm_request_threaded_irq(&pdev->dev, virq, NULL, max14577_muic_irq_handler, IRQF_NO_SUSPEND, muic_irq->name, info); if (ret) { dev_err(&pdev->dev, "failed: irq request (IRQ: %d, error :%d)\n", muic_irq->irq, ret); return ret; } } /* Initialize extcon device */ info->edev = devm_extcon_dev_allocate(&pdev->dev, max14577_extcon_cable); if (IS_ERR(info->edev)) { dev_err(&pdev->dev, "failed to allocate memory for extcon\n"); return -ENOMEM; } ret = devm_extcon_dev_register(&pdev->dev, info->edev); if (ret) { dev_err(&pdev->dev, "failed to register extcon device\n"); return ret; } /* Default h/w line path */ info->path_usb = CTRL1_SW_USB; info->path_uart = CTRL1_SW_UART; delay_jiffies = msecs_to_jiffies(DELAY_MS_DEFAULT); /* Set initial path for UART */ max14577_muic_set_path(info, info->path_uart, true); /* Check revision number of MUIC device*/ ret = max14577_read_reg(info->max14577->regmap, MAX14577_REG_DEVICEID, &id); if (ret < 0) { dev_err(&pdev->dev, "failed to read revision number\n"); return ret; } dev_info(info->dev, "device ID : 0x%x\n", id); /* Set ADC debounce time */ max14577_muic_set_debounce_time(info, ADC_DEBOUNCE_TIME_25MS); /* * Detect accessory after completing the initialization of platform * * - Use delayed workqueue to detect cable state and then * notify cable state to notifiee/platform through uevent. * After completing the booting of platform, the extcon provider * driver should notify cable state to upper layer. */ INIT_DELAYED_WORK(&info->wq_detcable, max14577_muic_detect_cable_wq); queue_delayed_work(system_power_efficient_wq, &info->wq_detcable, delay_jiffies); return ret; }
static int max14577_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct max14577 *max14577; struct max14577_platform_data *pdata = dev_get_platdata(&i2c->dev); struct device_node *np = i2c->dev.of_node; u8 reg_data; int ret = 0; if (np) { pdata = devm_kzalloc(&i2c->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) return -ENOMEM; i2c->dev.platform_data = pdata; } if (!pdata) { dev_err(&i2c->dev, "No platform data found.\n"); return -EINVAL; } max14577 = devm_kzalloc(&i2c->dev, sizeof(*max14577), GFP_KERNEL); if (!max14577) return -ENOMEM; i2c_set_clientdata(i2c, max14577); max14577->dev = &i2c->dev; max14577->i2c = i2c; max14577->irq = i2c->irq; max14577->regmap = devm_regmap_init_i2c(i2c, &max14577_regmap_config); if (IS_ERR(max14577->regmap)) { ret = PTR_ERR(max14577->regmap); dev_err(max14577->dev, "Failed to allocate register map: %d\n", ret); return ret; } ret = max14577_read_reg(max14577->regmap, MAX14577_REG_DEVICEID, ®_data); if (ret) { dev_err(max14577->dev, "Device not found on this channel: %d\n", ret); return ret; } max14577->vendor_id = ((reg_data & DEVID_VENDORID_MASK) >> DEVID_VENDORID_SHIFT); max14577->device_id = ((reg_data & DEVID_DEVICEID_MASK) >> DEVID_DEVICEID_SHIFT); dev_info(max14577->dev, "Device ID: 0x%x, vendor: 0x%x\n", max14577->device_id, max14577->vendor_id); ret = regmap_add_irq_chip(max14577->regmap, max14577->irq, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 0, &max14577_irq_chip, &max14577->irq_data); if (ret != 0) { dev_err(&i2c->dev, "Failed to request IRQ %d: %d\n", max14577->irq, ret); return ret; } ret = mfd_add_devices(max14577->dev, -1, max14577_devs, ARRAY_SIZE(max14577_devs), NULL, 0, regmap_irq_get_domain(max14577->irq_data)); if (ret < 0) goto err_mfd; device_init_wakeup(max14577->dev, 1); return 0; err_mfd: regmap_del_irq_chip(max14577->irq, max14577->irq_data); return ret; }
static int max14577_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct max14577_dev *max14577; struct max14577_platform_data *pdata = i2c->dev.platform_data; u8 reg_data; int ret = 0; max14577 = kzalloc(sizeof(struct max14577_dev), GFP_KERNEL); if (max14577 == NULL) return -ENOMEM; i2c_set_clientdata(i2c, max14577); max14577->dev = &i2c->dev; max14577->i2c = i2c; max14577->irq = i2c->irq; if (pdata) { max14577->pdata = pdata; } else { ret = -EIO; goto err; } pdata->set_cdetctrl1_reg = max14577_set_cdetctrl1_reg; pdata->get_cdetctrl1_reg = max14577_get_cdetctrl1_reg; pdata->set_control2_reg = max14577_set_control2_reg; pdata->get_control2_reg = max14577_get_control2_reg; mutex_init(&max14577->i2c_lock); ret = max14577_read_reg(i2c, MAX14577_REG_DEVICEID, ®_data); if (ret < 0) { pr_err("%s:%s device not found on this channel(%d)\n", MFD_DEV_NAME, __func__, ret); goto err; } else { /* print Device Id */ max14577->vendor_id = (reg_data & 0x7); max14577->device_id = ((reg_data & 0xF8) >> 0x3); pr_info("%s:%s device found: vendor=0x%x, device_id=0x%x\n", MFD_DEV_NAME, __func__, max14577->vendor_id, max14577->device_id); } ret = max14577_irq_init(max14577); if (ret < 0) goto err; ret = mfd_add_devices(max14577->dev, -1, max14577_devs, ARRAY_SIZE(max14577_devs), NULL, 0); if (ret < 0) goto err_mfd; device_init_wakeup(max14577->dev, pdata->wakeup); return ret; err_mfd: mfd_remove_devices(max14577->dev); err: kfree(max14577); return ret; }
static int max14577_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct max14577_dev *max14577; struct max14577_platform_data *pdata = NULL; u8 reg_data; int ret = 0; max14577 = kzalloc(sizeof(struct max14577_dev), GFP_KERNEL); if (max14577 == NULL) return -ENOMEM; if (i2c->dev.of_node) { pdata = devm_kzalloc(&i2c->dev, sizeof(struct max14577_platform_data), GFP_KERNEL); if (!pdata) { dev_err(&i2c->dev, "Failed to allocate memory\n"); ret = -ENOMEM; goto err; } ret = of_max14577_dt(&i2c->dev, pdata); if (ret < 0) { dev_err(&i2c->dev, "Failed to get device of_node\n"); kfree(pdata); goto err; } /*pdata update to other modules*/ i2c->dev.platform_data = pdata; } else pdata = i2c->dev.platform_data; i2c_set_clientdata(i2c, max14577); max14577->dev = &i2c->dev; max14577->i2c = i2c; max14577->irq = i2c->irq; if (pdata) { max14577->pdata = pdata; } else { ret = -EIO; goto err; } pdata->set_cdetctrl1_reg = max14577_set_cdetctrl1_reg; pdata->get_cdetctrl1_reg = max14577_get_cdetctrl1_reg; pdata->set_control2_reg = max14577_set_control2_reg; pdata->get_control2_reg = max14577_get_control2_reg; #ifdef CONFIG_REGULATOR_MAX77836 pdata->regulators = max77836_reglator_pdata; pdata->num_regulators = MAX77836_LDO_MAX; #endif #ifdef CONFIG_CHARGER_MAX14577 pdata->charger_data = &sec_battery_pdata; #endif mutex_init(&max14577->i2c_lock); ret = max14577_read_reg(i2c, MAX14577_REG_DEVICEID, ®_data); if (ret < 0) { pr_err("%s:%s device not found on this channel(%d)\n", MFD_DEV_NAME, __func__, ret); goto err; } else { /* print Device Id */ max14577->vendor_id = (reg_data & 0x7); max14577->device_id = ((reg_data & 0xF8) >> 0x3); pr_info("%s:%s device found: vendor=0x%x, device_id=0x%x\n", MFD_DEV_NAME, __func__, max14577->vendor_id, max14577->device_id); } max14577->i2c_pmic = i2c_new_dummy(i2c->adapter, MAX77836_PMIC_ADDR); i2c_set_clientdata(max14577->i2c_pmic, max14577); ret = max14577_irq_init(max14577); if (ret < 0) goto err_irq_init; ret = mfd_add_devices(max14577->dev, -1, max14577_devs, ARRAY_SIZE(max14577_devs), NULL, 0); if (ret < 0) goto err_mfd; device_init_wakeup(max14577->dev, pdata->wakeup); return ret; err_mfd: mfd_remove_devices(max14577->dev); err_irq_init: if (max14577->i2c_pmic) i2c_unregister_device(max14577->i2c_pmic); err: kfree(max14577); return ret; }