static int d2083_regulator_enable(struct regulator_dev *rdev) { struct d2083 *d2083 = rdev_get_drvdata(rdev); u8 reg_val; int ret = 0; unsigned int regulator_id = rdev_get_id(rdev); unsigned int reg_num; if (regulator_id >= D2083_NUMBER_OF_REGULATORS) return -EINVAL; if(!is_mode_control_enabled()){ reg_num = get_regulator_reg(regulator_id); d2083_reg_read(d2083, reg_num, ®_val); reg_val |= (1<<6); ret = d2083_reg_write(d2083, reg_num,reg_val); }else { reg_num = get_regulator_mctl_reg(regulator_id); ret = d2083_reg_read(d2083, reg_num, ®_val); if(ret < 0) { dlg_err("I2C read error\n"); return ret; } reg_val &= ~(D2083_REGULATOR_MCTL1 | D2083_REGULATOR_MCTL2 | D2083_REGULATOR_MCTL3); reg_val |= (D2083_REGULATOR_MCTL1_ON | D2083_REGULATOR_MCTL2_ON | D2083_REGULATOR_MCTL3_ON); switch(get_regulator_dsm_opmode(regulator_id)) { case D2083_REGULATOR_LPM_IN_DSM : reg_val &= ~(D2083_REGULATOR_MCTL0); reg_val |= (D2083_REGULATOR_MCTL0_SLEEP); break; case D2083_REGULATOR_OFF_IN_DSM : reg_val &= ~(D2083_REGULATOR_MCTL0); break; case D2083_REGULATOR_ON_IN_DSM : reg_val &= ~(D2083_REGULATOR_MCTL0); reg_val |= (D2083_REGULATOR_MCTL0_ON); break; } ret |= d2083_reg_write(d2083, reg_num, reg_val); } return ret; }
static int d2083_regulator_disable(struct regulator_dev *rdev) { struct d2083 *d2083 = rdev_get_drvdata(rdev); unsigned int regulator_id = rdev_get_id(rdev); unsigned int reg_num = 0; int ret = 0; u8 reg_val; if (regulator_id >= D2083_NUMBER_OF_REGULATORS) return -EINVAL; if(!is_mode_control_enabled()) { reg_num = get_regulator_reg(regulator_id); d2083_reg_read(d2083, reg_num, ®_val); reg_val &= ~(1<<6); d2083_reg_write(d2083, reg_num, reg_val); } else { reg_num = get_regulator_mctl_reg(regulator_id); /* 0x00 == D2083_REGULATOR_MCTL0_OFF | D2083_REGULATOR_MCTL1_OFF * | D2083_REGULATOR_MCTL2_OFF | D2083_REGULATOR_MCTL3_OFF */ ret = d2083_reg_write(d2083, reg_num, 0x00); } return ret; }
static inline u8 audio_read(int reg) { u8 val; d2083_reg_read(d2083, reg, &val); return val; }
int d2083_shutdown(struct d2083 *d2083) { u8 dst; //int ret; int last_adc; dlg_info("%s\n", __func__); if (d2083->read_dev == NULL) return -ENODEV; last_adc=d2083_get_last_vbat_adc(); d2083_reg_write(d2083, D2083_GPID3_REG, (0xFF&last_adc)); //8 LSB d2083_reg_write(d2083, D2083_GPID4_REG, (0xF&(last_adc>>8))); // 4 MSB last_adc=d2083_get_last_temp_adc(); d2083_reg_write(d2083, D2083_GPID5_REG, (0xFF&last_adc)); //8 LSB d2083_reg_write(d2083, D2083_GPID6_REG, (0xF&(last_adc>>8))); // 4 MSB d2083_clear_bits(d2083,D2083_CONTROLB_REG,D2083_CONTROLB_OTPREADEN); //otp reload disable d2083_clear_bits(d2083,D2083_POWERCONT_REG,D2083_POWERCONT_MCTRLEN); //mctl disable d2083_reg_write(d2083, D2083_BUCK1_REG, 0x54); //buck1 1.0 V 0x14 // 20120221 Go deepsleep : Manual LDO off d2083_reg_write(d2083, D2083_IRQMASKB_REG, 0x0); //onkey mask clear // buck4, ldo1, ldo3, ldo6, 7, 8, 9, 11, 13, 14, 15, 16, 17 d2083_clear_bits(d2083, D2083_LDO1_REG, (1<<6)); //LDO 1 disable d2083_clear_bits(d2083, D2083_LDO3_REG, (1<<6)); //LDO 3 disable d2083_clear_bits(d2083, D2083_LDO6_REG, (1<<6)); //LDO 6 disable d2083_clear_bits(d2083, D2083_LDO7_REG, (1<<6)); //LDO 7 disable d2083_clear_bits(d2083, D2083_LDO8_REG, (1<<6)); //LDO 8 disable d2083_clear_bits(d2083, D2083_LDO9_REG, (1<<6)); //LDO 9 disable d2083_clear_bits(d2083, D2083_LDO11_REG, (1<<6)); //LDO 11 disable d2083_clear_bits(d2083, D2083_LDO13_REG, (1<<6)); //LDO 13 disable d2083_clear_bits(d2083, D2083_LDO14_REG, (1<<6)); //LDO 14 disable d2083_clear_bits(d2083, D2083_LDO15_REG, (1<<6)); //LDO 15 disable d2083_clear_bits(d2083, D2083_LDO16_REG, (1<<6)); //LDO 16 disable d2083_clear_bits(d2083, D2083_LDO17_REG, (1<<6)); //LDO 17 disable d2083_clear_bits(d2083, D2083_LDO_AUD_REG, (1<<6)); //LDO_AUD disable d2083_reg_write(d2083, D2083_BUCK4_REG, 0x0); //BUCK 4 d2083_reg_write(d2083, D2083_SUPPLY_REG, 0x10); d2083_reg_write(d2083, D2083_POWERCONT_REG, 0x0E); d2083_reg_write(d2083, D2083_PDDIS_REG, 0xCF); d2083_reg_read(d2083, D2083_CONTROLB_REG, &dst); dst |= D2083_CONTROLB_DEEPSLEEP; d2083_reg_write(d2083, D2083_CONTROLB_REG, dst); return 0; }
static inline int get_global_mctl_mode(struct d2083 *d2083) { u8 reg_val; d2083_reg_read(d2083, D2083_STATUSA_REG, ®_val); // Remove "NOT" operation return ((reg_val & D2083_STATUSA_MCTL) >> D2083_STATUSA_MCTL_SHIFT); }
static inline bool is_mode_control_enabled(struct d2083 *d2083) { u8 reg_val; bool ret; d2083_reg_read(d2083, D2083_POWERCONT_REG, ®_val); ret = (reg_val & D2083_POWERCONT_MCTRLEN); return ret; }
static unsigned int get_regulator_mctl_mode(struct d2083 *d2083, int regulator_id) { //TODO: Make sure we can assume we have always current value in the buffer and do this: u8 reg_val, regulator_mctl_reg = get_regulator_mctl_reg(regulator_id); int ret = 0; ret = d2083_reg_read(d2083, regulator_mctl_reg, ®_val); reg_val &= D2083_REGULATOR_MCTL0; reg_val >>= MCTL0_SHIFT; return reg_val; }
static int d2083_regulator_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV,unsigned *selector) { struct d2083 *d2083 = rdev_get_drvdata(rdev); int mV_val; int min_mV = uV_to_mV(min_uV); int max_mV = uV_to_mV(max_uV); unsigned int reg_num, regulator_id = rdev_get_id(rdev); u8 val; int ret = 0; *selector = -1; // Neet to implement parameter *selector : reference v_table / num_voltages /* before we do anything check the lock bit */ ret = d2083_reg_read(d2083, D2083_SUPPLY_REG, &val); if(val & D2083_SUPPLY_VLOCK) d2083_clear_bits(d2083, D2083_SUPPLY_REG, D2083_SUPPLY_VLOCK); mV_val = d2083_regulator_mvolts_to_val(min_mV, regulator_id, rdev); /* Sanity check for maximum value */ if (d2083_regulator_val_to_mvolts(mV_val, regulator_id, rdev) > max_mV) return -EINVAL; reg_num = get_regulator_reg(regulator_id); ret = d2083_reg_read(d2083, reg_num, &val); val &= ~D2083_MAX_VSEL; d2083_reg_write(d2083, reg_num, (val | mV_val)); /* For BUCKs enable the ramp */ if (regulator_id <= D2083_BUCK_4) d2083_set_bits(d2083, D2083_SUPPLY_REG, (D2083_SUPPLY_VBUCK1GO << regulator_id)); *selector = regulator_id; return ret; }
void d2083_set_sType(u32 s_type) { u8 val; u8 mV_val = 0x00; if(s_type == SILICON_TYPE_SLOW) mV_val = CSR_VAL_ECO_SS_1G; else if(s_type == SILICON_TYPE_TYPICAL) mV_val = CSR_VAL_ECO_TT_1G; else if(s_type == SILICON_TYPE_FAST) mV_val = CSR_VAL_ECO_FF_1G; else mV_val = CSR_VAL_ECO_SS_1G; d2083_reg_read(d2083_regl_info, D2083_BUCK1_REG, &val); val &= ~D2083_MAX_VSEL; d2083_reg_write(d2083_regl_info, D2083_BUCK1_REG, (val | mV_val)); d2083_reg_read(d2083_regl_info, D2083_BUCK1_REG, &val); printk("Buck1 normal --> s_type = [%d], read reg[0x%x] <--, mV_val[0x%x]\n", s_type, val, mV_val); }
void set_MCTL_enabled(void) { u8 reg_val; if(d2083_regl_info==NULL){ dlg_err("MCTRL_EN bit is not set\n"); return; } d2083_reg_read(d2083_regl_info, D2083_POWERCONT_REG, ®_val); reg_val |= D2083_POWERCONT_MCTRLEN; d2083_reg_write(d2083_regl_info, D2083_POWERCONT_REG, reg_val); mctl_status=1; }
static int d2083_regulator_is_enabled(struct regulator_dev *rdev) { struct d2083 *d2083 = rdev_get_drvdata(rdev); unsigned int reg_num, regulator_id = rdev_get_id(rdev); int ret = -EINVAL; u8 reg_val = 0; if(!is_mode_control_enabled()){ reg_num = get_regulator_reg(regulator_id); ret = d2083_reg_read(d2083, reg_num, ®_val); if(ret < 0) { dlg_err("I2C read error. \n"); return ret; } /* 0x0 : off, 0x1 : on */ ret = reg_val & (1<<6); } else { if (regulator_id >= D2083_NUMBER_OF_REGULATORS) return -EINVAL; reg_num = get_regulator_mctl_reg(regulator_id); ret = d2083_reg_read(d2083, reg_num, ®_val); if(ret < 0) { dlg_err("I2C read error. \n"); return ret; } /* 0x0 : Off * 0x1 : On * 0x2 : Sleep * 0x3 : n/a */ ret = ((reg_val & (D2083_REGULATOR_MCTL1|D2083_REGULATOR_MCTL3)) >= 1) ? 1 : 0; } return ret; }
static int d2083_regulator_get_voltage(struct regulator_dev *rdev) { struct d2083 *d2083 = rdev_get_drvdata(rdev); unsigned int reg_num, regulator_id = rdev_get_id(rdev); int ret; u8 val; dlg_info("[[%s]], regulator_id[%d]\n", __func__, regulator_id); reg_num = get_regulator_reg(regulator_id); ret = d2083_reg_read(d2083, reg_num, &val); val &= D2083_MAX_VSEL; ret = mV_to_uV(d2083_regulator_val_to_mvolts(val, regulator_id, rdev)); return ret; }
static int set_regulator_mctl_mode(struct d2083 *d2083, int regulator_id, u8 mode) { u8 reg_val, mctl_reg; int ret = 0; if(regulator_id < 0 || regulator_id >= D2083_NUMBER_OF_REGULATORS) return -EINVAL; if(mode > REGULATOR_MCTL_TURBO) return -EINVAL; mctl_reg = get_regulator_mctl_reg(regulator_id); ret = d2083_reg_read(d2083, mctl_reg, ®_val); if(ret < 0) return ret; reg_val &= ~(D2083_REGULATOR_MCTL0 | D2083_REGULATOR_MCTL2); reg_val |= ((mode << MCTL0_SHIFT) | ( mode << MCTL2_SHIFT)); ret = d2083_reg_write(d2083, mctl_reg, reg_val); dlg_info("[REGULATOR] %s. reg_val = 0x%X\n", __func__, reg_val); return ret; }
int d2083_device_init(struct d2083 *d2083, int irq, struct d2083_platform_data *pdata) { int ret = 0;//, tmp; //struct regulator *regulator; #ifdef D2083_REG_DEBUG int i; u8 data; #endif if(d2083 != NULL) d2083_regl_info = d2083; else goto err; dlg_info("D2083 Driver version : %s\n", D2083_VERSION); d2083->pmic.max_dcdc = 25; // d2083->pdata = pdata; #if defined(CONFIG_KONA_PMU_BSC_HS_MODE) || defined(CONFIG_KONA_PMU_BSC_HS_1625KHZ) d2083_set_bits(d2083, D2083_CONTROLB_REG, D2083_CONTROLB_I2C_SPEED); /* Page write for I2C we donot support repeated write and I2C speed set to 1.7MHz */ d2083_clear_bits(d2083, D2083_CONTROLB_REG, D2083_CONTROLB_WRITEMODE); #else /* Page write for I2C we donot support repeated write and I2C speed set to 400KHz */ d2083_clear_bits(d2083, D2083_CONTROLB_REG, D2083_CONTROLB_WRITEMODE | D2083_CONTROLB_I2C_SPEED); #endif #if 0 // TEST ONLY { // register dump int i=0; u8 reg_val; for(i=0; i<=D2083_BIAS_CTRL_REG; i++) { d2083_reg_read(d2083, i, ®_val); printk(KERN_ERR "addr[0x%x] = [0x%x]\n", i, reg_val); } } #endif d2083_reg_write(d2083, D2083_BUCKA_REG,0x9A); #if 1 // 20120221 LDO13 issue d2083_reg_write(d2083, D2083_PDDIS_REG,0x0); d2083_reg_write(d2083, D2083_PULLDOWN_REG_D,0x0); // audio d2083_reg_write(d2083, D2083_PREAMP_A_CTRL1_REG,0x34); d2083_reg_write(d2083, D2083_PREAMP_A_CTRL2_REG,0x0); d2083_reg_write(d2083, D2083_SP_CTRL_REG,0xCC); // LDO d2083_reg_write(d2083, D2083_LDO1_REG, 0x00); //LDO 1 1.2V // spare d2083_reg_write(d2083, D2083_LDO3_REG, 0x24); //LDO 3 3.0V // VDD_SENSOR_3.0V d2083_reg_write(d2083, D2083_LDO6_REG, 0x20); //LDO 6 2.8V // VCAM_A_2.8V d2083_reg_write(d2083, D2083_LDO7_REG, 0x2A); //LDO 7 3.3V // VDD_VIB_3.3V d2083_reg_write(d2083, D2083_LDO8_REG, 0x64); //LDO 8 3.0V // VLCD_3.0V d2083_reg_write(d2083, D2083_LDO9_REG, 0x24); //LDO 9 3.0V // VDD_SDXC d2083_reg_write(d2083, D2083_LDO11_REG, 0x24); //LDO 11 3.0V // VSIM1_3.0V d2083_reg_write(d2083, D2083_LDO13_REG, 0x24); //LDO 13 3.0V // VDD_SDIO_3.0V d2083_reg_write(d2083, D2083_LDO14_REG, 0xC ); //LDO 14 1.8V // VTOUCH_1.8V d2083_reg_write(d2083, D2083_LDO15_REG, 0x2A); //LDO 15 3.3V // VTOUCH_3.3V d2083_reg_write(d2083, D2083_LDO16_REG, 0xC ); //LDO 16 1.8V // VCAMC_IO_1.8V d2083_reg_write(d2083, D2083_LDO17_REG, 0x20); //LDO 17 2.8V // VCAM_AF_2.8V d2083_reg_write(d2083, D2083_BUCK4_REG, 0x54); //BUCK 4 3.3V // VDD_3G_PAM_3.3V #endif d2083_reg_write(d2083,D2083_BBATCONT_REG,0x1F); d2083_set_bits(d2083,D2083_SUPPLY_REG,D2083_SUPPLY_BBCHGEN); /* DLG todo */ if (pdata && pdata->irq_init) { dlg_crit("\nD2083-core.c: IRQ PIN Configuration \n"); ret = pdata->irq_init(d2083); if (ret != 0) { dev_err(d2083->dev, "Platform init() failed: %d\n", ret); goto err_irq; } } d2083_dev_info = d2083; pm_power_off = d2083_system_poweroff; ret = d2083_irq_init(d2083, irq, pdata); if (ret < 0) goto err; //DLG todo d2083_worker_init(irq); //new for Samsung if (pdata && pdata->init) { ret = pdata->init(d2083); if (ret != 0) { dev_err(d2083->dev, "Platform init() failed: %d\n", ret); goto err_irq; } } // Regulator Specific Init ret = d2083_platform_regulator_init(d2083); if (ret != 0) { dev_err(d2083->dev, "Platform Regulator init() failed: %d\n", ret); goto err_irq; } d2083_client_dev_register(d2083, "d2083-battery", &(d2083->batt.pdev)); d2083_client_dev_register(d2083, "d2083-rtc", &(d2083->rtc.pdev)); d2083_client_dev_register(d2083, "d2083-onkey", &(d2083->onkey.pdev)); d2083_client_dev_register(d2083, "d2083-audio", &(d2083->audio.pdev)); d2083_system_event_init(d2083); #if defined(CONFIG_MACH_RHEA_SS_IVORY) || defined(CONFIG_MACH_RHEA_SS_NEVIS) || defined(CONFIG_MACH_RHEA_SS_NEVISP) d2083_debug_proc_init(d2083); #endif /* CONFIG_MACH_RHEA_SS_IVORY */ #ifdef D2083_REG_DEBUG for(i=0; i<D2083_MAX_REGISTER_CNT; i++) { d2083_reg_read(d2083, i, &data); d2083_write_reg_cache(i,data); } #endif // temporary code if (pdata->pmu_event_cb) pdata->pmu_event_cb(0, 0); //PMU_EVENT_INIT_PLATFORM // set MCTRL_EN enabled set_MCTL_enabled(); return 0; err_irq: d2083_irq_exit(d2083); d2083_dev_info = NULL; pm_power_off = NULL; err: dlg_crit("\n\nD2083-core.c: device init failed ! \n\n"); return ret; }
static long d2083_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct d2083 *d2083 = file->private_data; pmu_reg reg; int ret = 0; u8 reg_val, event_reg[4]; if (!d2083) return -ENOTTY; // _kg TODO: Checking if d2083_reg_write() and d2083_reg_read() // return with success. switch (cmd) { case BCM_PMU_IOCTL_ENABLE_INTS: ret = d2083_block_read(d2083, D2083_EVENTA_REG, 4, event_reg); dlg_info("int register 0x%X = 0x%X\n", D2083_EVENTA_REG, event_reg[0]); dlg_info("int register 0x%X = 0x%X\n", D2083_EVENTB_REG, event_reg[1]); dlg_info("int register 0x%X = 0x%X\n", D2083_EVENTC_REG, event_reg[2]); dlg_info("int register 0x%X = 0x%X\n", D2083_EVENTD_REG, event_reg[3]); /* Clear all latched interrupts if any */ d2083_reg_write(d2083, D2083_EVENTA_REG, 0xFF); d2083_reg_write(d2083, D2083_EVENTB_REG, 0xFF); d2083_reg_write(d2083, D2083_EVENTC_REG, 0xFF); d2083_reg_write(d2083, D2083_EVENTD_REG, 0xFF); enable_irq(d2083->chip_irq); break; case BCM_PMU_IOCTL_DISABLE_INTS: disable_irq_nosync(d2083->chip_irq); break; case BCM_PMU_IOCTL_READ_REG: if (copy_from_user(®, (pmu_reg *)arg, sizeof(pmu_reg)) != 0) return -EFAULT; // DLG eric. 03/Nov/2011. Change prototype //reg.val = d2083_reg_read(d2083, reg.reg); // TODO: Check parameter. ®.val ret = d2083_reg_read(d2083, reg.reg, ®_val); reg.val = (unsigned short)reg_val; if (copy_to_user((pmu_reg *)arg, ®, sizeof(pmu_reg)) != 0) return -EFAULT; break; case BCM_PMU_IOCTL_WRITE_REG: if (copy_from_user(®, (pmu_reg *)arg, sizeof(pmu_reg)) != 0) return -EFAULT; d2083_reg_write(d2083, reg.reg, (u8)reg.val); break; #if 0 case BCM_PMU_IOCTL_SET_VOLTAGE: case BCM_PMU_IOCTL_GET_VOLTAGE: case BCM_PMU_IOCTL_GET_REGULATOR_STATE: case BCM_PMU_IOCTL_SET_REGULATOR_STATE: case BCM_PMU_IOCTL_ACTIVATESIM: case BCM_PMU_IOCTL_DEACTIVATESIM: ret = d2083_ioctl_regulator(d2083, cmd, arg); break; #endif case BCM_PMU_IOCTL_POWERONOFF: // d2083_set_bits(d2083,D2083_POWERCONT_REG,D2083_POWERCONT_RTCAUTOEN); d2083_shutdown(d2083); break; default: dlg_err("%s: unsupported cmd\n", __func__); ret = -ENOTTY; } return ret; }