static int __devinit qpnp_regulator_probe(struct spmi_device *spmi) { struct qpnp_regulator_platform_data *pdata; struct qpnp_regulator *vreg; struct regulator_desc *rdesc; struct qpnp_regulator_platform_data of_pdata; struct regulator_init_data *init_data; char *reg_name; int rc; bool is_dt; vreg = kzalloc(sizeof(struct qpnp_regulator), GFP_KERNEL); if (!vreg) { dev_err(&spmi->dev, "%s: Can't allocate qpnp_regulator\n", __func__); return -ENOMEM; } is_dt = of_match_device(spmi_match_table, &spmi->dev); /* Check if device tree is in use. */ if (is_dt) { init_data = of_get_regulator_init_data(&spmi->dev, spmi->dev.of_node); if (!init_data) { dev_err(&spmi->dev, "%s: unable to allocate memory\n", __func__); kfree(vreg); return -ENOMEM; } memset(&of_pdata, 0, sizeof(struct qpnp_regulator_platform_data)); memcpy(&of_pdata.init_data, init_data, sizeof(struct regulator_init_data)); if (of_get_property(spmi->dev.of_node, "parent-supply", NULL)) of_pdata.init_data.supply_regulator = "parent"; rc = qpnp_regulator_get_dt_config(spmi, &of_pdata); if (rc) { dev_err(&spmi->dev, "%s: DT parsing failed, rc=%d\n", __func__, rc); kfree(vreg); return -ENOMEM; } pdata = &of_pdata; } else { pdata = spmi->dev.platform_data; } if (pdata == NULL) { dev_err(&spmi->dev, "%s: no platform data specified\n", __func__); kfree(vreg); return -EINVAL; } vreg->spmi_dev = spmi; vreg->prev_write_count = -1; vreg->write_count = 0; vreg->base_addr = pdata->base_addr; vreg->enable_time = pdata->enable_time; vreg->system_load = pdata->system_load; vreg->ocp_enable = pdata->ocp_enable; vreg->ocp_enable_time = pdata->ocp_enable_time; rdesc = &vreg->rdesc; rdesc->id = spmi->ctrl->nr; rdesc->owner = THIS_MODULE; rdesc->type = REGULATOR_VOLTAGE; reg_name = kzalloc(strnlen(pdata->init_data.constraints.name, MAX_NAME_LEN) + 1, GFP_KERNEL); if (!reg_name) { dev_err(&spmi->dev, "%s: Can't allocate regulator name\n", __func__); kfree(vreg); return -ENOMEM; } strlcpy(reg_name, pdata->init_data.constraints.name, strnlen(pdata->init_data.constraints.name, MAX_NAME_LEN) + 1); rdesc->name = reg_name; dev_set_drvdata(&spmi->dev, vreg); rc = qpnp_regulator_match(vreg); if (rc) { vreg_err(vreg, "regulator type unknown, rc=%d\n", rc); goto bail; } if (is_dt && rdesc->ops) { /* Fill in ops and mode masks when using device tree. */ if (rdesc->ops->enable) pdata->init_data.constraints.valid_ops_mask |= REGULATOR_CHANGE_STATUS; if (rdesc->ops->get_voltage) pdata->init_data.constraints.valid_ops_mask |= REGULATOR_CHANGE_VOLTAGE; if (rdesc->ops->get_mode) { pdata->init_data.constraints.valid_ops_mask |= REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_DRMS; pdata->init_data.constraints.valid_modes_mask = REGULATOR_MODE_NORMAL | REGULATOR_MODE_IDLE; } } rc = qpnp_regulator_init_registers(vreg, pdata); if (rc) { vreg_err(vreg, "common initialization failed, rc=%d\n", rc); goto bail; } vreg->rdev = regulator_register(rdesc, &spmi->dev, &(pdata->init_data), vreg, spmi->dev.of_node); if (IS_ERR(vreg->rdev)) { rc = PTR_ERR(vreg->rdev); vreg_err(vreg, "regulator_register failed, rc=%d\n", rc); goto bail; } qpnp_vreg_show_state(vreg->rdev, QPNP_REGULATOR_ACTION_INIT); return 0; bail: if (rc) vreg_err(vreg, "probe failed, rc=%d\n", rc); kfree(vreg->rdesc.name); kfree(vreg); return rc; }
static int __devinit qpnp_regulator_probe(struct spmi_device *spmi) { struct qpnp_regulator_platform_data *pdata; struct qpnp_regulator *vreg; struct regulator_desc *rdesc; struct qpnp_regulator_platform_data of_pdata; struct regulator_init_data *init_data; char *reg_name; int rc; bool is_dt; vreg = kzalloc(sizeof(struct qpnp_regulator), GFP_KERNEL); if (!vreg) { dev_err(&spmi->dev, "%s: Can't allocate qpnp_regulator\n", __func__); return -ENOMEM; } is_dt = of_match_device(spmi_match_table, &spmi->dev); if (is_dt) { init_data = of_get_regulator_init_data(&spmi->dev, spmi->dev.of_node); if (!init_data) { dev_err(&spmi->dev, "%s: unable to allocate memory\n", __func__); kfree(vreg); return -ENOMEM; } memset(&of_pdata, 0, sizeof(struct qpnp_regulator_platform_data)); memcpy(&of_pdata.init_data, init_data, sizeof(struct regulator_init_data)); if (of_get_property(spmi->dev.of_node, "parent-supply", NULL)) of_pdata.init_data.supply_regulator = "parent"; rc = qpnp_regulator_get_dt_config(spmi, &of_pdata); if (rc) { dev_err(&spmi->dev, "%s: DT parsing failed, rc=%d\n", __func__, rc); kfree(vreg); return -ENOMEM; } pdata = &of_pdata; } else { pdata = spmi->dev.platform_data; } if (pdata == NULL) { dev_err(&spmi->dev, "%s: no platform data specified\n", __func__); kfree(vreg); return -EINVAL; } vreg->spmi_dev = spmi; vreg->prev_write_count = -1; vreg->write_count = 0; vreg->base_addr = pdata->base_addr; vreg->enable_time = pdata->enable_time; vreg->system_load = pdata->system_load; vreg->ocp_enable = pdata->ocp_enable; vreg->ocp_irq = pdata->ocp_irq; vreg->ocp_max_retries = pdata->ocp_max_retries; vreg->ocp_retry_delay_ms = pdata->ocp_retry_delay_ms; if (vreg->ocp_max_retries == 0) vreg->ocp_max_retries = QPNP_VS_OCP_DEFAULT_MAX_RETRIES; if (vreg->ocp_retry_delay_ms == 0) vreg->ocp_retry_delay_ms = QPNP_VS_OCP_DEFAULT_RETRY_DELAY_MS; rdesc = &vreg->rdesc; rdesc->id = spmi->ctrl->nr; rdesc->owner = THIS_MODULE; rdesc->type = REGULATOR_VOLTAGE; reg_name = kzalloc(strnlen(pdata->init_data.constraints.name, MAX_NAME_LEN) + 1, GFP_KERNEL); if (!reg_name) { dev_err(&spmi->dev, "%s: Can't allocate regulator name\n", __func__); kfree(vreg); return -ENOMEM; } strlcpy(reg_name, pdata->init_data.constraints.name, strnlen(pdata->init_data.constraints.name, MAX_NAME_LEN) + 1); rdesc->name = reg_name; dev_set_drvdata(&spmi->dev, vreg); rc = qpnp_regulator_match(vreg); if (rc) { vreg_err(vreg, "regulator type unknown, rc=%d\n", rc); goto bail; } if (is_dt && rdesc->ops) { if (rdesc->ops->enable) pdata->init_data.constraints.valid_ops_mask |= REGULATOR_CHANGE_STATUS; if (rdesc->ops->get_voltage) pdata->init_data.constraints.valid_ops_mask |= REGULATOR_CHANGE_VOLTAGE; if (rdesc->ops->get_mode) { pdata->init_data.constraints.valid_ops_mask |= REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_DRMS; pdata->init_data.constraints.valid_modes_mask = REGULATOR_MODE_NORMAL | REGULATOR_MODE_IDLE; } } rc = qpnp_regulator_init_registers(vreg, pdata); if (rc) { vreg_err(vreg, "common initialization failed, rc=%d\n", rc); goto bail; } if (vreg->logical_type != QPNP_REGULATOR_LOGICAL_TYPE_VS) vreg->ocp_irq = 0; if (vreg->ocp_irq) { rc = devm_request_irq(&spmi->dev, vreg->ocp_irq, qpnp_regulator_vs_ocp_isr, IRQF_TRIGGER_RISING, "ocp", vreg); if (rc < 0) { vreg_err(vreg, "failed to request irq %d, rc=%d\n", vreg->ocp_irq, rc); goto bail; } INIT_DELAYED_WORK(&vreg->ocp_work, qpnp_regulator_vs_ocp_work); } vreg->rdev = regulator_register(rdesc, &spmi->dev, &(pdata->init_data), vreg, spmi->dev.of_node); if (IS_ERR(vreg->rdev)) { rc = PTR_ERR(vreg->rdev); if (rc != -EPROBE_DEFER) vreg_err(vreg, "regulator_register failed, rc=%d\n", rc); goto cancel_ocp_work; } qpnp_vreg_show_state(vreg->rdev, QPNP_REGULATOR_ACTION_INIT); return 0; cancel_ocp_work: if (vreg->ocp_irq) cancel_delayed_work_sync(&vreg->ocp_work); bail: if (rc && rc != -EPROBE_DEFER) vreg_err(vreg, "probe failed, rc=%d\n", rc); kfree(vreg->rdesc.name); kfree(vreg); return rc; }