Loading drivers/media/platform/msm/camera/cam_utils/cam_soc_util.c +535 −39 Original line number Diff line number Diff line Loading @@ -14,6 +14,9 @@ #include <linux/of.h> #include <linux/clk.h> #include <linux/slab.h> #include <linux/gpio.h> #include <linux/of_gpio.h> #include "cam_soc_util.h" #undef CDBG Loading Loading @@ -443,43 +446,304 @@ int cam_soc_util_set_clk_rate_level(struct cam_hw_soc_info *soc_info, return rc; }; int cam_soc_util_get_dt_properties(struct cam_hw_soc_info *soc_info) static int cam_soc_util_get_dt_gpio_req_tbl(struct device_node *of_node, struct cam_soc_gpio_data *gconf, uint16_t *gpio_array, uint16_t gpio_array_size) { int32_t rc = 0, i = 0; uint32_t count = 0; uint32_t *val_array = NULL; if (!of_get_property(of_node, "gpio-req-tbl-num", &count)) return 0; count /= sizeof(uint32_t); if (!count) { pr_err("gpio-req-tbl-num 0\n"); return 0; } val_array = kcalloc(count, sizeof(uint32_t), GFP_KERNEL); if (!val_array) return -ENOMEM; gconf->cam_gpio_req_tbl = kcalloc(count, sizeof(struct gpio), GFP_KERNEL); if (!gconf->cam_gpio_req_tbl) { rc = -ENOMEM; goto free_val_array; } gconf->cam_gpio_req_tbl_size = count; rc = of_property_read_u32_array(of_node, "gpio-req-tbl-num", val_array, count); if (rc) { pr_err("failed in reading gpio-req-tbl-num, rc = %d\n", rc); goto free_gpio_req_tbl; } for (i = 0; i < count; i++) { if (val_array[i] >= gpio_array_size) { pr_err("gpio req tbl index %d invalid\n", val_array[i]); goto free_gpio_req_tbl; } gconf->cam_gpio_req_tbl[i].gpio = gpio_array[val_array[i]]; CDBG("cam_gpio_req_tbl[%d].gpio = %d\n", i, gconf->cam_gpio_req_tbl[i].gpio); } rc = of_property_read_u32_array(of_node, "gpio-req-tbl-flags", val_array, count); if (rc) { pr_err("Failed in gpio-req-tbl-flags, rc %d\n", rc); goto free_gpio_req_tbl; } for (i = 0; i < count; i++) { gconf->cam_gpio_req_tbl[i].flags = val_array[i]; CDBG("cam_gpio_req_tbl[%d].flags = %ld\n", i, gconf->cam_gpio_req_tbl[i].flags); } for (i = 0; i < count; i++) { rc = of_property_read_string_index(of_node, "gpio-req-tbl-label", i, &gconf->cam_gpio_req_tbl[i].label); if (rc) { pr_err("Failed rc %d\n", rc); goto free_gpio_req_tbl; } CDBG("cam_gpio_req_tbl[%d].label = %s\n", i, gconf->cam_gpio_req_tbl[i].label); } kfree(val_array); return rc; free_gpio_req_tbl: kfree(gconf->cam_gpio_req_tbl); free_val_array: kfree(val_array); gconf->cam_gpio_req_tbl_size = 0; return rc; } static int cam_soc_util_get_gpio_info(struct cam_hw_soc_info *soc_info) { int32_t rc = 0, i = 0; uint16_t *gpio_array = NULL; int16_t gpio_array_size = 0; struct cam_soc_gpio_data *gconf = NULL; struct device_node *of_node = NULL; int count = 0, i = 0, rc = 0; struct platform_device *pdev = NULL; if (!soc_info || !soc_info->pdev) return -EINVAL; pdev = soc_info->pdev; of_node = pdev->dev.of_node; rc = of_property_read_u32(of_node, "cell-index", &soc_info->index); /* Validate input parameters */ if (!of_node) { pr_err("Invalid param of_node\n"); return -EINVAL; } gpio_array_size = of_gpio_count(of_node); if (gpio_array_size <= 0) return 0; CDBG("gpio count %d\n", gpio_array_size); gpio_array = kcalloc(gpio_array_size, sizeof(uint16_t), GFP_KERNEL); if (!gpio_array) goto free_gpio_conf; for (i = 0; i < gpio_array_size; i++) { gpio_array[i] = of_get_gpio(of_node, i); CDBG("gpio_array[%d] = %d", i, gpio_array[i]); } gconf = kzalloc(sizeof(*gconf), GFP_KERNEL); if (!gconf) return -ENOMEM; rc = cam_soc_util_get_dt_gpio_req_tbl(of_node, gconf, gpio_array, gpio_array_size); if (rc) { pr_err("device %s failed to read cell-index\n", pdev->name); pr_err("failed in msm_camera_get_dt_gpio_req_tbl\n"); goto free_gpio_array; } gconf->cam_gpio_common_tbl = kcalloc(gpio_array_size, sizeof(struct gpio), GFP_KERNEL); if (!gconf->cam_gpio_common_tbl) { rc = -ENOMEM; goto free_gpio_array; } for (i = 0; i <= gpio_array_size; i++) gconf->cam_gpio_common_tbl[i].gpio = gpio_array[i]; gconf->cam_gpio_common_tbl_size = gpio_array_size; soc_info->gpio_data = gconf; kfree(gpio_array); return rc; free_gpio_array: kfree(gpio_array); free_gpio_conf: kfree(gconf); soc_info->gpio_data = NULL; return rc; } static int cam_soc_util_request_gpio_table( struct cam_hw_soc_info *soc_info, bool gpio_en) { int rc = 0, i = 0; uint8_t size = 0; struct cam_soc_gpio_data *gpio_conf = soc_info->gpio_data; struct gpio *gpio_tbl = NULL; if (!gpio_conf) { CDBG("No GPIO entry\n"); return 0; } if (gpio_conf->cam_gpio_common_tbl_size <= 0) { pr_err("GPIO table size is invalid\n"); return -EINVAL; } size = gpio_conf->cam_gpio_req_tbl_size; gpio_tbl = gpio_conf->cam_gpio_req_tbl; if (!gpio_tbl || !size) { pr_err("Invalid gpio_tbl %pK / size %d\n", gpio_tbl, size); return -EINVAL; } for (i = 0; i < size; i++) { CDBG("i=%d, gpio=%d dir=%ld\n", i, gpio_tbl[i].gpio, gpio_tbl[i].flags); } if (gpio_en) { for (i = 0; i < size; i++) { rc = gpio_request_one(gpio_tbl[i].gpio, gpio_tbl[i].flags, gpio_tbl[i].label); if (rc) { /* * After GPIO request fails, contine to * apply new gpios, outout a error message * for driver bringup debug */ pr_err("gpio %d:%s request fails\n", gpio_tbl[i].gpio, gpio_tbl[i].label); } } } else { gpio_free_array(gpio_tbl, size); } return rc; } static int cam_soc_util_get_dt_regulator_info (struct cam_hw_soc_info *soc_info) { int rc = 0, count = 0, i = 0; struct device_node *of_node = NULL; struct platform_device *pdev = NULL; if (!soc_info || !soc_info->pdev) { pr_err("Invalid parameters\n"); return -EINVAL; } pdev = soc_info->pdev; of_node = pdev->dev.of_node; soc_info->num_rgltr = 0; count = of_property_count_strings(of_node, "regulator-names"); if (count != -EINVAL) { if (count <= 0) { pr_err("no regulators found\n"); count = 0; return -EINVAL; } soc_info->num_rgltr = count; } else { CDBG("No regulators node found\n"); return 0; } for (i = 0; i < soc_info->num_rgltr; i++) { rc = of_property_read_string_index(of_node, "regulator-names", i, &soc_info->rgltr_name[i]); CDBG("rgltr_name[%d] = %s\n", i, soc_info->rgltr_name[i]); if (rc) { pr_err("no regulator resource at cnt=%d\n", i); rc = -ENODEV; return rc; return -ENODEV; } } if (!of_property_read_bool(of_node, "rgltr-cntrl-support")) { CDBG("No regulator control parameter defined\n"); soc_info->rgltr_ctrl_support = false; return 0; } soc_info->rgltr_ctrl_support = true; rc = of_property_read_u32_array(of_node, "rgltr-min-voltage", soc_info->rgltr_min_volt, soc_info->num_rgltr); if (rc) { pr_err("No minimum volatage value found, rc=%d\n", rc); return -EINVAL; } rc = of_property_read_u32_array(of_node, "rgltr-max-voltage", soc_info->rgltr_max_volt, soc_info->num_rgltr); if (rc) { pr_err("No maximum volatage value found, rc=%d\n", rc); return -EINVAL; } rc = of_property_read_u32_array(of_node, "rgltr-load-current", soc_info->rgltr_op_mode, soc_info->num_rgltr); if (rc) { pr_err("No Load curent found rc=%d\n", rc); return -EINVAL; } return rc; } int cam_soc_util_get_dt_properties(struct cam_hw_soc_info *soc_info) { struct device_node *of_node = NULL; int count = 0, i = 0, rc = 0; struct platform_device *pdev = NULL; if (!soc_info || !soc_info->pdev) return -EINVAL; pdev = soc_info->pdev; of_node = pdev->dev.of_node; rc = of_property_read_u32(of_node, "cell-index", &soc_info->index); if (rc) { pr_err("device %s failed to read cell-index\n", pdev->name); return rc; } count = of_property_count_strings(of_node, "reg-names"); if (count <= 0) { pr_err("no reg-names found\n"); Loading Loading @@ -519,6 +783,7 @@ int cam_soc_util_get_dt_properties(struct cam_hw_soc_info *soc_info) &soc_info->irq_name); if (rc) { pr_warn("No interrupt line present\n"); rc = 0; } else { soc_info->irq_line = platform_get_resource_byname(pdev, IORESOURCE_IRQ, soc_info->irq_name); Loading @@ -529,7 +794,17 @@ int cam_soc_util_get_dt_properties(struct cam_hw_soc_info *soc_info) } } rc = cam_soc_util_get_dt_regulator_info(soc_info); if (rc) return rc; rc = cam_soc_util_get_dt_clk_info(soc_info); if (rc) return rc; rc = cam_soc_util_get_gpio_info(soc_info); if (rc) return rc; return rc; } Loading Loading @@ -559,18 +834,207 @@ static int cam_soc_util_get_regulator(struct platform_device *pdev, return rc; } int cam_soc_util_request_platform_resource(struct cam_hw_soc_info *soc_info, int cam_soc_util_regulator_disable(struct regulator *rgltr, const char *rgltr_name, uint32_t rgltr_min_volt, uint32_t rgltr_max_volt, uint32_t rgltr_op_mode, uint32_t rgltr_delay_ms) { int32_t rc = 0; if (!rgltr) { pr_err("Invalid NULL parameter\n"); return -EINVAL; } rc = regulator_disable(rgltr); if (rc) { pr_err("%s regulator disable failed\n", rgltr_name); return rc; } if (rgltr_delay_ms > 20) msleep(rgltr_delay_ms); else if (rgltr_delay_ms) usleep_range(rgltr_delay_ms * 1000, (rgltr_delay_ms * 1000) + 1000); if (regulator_count_voltages(rgltr) > 0) { regulator_set_load(rgltr, 0); regulator_set_voltage(rgltr, 0, rgltr_max_volt); } return rc; } int cam_soc_util_regulator_enable(struct regulator *rgltr, const char *rgltr_name, uint32_t rgltr_min_volt, uint32_t rgltr_max_volt, uint32_t rgltr_op_mode, uint32_t rgltr_delay) { int32_t rc = 0; if (!rgltr) { pr_err("Invalid NULL parameter\n"); return -EINVAL; } if (regulator_count_voltages(rgltr) > 0) { CDBG("voltage min=%d, max=%d\n", rgltr_min_volt, rgltr_max_volt); rc = regulator_set_voltage( rgltr, rgltr_min_volt, rgltr_max_volt); if (rc) { pr_err("%s set voltage failed\n", rgltr_name); return rc; } rc = regulator_set_load(rgltr, rgltr_op_mode); if (rc) { pr_err("%s set optimum mode failed\n", rgltr_name); return rc; } } rc = regulator_enable(rgltr); if (rc) { pr_err("%s regulator_enable failed\n", rgltr_name); return rc; } if (rgltr_delay > 20) msleep(rgltr_delay); else if (rgltr_delay) usleep_range(rgltr_delay * 1000, (rgltr_delay * 1000) + 1000); return rc; } static int cam_soc_util_request_pinctrl( struct cam_hw_soc_info *soc_info) { struct cam_soc_pinctrl_info *device_pctrl = &soc_info->pinctrl_info; struct device *dev = &soc_info->pdev->dev; device_pctrl->pinctrl = devm_pinctrl_get(dev); if (IS_ERR_OR_NULL(device_pctrl->pinctrl)) { CDBG("Pinctrl not available\n"); device_pctrl->pinctrl = NULL; return 0; } device_pctrl->gpio_state_active = pinctrl_lookup_state(device_pctrl->pinctrl, CAM_SOC_PINCTRL_STATE_DEFAULT); if (IS_ERR_OR_NULL(device_pctrl->gpio_state_active)) { pr_err("Failed to get the active state pinctrl handle\n"); device_pctrl->gpio_state_active = NULL; return -EINVAL; } device_pctrl->gpio_state_suspend = pinctrl_lookup_state(device_pctrl->pinctrl, CAM_SOC_PINCTRL_STATE_SLEEP); if (IS_ERR_OR_NULL(device_pctrl->gpio_state_suspend)) { pr_err("Failed to get the suspend state pinctrl handle\n"); device_pctrl->gpio_state_suspend = NULL; return -EINVAL; } return 0; } static void cam_soc_util_regulator_disable_default( struct cam_hw_soc_info *soc_info) { int j = 0; uint32_t num_rgltr = soc_info->num_rgltr; for (j = num_rgltr-1; j >= 0; j--) { if (soc_info->rgltr_ctrl_support == true) { cam_soc_util_regulator_disable(soc_info->rgltr[j], soc_info->rgltr_name[j], soc_info->rgltr_min_volt[j], soc_info->rgltr_max_volt[j], soc_info->rgltr_op_mode[j], soc_info->rgltr_delay[j]); } else { if (soc_info->rgltr[j]) regulator_disable(soc_info->rgltr[j]); } } } static int cam_soc_util_regulator_enable_default( struct cam_hw_soc_info *soc_info) { int j = 0, rc = 0; uint32_t num_rgltr = soc_info->num_rgltr; for (j = 0; j < num_rgltr; j++) { if (soc_info->rgltr_ctrl_support == true) { rc = cam_soc_util_regulator_enable(soc_info->rgltr[j], soc_info->rgltr_name[j], soc_info->rgltr_min_volt[j], soc_info->rgltr_max_volt[j], soc_info->rgltr_op_mode[j], soc_info->rgltr_delay[j]); } else { if (soc_info->rgltr[j]) rc = regulator_enable(soc_info->rgltr[j]); } if (rc) { pr_err("%s enable failed\n", soc_info->rgltr_name[j]); goto disable_rgltr; } } return rc; disable_rgltr: for (j--; j >= 0; j--) { if (soc_info->rgltr_ctrl_support == true) { cam_soc_util_regulator_disable(soc_info->rgltr[j], soc_info->rgltr_name[j], soc_info->rgltr_min_volt[j], soc_info->rgltr_max_volt[j], soc_info->rgltr_op_mode[j], soc_info->rgltr_delay[j]); } else { if (soc_info->rgltr[j]) regulator_disable(soc_info->rgltr[j]); } } return rc; } int cam_soc_util_request_platform_resource( struct cam_hw_soc_info *soc_info, irq_handler_t handler, void *irq_data) { int i = 0, rc = 0; struct platform_device *pdev = NULL; if (!soc_info || !soc_info->pdev) if (!soc_info || !soc_info->pdev) { pr_err("Invalid parameters\n"); return -EINVAL; } pdev = soc_info->pdev; for (i = 0; i < soc_info->num_mem_block; i++) { if (soc_info->reserve_mem) { if (!request_mem_region(soc_info->mem_block[i]->start, resource_size(soc_info->mem_block[i]), soc_info->mem_block_name[i])){ pr_err("Error Mem Region request Failed:%s\n", soc_info->mem_block_name[i]); rc = -ENOMEM; goto unmap_base; } } soc_info->reg_map[i].mem_base = ioremap( soc_info->mem_block[i]->start, resource_size(soc_info->mem_block[i])); Loading @@ -587,6 +1051,11 @@ int cam_soc_util_request_platform_resource(struct cam_hw_soc_info *soc_info, } for (i = 0; i < soc_info->num_rgltr; i++) { if (soc_info->rgltr_name[i] == NULL) { pr_err("can't find regulator name\n"); goto put_regulator; } rc = cam_soc_util_get_regulator(pdev, &soc_info->rgltr[i], soc_info->rgltr_name[i]); if (rc) Loading @@ -597,7 +1066,7 @@ int cam_soc_util_request_platform_resource(struct cam_hw_soc_info *soc_info, rc = devm_request_irq(&pdev->dev, soc_info->irq_line->start, handler, IRQF_TRIGGER_RISING, soc_info->irq_name, irq_data); if (rc < 0) { if (rc) { pr_err("irq request fail\n"); rc = -EBUSY; goto put_regulator; Loading @@ -617,6 +1086,16 @@ int cam_soc_util_request_platform_resource(struct cam_hw_soc_info *soc_info, } } rc = cam_soc_util_request_pinctrl(soc_info); if (rc) CDBG("Failed in request pinctrl, rc=%d\n", rc); rc = cam_soc_util_request_gpio_table(soc_info, true); if (rc) { pr_err("Failed in request gpio table, rc=%d\n", rc); goto put_clk; } return rc; put_clk: Loading Loading @@ -650,6 +1129,9 @@ int cam_soc_util_request_platform_resource(struct cam_hw_soc_info *soc_info, if (i == -1) i = soc_info->num_reg_map; for (i = i - 1; i >= 0; i--) { if (soc_info->reserve_mem) release_mem_region(soc_info->mem_block[i]->start, resource_size(soc_info->mem_block[i])); iounmap(soc_info->reg_map[i].mem_base); soc_info->reg_map[i].mem_base = NULL; soc_info->reg_map[i].size = 0; Loading @@ -663,8 +1145,11 @@ int cam_soc_util_release_platform_resource(struct cam_hw_soc_info *soc_info) int i; struct platform_device *pdev = NULL; if (!soc_info || !soc_info->pdev) if (!soc_info || !soc_info->pdev) { pr_err("Invalid parameter\n"); return -EINVAL; } pdev = soc_info->pdev; Loading Loading @@ -692,24 +1177,28 @@ int cam_soc_util_release_platform_resource(struct cam_hw_soc_info *soc_info) soc_info->irq_line->start, soc_info->irq_data); } if (soc_info->pinctrl_info.pinctrl) devm_pinctrl_put(soc_info->pinctrl_info.pinctrl); /* release for gpio */ cam_soc_util_request_gpio_table(soc_info, false); return 0; } int cam_soc_util_enable_platform_resource(struct cam_hw_soc_info *soc_info, bool enable_clocks, enum cam_vote_level clk_level, bool enable_irq) { int i, rc = 0; int rc = 0; if (!soc_info) return -EINVAL; for (i = 0; i < soc_info->num_rgltr; i++) { rc = regulator_enable(soc_info->rgltr[i]); rc = cam_soc_util_regulator_enable_default(soc_info); if (rc) { pr_err("Regulator enable %s failed\n", soc_info->rgltr_name[i]); goto disable_regulator; } pr_err("Regulators enable failed\n"); return rc; } if (enable_clocks) { Loading @@ -724,19 +1213,28 @@ int cam_soc_util_enable_platform_resource(struct cam_hw_soc_info *soc_info, goto disable_clk; } if (soc_info->pinctrl_info.pinctrl && soc_info->pinctrl_info.gpio_state_active) { rc = pinctrl_select_state(soc_info->pinctrl_info.pinctrl, soc_info->pinctrl_info.gpio_state_active); if (rc) goto disable_irq; } return rc; disable_irq: if (enable_irq) cam_soc_util_irq_disable(soc_info); disable_clk: if (enable_clocks) cam_soc_util_clk_disable_default(soc_info); disable_regulator: if (i == -1) i = soc_info->num_rgltr; for (i = i - 1; i >= 0; i--) { if (soc_info->rgltr[i]) regulator_disable(soc_info->rgltr[i]); } cam_soc_util_regulator_disable_default(soc_info); return rc; } Loading @@ -744,7 +1242,7 @@ int cam_soc_util_enable_platform_resource(struct cam_hw_soc_info *soc_info, int cam_soc_util_disable_platform_resource(struct cam_hw_soc_info *soc_info, bool disable_clocks, bool disble_irq) { int i, rc = 0; int rc = 0; if (!soc_info) return -EINVAL; Loading @@ -752,18 +1250,16 @@ int cam_soc_util_disable_platform_resource(struct cam_hw_soc_info *soc_info, if (disable_clocks) cam_soc_util_clk_disable_default(soc_info); for (i = soc_info->num_rgltr - 1; i >= 0; i--) { rc |= regulator_disable(soc_info->rgltr[i]); if (rc) { pr_err("Regulator disble %s failed\n", soc_info->rgltr_name[i]); continue; } } cam_soc_util_regulator_disable_default(soc_info); if (disble_irq) rc |= cam_soc_util_irq_disable(soc_info); if (soc_info->pinctrl_info.pinctrl && soc_info->pinctrl_info.gpio_state_suspend) rc = pinctrl_select_state(soc_info->pinctrl_info.pinctrl, soc_info->pinctrl_info.gpio_state_suspend); return rc; } Loading drivers/media/platform/msm/camera/cam_utils/cam_soc_util.h +91 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #include <linux/clk.h> #include <linux/interrupt.h> #include <linux/io.h> #include <linux/delay.h> #include <linux/platform_device.h> #include <linux/regulator/consumer.h> Loading Loading @@ -59,6 +60,10 @@ enum cam_vote_level { CAM_MAX_VOTE, }; /* pinctrl states */ #define CAM_SOC_PINCTRL_STATE_SLEEP "cam_suspend" #define CAM_SOC_PINCTRL_STATE_DEFAULT "cam_default" /** * struct cam_soc_reg_map: Information about the mapped register space * Loading @@ -73,6 +78,35 @@ struct cam_soc_reg_map { resource_size_t size; }; /** * struct cam_soc_pinctrl_info: Information about pinctrl data * * @pinctrl: pintrl object * @gpio_state_active: default pinctrl state * @gpio_state_suspend suspend state of pinctrl **/ struct cam_soc_pinctrl_info { struct pinctrl *pinctrl; struct pinctrl_state *gpio_state_active; struct pinctrl_state *gpio_state_suspend; }; /** * struct cam_soc_gpio_data: Information about the gpio pins * * @cam_gpio_common_tbl: It is list of al the gpios present in gpios node * @cam_gpio_common_tbl_size: It is equal to number of gpios prsent in * gpios node in DTSI * @cam_gpio_req_tbl It is list of al the requesetd gpios * @cam_gpio_req_tbl_size: It is size of requested gpios **/ struct cam_soc_gpio_data { struct gpio *cam_gpio_common_tbl; uint8_t cam_gpio_common_tbl_size; struct gpio *cam_gpio_req_tbl; uint8_t cam_gpio_req_tbl_size; }; /** * struct cam_hw_soc_info: Soc information pertaining to specific instance of * Camera hardware driver module Loading @@ -92,9 +126,16 @@ struct cam_soc_reg_map { * @num_reg_map: Number of mapped register space associated * with mem_block. num_reg_map = num_mem_block in * most cases * @reserve_mem: Whether to reserve memory for Mem blocks * @num_rgltr: Number of regulators * @rgltr_name: Array of regulator names * @rgltr_ctrl_support: Whether regulator control is supported * @rgltr_min_volt: Array of minimum regulator voltage * @rgltr_max_volt: Array of maximum regulator voltage * @rgltr_op_mode: Array of regulator operation mode * @rgltr_type: Array of regulator names * @rgltr: Array of associated regulator resources * @rgltr_delay: Array of regulator delay values * @num_clk: Number of clocks * @clk_name: Array of clock names * @clk: Array of associated clock resources Loading @@ -102,6 +143,8 @@ struct cam_soc_reg_map { * values at different vote levels * @src_clk_idx: Source clock index that is rate-controllable * @clk_level_valid: Indicates whether corresponding level is valid * @gpio_data: Pointer to gpio info * @pinctrl_info: Pointer to pinctrl info * @soc_private: Soc private data * */ Loading @@ -109,7 +152,6 @@ struct cam_hw_soc_info { struct platform_device *pdev; uint32_t hw_version; uint32_t index; const char *irq_name; struct resource *irq_line; void *irq_data; Loading @@ -120,10 +162,17 @@ struct cam_hw_soc_info { struct resource *mem_block[CAM_SOC_MAX_BLOCK]; struct cam_soc_reg_map reg_map[CAM_SOC_MAX_BASE]; uint32_t num_reg_map; uint32_t reserve_mem; uint32_t num_rgltr; const char *rgltr_name[CAM_SOC_MAX_REGULATOR]; uint32_t rgltr_ctrl_support; uint32_t rgltr_min_volt[CAM_SOC_MAX_REGULATOR]; uint32_t rgltr_max_volt[CAM_SOC_MAX_REGULATOR]; uint32_t rgltr_op_mode[CAM_SOC_MAX_REGULATOR]; uint32_t rgltr_type[CAM_SOC_MAX_REGULATOR]; struct regulator *rgltr[CAM_SOC_MAX_REGULATOR]; uint32_t rgltr_delay[CAM_SOC_MAX_REGULATOR]; uint32_t num_clk; const char *clk_name[CAM_SOC_MAX_CLK]; Loading @@ -132,6 +181,8 @@ struct cam_hw_soc_info { int32_t src_clk_idx; bool clk_level_valid[CAM_MAX_VOTE]; struct cam_soc_gpio_data *gpio_data; struct cam_soc_pinctrl_info pinctrl_info; void *soc_private; }; Loading Loading @@ -340,6 +391,45 @@ int cam_soc_util_irq_enable(struct cam_hw_soc_info *soc_info); */ int cam_soc_util_irq_disable(struct cam_hw_soc_info *soc_info); /** * cam_soc_util_regulator_enable() * * @brief: Enable single regulator * * @rgltr Regulator that needs to be turned ON * @rgltr_name Associated Regulator name * @rgltr_min_volt: Requested minimum volatage * @rgltr_max_volt: Requested maximum volatage * @rgltr_op_mode: Requested Load * @rgltr_delay: Requested delay needed aaftre enabling regulator * * @return: Success or failure */ int cam_soc_util_regulator_enable(struct regulator *rgltr, const char *rgltr_name, uint32_t rgltr_min_volt, uint32_t rgltr_max_volt, uint32_t rgltr_op_mode, uint32_t rgltr_delay); /** * cam_soc_util_regulator_enable() * * @brief: Disable single regulator * * @rgltr Regulator that needs to be turned ON * @rgltr_name Associated Regulator name * @rgltr_min_volt: Requested minimum volatage * @rgltr_max_volt: Requested maximum volatage * @rgltr_op_mode: Requested Load * @rgltr_delay: Requested delay needed aaftre enabling regulator * * @return: Success or failure */ int cam_soc_util_regulator_disable(struct regulator *rgltr, const char *rgltr_name, uint32_t rgltr_min_volt, uint32_t rgltr_max_volt, uint32_t rgltr_op_mode, uint32_t rgltr_delay); /** * cam_soc_util_w() * Loading Loading
drivers/media/platform/msm/camera/cam_utils/cam_soc_util.c +535 −39 Original line number Diff line number Diff line Loading @@ -14,6 +14,9 @@ #include <linux/of.h> #include <linux/clk.h> #include <linux/slab.h> #include <linux/gpio.h> #include <linux/of_gpio.h> #include "cam_soc_util.h" #undef CDBG Loading Loading @@ -443,43 +446,304 @@ int cam_soc_util_set_clk_rate_level(struct cam_hw_soc_info *soc_info, return rc; }; int cam_soc_util_get_dt_properties(struct cam_hw_soc_info *soc_info) static int cam_soc_util_get_dt_gpio_req_tbl(struct device_node *of_node, struct cam_soc_gpio_data *gconf, uint16_t *gpio_array, uint16_t gpio_array_size) { int32_t rc = 0, i = 0; uint32_t count = 0; uint32_t *val_array = NULL; if (!of_get_property(of_node, "gpio-req-tbl-num", &count)) return 0; count /= sizeof(uint32_t); if (!count) { pr_err("gpio-req-tbl-num 0\n"); return 0; } val_array = kcalloc(count, sizeof(uint32_t), GFP_KERNEL); if (!val_array) return -ENOMEM; gconf->cam_gpio_req_tbl = kcalloc(count, sizeof(struct gpio), GFP_KERNEL); if (!gconf->cam_gpio_req_tbl) { rc = -ENOMEM; goto free_val_array; } gconf->cam_gpio_req_tbl_size = count; rc = of_property_read_u32_array(of_node, "gpio-req-tbl-num", val_array, count); if (rc) { pr_err("failed in reading gpio-req-tbl-num, rc = %d\n", rc); goto free_gpio_req_tbl; } for (i = 0; i < count; i++) { if (val_array[i] >= gpio_array_size) { pr_err("gpio req tbl index %d invalid\n", val_array[i]); goto free_gpio_req_tbl; } gconf->cam_gpio_req_tbl[i].gpio = gpio_array[val_array[i]]; CDBG("cam_gpio_req_tbl[%d].gpio = %d\n", i, gconf->cam_gpio_req_tbl[i].gpio); } rc = of_property_read_u32_array(of_node, "gpio-req-tbl-flags", val_array, count); if (rc) { pr_err("Failed in gpio-req-tbl-flags, rc %d\n", rc); goto free_gpio_req_tbl; } for (i = 0; i < count; i++) { gconf->cam_gpio_req_tbl[i].flags = val_array[i]; CDBG("cam_gpio_req_tbl[%d].flags = %ld\n", i, gconf->cam_gpio_req_tbl[i].flags); } for (i = 0; i < count; i++) { rc = of_property_read_string_index(of_node, "gpio-req-tbl-label", i, &gconf->cam_gpio_req_tbl[i].label); if (rc) { pr_err("Failed rc %d\n", rc); goto free_gpio_req_tbl; } CDBG("cam_gpio_req_tbl[%d].label = %s\n", i, gconf->cam_gpio_req_tbl[i].label); } kfree(val_array); return rc; free_gpio_req_tbl: kfree(gconf->cam_gpio_req_tbl); free_val_array: kfree(val_array); gconf->cam_gpio_req_tbl_size = 0; return rc; } static int cam_soc_util_get_gpio_info(struct cam_hw_soc_info *soc_info) { int32_t rc = 0, i = 0; uint16_t *gpio_array = NULL; int16_t gpio_array_size = 0; struct cam_soc_gpio_data *gconf = NULL; struct device_node *of_node = NULL; int count = 0, i = 0, rc = 0; struct platform_device *pdev = NULL; if (!soc_info || !soc_info->pdev) return -EINVAL; pdev = soc_info->pdev; of_node = pdev->dev.of_node; rc = of_property_read_u32(of_node, "cell-index", &soc_info->index); /* Validate input parameters */ if (!of_node) { pr_err("Invalid param of_node\n"); return -EINVAL; } gpio_array_size = of_gpio_count(of_node); if (gpio_array_size <= 0) return 0; CDBG("gpio count %d\n", gpio_array_size); gpio_array = kcalloc(gpio_array_size, sizeof(uint16_t), GFP_KERNEL); if (!gpio_array) goto free_gpio_conf; for (i = 0; i < gpio_array_size; i++) { gpio_array[i] = of_get_gpio(of_node, i); CDBG("gpio_array[%d] = %d", i, gpio_array[i]); } gconf = kzalloc(sizeof(*gconf), GFP_KERNEL); if (!gconf) return -ENOMEM; rc = cam_soc_util_get_dt_gpio_req_tbl(of_node, gconf, gpio_array, gpio_array_size); if (rc) { pr_err("device %s failed to read cell-index\n", pdev->name); pr_err("failed in msm_camera_get_dt_gpio_req_tbl\n"); goto free_gpio_array; } gconf->cam_gpio_common_tbl = kcalloc(gpio_array_size, sizeof(struct gpio), GFP_KERNEL); if (!gconf->cam_gpio_common_tbl) { rc = -ENOMEM; goto free_gpio_array; } for (i = 0; i <= gpio_array_size; i++) gconf->cam_gpio_common_tbl[i].gpio = gpio_array[i]; gconf->cam_gpio_common_tbl_size = gpio_array_size; soc_info->gpio_data = gconf; kfree(gpio_array); return rc; free_gpio_array: kfree(gpio_array); free_gpio_conf: kfree(gconf); soc_info->gpio_data = NULL; return rc; } static int cam_soc_util_request_gpio_table( struct cam_hw_soc_info *soc_info, bool gpio_en) { int rc = 0, i = 0; uint8_t size = 0; struct cam_soc_gpio_data *gpio_conf = soc_info->gpio_data; struct gpio *gpio_tbl = NULL; if (!gpio_conf) { CDBG("No GPIO entry\n"); return 0; } if (gpio_conf->cam_gpio_common_tbl_size <= 0) { pr_err("GPIO table size is invalid\n"); return -EINVAL; } size = gpio_conf->cam_gpio_req_tbl_size; gpio_tbl = gpio_conf->cam_gpio_req_tbl; if (!gpio_tbl || !size) { pr_err("Invalid gpio_tbl %pK / size %d\n", gpio_tbl, size); return -EINVAL; } for (i = 0; i < size; i++) { CDBG("i=%d, gpio=%d dir=%ld\n", i, gpio_tbl[i].gpio, gpio_tbl[i].flags); } if (gpio_en) { for (i = 0; i < size; i++) { rc = gpio_request_one(gpio_tbl[i].gpio, gpio_tbl[i].flags, gpio_tbl[i].label); if (rc) { /* * After GPIO request fails, contine to * apply new gpios, outout a error message * for driver bringup debug */ pr_err("gpio %d:%s request fails\n", gpio_tbl[i].gpio, gpio_tbl[i].label); } } } else { gpio_free_array(gpio_tbl, size); } return rc; } static int cam_soc_util_get_dt_regulator_info (struct cam_hw_soc_info *soc_info) { int rc = 0, count = 0, i = 0; struct device_node *of_node = NULL; struct platform_device *pdev = NULL; if (!soc_info || !soc_info->pdev) { pr_err("Invalid parameters\n"); return -EINVAL; } pdev = soc_info->pdev; of_node = pdev->dev.of_node; soc_info->num_rgltr = 0; count = of_property_count_strings(of_node, "regulator-names"); if (count != -EINVAL) { if (count <= 0) { pr_err("no regulators found\n"); count = 0; return -EINVAL; } soc_info->num_rgltr = count; } else { CDBG("No regulators node found\n"); return 0; } for (i = 0; i < soc_info->num_rgltr; i++) { rc = of_property_read_string_index(of_node, "regulator-names", i, &soc_info->rgltr_name[i]); CDBG("rgltr_name[%d] = %s\n", i, soc_info->rgltr_name[i]); if (rc) { pr_err("no regulator resource at cnt=%d\n", i); rc = -ENODEV; return rc; return -ENODEV; } } if (!of_property_read_bool(of_node, "rgltr-cntrl-support")) { CDBG("No regulator control parameter defined\n"); soc_info->rgltr_ctrl_support = false; return 0; } soc_info->rgltr_ctrl_support = true; rc = of_property_read_u32_array(of_node, "rgltr-min-voltage", soc_info->rgltr_min_volt, soc_info->num_rgltr); if (rc) { pr_err("No minimum volatage value found, rc=%d\n", rc); return -EINVAL; } rc = of_property_read_u32_array(of_node, "rgltr-max-voltage", soc_info->rgltr_max_volt, soc_info->num_rgltr); if (rc) { pr_err("No maximum volatage value found, rc=%d\n", rc); return -EINVAL; } rc = of_property_read_u32_array(of_node, "rgltr-load-current", soc_info->rgltr_op_mode, soc_info->num_rgltr); if (rc) { pr_err("No Load curent found rc=%d\n", rc); return -EINVAL; } return rc; } int cam_soc_util_get_dt_properties(struct cam_hw_soc_info *soc_info) { struct device_node *of_node = NULL; int count = 0, i = 0, rc = 0; struct platform_device *pdev = NULL; if (!soc_info || !soc_info->pdev) return -EINVAL; pdev = soc_info->pdev; of_node = pdev->dev.of_node; rc = of_property_read_u32(of_node, "cell-index", &soc_info->index); if (rc) { pr_err("device %s failed to read cell-index\n", pdev->name); return rc; } count = of_property_count_strings(of_node, "reg-names"); if (count <= 0) { pr_err("no reg-names found\n"); Loading Loading @@ -519,6 +783,7 @@ int cam_soc_util_get_dt_properties(struct cam_hw_soc_info *soc_info) &soc_info->irq_name); if (rc) { pr_warn("No interrupt line present\n"); rc = 0; } else { soc_info->irq_line = platform_get_resource_byname(pdev, IORESOURCE_IRQ, soc_info->irq_name); Loading @@ -529,7 +794,17 @@ int cam_soc_util_get_dt_properties(struct cam_hw_soc_info *soc_info) } } rc = cam_soc_util_get_dt_regulator_info(soc_info); if (rc) return rc; rc = cam_soc_util_get_dt_clk_info(soc_info); if (rc) return rc; rc = cam_soc_util_get_gpio_info(soc_info); if (rc) return rc; return rc; } Loading Loading @@ -559,18 +834,207 @@ static int cam_soc_util_get_regulator(struct platform_device *pdev, return rc; } int cam_soc_util_request_platform_resource(struct cam_hw_soc_info *soc_info, int cam_soc_util_regulator_disable(struct regulator *rgltr, const char *rgltr_name, uint32_t rgltr_min_volt, uint32_t rgltr_max_volt, uint32_t rgltr_op_mode, uint32_t rgltr_delay_ms) { int32_t rc = 0; if (!rgltr) { pr_err("Invalid NULL parameter\n"); return -EINVAL; } rc = regulator_disable(rgltr); if (rc) { pr_err("%s regulator disable failed\n", rgltr_name); return rc; } if (rgltr_delay_ms > 20) msleep(rgltr_delay_ms); else if (rgltr_delay_ms) usleep_range(rgltr_delay_ms * 1000, (rgltr_delay_ms * 1000) + 1000); if (regulator_count_voltages(rgltr) > 0) { regulator_set_load(rgltr, 0); regulator_set_voltage(rgltr, 0, rgltr_max_volt); } return rc; } int cam_soc_util_regulator_enable(struct regulator *rgltr, const char *rgltr_name, uint32_t rgltr_min_volt, uint32_t rgltr_max_volt, uint32_t rgltr_op_mode, uint32_t rgltr_delay) { int32_t rc = 0; if (!rgltr) { pr_err("Invalid NULL parameter\n"); return -EINVAL; } if (regulator_count_voltages(rgltr) > 0) { CDBG("voltage min=%d, max=%d\n", rgltr_min_volt, rgltr_max_volt); rc = regulator_set_voltage( rgltr, rgltr_min_volt, rgltr_max_volt); if (rc) { pr_err("%s set voltage failed\n", rgltr_name); return rc; } rc = regulator_set_load(rgltr, rgltr_op_mode); if (rc) { pr_err("%s set optimum mode failed\n", rgltr_name); return rc; } } rc = regulator_enable(rgltr); if (rc) { pr_err("%s regulator_enable failed\n", rgltr_name); return rc; } if (rgltr_delay > 20) msleep(rgltr_delay); else if (rgltr_delay) usleep_range(rgltr_delay * 1000, (rgltr_delay * 1000) + 1000); return rc; } static int cam_soc_util_request_pinctrl( struct cam_hw_soc_info *soc_info) { struct cam_soc_pinctrl_info *device_pctrl = &soc_info->pinctrl_info; struct device *dev = &soc_info->pdev->dev; device_pctrl->pinctrl = devm_pinctrl_get(dev); if (IS_ERR_OR_NULL(device_pctrl->pinctrl)) { CDBG("Pinctrl not available\n"); device_pctrl->pinctrl = NULL; return 0; } device_pctrl->gpio_state_active = pinctrl_lookup_state(device_pctrl->pinctrl, CAM_SOC_PINCTRL_STATE_DEFAULT); if (IS_ERR_OR_NULL(device_pctrl->gpio_state_active)) { pr_err("Failed to get the active state pinctrl handle\n"); device_pctrl->gpio_state_active = NULL; return -EINVAL; } device_pctrl->gpio_state_suspend = pinctrl_lookup_state(device_pctrl->pinctrl, CAM_SOC_PINCTRL_STATE_SLEEP); if (IS_ERR_OR_NULL(device_pctrl->gpio_state_suspend)) { pr_err("Failed to get the suspend state pinctrl handle\n"); device_pctrl->gpio_state_suspend = NULL; return -EINVAL; } return 0; } static void cam_soc_util_regulator_disable_default( struct cam_hw_soc_info *soc_info) { int j = 0; uint32_t num_rgltr = soc_info->num_rgltr; for (j = num_rgltr-1; j >= 0; j--) { if (soc_info->rgltr_ctrl_support == true) { cam_soc_util_regulator_disable(soc_info->rgltr[j], soc_info->rgltr_name[j], soc_info->rgltr_min_volt[j], soc_info->rgltr_max_volt[j], soc_info->rgltr_op_mode[j], soc_info->rgltr_delay[j]); } else { if (soc_info->rgltr[j]) regulator_disable(soc_info->rgltr[j]); } } } static int cam_soc_util_regulator_enable_default( struct cam_hw_soc_info *soc_info) { int j = 0, rc = 0; uint32_t num_rgltr = soc_info->num_rgltr; for (j = 0; j < num_rgltr; j++) { if (soc_info->rgltr_ctrl_support == true) { rc = cam_soc_util_regulator_enable(soc_info->rgltr[j], soc_info->rgltr_name[j], soc_info->rgltr_min_volt[j], soc_info->rgltr_max_volt[j], soc_info->rgltr_op_mode[j], soc_info->rgltr_delay[j]); } else { if (soc_info->rgltr[j]) rc = regulator_enable(soc_info->rgltr[j]); } if (rc) { pr_err("%s enable failed\n", soc_info->rgltr_name[j]); goto disable_rgltr; } } return rc; disable_rgltr: for (j--; j >= 0; j--) { if (soc_info->rgltr_ctrl_support == true) { cam_soc_util_regulator_disable(soc_info->rgltr[j], soc_info->rgltr_name[j], soc_info->rgltr_min_volt[j], soc_info->rgltr_max_volt[j], soc_info->rgltr_op_mode[j], soc_info->rgltr_delay[j]); } else { if (soc_info->rgltr[j]) regulator_disable(soc_info->rgltr[j]); } } return rc; } int cam_soc_util_request_platform_resource( struct cam_hw_soc_info *soc_info, irq_handler_t handler, void *irq_data) { int i = 0, rc = 0; struct platform_device *pdev = NULL; if (!soc_info || !soc_info->pdev) if (!soc_info || !soc_info->pdev) { pr_err("Invalid parameters\n"); return -EINVAL; } pdev = soc_info->pdev; for (i = 0; i < soc_info->num_mem_block; i++) { if (soc_info->reserve_mem) { if (!request_mem_region(soc_info->mem_block[i]->start, resource_size(soc_info->mem_block[i]), soc_info->mem_block_name[i])){ pr_err("Error Mem Region request Failed:%s\n", soc_info->mem_block_name[i]); rc = -ENOMEM; goto unmap_base; } } soc_info->reg_map[i].mem_base = ioremap( soc_info->mem_block[i]->start, resource_size(soc_info->mem_block[i])); Loading @@ -587,6 +1051,11 @@ int cam_soc_util_request_platform_resource(struct cam_hw_soc_info *soc_info, } for (i = 0; i < soc_info->num_rgltr; i++) { if (soc_info->rgltr_name[i] == NULL) { pr_err("can't find regulator name\n"); goto put_regulator; } rc = cam_soc_util_get_regulator(pdev, &soc_info->rgltr[i], soc_info->rgltr_name[i]); if (rc) Loading @@ -597,7 +1066,7 @@ int cam_soc_util_request_platform_resource(struct cam_hw_soc_info *soc_info, rc = devm_request_irq(&pdev->dev, soc_info->irq_line->start, handler, IRQF_TRIGGER_RISING, soc_info->irq_name, irq_data); if (rc < 0) { if (rc) { pr_err("irq request fail\n"); rc = -EBUSY; goto put_regulator; Loading @@ -617,6 +1086,16 @@ int cam_soc_util_request_platform_resource(struct cam_hw_soc_info *soc_info, } } rc = cam_soc_util_request_pinctrl(soc_info); if (rc) CDBG("Failed in request pinctrl, rc=%d\n", rc); rc = cam_soc_util_request_gpio_table(soc_info, true); if (rc) { pr_err("Failed in request gpio table, rc=%d\n", rc); goto put_clk; } return rc; put_clk: Loading Loading @@ -650,6 +1129,9 @@ int cam_soc_util_request_platform_resource(struct cam_hw_soc_info *soc_info, if (i == -1) i = soc_info->num_reg_map; for (i = i - 1; i >= 0; i--) { if (soc_info->reserve_mem) release_mem_region(soc_info->mem_block[i]->start, resource_size(soc_info->mem_block[i])); iounmap(soc_info->reg_map[i].mem_base); soc_info->reg_map[i].mem_base = NULL; soc_info->reg_map[i].size = 0; Loading @@ -663,8 +1145,11 @@ int cam_soc_util_release_platform_resource(struct cam_hw_soc_info *soc_info) int i; struct platform_device *pdev = NULL; if (!soc_info || !soc_info->pdev) if (!soc_info || !soc_info->pdev) { pr_err("Invalid parameter\n"); return -EINVAL; } pdev = soc_info->pdev; Loading Loading @@ -692,24 +1177,28 @@ int cam_soc_util_release_platform_resource(struct cam_hw_soc_info *soc_info) soc_info->irq_line->start, soc_info->irq_data); } if (soc_info->pinctrl_info.pinctrl) devm_pinctrl_put(soc_info->pinctrl_info.pinctrl); /* release for gpio */ cam_soc_util_request_gpio_table(soc_info, false); return 0; } int cam_soc_util_enable_platform_resource(struct cam_hw_soc_info *soc_info, bool enable_clocks, enum cam_vote_level clk_level, bool enable_irq) { int i, rc = 0; int rc = 0; if (!soc_info) return -EINVAL; for (i = 0; i < soc_info->num_rgltr; i++) { rc = regulator_enable(soc_info->rgltr[i]); rc = cam_soc_util_regulator_enable_default(soc_info); if (rc) { pr_err("Regulator enable %s failed\n", soc_info->rgltr_name[i]); goto disable_regulator; } pr_err("Regulators enable failed\n"); return rc; } if (enable_clocks) { Loading @@ -724,19 +1213,28 @@ int cam_soc_util_enable_platform_resource(struct cam_hw_soc_info *soc_info, goto disable_clk; } if (soc_info->pinctrl_info.pinctrl && soc_info->pinctrl_info.gpio_state_active) { rc = pinctrl_select_state(soc_info->pinctrl_info.pinctrl, soc_info->pinctrl_info.gpio_state_active); if (rc) goto disable_irq; } return rc; disable_irq: if (enable_irq) cam_soc_util_irq_disable(soc_info); disable_clk: if (enable_clocks) cam_soc_util_clk_disable_default(soc_info); disable_regulator: if (i == -1) i = soc_info->num_rgltr; for (i = i - 1; i >= 0; i--) { if (soc_info->rgltr[i]) regulator_disable(soc_info->rgltr[i]); } cam_soc_util_regulator_disable_default(soc_info); return rc; } Loading @@ -744,7 +1242,7 @@ int cam_soc_util_enable_platform_resource(struct cam_hw_soc_info *soc_info, int cam_soc_util_disable_platform_resource(struct cam_hw_soc_info *soc_info, bool disable_clocks, bool disble_irq) { int i, rc = 0; int rc = 0; if (!soc_info) return -EINVAL; Loading @@ -752,18 +1250,16 @@ int cam_soc_util_disable_platform_resource(struct cam_hw_soc_info *soc_info, if (disable_clocks) cam_soc_util_clk_disable_default(soc_info); for (i = soc_info->num_rgltr - 1; i >= 0; i--) { rc |= regulator_disable(soc_info->rgltr[i]); if (rc) { pr_err("Regulator disble %s failed\n", soc_info->rgltr_name[i]); continue; } } cam_soc_util_regulator_disable_default(soc_info); if (disble_irq) rc |= cam_soc_util_irq_disable(soc_info); if (soc_info->pinctrl_info.pinctrl && soc_info->pinctrl_info.gpio_state_suspend) rc = pinctrl_select_state(soc_info->pinctrl_info.pinctrl, soc_info->pinctrl_info.gpio_state_suspend); return rc; } Loading
drivers/media/platform/msm/camera/cam_utils/cam_soc_util.h +91 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #include <linux/clk.h> #include <linux/interrupt.h> #include <linux/io.h> #include <linux/delay.h> #include <linux/platform_device.h> #include <linux/regulator/consumer.h> Loading Loading @@ -59,6 +60,10 @@ enum cam_vote_level { CAM_MAX_VOTE, }; /* pinctrl states */ #define CAM_SOC_PINCTRL_STATE_SLEEP "cam_suspend" #define CAM_SOC_PINCTRL_STATE_DEFAULT "cam_default" /** * struct cam_soc_reg_map: Information about the mapped register space * Loading @@ -73,6 +78,35 @@ struct cam_soc_reg_map { resource_size_t size; }; /** * struct cam_soc_pinctrl_info: Information about pinctrl data * * @pinctrl: pintrl object * @gpio_state_active: default pinctrl state * @gpio_state_suspend suspend state of pinctrl **/ struct cam_soc_pinctrl_info { struct pinctrl *pinctrl; struct pinctrl_state *gpio_state_active; struct pinctrl_state *gpio_state_suspend; }; /** * struct cam_soc_gpio_data: Information about the gpio pins * * @cam_gpio_common_tbl: It is list of al the gpios present in gpios node * @cam_gpio_common_tbl_size: It is equal to number of gpios prsent in * gpios node in DTSI * @cam_gpio_req_tbl It is list of al the requesetd gpios * @cam_gpio_req_tbl_size: It is size of requested gpios **/ struct cam_soc_gpio_data { struct gpio *cam_gpio_common_tbl; uint8_t cam_gpio_common_tbl_size; struct gpio *cam_gpio_req_tbl; uint8_t cam_gpio_req_tbl_size; }; /** * struct cam_hw_soc_info: Soc information pertaining to specific instance of * Camera hardware driver module Loading @@ -92,9 +126,16 @@ struct cam_soc_reg_map { * @num_reg_map: Number of mapped register space associated * with mem_block. num_reg_map = num_mem_block in * most cases * @reserve_mem: Whether to reserve memory for Mem blocks * @num_rgltr: Number of regulators * @rgltr_name: Array of regulator names * @rgltr_ctrl_support: Whether regulator control is supported * @rgltr_min_volt: Array of minimum regulator voltage * @rgltr_max_volt: Array of maximum regulator voltage * @rgltr_op_mode: Array of regulator operation mode * @rgltr_type: Array of regulator names * @rgltr: Array of associated regulator resources * @rgltr_delay: Array of regulator delay values * @num_clk: Number of clocks * @clk_name: Array of clock names * @clk: Array of associated clock resources Loading @@ -102,6 +143,8 @@ struct cam_soc_reg_map { * values at different vote levels * @src_clk_idx: Source clock index that is rate-controllable * @clk_level_valid: Indicates whether corresponding level is valid * @gpio_data: Pointer to gpio info * @pinctrl_info: Pointer to pinctrl info * @soc_private: Soc private data * */ Loading @@ -109,7 +152,6 @@ struct cam_hw_soc_info { struct platform_device *pdev; uint32_t hw_version; uint32_t index; const char *irq_name; struct resource *irq_line; void *irq_data; Loading @@ -120,10 +162,17 @@ struct cam_hw_soc_info { struct resource *mem_block[CAM_SOC_MAX_BLOCK]; struct cam_soc_reg_map reg_map[CAM_SOC_MAX_BASE]; uint32_t num_reg_map; uint32_t reserve_mem; uint32_t num_rgltr; const char *rgltr_name[CAM_SOC_MAX_REGULATOR]; uint32_t rgltr_ctrl_support; uint32_t rgltr_min_volt[CAM_SOC_MAX_REGULATOR]; uint32_t rgltr_max_volt[CAM_SOC_MAX_REGULATOR]; uint32_t rgltr_op_mode[CAM_SOC_MAX_REGULATOR]; uint32_t rgltr_type[CAM_SOC_MAX_REGULATOR]; struct regulator *rgltr[CAM_SOC_MAX_REGULATOR]; uint32_t rgltr_delay[CAM_SOC_MAX_REGULATOR]; uint32_t num_clk; const char *clk_name[CAM_SOC_MAX_CLK]; Loading @@ -132,6 +181,8 @@ struct cam_hw_soc_info { int32_t src_clk_idx; bool clk_level_valid[CAM_MAX_VOTE]; struct cam_soc_gpio_data *gpio_data; struct cam_soc_pinctrl_info pinctrl_info; void *soc_private; }; Loading Loading @@ -340,6 +391,45 @@ int cam_soc_util_irq_enable(struct cam_hw_soc_info *soc_info); */ int cam_soc_util_irq_disable(struct cam_hw_soc_info *soc_info); /** * cam_soc_util_regulator_enable() * * @brief: Enable single regulator * * @rgltr Regulator that needs to be turned ON * @rgltr_name Associated Regulator name * @rgltr_min_volt: Requested minimum volatage * @rgltr_max_volt: Requested maximum volatage * @rgltr_op_mode: Requested Load * @rgltr_delay: Requested delay needed aaftre enabling regulator * * @return: Success or failure */ int cam_soc_util_regulator_enable(struct regulator *rgltr, const char *rgltr_name, uint32_t rgltr_min_volt, uint32_t rgltr_max_volt, uint32_t rgltr_op_mode, uint32_t rgltr_delay); /** * cam_soc_util_regulator_enable() * * @brief: Disable single regulator * * @rgltr Regulator that needs to be turned ON * @rgltr_name Associated Regulator name * @rgltr_min_volt: Requested minimum volatage * @rgltr_max_volt: Requested maximum volatage * @rgltr_op_mode: Requested Load * @rgltr_delay: Requested delay needed aaftre enabling regulator * * @return: Success or failure */ int cam_soc_util_regulator_disable(struct regulator *rgltr, const char *rgltr_name, uint32_t rgltr_min_volt, uint32_t rgltr_max_volt, uint32_t rgltr_op_mode, uint32_t rgltr_delay); /** * cam_soc_util_w() * Loading