static ssize_t max8997_muic_show_status(struct device *dev, struct device_attribute *attr, char *buf) { struct max8997_muic_info *info = dev_get_drvdata(dev); u8 devid, int_value[3], status[3], intmask[3], ctrl[3], cdetctrl; max8997_read_reg(info->muic, MAX8997_MUIC_REG_ID, &devid); max8997_bulk_read(info->muic, MAX8997_MUIC_REG_INT1, 3, int_value); max8997_bulk_read(info->muic, MAX8997_MUIC_REG_STATUS1, 3, status); max8997_bulk_read(info->muic, MAX8997_MUIC_REG_INTMASK1, 3, intmask); max8997_bulk_read(info->muic, MAX8997_MUIC_REG_CTRL1, 3, ctrl); max8997_read_reg(info->muic, MAX8997_MUIC_REG_CDETCTRL, &cdetctrl); return sprintf(buf, "Device ID(0x%02x)\n" "INT1(0x%02x), INT2(0x%02x), INT3(0x%02x)\n" "STATUS1(0x%02x), STATUS2(0x%02x), STATUS3(0x%02x)\n" "INTMASK1(0x%02x), INTMASK2(0x%02x), INTMASK3(0x%02x)\n" "CTRL1(0x%02x), CTRL2(0x%02x), CTRL3(0x%02x)\n" "CDETCTRL(0x%02x)\n", devid, int_value[0], int_value[1], int_value[2], status[0], status[1], status[2], intmask[0], intmask[1], intmask[2], ctrl[0], ctrl[1], ctrl[2], cdetctrl); }
static int max8997_rtc_stop_alarm(struct max8997_rtc_info *info) { u8 data[RTC_NR_TIME]; int ret, i; if (!mutex_is_locked(&info->lock)) dev_warn(info->dev, "%s: should have mutex locked\n", __func__); ret = max8997_bulk_read(info->rtc, MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME, data); if (ret < 0) { dev_err(info->dev, "%s: fail to read alarm reg(%d)\n", __func__, ret); goto out; } for (i = 0; i < RTC_NR_TIME; i++) data[i] &= ~ALARM_ENABLE_MASK; ret = max8997_bulk_write(info->rtc, MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME, data); if (ret < 0) { dev_err(info->dev, "%s: fail to write alarm reg(%d)\n", __func__, ret); goto out; } ret = max8997_rtc_set_update_reg(info); out: return ret; }
static void max8997_muic_irq_work(struct work_struct *work) { struct max8997_muic_info *info = container_of(work, struct max8997_muic_info, irq_work); int irq_type = 0; int i, ret; if (!info->edev) return; mutex_lock(&info->mutex); for (i = 0; i < ARRAY_SIZE(muic_irqs); i++) if (info->irq == muic_irqs[i].virq) irq_type = muic_irqs[i].irq; ret = max8997_bulk_read(info->muic, MAX8997_MUIC_REG_STATUS1, 2, info->status); if (ret) { dev_err(info->dev, "failed to read muic register\n"); mutex_unlock(&info->mutex); return; } switch (irq_type) { case MAX8997_MUICIRQ_ADCError: case MAX8997_MUICIRQ_ADCLow: case MAX8997_MUICIRQ_ADC: /* Handle all of cable except for charger cable */ ret = max8997_muic_adc_handler(info); break; case MAX8997_MUICIRQ_VBVolt: case MAX8997_MUICIRQ_DBChg: case MAX8997_MUICIRQ_DCDTmr: case MAX8997_MUICIRQ_ChgDetRun: case MAX8997_MUICIRQ_ChgTyp: /* Handle charger cable */ ret = max8997_muic_chg_handler(info); break; case MAX8997_MUICIRQ_OVP: break; default: dev_info(info->dev, "misc interrupt: irq %d occurred\n", irq_type); mutex_unlock(&info->mutex); return; } if (ret < 0) dev_err(info->dev, "failed to handle MUIC interrupt\n"); mutex_unlock(&info->mutex); }
static void max8997_muic_detect_dev(struct max8997_muic_info *info) { struct i2c_client *client = info->muic; u8 status[2]; u8 adc, chgtyp, adcerr; int intr = INT_ATTACH; int ret; ret = max8997_bulk_read(client, MAX8997_MUIC_REG_STATUS1, 2, status); if (ret) { dev_err(info->dev, "%s: fail to read muic reg(%d)\n", __func__, ret); return; } dev_info(info->dev, "%s: STATUS1:0x%x, 2:0x%x\n", __func__, status[0], status[1]); if (max8997_muic_handle_dock_vol_key(info, status[0])) return; adc = status[0] & STATUS1_ADC_MASK; adcerr = status[0] & STATUS1_ADCERR_MASK; chgtyp = status[1] & STATUS2_CHGTYP_MASK; if (!adcerr && adc == ADC_OPEN) { if (chgtyp == CHGTYP_NO_VOLTAGE) intr = INT_DETACH; else if (chgtyp == CHGTYP_USB || chgtyp == CHGTYP_DOWNSTREAM_PORT || chgtyp == CHGTYP_DEDICATED_CHGR || chgtyp == CHGTYP_500MA || chgtyp == CHGTYP_1A) { if (info->cable_type == CABLE_TYPE_OTG || info->cable_type == CABLE_TYPE_DESKDOCK || info->cable_type == CABLE_TYPE_CARDOCK) intr = INT_DETACH; } } if (intr == INT_ATTACH) { dev_info(info->dev, "%s: ATTACHED\n", __func__); max8997_muic_handle_attach(info, status[0], status[1]); } else { dev_info(info->dev, "%s: DETACHED\n", __func__); max8997_muic_handle_detach(info); } return; }
static void max8997_muic_irq_work(struct work_struct *work) { struct max8997_muic_info *info = container_of(work, struct max8997_muic_info, irq_work); struct max8997_platform_data *pdata = dev_get_platdata(info->iodev->dev); u8 status[3]; u8 adc, chg_type; int irq_type = info->irq - pdata->irq_base; int ret; mutex_lock(&info->mutex); ret = max8997_bulk_read(info->muic, MAX8997_MUIC_REG_STATUS1, 3, status); if (ret) { dev_err(info->dev, "failed to read muic register\n"); mutex_unlock(&info->mutex); return; } dev_dbg(info->dev, "%s: STATUS1:0x%x, 2:0x%x\n", __func__, status[0], status[1]); switch (irq_type) { case MAX8997_MUICIRQ_ADC: adc = status[0] & STATUS1_ADC_MASK; adc >>= STATUS1_ADC_SHIFT; max8997_muic_handle_adc(info, adc); break; case MAX8997_MUICIRQ_ChgTyp: chg_type = status[1] & STATUS2_CHGTYP_MASK; chg_type >>= STATUS2_CHGTYP_SHIFT; max8997_muic_handle_charger_type(info, chg_type); break; default: dev_info(info->dev, "misc interrupt: %s occurred\n", muic_irqs[irq_type].name); break; } mutex_unlock(&info->mutex); return; }
static int max8997_muic_detect_dev(struct max8997_muic_info *info) { int ret = 0; int adc; int chg_type; bool attached; mutex_lock(&info->mutex); /* Read STATUSx register to detect accessory */ ret = max8997_bulk_read(info->muic, MAX8997_MUIC_REG_STATUS1, 2, info->status); if (ret) { dev_err(info->dev, "failed to read MUIC register\n"); mutex_unlock(&info->mutex); return ret; } adc = max8997_muic_get_cable_type(info, MAX8997_CABLE_GROUP_ADC, &attached); if (attached && adc != MAX8997_MUIC_ADC_OPEN) { ret = max8997_muic_adc_handler(info); if (ret < 0) { dev_err(info->dev, "Cannot detect ADC cable\n"); mutex_unlock(&info->mutex); return ret; } } chg_type = max8997_muic_get_cable_type(info, MAX8997_CABLE_GROUP_CHG, &attached); if (attached && chg_type != MAX8997_CHARGER_TYPE_NONE) { ret = max8997_muic_chg_handler(info); if (ret < 0) { dev_err(info->dev, "Cannot detect charger cable\n"); mutex_unlock(&info->mutex); return ret; } } mutex_unlock(&info->mutex); return 0; }
static int max8997_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) { struct max8997_rtc_info *info = dev_get_drvdata(dev); u8 data[RTC_NR_TIME]; u8 val; int i, ret; mutex_lock(&info->lock); ret = max8997_bulk_read(info->rtc, MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME, data); if (ret < 0) { dev_err(info->dev, "%s:%d fail to read alarm reg(%d)\n", __func__, __LINE__, ret); goto out; } max8997_rtc_data_to_tm(data, &alrm->time, info->rtc_24hr_mode); alrm->enabled = 0; for (i = 0; i < RTC_NR_TIME; i++) { if (data[i] & ALARM_ENABLE_MASK) { alrm->enabled = 1; break; } } alrm->pending = 0; ret = max8997_read_reg(info->max8997->i2c, MAX8997_REG_STATUS1, &val); if (ret < 0) { dev_err(info->dev, "%s:%d fail to read status1 reg(%d)\n", __func__, __LINE__, ret); goto out; } if (val & (1 << 4)) /* RTCA1 */ alrm->pending = 1; out: mutex_unlock(&info->lock); return 0; }
static int max8997_rtc_read_time(struct device *dev, struct rtc_time *tm) { struct max8997_rtc_info *info = dev_get_drvdata(dev); u8 data[RTC_NR_TIME]; int ret; mutex_lock(&info->lock); ret = max8997_bulk_read(info->rtc, MAX8997_RTC_SEC, RTC_NR_TIME, data); mutex_unlock(&info->lock); if (ret < 0) { dev_err(info->dev, "%s: fail to read time reg(%d)\n", __func__, ret); return ret; } max8997_rtc_data_to_tm(data, tm, info->rtc_24hr_mode); return rtc_valid_tm(tm); }
static int max8997_rtc_start_alarm(struct max8997_rtc_info *info) { u8 data[RTC_NR_TIME]; int ret; if (!mutex_is_locked(&info->lock)) dev_warn(info->dev, "%s: should have mutex locked\n", __func__); ret = max8997_bulk_read(info->rtc, MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME, data); if (ret < 0) { dev_err(info->dev, "%s: fail to read alarm reg(%d)\n", __func__, ret); goto out; } data[RTC_SEC] |= (1 << ALARM_ENABLE_SHIFT); data[RTC_MIN] |= (1 << ALARM_ENABLE_SHIFT); data[RTC_HOUR] |= (1 << ALARM_ENABLE_SHIFT); data[RTC_WEEKDAY] &= ~ALARM_ENABLE_MASK; if (data[RTC_MONTH] & 0xf) data[RTC_MONTH] |= (1 << ALARM_ENABLE_SHIFT); if (data[RTC_YEAR] & 0x7f) data[RTC_YEAR] |= (1 << ALARM_ENABLE_SHIFT); if (data[RTC_DATE] & 0x1f) data[RTC_DATE] |= (1 << ALARM_ENABLE_SHIFT); ret = max8997_bulk_write(info->rtc, MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME, data); if (ret < 0) { dev_err(info->dev, "%s: fail to write alarm reg(%d)\n", __func__, ret); goto out; } ret = max8997_rtc_set_update_reg(info); out: return ret; }
static void max8997_muic_detect_dev(struct max8997_muic_info *info) { int ret; u8 status[2], adc, chg_type; ret = max8997_bulk_read(info->muic, MAX8997_MUIC_REG_STATUS1, 2, status); if (ret) { dev_err(info->dev, "failed to read muic register\n"); return; } dev_info(info->dev, "STATUS1:0x%x, STATUS2:0x%x\n", status[0], status[1]); adc = status[0] & STATUS1_ADC_MASK; adc >>= STATUS1_ADC_SHIFT; chg_type = status[1] & STATUS2_CHGTYP_MASK; chg_type >>= STATUS2_CHGTYP_SHIFT; max8997_muic_handle_adc(info, adc); max8997_muic_handle_charger_type(info, chg_type); }
static void max8997_muic_detect_dev(struct max8997_muic_info *info, int irq) { struct i2c_client *client = info->muic; u8 status[2]; u8 adc, chgtyp, adcerr; int intr = INT_ATTACH; int ret; ret = max8997_bulk_read(client, MAX8997_MUIC_REG_STATUS1, 2, status); if (ret) { dev_err(info->dev, "%s: fail to read muic reg(%d)\n", __func__, ret); return; } dev_info(info->dev, "%s: STATUS1:0x%x, 2:0x%x\n", __func__, status[0], status[1]); if ((irq == info->irq_adc) && max8997_muic_handle_dock_vol_key(info, status[0])) return; adc = status[0] & STATUS1_ADC_MASK; adcerr = status[0] & STATUS1_ADCERR_MASK; chgtyp = status[1] & STATUS2_CHGTYP_MASK; switch (adc) { case ADC_MHL: #if defined(CONFIG_MACH_U1) break; #endif case (ADC_MHL + 1): case (ADC_DOCK_VOL_DN - 1): case (ADC_DOCK_PLAY_PAUSE_KEY + 2) ... (ADC_CEA936ATYPE1_CHG - 1): case (ADC_CARDOCK + 1): dev_warn(info->dev, "%s: unsupported ADC(0x%02x)\n", __func__, adc); intr = INT_DETACH; break; case ADC_OPEN: if (!adcerr) { if (chgtyp == CHGTYP_NO_VOLTAGE) intr = INT_DETACH; else if (chgtyp == CHGTYP_USB || chgtyp == CHGTYP_DOWNSTREAM_PORT || chgtyp == CHGTYP_DEDICATED_CHGR || chgtyp == CHGTYP_500MA || chgtyp == CHGTYP_1A) { if (info->cable_type == CABLE_TYPE_OTG || info->cable_type == CABLE_TYPE_DESKDOCK || info->cable_type == CABLE_TYPE_CARDOCK) intr = INT_DETACH; } } break; default: break; } #if defined(CONFIG_MUIC_MAX8997_OVPUI) if (intr == INT_ATTACH) { if (irq == info->irq_chgins) { if (info->is_ovp_state) { max8997_muic_handle_attach(info, status[0], status[1]); info->is_ovp_state = false; dev_info(info->dev, "OVP recovered\n"); return; } else { dev_info(info->dev, "Just inserted TA/USB\n"); return; } } else if (irq == info->irq_chgrm) { max8997_muic_handle_detach(info); info->is_ovp_state = true; dev_info(info->dev, "OVP occured\n"); return; } } else { info->is_ovp_state = false; if (irq == info->irq_chgrm) { dev_info(info->dev, "Just removed TA/USB\n"); return; } } #endif if (intr == INT_ATTACH) { dev_info(info->dev, "%s: ATTACHED\n", __func__); max8997_muic_handle_attach(info, status[0], status[1]); } else { dev_info(info->dev, "%s: DETACHED\n", __func__); max8997_muic_handle_detach(info); } return; }
static irqreturn_t max8997_irq_thread(int irq, void *data) { struct max8997_dev *max8997 = data; u8 irq_reg[MAX8997_IRQ_GROUP_NR] = {}; u8 irq_src; int ret; int i, cur_irq; ret = max8997_read_reg(max8997->i2c, MAX8997_REG_INTSRC, &irq_src); if (ret < 0) { dev_err(max8997->dev, "Failed to read interrupt source: %d\n", ret); return IRQ_NONE; } if (irq_src & MAX8997_IRQSRC_PMIC) { /* PMIC INT1 ~ INT4 */ max8997_bulk_read(max8997->i2c, MAX8997_REG_INT1, 4, &irq_reg[PMIC_INT1]); } if (irq_src & MAX8997_IRQSRC_FUELGAUGE) { /* * TODO: FUEL GAUGE * * This is to be supported by Max17042 driver. When * an interrupt incurs here, it should be relayed to a * Max17042 device that is connected (probably by * platform-data). However, we do not have interrupt * handling in Max17042 driver currently. The Max17042 IRQ * driver should be ready to be used as a stand-alone device and * a Max8997-dependent device. Because it is not ready in * Max17042-side and it is not too critical in operating * Max8997, we do not implement this in initial releases. */ irq_reg[FUEL_GAUGE] = 0; } if (irq_src & MAX8997_IRQSRC_MUIC) { /* MUIC INT1 ~ INT3 */ max8997_bulk_read(max8997->muic, MAX8997_MUIC_REG_INT1, 3, &irq_reg[MUIC_INT1]); } if (irq_src & MAX8997_IRQSRC_GPIO) { /* GPIO Interrupt */ u8 gpio_info[MAX8997_NUM_GPIO]; irq_reg[GPIO_LOW] = 0; irq_reg[GPIO_HI] = 0; max8997_bulk_read(max8997->i2c, MAX8997_REG_GPIOCNTL1, MAX8997_NUM_GPIO, gpio_info); for (i = 0; i < MAX8997_NUM_GPIO; i++) { bool interrupt = false; switch (gpio_info[i] & MAX8997_GPIO_INT_MASK) { case MAX8997_GPIO_INT_BOTH: if (max8997->gpio_status[i] != gpio_info[i]) interrupt = true; break; case MAX8997_GPIO_INT_RISE: if ((max8997->gpio_status[i] != gpio_info[i]) && (gpio_info[i] & MAX8997_GPIO_DATA_MASK)) interrupt = true; break; case MAX8997_GPIO_INT_FALL: if ((max8997->gpio_status[i] != gpio_info[i]) && !(gpio_info[i] & MAX8997_GPIO_DATA_MASK)) interrupt = true; break; default: break; } if (interrupt) { if (i < 8) irq_reg[GPIO_LOW] |= (1 << i); else irq_reg[GPIO_HI] |= (1 << (i - 8)); } } } if (irq_src & MAX8997_IRQSRC_FLASH) { /* Flash Status Interrupt */ ret = max8997_read_reg(max8997->i2c, MAX8997_REG_FLASHSTATUS, &irq_reg[FLASH_STATUS]); } /* Apply masking */ for (i = 0; i < MAX8997_IRQ_GROUP_NR; i++) irq_reg[i] &= ~max8997->irq_masks_cur[i]; /* Report */ for (i = 0; i < MAX8997_IRQ_NR; i++) { if (irq_reg[max8997_irqs[i].group] & max8997_irqs[i].mask) { cur_irq = irq_find_mapping(max8997->irq_domain, i); if (cur_irq) handle_nested_irq(cur_irq); } } return IRQ_HANDLED; }