static int max77660_haptic_set_duty_cycle(struct max77660_haptic *chip) { int duty, i; u8 duty_index = 0; int ret = 0; int reg1 = 0xFF, reg2 = 0xFF; bool internal_mode_valid = true; if (chip->mode == MAX77660_EXTERNAL_MODE) { duty = chip->pwm_period * chip->level / 100; ret = pwm_config(chip->pwm, duty, chip->pwm_period); } else { for (i = 0; i < 64; i++) { if (chip->level <= (i + 1) * 100 / 64) { duty_index = i; break; } } switch (chip->internal_mode_pattern) { case 0: reg1 = MAX77660_HAPTIC_REG_SIGDC1; reg2 = MAX77660_HAPTIC_REG_SIGPWMDC1; break; case 1: reg1 = MAX77660_HAPTIC_REG_SIGDC1; reg2 = MAX77660_HAPTIC_REG_SIGPWMDC2; break; case 2: reg1 = MAX77660_HAPTIC_REG_SIGDC2; reg2 = MAX77660_HAPTIC_REG_SIGPWMDC3; break; case 3: reg1 = MAX77660_HAPTIC_REG_SIGDC1; reg2 = MAX77660_HAPTIC_REG_SIGPWMDC4; break; default: internal_mode_valid = false; break; } if (internal_mode_valid) { if (chip->internal_mode_pattern % 2 == 1) max77660_reg_write(chip->dev->parent, MAX77660_HAPTIC_SLAVE, reg1, chip->feedback_duty_cycle); else max77660_reg_write(chip->dev->parent, MAX77660_HAPTIC_SLAVE, reg1, chip->feedback_duty_cycle << 4); max77660_reg_write(chip->dev->parent, MAX77660_HAPTIC_SLAVE, reg2, duty_index); } } return ret; }
static int max77660_adc_enable(struct max77660_adc *adc, int enable) { int ret; if (enable) ret = max77660_reg_write(adc->parent, MAX77660_PWR_SLAVE, MAX77660_REG_ADCCTRL, adc->adc_control | MAX77660_ADCCTRL_ADCEN); else ret = max77660_reg_write(adc->parent, MAX77660_PWR_SLAVE, MAX77660_REG_ADCCTRL, adc->adc_control); if (ret < 0) dev_err(adc->dev, "ADCCTRL write failed: %d\n", ret); return ret; }
static void max77660_haptic_enable(struct max77660_haptic *chip, bool enable) { // printk("Ivan max77660_haptic_enable = %d \n", enable); if (chip->enabled == enable) return; // mutex_lock(&chip->enable_lock); chip->enabled = enable; if (enable) { // printk("Ivan max77660_haptic_enable ENABLE! \n"); regulator_enable(chip->regulator); max77660_haptic_configure(chip); if (chip->mode == MAX77660_EXTERNAL_MODE) pwm_enable(chip->pwm); // haptic_enable_processing = 0; //Ivan } else { // printk("Ivan max77660_haptic_enable DISABLE! \n"); max77660_haptic_configure(chip); max77660_reg_write(chip->dev->parent, MAX77660_HAPTIC_SLAVE, MAX77660_HAPTIC_REG_CONF2, 2); if (chip->mode == MAX77660_EXTERNAL_MODE) pwm_disable(chip->pwm); regulator_disable(chip->regulator); } // mutex_unlock(&chip->enable_lock); }
static void max77660_power_reset(void) { struct max77660_chip *chip = max77660_chip; if (!chip) return; dev_info(chip->dev, "%s: PMIC Reset\n", __func__); /* * ES1.0 errata suggest that in place of doing read modify write, * write direct valid value. */ max77660_reg_write(chip->dev, MAX77660_PWR_SLAVE, MAX77660_REG_GLOBAL_CFG0, 1); do { } while (1); }
void max77660_power_forceoff(void) { struct max77660_chip *chip = max77660_chip; if (!chip) return; mdelay(500); dev_info(chip->dev, "%s: Global shutdown\n", __func__); /* * ES1.0 errata suggest that in place of doing read modify write, * write direct valid value. */ max77660_reg_write(chip->dev, MAX77660_PWR_SLAVE, MAX77660_REG_GLOBAL_CFG0, GLBLCNFG0_SFT_OFF_SYSRST_MASK); }
static int max77660_adc_wakeup_reset(struct max77660_adc *adc) { int ret; ret = max77660_reg_write(adc->parent, MAX77660_PWR_SLAVE, MAX77660_REG_ADCINTM, 0xFF); if (ret < 0) { dev_err(adc->dev, "ADCINTM write failed\n"); return ret; } ret = max77660_reg_update(adc->parent, MAX77660_PWR_SLAVE, MAX77660_REG_ADCCTRL, 0, MAX77660_ADCCTRL_ADCCONT); if (ret < 0) { dev_err(adc->dev, "ADCCTR update failed: %d\n", ret); return ret; } return 0; }
static void max77660_haptic_configure(struct max77660_haptic *chip) { u8 value1, value2, reg1, reg2; bool internal_mode_valid = true; value1 = chip->type << MAX77660_MOTOR_TYPE_SHIFT | chip->enabled << MAX77660_ENABLE_SHIFT | chip->mode << MAX77660_MODE_SHIFT | chip->pwm_divisor; max77660_reg_write(chip->dev->parent, MAX77660_HAPTIC_SLAVE, MAX77660_HAPTIC_REG_CONF2, value1); value1 = chip->invert << MAX77660_INVERT_SHIFT | chip->cont_mode << MAX77660_CONT_MODE_SHIFT | chip->motor_startup_val << MAX77660_MOTOR_STRT_SHIFT | chip->scf_val; max77660_reg_write(chip->dev->parent, MAX77660_HAPTIC_SLAVE, MAX77660_HAPTIC_REG_CONF1, value1); if (chip->mode == MAX77660_INTERNAL_MODE) { if (chip->enabled) { switch (chip->internal_mode_pattern) { case 0: value1 = chip->pattern_cycle << 4; reg1 = MAX77660_HAPTIC_REG_CYCLECONF1; value2 = chip->pattern_signal_period; reg2 = MAX77660_HAPTIC_REG_SIGCONF1; break; case 1: value1 = chip->pattern_cycle; reg1 = MAX77660_HAPTIC_REG_CYCLECONF1; value2 = chip->pattern_signal_period; reg2 = MAX77660_HAPTIC_REG_SIGCONF2; break; case 2: value1 = chip->pattern_cycle << 4; reg1 = MAX77660_HAPTIC_REG_CYCLECONF2; value2 = chip->pattern_signal_period; reg2 = MAX77660_HAPTIC_REG_SIGCONF3; break; case 3: value1 = chip->pattern_cycle; reg1 = MAX77660_HAPTIC_REG_CYCLECONF2; value2 = chip->pattern_signal_period; reg2 = MAX77660_HAPTIC_REG_SIGCONF4; break; default: internal_mode_valid = false; break; } if (internal_mode_valid) { max77660_reg_write(chip->dev->parent, MAX77660_HAPTIC_SLAVE, reg1, value1); max77660_reg_write(chip->dev->parent, MAX77660_HAPTIC_SLAVE, reg2, value2); value1 = chip->internal_mode_pattern << MAX77660_CYCLE_SHIFT | chip->internal_mode_pattern << MAX77660_SIG_PERIOD_SHIFT | chip->internal_mode_pattern << MAX77660_SIG_DUTY_SHIFT | chip->internal_mode_pattern << MAX77660_PWM_DUTY_SHIFT; max77660_reg_write(chip->dev->parent, MAX77660_HAPTIC_SLAVE, MAX77660_HAPTIC_REG_DRVCONF, value1); } } } }
static int max77660_adc_wakeup_configure(struct max77660_adc *adc) { int thres_h, thres_l, ch; u8 int_mask, ch1, ch0; u8 adc_avg; int ret; thres_h = 0; thres_l = 0; int_mask = 0xFF; ch = adc->adc_wake_props.adc_channel_number; if (adc->adc_wake_props.adc_high_threshold > 0) { thres_h = adc->adc_wake_props.adc_high_threshold & 0xFFF; int_mask &= ~MAX77660_ADCINT_DTRINT; } if (adc->adc_wake_props.adc_low_threshold > 0) { thres_l = adc->adc_wake_props.adc_low_threshold & 0xFFF; int_mask &= ~MAX77660_ADCINT_DTFINT; } ch0 = (ch > 7) ? 0 : BIT(ch); ch1 = (ch > 7) ? BIT(ch - 8) : 0; if (adc->adc_wake_props.adc_avg_sample <= 1) adc_avg = MAX77660_ADCCTRL_ADCAVG(0); else if (adc->adc_wake_props.adc_avg_sample <= 2) adc_avg = MAX77660_ADCCTRL_ADCAVG(1); else if (adc->adc_wake_props.adc_avg_sample <= 16) adc_avg = MAX77660_ADCCTRL_ADCAVG(2); else adc_avg = MAX77660_ADCCTRL_ADCAVG(3); ret = max77660_reg_write(adc->parent, MAX77660_PWR_SLAVE, MAX77660_REG_DTRL, thres_h & 0xFF); if (ret < 0) { dev_err(adc->dev, "DTRL write failed: %d\n", ret); return ret; } ret = max77660_reg_write(adc->parent, MAX77660_PWR_SLAVE, MAX77660_REG_DTRH, (thres_h >> 8) & 0xF); if (ret < 0) { dev_err(adc->dev, "DTRH write failed: %d\n", ret); return ret; } ret = max77660_reg_write(adc->parent, MAX77660_PWR_SLAVE, MAX77660_REG_DTFL, thres_l & 0xFF); if (ret < 0) { dev_err(adc->dev, "DTFL write failed: %d\n", ret); return ret; } ret = max77660_reg_write(adc->parent, MAX77660_PWR_SLAVE, MAX77660_REG_DTFH, (thres_l >> 8) & 0xF); if (ret < 0) { dev_err(adc->dev, "DTFH write failed: %d\n", ret); return ret; } ret = max77660_reg_write(adc->parent, MAX77660_PWR_SLAVE, MAX77660_REG_ADCSEL0, ch0); if (ret < 0) { dev_err(adc->dev, "ADCSEL0 write failed: %d\n", ret); return ret; } ret = max77660_reg_write(adc->parent, MAX77660_PWR_SLAVE, MAX77660_REG_ADCSEL1, ch1); if (ret < 0) { dev_err(adc->dev, "ADCSEL1 write failed: %d\n", ret); return ret; } ret = max77660_reg_update(adc->parent, MAX77660_PWR_SLAVE, MAX77660_REG_ADCCTRL, adc_avg, MAX77660_ADCCTRL_ADCAVG_MASK); if (ret < 0) { dev_err(adc->dev, "ADCCTRL update failed: %d\n", ret); return ret; } ret = max77660_reg_write(adc->parent, MAX77660_PWR_SLAVE, MAX77660_REG_ADCINTM, int_mask); if (ret < 0) { dev_err(adc->dev, "ADCINTM write failed\n"); return ret; } ret = max77660_reg_update(adc->parent, MAX77660_PWR_SLAVE, MAX77660_REG_ADCCTRL, MAX77660_ADCCTRL_ADCCONT, MAX77660_ADCCTRL_ADCCONT); if (ret < 0) { dev_err(adc->dev, "ADCCTR update failed: %d\n", ret); return ret; } return 0; }
static int max77660_adc_start_convertion(struct max77660_adc *adc, int adc_chan) { u8 adc_l; u8 adc_h; int ret; u8 chan0 = 0; u8 chan1 = 0; ret = max77660_adc_enable(adc, true); if (ret < 0) return ret; ret = max77660_adc_start_mask_interrupt(adc, MAX77660_ADCINT_ADCCONVINT, 0); if (ret < 0) goto out; if (adc_chan < 8) chan0 = BIT(adc_chan); else chan1 = BIT(adc_chan - 8); ret = max77660_reg_write(adc->parent, MAX77660_PWR_SLAVE, MAX77660_REG_ADCSEL0, chan0); if (ret < 0) { dev_err(adc->dev, "ADCSEL0 write failed: %d\n", ret); goto out; } ret = max77660_reg_write(adc->parent, MAX77660_PWR_SLAVE, MAX77660_REG_ADCSEL1, chan1); if (ret < 0) { dev_err(adc->dev, "ADCSEL1 write failed: %d\n", ret); goto out; } ret = max77660_reg_write(adc->parent, MAX77660_PWR_SLAVE, MAX77660_REG_ADCCHSEL, adc_chan); if (ret < 0) { dev_err(adc->dev, "ADCCHSEL write failed: %d\n", ret); goto out; } if (adc_chan >= MAX77660_ADC_CH_ADC0) { int chan_num = adc_chan - MAX77660_ADC_CH_ADC0; u8 iadc = adc->iadc_val; iadc |= MAX77660_IADC_IADCMUX(chan_num); ret = max77660_reg_write(adc->parent, MAX77660_PWR_SLAVE, MAX77660_REG_IADC, iadc); if (ret < 0) { dev_err(adc->dev, "IADC write failed: %d\n", ret); goto out; } } if (adc->adc_info[adc_chan].acquisition_time_us) udelay(adc->adc_info[adc_chan].acquisition_time_us); INIT_COMPLETION(adc->conv_completion); ret = max77660_reg_update(adc->parent, MAX77660_PWR_SLAVE, MAX77660_REG_ADCCTRL, MAX77660_ADCCTRL_ADCCONV, MAX77660_ADCCTRL_ADCCONV); if (ret < 0) { dev_err(adc->dev, "ADCCTR write failed: %d\n", ret); goto out; } ret = wait_for_completion_timeout(&adc->conv_completion, ADC_CONVERTION_TIMEOUT); if (ret == 0) { dev_err(adc->dev, "ADC conversion not completed\n"); ret = -ETIMEDOUT; goto out; } ret = max77660_reg_read(adc->parent, MAX77660_PWR_SLAVE, MAX77660_REG_ADCDATAL, &adc_l); if (ret < 0) { dev_err(adc->dev, "ADCDATAL read failed: %d\n", ret); goto out; } ret = max77660_reg_read(adc->parent, MAX77660_PWR_SLAVE, MAX77660_REG_ADCDATAH, &adc_h); if (ret < 0) { dev_err(adc->dev, "ADCDATAH read failed: %d\n", ret); goto out; } ret = ((adc_h & 0xF) << 8) | adc_l; out: max77660_adc_start_mask_interrupt(adc, MAX77660_ADCINT_ADCCONVINT, 1); max77660_adc_enable(adc, false); return ret; }