static int pm8xxx_read_block_irq(struct pm_irq_chip *chip, u8 bp, u8 *ip) { int rc; spin_lock(&chip->pm_irq_lock); rc = pm8xxx_writeb(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, bp); if (rc) { pr_err("Failed Selecting Block %d rc=%d\n", bp, rc); goto bail; } rc = pm8xxx_readb(chip->dev, SSBI_REG_ADDR_IRQ_IT_STATUS, ip); if (rc) pr_err("Failed Reading Status rc=%d\n", rc); bail: spin_unlock(&chip->pm_irq_lock); return rc; }
static void led_lc_set(struct pm8xxx_led_data *led, enum led_brightness value) { int rc, offset; u8 level; level = (value << PM8XXX_DRV_LED_CTRL_SHIFT) & PM8XXX_DRV_LED_CTRL_MASK; offset = PM8XXX_LED_OFFSET(led->id); led->reg &= ~PM8XXX_DRV_LED_CTRL_MASK; led->reg |= level; rc = pm8xxx_writeb(led->dev->parent, SSBI_REG_ADDR_LED_CTRL(offset), led->reg); if (rc) dev_err(led->cdev.dev, "can't set (%d) led value rc=%d\n", led->id, rc); }
static int pm8xxx_debug_data_set(void *data, u64 val) { struct pm8xxx_debug_device *debugdev = data; u8 reg = val; int rc; mutex_lock(&debugdev->debug_mutex); if (pm8xxx_debug_addr_is_valid(debugdev->addr)) { rc = pm8xxx_writeb(debugdev->parent, debugdev->addr, reg); if (rc) pr_err("pm8xxx_writeb(0x%03X)=0x%02X failed: rc=%d\n", debugdev->addr, reg, rc); } mutex_unlock(&debugdev->debug_mutex); return 0; }
static int pm8xxx_misc_masked_write(struct pm8xxx_misc_chip *chip, u16 addr, u8 mask, u8 val) { int rc; u8 reg; rc = pm8xxx_readb(chip->dev->parent, addr, ®); if (rc) { pr_err("pm8xxx_readb(0x%03X) failed, rc=%d\n", addr, rc); return rc; } reg &= ~mask; reg |= val & mask; rc = pm8xxx_writeb(chip->dev->parent, addr, reg); if (rc) pr_err("pm8xxx_writeb(0x%03X)=0x%02X failed, rc=%d\n", addr, reg, rc); return rc; }
static int pm_chg_masked_write(struct pm8921_chg_chip *chip, u16 addr, u8 mask, u8 val) { int rc; u8 reg; rc = pm8xxx_readb(chip->dev->parent, addr, ®); if (rc) { pr_err("pm8xxx_readb failed: addr=%03X, rc=%d\n", addr, rc); return rc; } reg &= ~mask; reg |= val & mask; rc = pm8xxx_writeb(chip->dev->parent, addr, reg); if (rc) { pr_err("pm8xxx_writeb failed: addr=%03X, rc=%d\n", addr, rc); return rc; } return 0; }
int pm8xxx_vibrator_config(struct pm8xxx_vib_config *vib_config) { u8 reg = 0; int rc; mutex_lock(&vib_dev->vib_mutex); VIB_DEBUG_LOG(KERN_INFO, "called.drive_mV=%d,active_low=%d,enable_mode=%d\n" ,vib_config->drive_mV, vib_config->active_low, vib_config->enable_mode); if (vib_dev == NULL) { VIB_LOG(KERN_ERR, "vib_dev is NULL\n"); mutex_unlock(&vib_dev->vib_mutex); return -EINVAL; } if (vib_config->drive_mV) { if ((vib_config->drive_mV < VIB_MIN_LEVEL_mV) || (vib_config->drive_mV > VIB_MAX_LEVEL_mV)) { VIB_LOG(KERN_ERR, "Invalid vibrator drive strength\n"); mutex_unlock(&vib_dev->vib_mutex); return -EINVAL; } } reg = (vib_config->drive_mV / 100) << VIB_DRV_SEL_SHIFT; reg |= (!!vib_config->active_low) << VIB_DRV_LOGIC_SHIFT; reg |= vib_config->enable_mode; rc = pm8xxx_writeb(vib_dev->dev->parent, VIB_DRV, reg); VIB_DEBUG_LOG(KERN_INFO, "pm8xxx_writeb() called. rc=%d,reg=0x%02X,data=0x%02X\n", rc, VIB_DRV, reg); if (rc) VIB_LOG(KERN_ERR, "pm8xxx write failed: rc=%d\n",rc); mutex_unlock(&vib_dev->vib_mutex); VIB_DEBUG_LOG(KERN_INFO, "end.rc=%d\n", rc); return rc; }
/** * pm8xxx_get_irq_stat - get the status of the irq line * @chip: pointer to identify a pmic irq controller * @irq: the irq number * * The pm8xxx gpio and mpp rely on the interrupt block to read * the values on their pins. This function is to facilitate reading * the status of a gpio or an mpp line. The caller has to convert the * gpio number to irq number. * * RETURNS: * an int indicating the value read on that line */ int pm8xxx_get_irq_stat(struct pm_irq_chip *chip, int irq) { int pmirq, rc; u8 block, bits, bit; unsigned long flags; if (chip == NULL || irq < chip->irq_base || irq >= chip->irq_base + chip->num_irqs) return -EINVAL; pmirq = irq - chip->irq_base; block = pmirq / 8; bit = pmirq % 8; spin_lock_irqsave(&chip->pm_irq_lock, flags); rc = pm8xxx_writeb(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL(chip->base_addr), block); if (rc) { pr_err("Failed Selecting block irq=%d pmirq=%d blk=%d rc=%d\n", irq, pmirq, block, rc); goto bail_out; } rc = pm8xxx_readb(chip->dev, SSBI_REG_ADDR_IRQ_RT_STATUS(chip->base_addr), &bits); if (rc) { pr_err("Failed Configuring irq=%d pmirq=%d blk=%d rc=%d\n", irq, pmirq, block, rc); goto bail_out; } rc = (bits & (1 << bit)) ? 1 : 0; bail_out: spin_unlock_irqrestore(&chip->pm_irq_lock, flags); return rc; }
static int pm8xxx_pwm_bank_enable(struct pwm_device *pwm, int enable) { int rc; u8 reg; struct pm8xxx_pwm_chip *chip; chip = pwm->chip; if (enable) reg = chip->bank_mask | (1 << pwm->pwm_id); else reg = chip->bank_mask & ~(1 << pwm->pwm_id); rc = pm8xxx_writeb(chip->dev->parent, SSBI_REG_ADDR_LPG_BANK_EN, reg); if (rc) { pr_err("pm8xxx_writeb(): rc=%d (Enable LPG Bank)\n", rc); return rc; } chip->bank_mask = reg; return 0; }
static int pmic8xxx_set_pon1(struct device *dev, u32 debounce_us, bool pull_up) { int err; u32 delay; u8 pon_cntl; if (debounce_us > USEC_PER_SEC * 2 || debounce_us < USEC_PER_SEC / 64) { dev_err(dev, "invalid power key trigger delay\n"); return -EINVAL; } delay = (debounce_us << 6) / USEC_PER_SEC; delay = ilog2(delay); err = pm8xxx_readb(dev->parent, PON_CNTL_1, &pon_cntl); if (err < 0) { dev_err(dev, "failed reading PON_CNTL_1 err=%d\n", err); return err; } pon_cntl &= ~PON_CNTL_TRIG_DELAY_MASK; pon_cntl |= (delay & PON_CNTL_TRIG_DELAY_MASK); if (pull_up) pon_cntl |= PON_CNTL_PULL_UP; else pon_cntl &= ~PON_CNTL_PULL_UP; err = pm8xxx_writeb(dev->parent, PON_CNTL_1, pon_cntl); if (err < 0) { dev_err(dev, "failed writing PON_CNTL_1 err=%d\n", err); return err; } return 0; }
static void led_flash_set(struct pm8xxx_led_data *led, enum led_brightness value) { int rc; u8 level; u16 reg_addr; level = (value << PM8XXX_DRV_FLASH_SHIFT) & PM8XXX_DRV_FLASH_MASK; led->reg &= ~PM8XXX_DRV_FLASH_MASK; led->reg |= level; if (led->id == PM8XXX_ID_FLASH_LED_0) reg_addr = SSBI_REG_ADDR_FLASH_DRV0; else reg_addr = SSBI_REG_ADDR_FLASH_DRV1; rc = pm8xxx_writeb(led->dev->parent, reg_addr, led->reg); if (rc < 0) dev_err(led->cdev.dev, "can't set flash led%d level rc=%d\n", led->id, rc); }
static int pm8821_irq_masked_write(struct pm_irq_chip *chip, u16 addr, u8 mask, u8 val) { int rc; u8 reg; rc = pm8xxx_readb(chip->dev, addr, ®); if (rc) { pr_err("read failed addr = %03X, rc = %d\n", addr, rc); return rc; } reg &= ~mask; reg |= val & mask; rc = pm8xxx_writeb(chip->dev, addr, reg); if (rc) { pr_err("write failed addr = %03X, rc = %d\n", addr, rc); return rc; } return 0; }
static int pm8xxx_pwm_start(struct pwm_device *pwm, int start, int ramp_start) { int rc; u8 reg; if (start) { reg = pwm->pwm_lpg_ctl[0] | PM8XXX_PWM_PWM_START; if (ramp_start) reg |= PM8XXX_PWM_RAMP_GEN_START; else reg &= ~PM8XXX_PWM_RAMP_GEN_START; } else { reg = pwm->pwm_lpg_ctl[0] & ~PM8XXX_PWM_PWM_START; reg &= ~PM8XXX_PWM_RAMP_GEN_START; } rc = pm8xxx_writeb(pwm->chip->dev->parent, SSBI_REG_ADDR_LPG_CTL(0), reg); if (rc) pr_err("pm8xxx_writeb(): rc=%d (Enable PWM Ctl 0)\n", rc); else pwm->pwm_lpg_ctl[0] = reg; return rc; }
int pm8058_mic_bias_enable(bool enable) { int rc = 0; u8 reg; u16 mic_bias_addr = loc_dat->mic_bias_pf->mic_bias_addr; dev_dbg(loc_dat->dev, "%s - %s MIC Bias\n", __func__, enable ? "Enabling" : "Disabling"); LOCK(&loc_dat->lock); if (enable) { if (!loc_dat->mic_bias_enable_counter) { rc = pm8xxx_readb(loc_dat->dev->parent, mic_bias_addr, ®); if (rc < 0) { dev_err(loc_dat->dev, "pm8058 read failed\n"); goto error; } reg &= PM8058_OTHC_EN_SIG_MASK; reg |= (OTHC_SIGNAL_ALWAYS_ON << PM8058_OTHC_EN_SIG_SHIFT); rc = pm8xxx_writeb(loc_dat->dev->parent, mic_bias_addr, reg); if (rc < 0) { dev_err(loc_dat->dev, "pm8058 write failed\n"); goto error; } /*Wait a bit to get basicly stable ADC value*/ msleep(WAIT_MIC_BIAS_VOLTAGE_STABLE_DELAY); } loc_dat->mic_bias_enable_counter++; dev_vdbg(loc_dat->dev, "%s - Increasing MIC_BIAS_COUNTER %u\n", __func__, loc_dat->mic_bias_enable_counter); } else { if (1 <= loc_dat->mic_bias_enable_counter) { if (1 == loc_dat->mic_bias_enable_counter) { rc = pm8xxx_readb(loc_dat->dev->parent, mic_bias_addr, ®); if (rc < 0) { dev_err(loc_dat->dev, "pm8058 read failed\n"); goto error; } reg &= PM8058_OTHC_EN_SIG_MASK; reg |= (OTHC_SIGNAL_OFF << PM8058_OTHC_EN_SIG_SHIFT); rc = pm8xxx_writeb(loc_dat->dev->parent, mic_bias_addr, reg); if (rc < 0) { dev_err(loc_dat->dev, "pm8058 write failed\n"); goto error; } if (!rc) dev_dbg(loc_dat->dev, "%s - MIC Bias disabled\n", __func__); } loc_dat->mic_bias_enable_counter--; dev_vdbg(loc_dat->dev, "%s - Decreasing MIC_BIAS_COUNTER %u\n", __func__, loc_dat->mic_bias_enable_counter); } else { dev_vdbg(loc_dat->dev, "%s - No need to decrease " "MIC_BIAS_COUNTER\n", __func__); } } error: UNLOCK(&loc_dat->lock); if (rc) dev_err(loc_dat->dev, "Unable to toggle MIC Bias\n"); return rc; }
/* * Set an SMPS regulator to be disabled in its CTRL register, but enabled * in the master enable register. Also set it's pull down enable bit. * Take care to make sure that the output voltage doesn't change if switching * from advanced mode to legacy mode. */ static int __pm8058_disable_smps_locally_set_pull_down(struct pm8xxx_misc_chip *chip, u16 ctrl_addr, u16 test2_addr, u16 master_enable_addr, u8 master_enable_bit) { int rc = 0; u8 vref_sel, vlow_sel, band, vprog, bank, reg; bank = PM8058_REGULATOR_BANK_SEL(7); rc = pm8xxx_writeb(chip->dev->parent, test2_addr, bank); if (rc) { pr_err("%s: pm8xxx_writeb(0x%03X) failed: rc=%d\n", __func__, test2_addr, rc); goto done; } rc = pm8xxx_readb(chip->dev->parent, test2_addr, ®); if (rc) { pr_err("%s: FAIL pm8xxx_readb(0x%03X): rc=%d\n", __func__, test2_addr, rc); goto done; } /* Check if in advanced mode. */ if ((reg & PM8058_SMPS_ADVANCED_MODE_MASK) == PM8058_SMPS_ADVANCED_MODE) { /* Determine current output voltage. */ rc = pm8xxx_readb(chip->dev->parent, ctrl_addr, ®); if (rc) { pr_err("%s: FAIL pm8xxx_readb(0x%03X): rc=%d\n", __func__, ctrl_addr, rc); goto done; } band = (reg & PM8058_SMPS_ADVANCED_BAND_MASK) >> PM8058_SMPS_ADVANCED_BAND_SHIFT; switch (band) { case 3: vref_sel = 0; vlow_sel = 0; break; case 2: vref_sel = PM8058_SMPS_LEGACY_VREF_SEL; vlow_sel = 0; break; case 1: vref_sel = PM8058_SMPS_LEGACY_VREF_SEL; vlow_sel = PM8058_SMPS_LEGACY_VLOW_SEL; break; default: pr_err("%s: regulator already disabled\n", __func__); return -EPERM; } vprog = (reg & PM8058_SMPS_ADVANCED_VPROG_MASK); /* Round up if fine step is in use. */ vprog = (vprog + 1) >> 1; if (vprog > PM8058_SMPS_LEGACY_VPROG_MASK) vprog = PM8058_SMPS_LEGACY_VPROG_MASK; /* Set VLOW_SEL bit. */ bank = PM8058_REGULATOR_BANK_SEL(1); rc = pm8xxx_writeb(chip->dev->parent, test2_addr, bank); if (rc) { pr_err("%s: FAIL pm8xxx_writeb(0x%03X): rc=%d\n", __func__, test2_addr, rc); goto done; } rc = pm8xxx_misc_masked_write(chip, test2_addr, PM8058_REGULATOR_BANK_WRITE | PM8058_REGULATOR_BANK_MASK | PM8058_SMPS_LEGACY_VLOW_SEL, PM8058_REGULATOR_BANK_WRITE | PM8058_REGULATOR_BANK_SEL(1) | vlow_sel); if (rc) goto done; /* Switch to legacy mode */ bank = PM8058_REGULATOR_BANK_SEL(7); rc = pm8xxx_writeb(chip->dev->parent, test2_addr, bank); if (rc) { pr_err("%s: FAIL pm8xxx_writeb(0x%03X): rc=%d\n", __func__, test2_addr, rc); goto done; } rc = pm8xxx_misc_masked_write(chip, test2_addr, PM8058_REGULATOR_BANK_WRITE | PM8058_REGULATOR_BANK_MASK | PM8058_SMPS_ADVANCED_MODE_MASK, PM8058_REGULATOR_BANK_WRITE | PM8058_REGULATOR_BANK_SEL(7) | PM8058_SMPS_LEGACY_MODE); if (rc) goto done; /* Enable locally, enable pull down, keep voltage the same. */ rc = pm8xxx_misc_masked_write(chip, ctrl_addr, PM8058_REGULATOR_ENABLE_MASK | PM8058_REGULATOR_PULL_DOWN_MASK | PM8058_SMPS_LEGACY_VREF_SEL | PM8058_SMPS_LEGACY_VPROG_MASK, PM8058_REGULATOR_ENABLE | PM8058_REGULATOR_PULL_DOWN_EN | vref_sel | vprog); if (rc) goto done; }
static void pm8xxx_led_current_set(struct led_classdev *led_cdev, enum led_brightness brightness) { struct pm8xxx_led_data *led = container_of(led_cdev, struct pm8xxx_led_data, cdev); int rc, offset; u8 level; int *pduties; LED_INFO("%s, bank:%d, brightness:%d\n", __func__, led->bank, brightness); cancel_delayed_work_sync(&led->fade_delayed_work); virtual_key_state = brightness; if (flag_hold_virtual_key == 1) { LED_INFO("%s, key control \n", __func__); return; } if(brightness) { level = (led->out_current << PM8XXX_DRV_LED_CTRL_SHIFT) & PM8XXX_DRV_LED_CTRL_MASK; offset = PM8XXX_LED_OFFSET(led->id); led->reg &= ~PM8XXX_DRV_LED_CTRL_MASK; led->reg |= level; rc = pm8xxx_writeb(led->dev->parent, SSBI_REG_ADDR_LED_CTRL(offset), led->reg); if (rc) LED_ERR("%s can't set (%d) led value rc=%d\n", __func__, led->id, rc); if (led->function_flags & LED_BRETH_FUNCTION) { pduties = led->duties; pm8xxx_pwm_lut_config(led->pwm_led, led->period_us, pduties, led->duty_time_ms, led->start_index, led->duites_size, 0, 0, led->lut_flag); pm8xxx_pwm_lut_enable(led->pwm_led, 0); pm8xxx_pwm_lut_enable(led->pwm_led, 1); } else { pwm_config(led->pwm_led, 64000, 64000); pwm_enable(led->pwm_led); } } else { if (led->function_flags & LED_BRETH_FUNCTION) { pduties = led->duties + led->duites_size; pm8xxx_pwm_lut_config(led->pwm_led, led->period_us, pduties, led->duty_time_ms, led->start_index, led->duites_size, 0, 0, led->lut_flag); pm8xxx_pwm_lut_enable(led->pwm_led, 0); pm8xxx_pwm_lut_enable(led->pwm_led, 1); queue_delayed_work(g_led_work_queue, &led->fade_delayed_work, msecs_to_jiffies(led->duty_time_ms*led->duites_size)); } else { pwm_disable(led->pwm_led); level = (0 << PM8XXX_DRV_LED_CTRL_SHIFT) & PM8XXX_DRV_LED_CTRL_MASK; offset = PM8XXX_LED_OFFSET(led->id); led->reg &= ~PM8XXX_DRV_LED_CTRL_MASK; led->reg |= level; rc = pm8xxx_writeb(led->dev->parent, SSBI_REG_ADDR_LED_CTRL(offset), led->reg); if (rc) LED_ERR("%s can't set (%d) led value rc=%d\n", __func__, led->id, rc); } } }
static ssize_t pm8xxx_led_blink_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct led_classdev *led_cdev; struct pm8xxx_led_data *ldata; int val; int level, offset; int led_is_green; val = -1; sscanf(buf, "%u", &val); if (val < 0 || val > 255) return -EINVAL; current_blink= val; led_cdev = (struct led_classdev *) dev_get_drvdata(dev); ldata = container_of(led_cdev, struct pm8xxx_led_data, cdev); LED_INFO("%s: bank %d blink %d sync %d\n", __func__, ldata->bank, val, ldata->led_sync); printk("%s: [BB] bank %d blink %d sync %d\n", __func__, ldata->bank, val, ldata->led_sync); if (!strcmp(ldata->cdev.name, "green")) { led_is_green = 1; } if (!strcmp(ldata->cdev.name, "amber")) { led_is_green = 0; } switch (val) { case BLINK_STOP: if (ldata->gpio_status_switch != NULL) ldata->gpio_status_switch(0); pwm_disable(ldata->pwm_led); if(ldata->led_sync) { if (!strcmp(ldata->cdev.name, "green")) { if (green_back_led_data->gpio_status_switch != NULL) green_back_led_data->gpio_status_switch(0); pwm_disable(green_back_led_data->pwm_led); } if (!strcmp(ldata->cdev.name, "amber")) { if (amber_back_led_data->gpio_status_switch != NULL) amber_back_led_data->gpio_status_switch(0); pwm_disable(amber_back_led_data->pwm_led); } } if (blink_buttons > 0) { if (led_is_green == 1) { green_blink_value = 0; } else { amber_blink_value = 0; } pm8xxx_buttons_blink(0); } break; case BLINK_UNCHANGE: pwm_disable(ldata->pwm_led); if (led_cdev->brightness) { if (ldata->gpio_status_switch != NULL) ldata->gpio_status_switch(1); pwm_config(ldata->pwm_led, 6400 * ldata->pwm_coefficient / 100, 6400); pwm_enable(ldata->pwm_led); if(ldata->led_sync) { if (!strcmp(ldata->cdev.name, "green")) { if (green_back_led_data->gpio_status_switch != NULL) green_back_led_data->gpio_status_switch(1); pwm_config(green_back_led_data->pwm_led, 64000, 64000); pwm_enable(green_back_led_data->pwm_led); } if (!strcmp(ldata->cdev.name, "amber")) { if (amber_back_led_data->gpio_status_switch != NULL) amber_back_led_data->gpio_status_switch(1); pwm_config(amber_back_led_data->pwm_led, 64000, 64000); pwm_enable(amber_back_led_data->pwm_led); } } if (blink_buttons > 0 && val > 0) { if (led_is_green == 1) { green_blink_value = 1; } else { amber_blink_value = 1; } pm8xxx_buttons_blink(1); } } else { pwm_disable(ldata->pwm_led); if (ldata->gpio_status_switch != NULL) ldata->gpio_status_switch(0); if(ldata->led_sync) { if (!strcmp(ldata->cdev.name, "green")){ if (green_back_led_data->gpio_status_switch != NULL) green_back_led_data->gpio_status_switch(0); pwm_disable(green_back_led_data->pwm_led); level = ( 0 << PM8XXX_DRV_LED_CTRL_SHIFT) & PM8XXX_DRV_LED_CTRL_MASK; offset = PM8XXX_LED_OFFSET(green_back_led_data->id); green_back_led_data->reg &= ~PM8XXX_DRV_LED_CTRL_MASK; green_back_led_data->reg |= level; pm8xxx_writeb(green_back_led_data->dev->parent, SSBI_REG_ADDR_LED_CTRL(offset), green_back_led_data->reg); } if (!strcmp(ldata->cdev.name, "amber")){ if (amber_back_led_data->gpio_status_switch != NULL) amber_back_led_data->gpio_status_switch(0); pwm_disable(amber_back_led_data->pwm_led); level = ( 0 << PM8XXX_DRV_LED_CTRL_SHIFT) & PM8XXX_DRV_LED_CTRL_MASK; offset = PM8XXX_LED_OFFSET(amber_back_led_data->id); amber_back_led_data->reg &= ~PM8XXX_DRV_LED_CTRL_MASK; amber_back_led_data->reg |= level; pm8xxx_writeb(amber_back_led_data->dev->parent, SSBI_REG_ADDR_LED_CTRL(offset), amber_back_led_data->reg); } } if (blink_buttons > 0) { if (led_is_green == 1) { green_blink_value = 0; } else { amber_blink_value = 0; } pm8xxx_buttons_blink(0); } } break; case BLINK_64MS_PER_2SEC: if (ldata->gpio_status_switch != NULL) ldata->gpio_status_switch(1); pwm_disable(ldata->pwm_led); pwm_config(ldata->pwm_led, ldata->blink_duty_per_2sec, 2000000); pwm_enable(ldata->pwm_led); if(ldata->led_sync) { if (!strcmp(ldata->cdev.name, "green")) { if (green_back_led_data->gpio_status_switch != NULL) green_back_led_data->gpio_status_switch(1); pwm_disable(green_back_led_data->pwm_led); pwm_config(green_back_led_data->pwm_led, ldata->blink_duty_per_2sec, 2000000); pwm_enable(green_back_led_data->pwm_led); } if (!strcmp(ldata->cdev.name, "amber")) { if (amber_back_led_data->gpio_status_switch != NULL) amber_back_led_data->gpio_status_switch(1); pwm_disable(amber_back_led_data->pwm_led); pwm_config(amber_back_led_data->pwm_led, ldata->blink_duty_per_2sec, 2000000); pwm_enable(amber_back_led_data->pwm_led); } } if (blink_buttons > 0 && val > 0) { if (led_is_green == 1) { green_blink_value = 1; } else { amber_blink_value = 1; } pm8xxx_buttons_blink(1); } break; case BLINK_64MS_ON_310MS_PER_2SEC: cancel_delayed_work_sync(&ldata->blink_delayed_work); pwm_disable(ldata->pwm_led); ldata->duty_time_ms = 64; ldata->period_us = 2000000; if(ldata->led_sync) { if (!strcmp(ldata->cdev.name, "green")) { pwm_disable(green_back_led_data->pwm_led); green_back_led_data->duty_time_ms = 64; green_back_led_data->period_us = 2000000; } if (!strcmp(ldata->cdev.name, "amber")) { pwm_disable(amber_back_led_data->pwm_led); amber_back_led_data->duty_time_ms = 64; amber_back_led_data->period_us = 2000000; } } queue_delayed_work(g_led_work_queue, &ldata->blink_delayed_work, msecs_to_jiffies(310)); break; case BLINK_64MS_ON_2SEC_PER_2SEC: cancel_delayed_work_sync(&ldata->blink_delayed_work); pwm_disable(ldata->pwm_led); ldata->duty_time_ms = 64; ldata->period_us = 2000000; if(ldata->led_sync) { if (!strcmp(ldata->cdev.name, "green")) { pwm_disable(green_back_led_data->pwm_led); green_back_led_data->duty_time_ms = 64; green_back_led_data->period_us = 2000000; } if (!strcmp(ldata->cdev.name, "amber")) { pwm_disable(amber_back_led_data->pwm_led); amber_back_led_data->duty_time_ms = 64; amber_back_led_data->period_us = 2000000; } } queue_delayed_work(g_led_work_queue, &ldata->blink_delayed_work, msecs_to_jiffies(1000)); break; case BLINK_1SEC_PER_2SEC: pwm_disable(ldata->pwm_led); pwm_config(ldata->pwm_led, 1000000, 2000000); pwm_enable(ldata->pwm_led); if(ldata->led_sync) { if (!strcmp(ldata->cdev.name, "green")) { pwm_disable(green_back_led_data->pwm_led); pwm_config(green_back_led_data->pwm_led, 1000000, 2000000); pwm_enable(green_back_led_data->pwm_led); } if (!strcmp(ldata->cdev.name, "amber")) { pwm_disable(amber_back_led_data->pwm_led); pwm_config(amber_back_led_data->pwm_led, 1000000, 2000000); pwm_enable(amber_back_led_data->pwm_led); } } break; default: LED_ERR("%s: bank %d did not support blink type %d\n", __func__, ldata->bank, val); return -EINVAL; } return count; }
static void pm8xxx_led_gpio_set(struct led_classdev *led_cdev, enum led_brightness brightness) { int rc, offset; u8 level; struct pm8xxx_led_data *led = container_of(led_cdev, struct pm8xxx_led_data, cdev); LED_INFO("%s, bank:%d, brightness:%d sync: %d\n", __func__, led->bank, brightness, led->led_sync); if (led->gpio_status_switch != NULL) led->gpio_status_switch(0); pwm_disable(led->pwm_led); if(led->led_sync) { if (!strcmp(led->cdev.name, "green")){ if (green_back_led_data->gpio_status_switch != NULL) green_back_led_data->gpio_status_switch(0); pwm_disable(green_back_led_data->pwm_led); level = ( 0 << PM8XXX_DRV_LED_CTRL_SHIFT) & PM8XXX_DRV_LED_CTRL_MASK; offset = PM8XXX_LED_OFFSET(green_back_led_data->id); green_back_led_data->reg &= ~PM8XXX_DRV_LED_CTRL_MASK; green_back_led_data->reg |= level; rc = pm8xxx_writeb(green_back_led_data->dev->parent, SSBI_REG_ADDR_LED_CTRL(offset), green_back_led_data->reg); } if (!strcmp(led->cdev.name, "amber")){ if (amber_back_led_data->gpio_status_switch != NULL) amber_back_led_data->gpio_status_switch(0); pwm_disable(amber_back_led_data->pwm_led); level = ( 0 << PM8XXX_DRV_LED_CTRL_SHIFT) & PM8XXX_DRV_LED_CTRL_MASK; offset = PM8XXX_LED_OFFSET(amber_back_led_data->id); amber_back_led_data->reg &= ~PM8XXX_DRV_LED_CTRL_MASK; amber_back_led_data->reg |= level; rc = pm8xxx_writeb(amber_back_led_data->dev->parent, SSBI_REG_ADDR_LED_CTRL(offset), amber_back_led_data->reg); } } if (brightness) { if (led->gpio_status_switch != NULL) led->gpio_status_switch(1); pwm_config(led->pwm_led, 6400 * led->pwm_coefficient / 100, 6400); pwm_enable(led->pwm_led); if(led->led_sync) { if (!strcmp(led->cdev.name, "green")) { if (green_back_led_data->gpio_status_switch != NULL) green_back_led_data->gpio_status_switch(1); level = (green_back_led_data->out_current << PM8XXX_DRV_LED_CTRL_SHIFT) & PM8XXX_DRV_LED_CTRL_MASK; offset = PM8XXX_LED_OFFSET(green_back_led_data->id); green_back_led_data->reg &= ~PM8XXX_DRV_LED_CTRL_MASK; green_back_led_data->reg |= level; rc = pm8xxx_writeb(green_back_led_data->dev->parent, SSBI_REG_ADDR_LED_CTRL(offset), green_back_led_data->reg); pwm_config(green_back_led_data->pwm_led, 64000, 64000); pwm_enable(green_back_led_data->pwm_led); } if (!strcmp(led->cdev.name, "amber")) { if (amber_back_led_data->gpio_status_switch != NULL) amber_back_led_data->gpio_status_switch(1); level = (amber_back_led_data->out_current << PM8XXX_DRV_LED_CTRL_SHIFT) & PM8XXX_DRV_LED_CTRL_MASK; offset = PM8XXX_LED_OFFSET(amber_back_led_data->id); amber_back_led_data->reg &= ~PM8XXX_DRV_LED_CTRL_MASK; amber_back_led_data->reg |= level; rc = pm8xxx_writeb(amber_back_led_data->dev->parent, SSBI_REG_ADDR_LED_CTRL(offset), amber_back_led_data->reg); pwm_config(amber_back_led_data->pwm_led, 64000, 64000); pwm_enable(amber_back_led_data->pwm_led); } } } }
static int __devinit pmic8xxx_pwrkey_probe(struct platform_device *pdev) { struct input_dev *pwr; int key_release_irq = platform_get_irq(pdev, 0); int key_press_irq = platform_get_irq(pdev, 1); int err; unsigned int delay; u8 pon_cntl; struct pmic8xxx_pwrkey *pwrkey; const struct pm8xxx_pwrkey_platform_data *pdata = dev_get_platdata(&pdev->dev); if (!pdata) { dev_err(&pdev->dev, "power key platform data not supplied\n"); return -EINVAL; } if (pdata->kpd_trigger_delay_us > 62500) { dev_err(&pdev->dev, "invalid power key trigger delay\n"); return -EINVAL; } pwrkey = kzalloc(sizeof(*pwrkey), GFP_KERNEL); if (!pwrkey) return -ENOMEM; pwr = input_allocate_device(); if (!pwr) { dev_dbg(&pdev->dev, "Can't allocate power button\n"); err = -ENOMEM; goto free_pwrkey; } input_set_capability(pwr, EV_KEY, KEY_POWER); pwr->name = "pmic8xxx_pwrkey"; pwr->phys = "pmic8xxx_pwrkey/input0"; pwr->dev.parent = &pdev->dev; delay = (pdata->kpd_trigger_delay_us << 10) / USEC_PER_SEC; delay = 1 + ilog2(delay); err = pm8xxx_readb(pdev->dev.parent, PON_CNTL_1, &pon_cntl); if (err < 0) { dev_err(&pdev->dev, "failed reading PON_CNTL_1 err=%d\n", err); goto free_input_dev; } pon_cntl &= ~PON_CNTL_TRIG_DELAY_MASK; pon_cntl |= (delay & PON_CNTL_TRIG_DELAY_MASK); if (pdata->pull_up) pon_cntl |= PON_CNTL_PULL_UP; else pon_cntl &= ~PON_CNTL_PULL_UP; err = pm8xxx_writeb(pdev->dev.parent, PON_CNTL_1, pon_cntl); if (err < 0) { dev_err(&pdev->dev, "failed writing PON_CNTL_1 err=%d\n", err); goto free_input_dev; } err = input_register_device(pwr); if (err) { dev_dbg(&pdev->dev, "Can't register power key: %d\n", err); goto free_input_dev; } pwrkey->key_press_irq = key_press_irq; pwrkey->pwr = pwr; #ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_SWEEP2WAKE sweep2wake_setdev(pwr); #endif platform_set_drvdata(pdev, pwrkey); platform_set_drvdata(pdev, pwrkey); err = request_irq(key_press_irq, pwrkey_press_irq, IRQF_TRIGGER_RISING, "pmic8xxx_pwrkey_press", pwrkey); if (err < 0) { dev_dbg(&pdev->dev, "Can't get %d IRQ for pwrkey: %d\n", key_press_irq, err); goto unreg_input_dev; } err = request_irq(key_release_irq, pwrkey_release_irq, IRQF_TRIGGER_RISING, "pmic8xxx_pwrkey_release", pwrkey); if (err < 0) { dev_dbg(&pdev->dev, "Can't get %d IRQ for pwrkey: %d\n", key_release_irq, err); goto free_press_irq; } device_init_wakeup(&pdev->dev, pdata->wakeup); return 0; free_press_irq: free_irq(key_press_irq, NULL); unreg_input_dev: platform_set_drvdata(pdev, NULL); input_unregister_device(pwr); pwr = NULL; free_input_dev: input_free_device(pwr); free_pwrkey: kfree(pwrkey); return err; }
static int __devinit pmic8xxx_pwrkey_probe(struct platform_device *pdev) { struct input_dev *pwr; int key_release_irq = platform_get_irq(pdev, 0); int key_press_irq = platform_get_irq(pdev, 1); int err; unsigned int delay; u8 pon_cntl; struct pmic8xxx_pwrkey *pwrkey; const struct pm8xxx_pwrkey_platform_data *pdata = dev_get_platdata(&pdev->dev); if (!pdata) { dev_err(&pdev->dev, "power key platform data not supplied\n"); return -EINVAL; } /* Valid range of pwr key trigger delay is 1/64 sec to 2 seconds. */ if (pdata->kpd_trigger_delay_us > USEC_PER_SEC * 2 || pdata->kpd_trigger_delay_us < USEC_PER_SEC / 64) { dev_err(&pdev->dev, "invalid power key trigger delay\n"); return -EINVAL; } pwrkey = kzalloc(sizeof(*pwrkey), GFP_KERNEL); if (!pwrkey) return -ENOMEM; pwrkey->pdata = pdata; pwr = input_allocate_device(); if (!pwr) { dev_dbg(&pdev->dev, "Can't allocate power button\n"); err = -ENOMEM; goto free_pwrkey; } input_set_capability(pwr, EV_KEY, KEY_POWER); pwr->name = "pmic8xxx_pwrkey"; pwr->phys = "pmic8xxx_pwrkey/input0"; pwr->dev.parent = &pdev->dev; delay = (pdata->kpd_trigger_delay_us << 6) / USEC_PER_SEC; delay = ilog2(delay); err = pm8xxx_readb(pdev->dev.parent, PON_CNTL_1, &pon_cntl); if (err < 0) { dev_err(&pdev->dev, "failed reading PON_CNTL_1 err=%d\n", err); goto free_input_dev; } pon_cntl &= ~PON_CNTL_TRIG_DELAY_MASK; pon_cntl |= (delay & PON_CNTL_TRIG_DELAY_MASK); if (pdata->pull_up) pon_cntl |= PON_CNTL_PULL_UP; else pon_cntl &= ~PON_CNTL_PULL_UP; err = pm8xxx_writeb(pdev->dev.parent, PON_CNTL_1, pon_cntl); if (err < 0) { dev_err(&pdev->dev, "failed writing PON_CNTL_1 err=%d\n", err); goto free_input_dev; } err = input_register_device(pwr); if (err) { dev_dbg(&pdev->dev, "Can't register power key: %d\n", err); goto free_input_dev; } pwrkey->key_press_irq = key_press_irq; pwrkey->key_release_irq = key_release_irq; pwrkey->pwr = pwr; platform_set_drvdata(pdev, pwrkey); /* check power key status during boot */ err = pm8xxx_read_irq_stat(pdev->dev.parent, key_press_irq); if (err < 0) { dev_err(&pdev->dev, "reading irq status failed\n"); goto unreg_input_dev; } pwrkey->press = !!err; if (pwrkey->press) { input_report_key(pwrkey->pwr, KEY_POWER, 1); input_sync(pwrkey->pwr); } #ifdef CONFIG_TOUCHSCREEN_PREVENT_SLEEP #ifdef CONFIG_TOUCHSCREEN_SWEEP2WAKE pr_info("[wake_up_display]: set device %s\n", pwr->name); #else power_on_display_dt2w(pwr); pr_info("[wake_up_display]: set device %s\n", pwr->name); #endif #endif err = request_any_context_irq(key_press_irq, pwrkey_press_irq, IRQF_TRIGGER_RISING, "pmic8xxx_pwrkey_press", pwrkey); if (err < 0) { dev_dbg(&pdev->dev, "Can't get %d IRQ for pwrkey: %d\n", key_press_irq, err); goto unreg_input_dev; } err = request_any_context_irq(key_release_irq, pwrkey_release_irq, IRQF_TRIGGER_RISING, "pmic8xxx_pwrkey_release", pwrkey); if (err < 0) { dev_dbg(&pdev->dev, "Can't get %d IRQ for pwrkey: %d\n", key_release_irq, err); goto free_press_irq; } device_init_wakeup(&pdev->dev, pdata->wakeup); return 0; free_press_irq: free_irq(key_press_irq, NULL); unreg_input_dev: platform_set_drvdata(pdev, NULL); input_unregister_device(pwr); pwr = NULL; free_input_dev: input_free_device(pwr); free_pwrkey: kfree(pwrkey); return err; }
extern void pm8xxx_led_current_set(struct led_classdev *led_cdev, enum led_brightness brightness) { struct pm8xxx_led_data *led = container_of(led_cdev, struct pm8xxx_led_data, cdev); int rc, offset; u8 level; int *pduties; LED_INFO("%s, bank:%d, brightness:%d\n", __func__, led->bank, brightness); cancel_delayed_work_sync(&led->fade_delayed_work); virtual_key_state = brightness; if (flag_hold_virtual_key == 1) { LED_INFO("%s, key control \n", __func__); return; } if(brightness) { level = (led->out_current << PM8XXX_DRV_LED_CTRL_SHIFT) & PM8XXX_DRV_LED_CTRL_MASK; offset = PM8XXX_LED_OFFSET(led->id); led->reg &= ~PM8XXX_DRV_LED_CTRL_MASK; led->reg |= level; rc = pm8xxx_writeb(led->dev->parent, SSBI_REG_ADDR_LED_CTRL(offset), led->reg); if (rc) LED_ERR("%s can't set (%d) led value rc=%d\n", __func__, led->id, rc); if (led->function_flags & LED_BRETH_FUNCTION) { pduties = led->duties; pm8xxx_pwm_lut_config(led->pwm_led, led->period_us, pduties, led->duty_time_ms, led->start_index, led->duites_size, 0, 0, led->lut_flag); pm8xxx_pwm_lut_enable(led->pwm_led, 0); pm8xxx_pwm_lut_enable(led->pwm_led, 1); } else { pwm_config(led->pwm_led, 64000, 64000); pwm_enable(led->pwm_led); } } else { if (led->function_flags & LED_BRETH_FUNCTION) { wake_lock_timeout(&pmic_led_wake_lock, HZ*2); pduties = led->duties + led->duites_size; pm8xxx_pwm_lut_config(led->pwm_led, led->period_us, pduties, led->duty_time_ms, led->start_index, led->duites_size, 0, 0, led->lut_flag); pm8xxx_pwm_lut_enable(led->pwm_led, 0); pm8xxx_pwm_lut_enable(led->pwm_led, 1); queue_delayed_work(g_led_work_queue, &led->fade_delayed_work, msecs_to_jiffies(led->duty_time_ms*led->duites_size)); } else { pwm_disable(led->pwm_led); level = (0 << PM8XXX_DRV_LED_CTRL_SHIFT) & PM8XXX_DRV_LED_CTRL_MASK; offset = PM8XXX_LED_OFFSET(led->id); led->reg &= ~PM8XXX_DRV_LED_CTRL_MASK; led->reg |= level; rc = pm8xxx_writeb(led->dev->parent, SSBI_REG_ADDR_LED_CTRL(offset), led->reg); if (rc) LED_ERR("%s can't set (%d) led value rc=%d\n", __func__, led->id, rc); } } // checking for buttons device if (led_cdev_buttons == led_cdev) { printk("[BB] led_current_set %d \n", brightness); if (brightness>0) { // screen turning off together with buttons led buttons_turning_on_with_screen_on = 1; } else { // screen turning off together without buttons led buttons_turning_on_with_screen_on = 0; } } // no blink needed pm8xxx_led_current_set_flagged( led_cdev, brightness, 0); }
static int __devinit pmic8xxx_pwrkey_probe(struct platform_device *pdev) { struct input_dev *pwr; int key_release_irq = platform_get_irq(pdev, 0); int key_press_irq = platform_get_irq(pdev, 1); int err; unsigned int delay; u8 pon_cntl; struct pmic8xxx_pwrkey *pwrkey; const struct pm8xxx_pwrkey_platform_data *pdata = dev_get_platdata(&pdev->dev); if (!pdata) { dev_err(&pdev->dev, "power key platform data not supplied\n"); return -EINVAL; } /* Valid range of pwr key trigger delay is 1/64 sec to 2 seconds. */ if (pdata->kpd_trigger_delay_us > USEC_PER_SEC * 2 || pdata->kpd_trigger_delay_us < USEC_PER_SEC / 64) { dev_err(&pdev->dev, "invalid power key trigger delay\n"); return -EINVAL; } pwrkey = kzalloc(sizeof(*pwrkey), GFP_KERNEL); if (!pwrkey) return -ENOMEM; init_timer(&pwrkey->hibernate_timer); pwrkey->hibernate_timer.data = (unsigned long)pwrkey; pwrkey->hibernate_timer.function = hibernate_timer_handle; pwrkey->pdata = pdata; pwr = input_allocate_device(); if (!pwr) { dev_dbg(&pdev->dev, "Can't allocate power button\n"); err = -ENOMEM; goto free_pwrkey; } input_set_capability(pwr, EV_KEY, KEY_POWER); pwr->name = "pmic8xxx_pwrkey"; pwr->phys = "pmic8xxx_pwrkey/input0"; pwr->dev.parent = &pdev->dev; delay = (pdata->kpd_trigger_delay_us << 6) / USEC_PER_SEC; delay = ilog2(delay); err = pm8xxx_readb(pdev->dev.parent, PON_CNTL_1, &pon_cntl); if (err < 0) { dev_err(&pdev->dev, "failed reading PON_CNTL_1 err=%d\n", err); goto free_input_dev; } pon_cntl &= ~PON_CNTL_TRIG_DELAY_MASK; pon_cntl |= (delay & PON_CNTL_TRIG_DELAY_MASK); if (pdata->pull_up) pon_cntl |= PON_CNTL_PULL_UP; else pon_cntl &= ~PON_CNTL_PULL_UP; err = pm8xxx_writeb(pdev->dev.parent, PON_CNTL_1, pon_cntl); if (err < 0) { dev_err(&pdev->dev, "failed writing PON_CNTL_1 err=%d\n", err); goto free_input_dev; } err = input_register_device(pwr); if (err) { dev_dbg(&pdev->dev, "Can't register power key: %d\n", err); goto free_input_dev; } pwrkey->key_press_irq = key_press_irq; pwrkey->pwr = pwr; platform_set_drvdata(pdev, pwrkey); the_pwrkey = pwrkey; err = request_any_context_irq(key_press_irq, pwrkey_press_irq, IRQF_TRIGGER_RISING, "pmic8xxx_pwrkey_press", pwrkey); if (err < 0) { dev_dbg(&pdev->dev, "Can't get %d IRQ for pwrkey: %d\n", key_press_irq, err); goto unreg_input_dev; } err = request_any_context_irq(key_release_irq, pwrkey_release_irq, IRQF_TRIGGER_RISING, "pmic8xxx_pwrkey_release", pwrkey); if (err < 0) { dev_dbg(&pdev->dev, "Can't get %d IRQ for pwrkey: %d\n", key_release_irq, err); goto free_press_irq; } device_init_wakeup(&pdev->dev, pdata->wakeup); return 0; free_press_irq: free_irq(key_press_irq, NULL); unreg_input_dev: platform_set_drvdata(pdev, NULL); input_unregister_device(pwr); pwr = NULL; free_input_dev: input_free_device(pwr); free_pwrkey: kfree(pwrkey); return err; }
static void pm8xxx_led_current_set_flagged(struct led_classdev *led_cdev, enum led_brightness brightness, int blink) { struct pm8xxx_led_data *led = container_of(led_cdev, struct pm8xxx_led_data, cdev); int rc, offset; u8 level; int *pduties; LED_INFO("%s, bank:%d, brightness:%d\n", __func__, led->bank, brightness); cancel_delayed_work_sync(&led->fade_delayed_work); virtual_key_state = brightness; if (flag_hold_virtual_key == 1) { LED_INFO("%s, key control \n", __func__); return; } if(brightness) { level = (led->out_current << PM8XXX_DRV_LED_CTRL_SHIFT) & PM8XXX_DRV_LED_CTRL_MASK; offset = PM8XXX_LED_OFFSET(led->id); led->reg &= ~PM8XXX_DRV_LED_CTRL_MASK; led->reg |= level; rc = pm8xxx_writeb(led->dev->parent, SSBI_REG_ADDR_LED_CTRL(offset), led->reg); if (rc) LED_ERR("%s can't set (%d) led value rc=%d\n", __func__, led->id, rc); if (led->function_flags & LED_BRETH_FUNCTION) { if (blink == 0) { buttons_led_is_on = 1; // no blink needed pduties = &dutys_array[0]; pm8xxx_pwm_lut_config(led->pwm_led, led->period_us, pduties, led->duty_time_ms, led->start_index, led->duites_size, 0, 0, led->lut_flag); } else { pduties = &dutys_array[0]; // LUT_LOOP for blinking pm8xxx_pwm_lut_config(led->pwm_led, led->period_us, pduties, led->duty_time_ms, // slower, 2x led->start_index, led->duites_size * 8, // 16 duty entries -> original size * 2, + 6 * 8 zeroes for pause 0, 0, PM_PWM_LUT_LOOP | PM_PWM_LUT_PAUSE_HI_EN); } pm8xxx_pwm_lut_enable(led->pwm_led, 0); pm8xxx_pwm_lut_enable(led->pwm_led, 1); } else { pwm_config(led->pwm_led, 6400 * led->pwm_coefficient / 100, 6400); pwm_enable(led->pwm_led); } } else { if (led->function_flags & LED_BRETH_FUNCTION) { buttons_led_is_on = 0; wake_lock_timeout(&pmic_led_wake_lock, HZ*2); pduties = &dutys_array[8]; pm8xxx_pwm_lut_config(led->pwm_led, led->period_us, pduties, led->duty_time_ms, led->start_index, led->duites_size, 0, 0, led->lut_flag); pm8xxx_pwm_lut_enable(led->pwm_led, 0); pm8xxx_pwm_lut_enable(led->pwm_led, 1); queue_delayed_work(g_led_work_queue, &led->fade_delayed_work, msecs_to_jiffies(led->duty_time_ms*led->duites_size)); } else { pwm_disable(led->pwm_led); level = (0 << PM8XXX_DRV_LED_CTRL_SHIFT) & PM8XXX_DRV_LED_CTRL_MASK; offset = PM8XXX_LED_OFFSET(led->id); led->reg &= ~PM8XXX_DRV_LED_CTRL_MASK; led->reg |= level; rc = pm8xxx_writeb(led->dev->parent, SSBI_REG_ADDR_LED_CTRL(offset), led->reg); if (rc) LED_ERR("%s can't set (%d) led value rc=%d\n", __func__, led->id, rc); } } }
static int __pm8058_disable_smps_locally_set_pull_down(struct pm8xxx_misc_chip *chip, u16 ctrl_addr, u16 test2_addr, u16 master_enable_addr, u8 master_enable_bit) { int rc = 0; u8 vref_sel, vlow_sel, band, vprog, bank, reg; bank = PM8058_REGULATOR_BANK_SEL(7); rc = pm8xxx_writeb(chip->dev->parent, test2_addr, bank); if (rc) { pr_err("%s: pm8xxx_writeb(0x%03X) failed: rc=%d\n", __func__, test2_addr, rc); goto done; } rc = pm8xxx_readb(chip->dev->parent, test2_addr, ®); if (rc) { pr_err("%s: FAIL pm8xxx_readb(0x%03X): rc=%d\n", __func__, test2_addr, rc); goto done; } if ((reg & PM8058_SMPS_ADVANCED_MODE_MASK) == PM8058_SMPS_ADVANCED_MODE) { rc = pm8xxx_readb(chip->dev->parent, ctrl_addr, ®); if (rc) { pr_err("%s: FAIL pm8xxx_readb(0x%03X): rc=%d\n", __func__, ctrl_addr, rc); goto done; } band = (reg & PM8058_SMPS_ADVANCED_BAND_MASK) >> PM8058_SMPS_ADVANCED_BAND_SHIFT; switch (band) { case 3: vref_sel = 0; vlow_sel = 0; break; case 2: vref_sel = PM8058_SMPS_LEGACY_VREF_SEL; vlow_sel = 0; break; case 1: vref_sel = PM8058_SMPS_LEGACY_VREF_SEL; vlow_sel = PM8058_SMPS_LEGACY_VLOW_SEL; break; default: pr_err("%s: regulator already disabled\n", __func__); return -EPERM; } vprog = (reg & PM8058_SMPS_ADVANCED_VPROG_MASK); vprog = (vprog + 1) >> 1; if (vprog > PM8058_SMPS_LEGACY_VPROG_MASK) vprog = PM8058_SMPS_LEGACY_VPROG_MASK; bank = PM8058_REGULATOR_BANK_SEL(1); rc = pm8xxx_writeb(chip->dev->parent, test2_addr, bank); if (rc) { pr_err("%s: FAIL pm8xxx_writeb(0x%03X): rc=%d\n", __func__, test2_addr, rc); goto done; } rc = pm8xxx_misc_masked_write(chip, test2_addr, PM8058_REGULATOR_BANK_WRITE | PM8058_REGULATOR_BANK_MASK | PM8058_SMPS_LEGACY_VLOW_SEL, PM8058_REGULATOR_BANK_WRITE | PM8058_REGULATOR_BANK_SEL(1) | vlow_sel); if (rc) goto done; bank = PM8058_REGULATOR_BANK_SEL(7); rc = pm8xxx_writeb(chip->dev->parent, test2_addr, bank); if (rc) { pr_err("%s: FAIL pm8xxx_writeb(0x%03X): rc=%d\n", __func__, test2_addr, rc); goto done; } rc = pm8xxx_misc_masked_write(chip, test2_addr, PM8058_REGULATOR_BANK_WRITE | PM8058_REGULATOR_BANK_MASK | PM8058_SMPS_ADVANCED_MODE_MASK, PM8058_REGULATOR_BANK_WRITE | PM8058_REGULATOR_BANK_SEL(7) | PM8058_SMPS_LEGACY_MODE); if (rc) goto done; rc = pm8xxx_misc_masked_write(chip, ctrl_addr, PM8058_REGULATOR_ENABLE_MASK | PM8058_REGULATOR_PULL_DOWN_MASK | PM8058_SMPS_LEGACY_VREF_SEL | PM8058_SMPS_LEGACY_VPROG_MASK, PM8058_REGULATOR_ENABLE | PM8058_REGULATOR_PULL_DOWN_EN | vref_sel | vprog); if (rc) goto done; }
static int __devinit pmic8xxx_pwrkey_probe(struct platform_device *pdev) { struct input_dev *pwr; int key_release_irq = platform_get_irq(pdev, 0); int key_press_irq = platform_get_irq(pdev, 1); int err; unsigned int delay; u8 pon_cntl; int ret; struct pmic8xxx_pwrkey *pwrkey; struct device *sec_powerkey; const struct pm8xxx_pwrkey_platform_data *pdata = dev_get_platdata(&pdev->dev); if (!pdata) { dev_err(&pdev->dev, "power key platform data not supplied\n"); return -EINVAL; } /* Valid range of pwr key trigger delay is 1/64 sec to 2 seconds. */ if (pdata->kpd_trigger_delay_us > USEC_PER_SEC * 2 || pdata->kpd_trigger_delay_us < USEC_PER_SEC / 64) { dev_err(&pdev->dev, "invalid power key trigger delay\n"); return -EINVAL; } pwrkey = kzalloc(sizeof(*pwrkey), GFP_KERNEL); if (!pwrkey) return -ENOMEM; pwrkey->pdata = pdata; pwr = input_allocate_device(); if (!pwr) { dev_dbg(&pdev->dev, "Can't allocate power button\n"); err = -ENOMEM; goto free_pwrkey; } input_set_capability(pwr, EV_KEY, KEY_POWER); pwr->name = "pmic8xxx_pwrkey"; pwr->phys = "pmic8xxx_pwrkey/input0"; pwr->dev.parent = &pdev->dev; delay = (pdata->kpd_trigger_delay_us << 6) / USEC_PER_SEC; delay = ilog2(delay); err = pm8xxx_readb(pdev->dev.parent, PON_CNTL_1, &pon_cntl); if (err < 0) { dev_err(&pdev->dev, "failed reading PON_CNTL_1 err=%d\n", err); goto free_input_dev; } pon_cntl &= ~PON_CNTL_TRIG_DELAY_MASK; pon_cntl |= (delay & PON_CNTL_TRIG_DELAY_MASK); if (pdata->pull_up) pon_cntl |= PON_CNTL_PULL_UP; else pon_cntl &= ~PON_CNTL_PULL_UP; err = pm8xxx_writeb(pdev->dev.parent, PON_CNTL_1, pon_cntl); if (err < 0) { dev_err(&pdev->dev, "failed writing PON_CNTL_1 err=%d\n", err); goto free_input_dev; } err = input_register_device(pwr); if (err) { dev_dbg(&pdev->dev, "Can't register power key: %d\n", err); goto free_input_dev; } pwrkey->key_press_irq = key_press_irq; pwrkey->key_release_irq = key_release_irq; pwrkey->pwr = pwr; platform_set_drvdata(pdev, pwrkey); if (poweroff_charging) wake_lock_init(&pwrkey->wake_lock, WAKE_LOCK_SUSPEND, "pmic_pwrkey"); /* check power key status during boot */ err = pm8xxx_read_irq_stat(pdev->dev.parent, key_press_irq); if (err < 0) { dev_err(&pdev->dev, "reading irq status failed\n"); goto unreg_input_dev; } pwrkey->press = !!err; if (pwrkey->press) { input_report_key(pwrkey->pwr, KEY_POWER, 1); input_sync(pwrkey->pwr); } err = request_any_context_irq(key_press_irq, pwrkey_press_irq, IRQF_TRIGGER_RISING, "pmic8xxx_pwrkey_press", pwrkey); if (err < 0) { dev_dbg(&pdev->dev, "Can't get %d IRQ for pwrkey: %d\n", key_press_irq, err); goto unreg_input_dev; } err = request_any_context_irq(key_release_irq, pwrkey_release_irq, IRQF_TRIGGER_RISING, "pmic8xxx_pwrkey_release", pwrkey); if (err < 0) { dev_dbg(&pdev->dev, "Can't get %d IRQ for pwrkey: %d\n", key_release_irq, err); goto free_press_irq; } sec_powerkey = device_create(sec_class, NULL, 0, NULL, "sec_powerkey"); if (IS_ERR(sec_powerkey)) pr_err("Failed to create device(sec_powerkey)!\n"); ret = device_create_file(sec_powerkey, &dev_attr_sec_powerkey_pressed); if (ret) { pr_err("Failed to create device file in sysfs entries(%s)!\n", dev_attr_sec_powerkey_pressed.attr.name); } dev_set_drvdata(sec_powerkey, pwrkey); device_init_wakeup(&pdev->dev, pdata->wakeup); return 0; free_press_irq: free_irq(key_press_irq, NULL); unreg_input_dev: platform_set_drvdata(pdev, NULL); input_unregister_device(pwr); pwr = NULL; free_input_dev: input_free_device(pwr); free_pwrkey: kfree(pwrkey); return err; }