static int ncp6335d_get_voltage(struct regulator_dev *rdev) { unsigned int val; int rc; struct ncp6335d_info *dd = rdev_get_drvdata(rdev); mutex_lock(&dd->ncp_mutex); if (dd->is_suspend) { rc = dd->curr_voltage; dev_dbg(dd->dev, "Get voltage after suspend, (%d)\n", rc); goto out; } rc = ncp6335x_read(dd, dd->vsel_reg, &val); if (rc) { dev_err(dd->dev, "Unable to get volatge rc(%d)", rc); return rc; } dd->curr_voltage = ((val & NCP6335D_VOUT_SEL_MASK) * dd->step_size) + dd->min_voltage; rc = dd->curr_voltage; dump_registers(dd, dd->vsel_reg, __func__); out: mutex_unlock(&dd->ncp_mutex); return rc; }
static void dump_registers(struct ncp6335d_info *dd, unsigned int reg, const char *func) { unsigned int val = 0; ncp6335x_read(dd, reg, &val); dev_dbg(dd->dev, "%s: NCP6335D: Reg = %x, Val = %x\n", func, reg, val); }
static void dump_registers(struct ncp6335d_info *dd, unsigned int reg, const char *func) { unsigned int val = 0; ncp6335x_read(dd, reg, &val); dev_dbg(dd->dev, "%s: NCP6335D: Reg = %x, Val = %x\n", func, reg, val); #ifdef CONFIG_MACH_YULONG if (reg == 0x13 && val != 0x19) { // add by wangshujun 2014.12.17, // some ncp chip reg 0x13 default value is not 0x19 // it will lead to system reboot,so we force modify it to 19h pr_err("yulong:NCP6335D reg 0x%x val origin is 0x%x\n", reg, val); val = 0x19; ncp6335x_write(dd, reg, val); ncp6335x_read(dd, reg, &val); pr_err("yulong:NCP6335D reg 0x%x modify to 0x%x\n", reg, val); } #endif }
static int ncp6335d_restore_working_reg(struct device_node *node, struct ncp6335d_info *dd) { int ret; unsigned int val1; unsigned int val2; unsigned int val3; /* Restore register from back up register */ ret = ncp6335x_read(dd, dd->vsel_backup_reg, &val1); dev_err(dd->dev, "%s: khl NCP6335D: Reg_back1= %x, Val = %x\n", __func__, dd->vsel_backup_reg, val1); if (ret < 0) { dev_err(dd->dev, "Failed to get backup data from reg %d, ret = %d\n", dd->vsel_backup_reg, ret); return ret; } ret = ncp6335x_read(dd, dd->vsel_reg, &val2); dev_err(dd->dev, "%s: khl NCP6335D: Reg_back2= %x, Val = %x\n", __func__, dd->vsel_reg, val2); #if 0 ret = ncp6335x_update_bits(dd, dd->vsel_reg, NCP6335D_VOUT_SEL_MASK, val); #else ret = ncp6335x_update_bits(dd, dd->vsel_reg, 0xFF, (val1 |0x80)); ret = ncp6335x_read(dd, dd->vsel_reg, &val3); dev_err(dd->dev, "%s: khl NCP6335D: Reg_back3= %x, Val = %x\n", __func__, dd->vsel_reg, val3); #endif if (ret < 0) { dev_err(dd->dev, "Failed to update working reg %d, ret = %d\n", dd->vsel_reg, ret); return ret; } return ret; }
static int get_reg(void *data, u64 *val) { struct ncp6335d_info *dd = data; int rc; unsigned int temp = 0; rc = ncp6335x_read(dd, dd->peek_poke_address, &temp); if (rc < 0) dev_err(dd->dev, "Couldn't read reg %x rc = %d\n", dd->peek_poke_address, rc); else *val = temp; return rc; }
static int ncp6335d_get_voltage(struct regulator_dev *rdev) { unsigned int val; int rc; struct ncp6335d_info *dd = rdev_get_drvdata(rdev); rc = ncp6335x_read(dd, dd->vsel_reg, &val); if (rc) { dev_err(dd->dev, "Unable to get volatge rc(%d)", rc); return rc; } dd->curr_voltage = ((val & NCP6335D_VOUT_SEL_MASK) * dd->step_size) + dd->min_voltage; dump_registers(dd, dd->vsel_reg, __func__); return dd->curr_voltage; }
static unsigned int ncp6335d_get_mode(struct regulator_dev *rdev) { unsigned int val; int rc; struct ncp6335d_info *dd = rdev_get_drvdata(rdev); rc = ncp6335x_read(dd, REG_NCP6335D_COMMAND, &val); if (rc) { dev_err(dd->dev, "Unable to get regulator mode rc(%d)\n", rc); return rc; } dump_registers(dd, REG_NCP6335D_COMMAND, __func__); if (val & dd->mode_bit) return REGULATOR_MODE_FAST; return REGULATOR_MODE_NORMAL; }
static int ncp6335d_restore_working_reg(struct device_node *node, struct ncp6335d_info *dd) { int ret; unsigned int val; /* Restore register from back up register */ ret = ncp6335x_read(dd, dd->vsel_backup_reg, &val); if (ret < 0) { dev_err(dd->dev, "Failed to get backup data from reg %d, ret = %d\n", dd->vsel_backup_reg, ret); return ret; } ret = ncp6335x_update_bits(dd, dd->vsel_reg, NCP6335D_VOUT_SEL_MASK, val); if (ret < 0) { dev_err(dd->dev, "Failed to update working reg %d, ret = %d\n", dd->vsel_reg, ret); return ret; } return ret; }
static int ncp6335d_regulator_probe(struct i2c_client *client, const struct i2c_device_id *id) { int rc; unsigned int val = 0; struct ncp6335d_info *dd; const struct ncp6335d_platform_data *pdata; struct regulator_config config = { }; #ifdef CONFIG_MACH_YULONG /* the i2c address of ncp6335d is somehow changed, trying to poll if failed. [email protected] 2014-12-29*/ int i2c_addr_backup[3] = { 0x18, 0x10, 0x14}; int i_a = 0; pr_err("%s:ncp addr is 0x%2x\n",__func__,client->addr); #endif if (client->dev.of_node) pdata = ncp6335d_get_of_platform_data(client); else pdata = client->dev.platform_data; if (!pdata) { dev_err(&client->dev, "Platform data not specified\n"); return -EINVAL; } dd = devm_kzalloc(&client->dev, sizeof(*dd), GFP_KERNEL); if (!dd) { dev_err(&client->dev, "Unable to allocate memory\n"); return -ENOMEM; } if (client->dev.of_node) { rc = ncp6335d_parse_dt(client, dd); if (rc) return rc; } else { dd->step_size = NCP6335D_STEP_VOLTAGE_UV; dd->min_voltage = NCP6335D_MIN_VOLTAGE_UV; dd->min_slew_ns = NCP6335D_MIN_SLEW_NS; dd->max_slew_ns = NCP6335D_MAX_SLEW_NS; } dd->regmap = devm_regmap_init_i2c(client, &ncp6335d_regmap_config); if (IS_ERR(dd->regmap)) { dev_err(&client->dev, "Error allocating regmap\n"); return PTR_ERR(dd->regmap); } #ifdef CONFIG_MACH_YULONG AGAIN: #endif rc = ncp6335x_read(dd, REG_NCP6335D_PID, &val); if (rc) { dev_err(&client->dev, "Unable to identify NCP6335D, rc(%d)\n", rc); #ifdef CONFIG_MACH_YULONG dev_err(&client->dev, "ncp addr is 0x%2x, force addr as 0x%2x and retry\n", client->addr, i2c_addr_backup[i_a]); while (i_a < 3) { client->addr = i2c_addr_backup[i_a]; i_a++; goto AGAIN; } #endif return rc; } dev_info(&client->dev, "Detected Regulator NCP6335D PID = %d\n", val); dd->init_data = pdata->init_data; dd->dev = &client->dev; i2c_set_clientdata(client, dd); mutex_init(&dd->ncp_mutex); rc = ncp6335d_init(client, dd, pdata); if (rc) { dev_err(&client->dev, "Unable to intialize the regulator\n"); return -EINVAL; } config.dev = &client->dev; config.init_data = dd->init_data; config.regmap = dd->regmap; config.driver_data = dd; config.of_node = client->dev.of_node; dd->regulator = regulator_register(&rdesc, &config); if (IS_ERR(dd->regulator)) { dev_err(&client->dev, "Unable to register regulator rc(%ld)", PTR_ERR(dd->regulator)); return PTR_ERR(dd->regulator); } dd->debug_root = debugfs_create_dir("ncp6335x", NULL); if (!dd->debug_root) dev_err(&client->dev, "Couldn't create debug dir\n"); if (dd->debug_root) { struct dentry *ent; ent = debugfs_create_x32("address", S_IFREG | S_IWUSR | S_IRUGO, dd->debug_root, &(dd->peek_poke_address)); if (!ent) dev_err(&client->dev, "Couldn't create address debug file rc = %d\n", rc); ent = debugfs_create_file("data", S_IFREG | S_IWUSR | S_IRUGO, dd->debug_root, dd, &poke_poke_debug_ops); if (!ent) dev_err(&client->dev, "Couldn't create data debug file rc = %d\n", rc); } return 0; }
static int ncp6335d_init(struct i2c_client *client, struct ncp6335d_info *dd, const struct ncp6335d_platform_data *pdata) { int rc; unsigned int val; switch (pdata->default_vsel) { case NCP6335D_VSEL0: dd->vsel_reg = REG_NCP6335D_PROGVSEL0; dd->vsel_backup_reg = REG_NCP6335D_PROGVSEL1; dd->mode_bit = NCP6335D_PWM_MODE0; break; case NCP6335D_VSEL1: dd->vsel_reg = REG_NCP6335D_PROGVSEL1; dd->vsel_backup_reg = REG_NCP6335D_PROGVSEL0; dd->mode_bit = NCP6335D_PWM_MODE1; break; default: dev_err(dd->dev, "Invalid VSEL ID %d\n", pdata->default_vsel); return -EINVAL; } if (of_property_read_bool(client->dev.of_node, "onnn,restore-reg")) { rc = ncp6335d_restore_working_reg(client->dev.of_node, dd); if (rc) return rc; } rc = ncp6335d_parse_gpio(client->dev.of_node, dd); if (rc) return rc; /* get the current programmed voltage */ rc = ncp6335x_read(dd, dd->vsel_reg, &val); if (rc) { dev_err(dd->dev, "Unable to get volatge rc(%d)", rc); return rc; } dd->curr_voltage = ((val & NCP6335D_VOUT_SEL_MASK) * dd->step_size) + dd->min_voltage; /* set discharge */ rc = ncp6335x_update_bits(dd, REG_NCP6335D_PGOOD, NCP6335D_PGOOD_DISCHG, (pdata->discharge_enable ? NCP6335D_PGOOD_DISCHG : 0)); if (rc) { dev_err(dd->dev, "Unable to set Active Discharge rc(%d)\n", rc); return -EINVAL; } /* set slew rate */ if (pdata->slew_rate_ns < dd->min_slew_ns || pdata->slew_rate_ns > dd->max_slew_ns) { dev_err(dd->dev, "Invalid slew rate %d\n", pdata->slew_rate_ns); return -EINVAL; } dd->slew_rate = pdata->slew_rate_ns; val = DIV_ROUND_UP(pdata->slew_rate_ns, dd->min_slew_ns); val = ilog2(val); rc = ncp6335x_update_bits(dd, REG_NCP6335D_TIMING, NCP6335D_SLEW_MASK, val << NCP6335D_SLEW_SHIFT); if (rc) dev_err(dd->dev, "Unable to set slew rate rc(%d)\n", rc); /* Set Sleep mode bit */ rc = ncp6335x_update_bits(dd, REG_NCP6335D_COMMAND, NCP6335D_SLEEP_MODE, pdata->sleep_enable ? NCP6335D_SLEEP_MODE : 0); if (rc) dev_err(dd->dev, "Unable to set sleep mode (%d)\n", rc); dump_registers(dd, REG_NCP6335D_COMMAND, __func__); dump_registers(dd, REG_NCP6335D_PROGVSEL0, __func__); dump_registers(dd, REG_NCP6335D_TIMING, __func__); dump_registers(dd, REG_NCP6335D_PGOOD, __func__); return rc; }
static int ncp6335d_regulator_probe(struct i2c_client *client, const struct i2c_device_id *id) { int rc; unsigned int val = 0; struct ncp6335d_info *dd; const struct ncp6335d_platform_data *pdata; struct regulator_config config = { }; if (client->dev.of_node) pdata = ncp6335d_get_of_platform_data(client); else pdata = client->dev.platform_data; if (!pdata) { dev_err(&client->dev, "Platform data not specified\n"); return -EINVAL; } dd = devm_kzalloc(&client->dev, sizeof(*dd), GFP_KERNEL); if (!dd) { dev_err(&client->dev, "Unable to allocate memory\n"); return -ENOMEM; } if (client->dev.of_node) { rc = ncp6335d_parse_dt(client, dd); if (rc) return rc; } else { dd->step_size = NCP6335D_STEP_VOLTAGE_UV; dd->min_voltage = NCP6335D_MIN_VOLTAGE_UV; dd->min_slew_ns = NCP6335D_MIN_SLEW_NS; dd->max_slew_ns = NCP6335D_MAX_SLEW_NS; } dd->regmap = devm_regmap_init_i2c(client, &ncp6335d_regmap_config); if (IS_ERR(dd->regmap)) { dev_err(&client->dev, "Error allocating regmap\n"); return PTR_ERR(dd->regmap); } rc = ncp6335x_read(dd, REG_NCP6335D_PID, &val); if (rc) { dev_err(&client->dev, "Unable to identify NCP6335D, rc(%d)\n", rc); return rc; } dev_info(&client->dev, "Detected Regulator NCP6335D PID = %d\n", val); dd->init_data = pdata->init_data; dd->dev = &client->dev; i2c_set_clientdata(client, dd); rc = ncp6335d_init(client, dd, pdata); if (rc) { dev_err(&client->dev, "Unable to intialize the regulator\n"); return -EINVAL; } config.dev = &client->dev; config.init_data = dd->init_data; config.regmap = dd->regmap; config.driver_data = dd; config.of_node = client->dev.of_node; dd->regulator = regulator_register(&rdesc, &config); if (IS_ERR(dd->regulator)) { dev_err(&client->dev, "Unable to register regulator rc(%ld)", PTR_ERR(dd->regulator)); return PTR_ERR(dd->regulator); } dd->debug_root = debugfs_create_dir("ncp6335x", NULL); if (!dd->debug_root) dev_err(&client->dev, "Couldn't create debug dir\n"); if (dd->debug_root) { struct dentry *ent; ent = debugfs_create_x32("address", S_IFREG | S_IWUSR | S_IRUGO, dd->debug_root, &(dd->peek_poke_address)); if (!ent) dev_err(&client->dev, "Couldn't create address debug file rc = %d\n", rc); ent = debugfs_create_file("data", S_IFREG | S_IWUSR | S_IRUGO, dd->debug_root, dd, &poke_poke_debug_ops); if (!ent) dev_err(&client->dev, "Couldn't create data debug file rc = %d\n", rc); } return 0; }