diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-05-10 22:39:45 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-05-10 22:39:45 +0000 |
commit | f364597eb683e2b774b96af4383079153a243048 (patch) | |
tree | 67510ff7fe011860773f4baa11fd04ebcbcc316b | |
parent | 33b619ce25d7197b240d89b2c033822820f66ec2 (diff) | |
parent | 676c16df8585f0b8178dc5c22fee18033ea03ec8 (diff) | |
download | lwis-f364597eb683e2b774b96af4383079153a243048.tar.gz |
Snap for 9990464 from 676c16df8585f0b8178dc5c22fee18033ea03ec8 to android13-gs-pixel-5.10-releaseandroid-13.0.0_r0.94
Change-Id: I0cc6d59e68488c3d23bc32a1d4d757c055756b45
-rw-r--r-- | lwis_device.c | 367 | ||||
-rw-r--r-- | lwis_device.h | 4 | ||||
-rw-r--r-- | lwis_device_i2c.c | 57 | ||||
-rw-r--r-- | lwis_device_ioreg.c | 48 | ||||
-rw-r--r-- | lwis_device_top.c | 3 | ||||
-rw-r--r-- | lwis_dt.c | 179 | ||||
-rw-r--r-- | lwis_gpio.h | 2 |
7 files changed, 271 insertions, 389 deletions
diff --git a/lwis_device.c b/lwis_device.c index 0c29b28..56ceafc 100644 --- a/lwis_device.c +++ b/lwis_device.c @@ -366,10 +366,12 @@ static void lwis_assign_top_to_other(struct lwis_device *top_dev) mutex_unlock(&core.lock); } -static int lwis_dev_power_up_by_seqs(struct lwis_device *lwis_dev) +static int process_power_sequence(struct lwis_device *lwis_dev, + struct lwis_device_power_sequence_list *list, bool set_active, + bool skip_error) { - struct lwis_device_power_sequence_list *list; - int ret; + int ret = 0; + int last_error = 0; int i; if (lwis_dev == NULL) { @@ -377,7 +379,6 @@ static int lwis_dev_power_up_by_seqs(struct lwis_device *lwis_dev) return -ENODEV; } - list = lwis_dev->power_up_sequence; if (list == NULL || list->count == 0) { dev_err(lwis_dev->dev, "No power_up_sequence defined\n"); return -EINVAL; @@ -392,102 +393,241 @@ static int lwis_dev_power_up_by_seqs(struct lwis_device *lwis_dev) if (strcmp(list->seq_info[i].type, "regulator") == 0) { if (lwis_dev->regulators == NULL) { dev_err(lwis_dev->dev, "No regulators defined\n"); - return -EINVAL; + ret = -EINVAL; + if (!skip_error) { + return ret; + } else { + last_error = ret; + continue; + } + } + if (set_active) { + ret = lwis_regulator_enable_by_name(lwis_dev->regulators, + list->seq_info[i].name); + } else { + ret = lwis_regulator_disable_by_name(lwis_dev->regulators, + list->seq_info[i].name); } - ret = lwis_regulator_enable_by_name(lwis_dev->regulators, - list->seq_info[i].name); if (ret) { - dev_err(lwis_dev->dev, "Error enabling regulators (%d)\n", ret); - return ret; + dev_err(lwis_dev->dev, "Error set regulators (%d)\n", ret); + if (!skip_error) { + return ret; + } + last_error = ret; } } else if (strcmp(list->seq_info[i].type, "gpio") == 0) { - struct gpio_descs *gpios = NULL; struct lwis_gpios_info *gpios_info = NULL; + int set_value = 0; + bool set_state = true; gpios_info = lwis_gpios_get_info_by_name(lwis_dev->gpios_list, list->seq_info[i].name); if (IS_ERR(gpios_info)) { dev_err(lwis_dev->dev, "Get %s gpios info failed\n", list->seq_info[i].name); - return PTR_ERR(gpios_info); + ret = PTR_ERR(gpios_info); + if (!skip_error) { + return ret; + } else { + last_error = ret; + continue; + } } - gpios = lwis_gpio_list_get(&lwis_dev->plat_dev->dev, - list->seq_info[i].name); - if (IS_ERR_OR_NULL(gpios)) { - if (PTR_ERR(gpios) == -EBUSY && gpios_info->is_shared) { - dev_warn(lwis_dev->dev, - "Shared gpios requested by another device\n"); - } else { - dev_err(lwis_dev->dev, "Failed to obtain gpio list (%ld)\n", - PTR_ERR(gpios)); - return PTR_ERR(gpios); + if (set_active) { + struct gpio_descs *gpios = NULL; + gpios = lwis_gpio_list_get(&lwis_dev->plat_dev->dev, + list->seq_info[i].name); + if (IS_ERR_OR_NULL(gpios)) { + gpios_info->gpios = NULL; + ret = PTR_ERR(gpios); + if (ret == -EBUSY && gpios_info->is_shared) { + dev_warn( + lwis_dev->dev, + "Shared gpios requested by another device\n"); + ret = 0; + continue; + } else { + dev_err(lwis_dev->dev, + "Failed to obtain gpio list (%d)\n", ret); + if (!skip_error) { + return ret; + } else { + last_error = ret; + continue; + } + } } - gpios_info->gpios = NULL; + gpios_info->gpios = gpios; + set_value = 1; } else { - if (gpios_info->is_pulse) { - ret = lwis_gpio_list_set_output_value(gpios, 0); - if (ret) { - dev_err(lwis_dev->dev, "Error set GPIO pins (%d)\n", - ret); + if (gpios_info->gpios == NULL) { + if (gpios_info->is_shared) { + continue; + } + dev_err(lwis_dev->dev, "No %s gpios defined\n", + list->seq_info[i].name); + ret = -ENODEV; + if (!skip_error) { return ret; + } else { + last_error = ret; + continue; + } + } + set_value = 0; + } + + if (gpios_info->is_shared && !set_active) { + struct lwis_device *lwis_dev_it; + struct lwis_gpios_info *gpios_info_it; + + /* Look up if gpio it's already acquired */ + mutex_lock(&core.lock); + list_for_each_entry (lwis_dev_it, &core.lwis_dev_list, dev_list) { + if ((lwis_dev->id != lwis_dev_it->id) && + lwis_dev_it->enabled && lwis_dev_it->gpios_list) { + gpios_info_it = lwis_gpios_get_info_by_name( + lwis_dev_it->gpios_list, + list->seq_info[i].name); + if (IS_ERR(gpios_info_it)) { + continue; + } + if (gpios_info_it->id == gpios_info->id && + gpios_info_it->gpios == NULL) { + dev_info(lwis_dev->dev, + "Handover shared GPIO to %s\n", + lwis_dev_it->name); + gpios_info_it->gpios = gpios_info->gpios; + gpios_info_it->hold_dev = + gpios_info->hold_dev; + set_state = false; + gpios_info->gpios = NULL; + } + break; } - usleep_range(1000, 1500); } - ret = lwis_gpio_list_set_output_value(gpios, 1); + mutex_unlock(&core.lock); + } + if (!set_state) { + continue; + } + + if (gpios_info->is_pulse) { + ret = lwis_gpio_list_set_output_value(gpios_info->gpios, + 1 - set_value); if (ret) { dev_err(lwis_dev->dev, "Error set GPIO pins (%d)\n", ret); + if (!skip_error) { + return ret; + } + last_error = ret; + } + usleep_range(1000, 1500); + } + ret = lwis_gpio_list_set_output_value(gpios_info->gpios, set_value); + if (ret) { + dev_err(lwis_dev->dev, "Error set GPIO pins (%d)\n", ret); + if (!skip_error) { return ret; } - gpios_info->gpios = gpios; + last_error = ret; + } + + if (!set_active) { + /* Release "ownership" of the GPIO pins */ + lwis_gpio_list_put(gpios_info->gpios, gpios_info->hold_dev); + gpios_info->gpios = NULL; } } else if (strcmp(list->seq_info[i].type, "pinctrl") == 0) { - bool activate_mclk = true; + bool set_state = true; - lwis_dev->mclk_ctrl = devm_pinctrl_get(&lwis_dev->plat_dev->dev); - if (IS_ERR(lwis_dev->mclk_ctrl)) { - dev_err(lwis_dev->dev, "Failed to get mclk\n"); - ret = PTR_ERR(lwis_dev->mclk_ctrl); - lwis_dev->mclk_ctrl = NULL; - return ret; + if (set_active) { + lwis_dev->mclk_ctrl = devm_pinctrl_get(&lwis_dev->plat_dev->dev); + if (IS_ERR(lwis_dev->mclk_ctrl)) { + dev_err(lwis_dev->dev, "Failed to get mclk\n"); + ret = PTR_ERR(lwis_dev->mclk_ctrl); + lwis_dev->mclk_ctrl = NULL; + if (!skip_error) { + return ret; + } else { + last_error = ret; + continue; + } + } + } else { + if (lwis_dev->mclk_ctrl == NULL) { + dev_err(lwis_dev->dev, "No pinctrl defined\n"); + ret = -ENODEV; + if (!skip_error) { + return ret; + } else { + last_error = ret; + continue; + } + } } - if (lwis_dev->shared_pinctrl > 0) { + if (lwis_dev->shared_pinctrl) { struct lwis_device *lwis_dev_it; - /* Look up if pinctrl it's already enabled */ + /* Look up if pinctrl it's already acquired */ mutex_lock(&core.lock); list_for_each_entry (lwis_dev_it, &core.lwis_dev_list, dev_list) { if ((lwis_dev->id != lwis_dev_it->id) && (lwis_dev_it->shared_pinctrl == lwis_dev->shared_pinctrl) && lwis_dev_it->enabled) { - activate_mclk = false; - devm_pinctrl_put(lwis_dev->mclk_ctrl); - lwis_dev->mclk_ctrl = NULL; dev_info(lwis_dev->dev, "mclk already acquired\n"); + if (set_active) { + devm_pinctrl_put(lwis_dev->mclk_ctrl); + } else { + /* + * Move mclk owner to the device who + * still using it + */ + lwis_dev_it->mclk_ctrl = + lwis_dev->mclk_ctrl; + } + set_state = false; + lwis_dev->mclk_ctrl = NULL; break; } } mutex_unlock(&core.lock); } - if (activate_mclk) { - /* Set MCLK state to on */ + if (set_state) { + /* Set MCLK state */ ret = lwis_pinctrl_set_state(lwis_dev->mclk_ctrl, list->seq_info[i].name); if (ret) { dev_err(lwis_dev->dev, "Error setting %s state (%d)\n", list->seq_info[i].name, ret); + if (set_active) { + devm_pinctrl_put(lwis_dev->mclk_ctrl); + lwis_dev->mclk_ctrl = NULL; + } + if (!skip_error) { + return ret; + } else { + last_error = ret; + continue; + } + } + if (!set_active) { devm_pinctrl_put(lwis_dev->mclk_ctrl); lwis_dev->mclk_ctrl = NULL; - return ret; } } } usleep_range(list->seq_info[i].delay_us, list->seq_info[i].delay_us); } - return 0; + if (last_error) { + return last_error; + } + + return ret; } static int lwis_dev_power_up_by_default(struct lwis_device *lwis_dev) @@ -675,10 +815,11 @@ int lwis_dev_power_up_locked(struct lwis_device *lwis_dev) if (lwis_dev->type == DEVICE_TYPE_I2C) { mutex_lock(i2c_dev->group_i2c_lock); } - if (lwis_dev->power_up_seqs_present) { - ret = lwis_dev_power_up_by_seqs(lwis_dev); + if (lwis_dev->power_up_sequence) { + ret = process_power_sequence(lwis_dev, lwis_dev->power_up_sequence, + /*set_active=*/true, /*skip_error=*/false); if (ret) { - dev_err(lwis_dev->dev, "Error lwis_dev_power_up_by_seqs (%d)\n", ret); + dev_err(lwis_dev->dev, "Error process_power_sequence (%d)\n", ret); if (lwis_dev->type == DEVICE_TYPE_I2C) { mutex_unlock(i2c_dev->group_i2c_lock); } @@ -726,127 +867,6 @@ error_power_up: return ret; } -static int lwis_dev_power_down_by_seqs(struct lwis_device *lwis_dev) -{ - struct lwis_device_power_sequence_list *list; - int last_error = 0; - int ret; - int i; - - if (lwis_dev == NULL) { - pr_err("lwis_dev is NULL\n"); - return -ENODEV; - } - - list = lwis_dev->power_down_sequence; - if (list == NULL || list->count == 0) { - dev_err(lwis_dev->dev, "No power_up_sequence defined\n"); - return -EINVAL; - } - - for (i = 0; i < list->count; ++i) { -#ifdef LWIS_PWR_SEQ_DEBUG - dev_info(lwis_dev->dev, "%s: %d - type:%s name:%s delay_us:%d", __func__, i, - list->seq_info[i].type, list->seq_info[i].name, - list->seq_info[i].delay_us); -#endif - if (strcmp(list->seq_info[i].type, "regulator") == 0) { - if (lwis_dev->regulators == NULL) { - dev_err(lwis_dev->dev, "No regulators defined\n"); - last_error = -EINVAL; - continue; - } - ret = lwis_regulator_disable_by_name(lwis_dev->regulators, - list->seq_info[i].name); - if (ret) { - dev_err(lwis_dev->dev, "Error disabling regulators (%d)\n", ret); - last_error = ret; - } - } else if (strcmp(list->seq_info[i].type, "gpio") == 0) { - struct lwis_gpios_info *gpios_info = NULL; - - gpios_info = lwis_gpios_get_info_by_name(lwis_dev->gpios_list, - list->seq_info[i].name); - if (IS_ERR(gpios_info)) { - dev_err(lwis_dev->dev, "Get %s gpios info failed\n", - list->seq_info[i].name); - last_error = PTR_ERR(gpios_info); - continue; - } - - if (gpios_info->gpios == NULL) { - if (gpios_info->is_shared) { - continue; - } - dev_err(lwis_dev->dev, "No %s gpios defined\n", - list->seq_info[i].name); - last_error = -ENODEV; - continue; - } - - ret = lwis_gpio_list_set_output_value(gpios_info->gpios, 0); - if (ret) { - dev_err(lwis_dev->dev, "Error set GPIO pins (%d)\n", ret); - last_error = ret; - } - - /* Release "ownership" of the GPIO pins */ - lwis_gpio_list_put(gpios_info->gpios, &lwis_dev->plat_dev->dev); - gpios_info->gpios = NULL; - } else if (strcmp(list->seq_info[i].type, "pinctrl") == 0) { - bool deactivate_mclk = true; - - if (lwis_dev->mclk_ctrl == NULL) { - dev_err(lwis_dev->dev, "No pinctrl defined\n"); - last_error = -ENODEV; - continue; - } - - if (lwis_dev->shared_pinctrl) { - struct lwis_device *lwis_dev_it; - /* Look up if pinctrl still used by other device */ - mutex_lock(&core.lock); - list_for_each_entry (lwis_dev_it, &core.lwis_dev_list, dev_list) { - if ((lwis_dev->id != lwis_dev_it->id) && - (lwis_dev_it->shared_pinctrl == - lwis_dev->shared_pinctrl) && - lwis_dev_it->enabled) { - /* - * Move mclk owner to the device who - * still using it - */ - lwis_dev_it->mclk_ctrl = lwis_dev->mclk_ctrl; - lwis_dev->mclk_ctrl = NULL; - deactivate_mclk = false; - break; - } - } - mutex_unlock(&core.lock); - } - - if (deactivate_mclk) { - /* Set MCLK state to off */ - ret = lwis_pinctrl_set_state(lwis_dev->mclk_ctrl, - list->seq_info[i].name); - if (ret) { - dev_err(lwis_dev->dev, "Error setting %s state (%d)\n", - list->seq_info[i].name, ret); - last_error = ret; - } - devm_pinctrl_put(lwis_dev->mclk_ctrl); - lwis_dev->mclk_ctrl = NULL; - } - } - usleep_range(list->seq_info[i].delay_us, list->seq_info[i].delay_us); - } - - if (last_error) { - return last_error; - } - - return 0; -} - static int lwis_dev_power_down_by_default(struct lwis_device *lwis_dev) { int last_error = 0; @@ -988,10 +1008,11 @@ int lwis_dev_power_down_locked(struct lwis_device *lwis_dev) if (lwis_dev->type == DEVICE_TYPE_I2C) { mutex_lock(i2c_dev->group_i2c_lock); } - if (lwis_dev->power_down_seqs_present) { - ret = lwis_dev_power_down_by_seqs(lwis_dev); + if (lwis_dev->power_down_sequence) { + ret = process_power_sequence(lwis_dev, lwis_dev->power_down_sequence, + /*set_active=*/false, /*skip_error=*/true); if (ret) { - dev_err(lwis_dev->dev, "Error lwis_dev_power_down_by_seqs (%d)\n", ret); + dev_err(lwis_dev->dev, "Error process_power_sequence (%d)\n", ret); last_error = ret; } } else { diff --git a/lwis_device.h b/lwis_device.h index b209bfd..42c0bdb 100644 --- a/lwis_device.h +++ b/lwis_device.h @@ -230,12 +230,8 @@ struct lwis_device { /* BTS scenario index */ unsigned int bts_scenario; - /* Does power-up-seqs present */ - bool power_up_seqs_present; /* Power up sequence information */ struct lwis_device_power_sequence_list *power_up_sequence; - /* Does power-down-seqs present */ - bool power_down_seqs_present; /* Power down sequence information */ struct lwis_device_power_sequence_list *power_down_sequence; /* GPIOs list */ diff --git a/lwis_device_i2c.c b/lwis_device_i2c.c index 4849552..3adfa57 100644 --- a/lwis_device_i2c.c +++ b/lwis_device_i2c.c @@ -99,6 +99,12 @@ static int lwis_i2c_device_disable(struct lwis_device *lwis_dev) struct lwis_i2c_device *i2c_dev; i2c_dev = container_of(lwis_dev, struct lwis_i2c_device, base_dev); + if (IS_ERR_OR_NULL(i2c_dev->state_pinctrl)) { + dev_err(lwis_dev->dev, "i2c state_pinctrl is invalid (%lu)\n", + PTR_ERR(i2c_dev->state_pinctrl)); + i2c_dev->state_pinctrl = NULL; + } + #if IS_ENABLED(CONFIG_INPUT_STMVL53L1) if (is_shared_i2c_with_stmvl53l1(i2c_dev->state_pinctrl)) { /* Disable the shared i2c bus */ @@ -208,6 +214,7 @@ static int lwis_i2c_device_setup(struct lwis_i2c_device *i2c_dev) if (IS_ERR(pinctrl)) { dev_err(i2c_dev->base_dev.dev, "Cannot instantiate pinctrl instance (%lu)\n", PTR_ERR(pinctrl)); + i2c_dev->state_pinctrl = NULL; return PTR_ERR(pinctrl); } @@ -311,59 +318,17 @@ error_probe: static int lwis_i2c_device_suspend(struct device *dev) { struct lwis_device *lwis_dev = dev_get_drvdata(dev); - struct lwis_client *lwis_client, *n; - int ret = 0; - if (lwis_dev->enabled == 0) { - return ret; + if (lwis_dev->pm_hibernation == 0) { + /* TODO(b/265688764): Cleaning up system deep sleep for flash driver. */ + return 0; } - if (lwis_dev->pm_hibernation == 0) { + if (lwis_dev->enabled != 0) { dev_warn(lwis_dev->dev, "Can't suspend because %s is in use!\n", lwis_dev->name); return -EBUSY; } - /* Send an error event to userspace to handle the system suspend */ - lwis_device_error_event_emit(lwis_dev, LWIS_ERROR_EVENT_ID_SYSTEM_SUSPEND, - /*payload=*/NULL, /*payload_size=*/0); - - list_for_each_entry_safe (lwis_client, n, &lwis_dev->clients, node) { - if (!lwis_client->is_enabled) { - continue; - } - - /* Clear event states for this client */ - lwis_client_event_states_clear(lwis_client); - - /* Flush all periodic io to complete */ - ret = lwis_periodic_io_client_flush(lwis_client); - if (ret) { - dev_err(lwis_dev->dev, - "Failed to wait for in-process periodic io to complete\n"); - } - - /* Flush all pending transactions */ - ret = lwis_transaction_client_flush(lwis_client); - if (ret) { - dev_err(lwis_dev->dev, "Failed to flush pending transactions\n"); - } - - /* Run cleanup transactions. */ - lwis_transaction_client_cleanup(lwis_client); - - lwis_client->is_enabled = false; - } - - mutex_lock(&lwis_dev->client_lock); - ret = lwis_dev_power_down_locked(lwis_dev); - if (ret < 0) { - dev_err(lwis_dev->dev, "Failed to power down device\n"); - } - - lwis_device_event_states_clear_locked(lwis_dev); - lwis_dev->enabled = 0; - dev_warn(lwis_dev->dev, "Device disabled when system suspend\n"); - mutex_unlock(&lwis_dev->client_lock); return 0; } diff --git a/lwis_device_ioreg.c b/lwis_device_ioreg.c index ef71b79..5474430 100644 --- a/lwis_device_ioreg.c +++ b/lwis_device_ioreg.c @@ -173,54 +173,12 @@ error_probe: static int lwis_ioreg_device_suspend(struct device *dev) { struct lwis_device *lwis_dev = dev_get_drvdata(dev); - struct lwis_client *lwis_client, *n; - int ret = 0; - - if (lwis_dev->enabled == 0) { - return ret; - } - - /* Send an error event to userspace to handle the system suspend */ - lwis_device_error_event_emit(lwis_dev, LWIS_ERROR_EVENT_ID_SYSTEM_SUSPEND, - /*payload=*/NULL, /*payload_size=*/0); - - list_for_each_entry_safe (lwis_client, n, &lwis_dev->clients, node) { - if (!lwis_client->is_enabled) { - continue; - } - - /* Clear event states for this client */ - lwis_client_event_states_clear(lwis_client); - - /* Flush all periodic io to complete */ - ret = lwis_periodic_io_client_flush(lwis_client); - if (ret) { - dev_err(lwis_dev->dev, - "Failed to wait for in-process periodic io to complete\n"); - } - - /* Flush all pending transactions */ - ret = lwis_transaction_client_flush(lwis_client); - if (ret) { - dev_err(lwis_dev->dev, "Failed to flush pending transactions\n"); - } - - /* Run cleanup transactions. */ - lwis_transaction_client_cleanup(lwis_client); - - lwis_client->is_enabled = false; - } - mutex_lock(&lwis_dev->client_lock); - ret = lwis_dev_power_down_locked(lwis_dev); - if (ret < 0) { - dev_err(lwis_dev->dev, "Failed to power down device\n"); + if (lwis_dev->enabled != 0) { + dev_warn(lwis_dev->dev, "Can't suspend because %s is in use!\n", lwis_dev->name); + return -EBUSY; } - lwis_device_event_states_clear_locked(lwis_dev); - lwis_dev->enabled = 0; - dev_warn(lwis_dev->dev, "Device disabled when system suspend\n"); - mutex_unlock(&lwis_dev->client_lock); return 0; } diff --git a/lwis_device_top.c b/lwis_device_top.c index c5de1ed..6c72371 100644 --- a/lwis_device_top.c +++ b/lwis_device_top.c @@ -215,13 +215,14 @@ static int lwis_top_event_subscribe(struct lwis_device *lwis_dev, int64_t trigge return -EINVAL; } + spin_lock_irqsave(&lwis_top_dev->base_dev.lock, flags); event_subscriber_list = event_subscriber_list_find_or_create(lwis_dev, trigger_event_id); if (!event_subscriber_list) { + spin_unlock_irqrestore(&lwis_top_dev->base_dev.lock, flags); dev_err(lwis_dev->dev, "Can't find/create event subscriber list\n"); return -EINVAL; } - spin_lock_irqsave(&lwis_top_dev->base_dev.lock, flags); list_for_each (it_event_subscriber, &event_subscriber_list->list) { old_subscription = list_entry(it_event_subscriber, struct lwis_event_subscribe_info, list_node); @@ -682,8 +682,12 @@ static void parse_bitwidths(struct lwis_device *lwis_dev) lwis_dev->native_value_bitwidth = value_bitwidth; } -static int parse_power_up_seqs(struct lwis_device *lwis_dev) +static int parse_power_seqs(struct lwis_device *lwis_dev, const char *seq_name, + struct lwis_device_power_sequence_list **list) { + char str_seq_name[LWIS_MAX_NAME_STRING_LEN]; + char str_seq_type[LWIS_MAX_NAME_STRING_LEN]; + char str_seq_delay[LWIS_MAX_NAME_STRING_LEN]; struct device *dev; struct device_node *dev_node; int power_seq_count; @@ -697,88 +701,102 @@ static int parse_power_up_seqs(struct lwis_device *lwis_dev) int type_gpio_count = 0; int type_regulator_count = 0; + scnprintf(str_seq_name, LWIS_MAX_NAME_STRING_LEN, "%s-seqs", seq_name); + scnprintf(str_seq_type, LWIS_MAX_NAME_STRING_LEN, "%s-seq-types", seq_name); + scnprintf(str_seq_delay, LWIS_MAX_NAME_STRING_LEN, "%s-seq-delays-us", seq_name); + dev = &lwis_dev->plat_dev->dev; dev_node = dev->of_node; + *list = NULL; - lwis_dev->power_up_seqs_present = false; - lwis_dev->power_up_sequence = NULL; - lwis_dev->gpios_list = NULL; - - power_seq_count = of_property_count_strings(dev_node, "power-up-seqs"); - power_seq_type_count = of_property_count_strings(dev_node, "power-up-seq-types"); + power_seq_count = of_property_count_strings(dev_node, str_seq_name); + power_seq_type_count = of_property_count_strings(dev_node, str_seq_type); power_seq_delay_count = - of_property_count_elems_of_size(dev_node, "power-up-seq-delays-us", sizeof(u32)); + of_property_count_elems_of_size(dev_node, str_seq_delay, sizeof(u32)); - /* No power-up-seqs found, just return */ + /* No power-seqs found, just return */ if (power_seq_count <= 0) { return 0; } if (power_seq_count != power_seq_type_count || power_seq_count != power_seq_delay_count) { - pr_err("Count of power-up-seqs-* are not match\n"); + pr_err("Count of power sequence %s is not match\n", str_seq_name); return -EINVAL; } - lwis_dev->power_up_sequence = lwis_dev_power_seq_list_alloc(power_seq_count); - if (IS_ERR(lwis_dev->power_up_sequence)) { + *list = lwis_dev_power_seq_list_alloc(power_seq_count); + if (IS_ERR(*list)) { pr_err("Failed to allocate power sequence list\n"); - return PTR_ERR(lwis_dev->power_up_sequence); + return PTR_ERR(*list); } for (i = 0; i < power_seq_count; ++i) { - ret = of_property_read_string_index(dev_node, "power-up-seqs", i, &name); + ret = of_property_read_string_index(dev_node, str_seq_name, i, &name); if (ret < 0) { pr_err("Error adding power sequence[%d]\n", i); - goto error_parse_power_up_seqs; + goto error_parse_power_seqs; } - strlcpy(lwis_dev->power_up_sequence->seq_info[i].name, name, - LWIS_MAX_NAME_STRING_LEN); + strscpy((*list)->seq_info[i].name, name, LWIS_MAX_NAME_STRING_LEN); - ret = of_property_read_string_index(dev_node, "power-up-seq-types", i, &type); + ret = of_property_read_string_index(dev_node, str_seq_type, i, &type); if (ret < 0) { pr_err("Error adding power sequence type[%d]\n", i); - goto error_parse_power_up_seqs; + goto error_parse_power_seqs; } - strlcpy(lwis_dev->power_up_sequence->seq_info[i].type, type, - LWIS_MAX_NAME_STRING_LEN); + strscpy((*list)->seq_info[i].type, type, LWIS_MAX_NAME_STRING_LEN); if (strcmp(type, "gpio") == 0) { type_gpio_count++; } else if (strcmp(type, "regulator") == 0) { type_regulator_count++; } - ret = of_property_read_u32_index(dev_node, "power-up-seq-delays-us", i, &delay_us); + ret = of_property_read_u32_index(dev_node, str_seq_delay, i, &delay_us); if (ret < 0) { pr_err("Error adding power sequence delay[%d]\n", i); - goto error_parse_power_up_seqs; + goto error_parse_power_seqs; } - lwis_dev->power_up_sequence->seq_info[i].delay_us = delay_us; + (*list)->seq_info[i].delay_us = delay_us; } #ifdef LWIS_DT_DEBUG - lwis_dev_power_seq_list_print(lwis_dev->power_up_sequence); + lwis_dev_power_seq_list_print(*list); #endif - lwis_dev->power_up_seqs_present = true; - - if (type_gpio_count > 0) { + if (type_gpio_count > 0 && lwis_dev->gpios_list == NULL) { lwis_dev->gpios_list = lwis_gpios_list_alloc(type_gpio_count); if (IS_ERR(lwis_dev->gpios_list)) { pr_err("Failed to allocate gpios list\n"); ret = PTR_ERR(lwis_dev->gpios_list); - goto error_parse_power_up_seqs; + goto error_parse_power_seqs; } type_gpio_count = 0; for (i = 0; i < power_seq_count; ++i) { struct lwis_gpios_info *gpios_info; char *seq_item_name; + struct device *dev; + struct gpio_descs *descs; - if (strcmp(lwis_dev->power_up_sequence->seq_info[i].type, "gpio") != 0) { + if (strcmp((*list)->seq_info[i].type, "gpio") != 0) { continue; } gpios_info = &lwis_dev->gpios_list->gpios_info[type_gpio_count]; - seq_item_name = lwis_dev->power_up_sequence->seq_info[i].name; + seq_item_name = (*list)->seq_info[i].name; + dev = &lwis_dev->plat_dev->dev; + descs = lwis_gpio_list_get(dev, seq_item_name); + if (IS_ERR(descs)) { + pr_err("Error parsing GPIO list %s (%ld)\n", seq_item_name, + PTR_ERR(descs)); + ret = PTR_ERR(descs); + goto error_parse_power_seqs; + } + gpios_info->id = desc_to_gpio(descs->desc[0]); + gpios_info->hold_dev = dev; + /* + * The GPIO pins are valid, release the list as we do not need to hold + * on to the pins yet + */ + lwis_gpio_list_put(descs, dev); gpios_info->gpios = NULL; gpios_info->irq_list = NULL; @@ -798,38 +816,37 @@ static int parse_power_up_seqs(struct lwis_device *lwis_dev) } } - if (type_regulator_count > 0) { + if (type_regulator_count > 0 && lwis_dev->regulators == NULL) { lwis_dev->regulators = lwis_regulator_list_alloc(type_regulator_count); if (IS_ERR(lwis_dev->regulators)) { pr_err("Failed to allocate regulator list\n"); ret = PTR_ERR(lwis_dev->regulators); - goto error_parse_power_up_seqs; + goto error_parse_power_seqs; } for (i = 0; i < power_seq_count; ++i) { struct device *dev; char *seq_item_name; - if (strcmp(lwis_dev->power_up_sequence->seq_info[i].type, - "regulator") != 0) { + if (strcmp((*list)->seq_info[i].type, "regulator") != 0) { continue; } dev = &lwis_dev->plat_dev->dev; - seq_item_name = lwis_dev->power_up_sequence->seq_info[i].name; + seq_item_name = (*list)->seq_info[i].name; ret = lwis_regulator_get(lwis_dev->regulators, seq_item_name, /*voltage=*/0, dev); if (ret < 0) { pr_err("Cannot find regulator: %s\n", seq_item_name); - goto error_parse_power_up_seqs; + goto error_parse_power_seqs; } } } return 0; -error_parse_power_up_seqs: +error_parse_power_seqs: if (lwis_dev->regulators) { lwis_regulator_put_all(lwis_dev->regulators); lwis_regulator_list_free(lwis_dev->regulators); @@ -837,86 +854,8 @@ error_parse_power_up_seqs: } lwis_gpios_list_free(lwis_dev->gpios_list); lwis_dev->gpios_list = NULL; - lwis_dev_power_seq_list_free(lwis_dev->power_up_sequence); - lwis_dev->power_up_sequence = NULL; - return ret; -} - -static int parse_power_down_seqs(struct lwis_device *lwis_dev) -{ - struct device *dev; - struct device_node *dev_node; - int power_seq_count; - int power_seq_type_count; - int power_seq_delay_count; - int i; - int ret; - const char *name; - const char *type; - int delay_us; - - dev = &lwis_dev->plat_dev->dev; - dev_node = dev->of_node; - - lwis_dev->power_down_seqs_present = false; - lwis_dev->power_down_sequence = NULL; - - power_seq_count = of_property_count_strings(dev_node, "power-down-seqs"); - power_seq_type_count = of_property_count_strings(dev_node, "power-down-seq-types"); - power_seq_delay_count = - of_property_count_elems_of_size(dev_node, "power-down-seq-delays-us", sizeof(u32)); - - /* No power-down-seqs found, just return */ - if (power_seq_count <= 0) { - return 0; - } - if (power_seq_count != power_seq_type_count || power_seq_count != power_seq_delay_count) { - pr_err("Count of power-down-seqs-* are not match\n"); - return -EINVAL; - } - - lwis_dev->power_down_sequence = lwis_dev_power_seq_list_alloc(power_seq_count); - if (IS_ERR(lwis_dev->power_down_sequence)) { - pr_err("Failed to allocate power sequence list\n"); - return PTR_ERR(lwis_dev->power_down_sequence); - } - - for (i = 0; i < power_seq_count; ++i) { - ret = of_property_read_string_index(dev_node, "power-down-seqs", i, &name); - if (ret < 0) { - pr_err("Error adding power sequence[%d]\n", i); - goto error_parse_power_down_seqs; - } - strlcpy(lwis_dev->power_down_sequence->seq_info[i].name, name, - LWIS_MAX_NAME_STRING_LEN); - - ret = of_property_read_string_index(dev_node, "power-down-seq-types", i, &type); - if (ret < 0) { - pr_err("Error adding power sequence type[%d]\n", i); - goto error_parse_power_down_seqs; - } - strlcpy(lwis_dev->power_down_sequence->seq_info[i].type, type, - LWIS_MAX_NAME_STRING_LEN); - - ret = of_property_read_u32_index(dev_node, "power-down-seq-delays-us", i, - &delay_us); - if (ret < 0) { - pr_err("Error adding power sequence delay[%d]\n", i); - goto error_parse_power_down_seqs; - } - lwis_dev->power_down_sequence->seq_info[i].delay_us = delay_us; - } - -#ifdef LWIS_DT_DEBUG - lwis_dev_power_seq_list_print(lwis_dev->power_down_sequence); -#endif - - lwis_dev->power_down_seqs_present = true; - return 0; - -error_parse_power_down_seqs: - lwis_dev_power_seq_list_free(lwis_dev->power_down_sequence); - lwis_dev->power_down_sequence = NULL; + lwis_dev_power_seq_list_free(*list); + *list = NULL; return ret; } @@ -1033,13 +972,13 @@ int lwis_base_parse_dt(struct lwis_device *lwis_dev) return ret; } - ret = parse_power_up_seqs(lwis_dev); + ret = parse_power_seqs(lwis_dev, "power-up", &lwis_dev->power_up_sequence); if (ret) { pr_err("Error parsing power-up-seqs\n"); return ret; } - ret = parse_power_down_seqs(lwis_dev); + ret = parse_power_seqs(lwis_dev, "power-down", &lwis_dev->power_down_sequence); if (ret) { pr_err("Error parsing power-down-seqs\n"); return ret; diff --git a/lwis_gpio.h b/lwis_gpio.h index cfccd27..bbd77ff 100644 --- a/lwis_gpio.h +++ b/lwis_gpio.h @@ -20,6 +20,8 @@ * This structure is to store the gpios information */ struct lwis_gpios_info { + int id; + struct device *hold_dev; char name[LWIS_MAX_NAME_STRING_LEN]; bool is_shared; bool is_pulse; |