/* Check GROUND accessory with charger cable */ if (adc == MAX77843_MUIC_ADC_GROUND) { if (chg_type == MAX77843_MUIC_CHG_NONE) { /* * The following state when charger cable is * disconnected but the GROUND accessory still * connected.
*/
*attached = false;
cable_type = info->prev_chg_type;
info->prev_chg_type = MAX77843_MUIC_CHG_NONE;
} else {
/* * The following state when charger cable is * connected on the GROUND accessory.
*/
*attached = true;
cable_type = MAX77843_MUIC_CHG_GND;
info->prev_chg_type = MAX77843_MUIC_CHG_GND;
} break;
}
switch (gnd_cable_type) { case MAX77843_MUIC_GND_USB_HOST: case MAX77843_MUIC_GND_USB_HOST_VB:
ret = max77843_muic_set_path(info,
MAX77843_MUIC_CONTROL1_SW_USB,
attached, false); if (ret < 0) return ret;
extcon_set_state_sync(info->edev, EXTCON_USB_HOST, attached);
max77843_charger_set_otg_vbus(info, attached); break; case MAX77843_MUIC_GND_MHL_VB: case MAX77843_MUIC_GND_MHL:
ret = max77843_muic_set_path(info,
MAX77843_MUIC_CONTROL1_SW_OPEN,
attached, false); if (ret < 0) return ret;
switch (cable_type) { case MAX77843_MUIC_ADC_RESERVED_ACC_3: /* SmartDock */
ret = max77843_muic_dock_handler(info, attached); if (ret < 0) return ret; break; case MAX77843_MUIC_ADC_GROUND:
ret = max77843_muic_adc_gnd_handler(info); if (ret < 0) return ret; break; case MAX77843_MUIC_ADC_FACTORY_MODE_USB_OFF: case MAX77843_MUIC_ADC_FACTORY_MODE_USB_ON: case MAX77843_MUIC_ADC_FACTORY_MODE_UART_OFF:
ret = max77843_muic_jig_handler(info, cable_type, attached); if (ret < 0) return ret; break; case MAX77843_MUIC_ADC_SEND_END_BUTTON: case MAX77843_MUIC_ADC_REMOTE_S1_BUTTON: case MAX77843_MUIC_ADC_REMOTE_S2_BUTTON: case MAX77843_MUIC_ADC_REMOTE_S3_BUTTON: case MAX77843_MUIC_ADC_REMOTE_S4_BUTTON: case MAX77843_MUIC_ADC_REMOTE_S5_BUTTON: case MAX77843_MUIC_ADC_REMOTE_S6_BUTTON: case MAX77843_MUIC_ADC_REMOTE_S7_BUTTON: case MAX77843_MUIC_ADC_REMOTE_S8_BUTTON: case MAX77843_MUIC_ADC_REMOTE_S9_BUTTON: case MAX77843_MUIC_ADC_REMOTE_S10_BUTTON: case MAX77843_MUIC_ADC_REMOTE_S11_BUTTON: case MAX77843_MUIC_ADC_REMOTE_S12_BUTTON: case MAX77843_MUIC_ADC_RESERVED_ACC_1: case MAX77843_MUIC_ADC_RESERVED_ACC_2: case MAX77843_MUIC_ADC_RESERVED_ACC_4: case MAX77843_MUIC_ADC_RESERVED_ACC_5: case MAX77843_MUIC_ADC_AUDIO_DEVICE_TYPE2: case MAX77843_MUIC_ADC_PHONE_POWERED_DEV: case MAX77843_MUIC_ADC_TTY_CONVERTER: case MAX77843_MUIC_ADC_UART_CABLE: case MAX77843_MUIC_ADC_CEA936A_TYPE1_CHG: case MAX77843_MUIC_ADC_AV_CABLE_NOLOAD: case MAX77843_MUIC_ADC_CEA936A_TYPE2_CHG: case MAX77843_MUIC_ADC_FACTORY_MODE_UART_ON: case MAX77843_MUIC_ADC_AUDIO_DEVICE_TYPE1: case MAX77843_MUIC_ADC_OPEN:
dev_err(info->dev, "accessory is %s but it isn't used (adc:0x%x)\n",
attached ? "attached" : "detached", cable_type); return -EAGAIN; default:
dev_err(info->dev, "failed to detect %s accessory (adc:0x%x)\n",
attached ? "attached" : "detached", cable_type); return -EINVAL;
}
ret = regmap_bulk_read(max77843->regmap_muic,
MAX77843_MUIC_REG_STATUS1, info->status,
MAX77843_MUIC_STATUS_NUM); if (ret) {
dev_err(info->dev, "Cannot read STATUS registers\n");
mutex_unlock(&info->mutex); return;
}
if (info->irq_adc) {
ret = max77843_muic_adc_handler(info); if (ret)
dev_err(info->dev, "Unknown cable type\n");
info->irq_adc = false;
}
if (info->irq_chg) {
ret = max77843_muic_chg_handler(info); if (ret)
dev_err(info->dev, "Unknown charger type\n");
info->irq_chg = false;
}
mutex_unlock(&info->mutex);
}
static irqreturn_t max77843_muic_irq_handler(int irq, void *data)
{ struct max77843_muic_info *info = data; int i, irq_type = -1;
for (i = 0; i < ARRAY_SIZE(max77843_muic_irqs); i++) if (irq == max77843_muic_irqs[i].virq)
irq_type = max77843_muic_irqs[i].irq;
switch (irq_type) { case MAX77843_MUIC_IRQ_INT1_ADC: case MAX77843_MUIC_IRQ_INT1_ADCERROR: case MAX77843_MUIC_IRQ_INT1_ADC1K:
info->irq_adc = true; break; case MAX77843_MUIC_IRQ_INT2_CHGTYP: case MAX77843_MUIC_IRQ_INT2_CHGDETRUN: case MAX77843_MUIC_IRQ_INT2_DCDTMR: case MAX77843_MUIC_IRQ_INT2_DXOVP: case MAX77843_MUIC_IRQ_INT2_VBVOLT:
info->irq_chg = true; break; case MAX77843_MUIC_IRQ_INT3_VBADC: case MAX77843_MUIC_IRQ_INT3_VDNMON: case MAX77843_MUIC_IRQ_INT3_DNRES: case MAX77843_MUIC_IRQ_INT3_MPNACK: case MAX77843_MUIC_IRQ_INT3_MRXBUFOW: case MAX77843_MUIC_IRQ_INT3_MRXTRF: case MAX77843_MUIC_IRQ_INT3_MRXPERR: case MAX77843_MUIC_IRQ_INT3_MRXRDY: break; default:
dev_err(info->dev, "Cannot recognize IRQ(%d)\n", irq_type); break;
}
/* Initialize i2c and regmap */
ret = max77843_init_muic_regmap(max77843); if (ret) {
dev_err(&pdev->dev, "Failed to init MUIC regmap\n"); return ret;
}
/* Turn off auto detection configuration */
ret = regmap_update_bits(max77843->regmap_muic,
MAX77843_MUIC_REG_CONTROL4,
MAX77843_MUIC_CONTROL4_USBAUTO_MASK |
MAX77843_MUIC_CONTROL4_FCTAUTO_MASK,
CONTROL4_AUTO_DISABLE);
/* Initialize extcon device */
info->edev = devm_extcon_dev_allocate(&pdev->dev,
max77843_extcon_cable); if (IS_ERR(info->edev)) {
dev_err(&pdev->dev, "Failed to allocate memory for extcon\n");
ret = PTR_ERR(info->edev); goto err_muic_irq;
}
ret = devm_extcon_dev_register(&pdev->dev, info->edev); if (ret) {
dev_err(&pdev->dev, "Failed to register extcon device\n"); goto err_muic_irq;
}
/* Set ADC debounce time */
max77843_muic_set_debounce_time(info, MAX77843_DEBOUNCE_TIME_25MS);
/* Set initial path for UART when JIG is connected to get serial logs */
ret = regmap_bulk_read(max77843->regmap_muic,
MAX77843_MUIC_REG_STATUS1, info->status,
MAX77843_MUIC_STATUS_NUM); if (ret) {
dev_err(info->dev, "Cannot read STATUS registers\n"); goto err_muic_irq;
}
cable_type = max77843_muic_get_cable_type(info, MAX77843_CABLE_GROUP_ADC,
&attached); if (attached && cable_type == MAX77843_MUIC_ADC_FACTORY_MODE_UART_OFF)
max77843_muic_set_path(info, MAX77843_MUIC_CONTROL1_SW_UART, true, false);
/* Check revision number of MUIC device */
ret = regmap_read(max77843->regmap_muic, MAX77843_MUIC_REG_ID, &id); if (ret < 0) {
dev_err(&pdev->dev, "Failed to read revision number\n"); goto err_muic_irq;
}
dev_info(info->dev, "MUIC device ID : 0x%x\n", id);
/* Support virtual irq domain for max77843 MUIC device */
INIT_WORK(&info->irq_work, max77843_muic_irq_work);
/* Clear IRQ bits before request IRQs */
ret = regmap_bulk_read(max77843->regmap_muic,
MAX77843_MUIC_REG_INT1, info->status,
MAX77843_MUIC_STATUS_NUM); if (ret) {
dev_err(&pdev->dev, "Failed to Clear IRQ bits\n"); goto err_muic_irq;
}
for (i = 0; i < ARRAY_SIZE(max77843_muic_irqs); i++) { struct max77843_muic_irq *muic_irq = &max77843_muic_irqs[i]; int virq = 0;
virq = regmap_irq_get_virq(max77843->irq_data_muic,
muic_irq->irq); if (virq <= 0) {
ret = -EINVAL; goto err_muic_irq;
}
muic_irq->virq = virq;
ret = devm_request_threaded_irq(&pdev->dev, virq, NULL,
max77843_muic_irq_handler, IRQF_NO_SUSPEND,
muic_irq->name, info); if (ret) {
dev_err(&pdev->dev, "Failed to request irq (IRQ: %d, error: %d)\n",
muic_irq->irq, ret); goto err_muic_irq;
}
}
/* Detect accessory after completing the initialization of platform */
INIT_DELAYED_WORK(&info->wq_detcable, max77843_muic_detect_cable_wq);
queue_delayed_work(system_power_efficient_wq,
&info->wq_detcable, msecs_to_jiffies(DELAY_MS_DEFAULT));
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.