summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-05-10 22:39:45 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-05-10 22:39:45 +0000
commitf364597eb683e2b774b96af4383079153a243048 (patch)
tree67510ff7fe011860773f4baa11fd04ebcbcc316b
parent33b619ce25d7197b240d89b2c033822820f66ec2 (diff)
parent676c16df8585f0b8178dc5c22fee18033ea03ec8 (diff)
downloadlwis-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.c367
-rw-r--r--lwis_device.h4
-rw-r--r--lwis_device_i2c.c57
-rw-r--r--lwis_device_ioreg.c48
-rw-r--r--lwis_device_top.c3
-rw-r--r--lwis_dt.c179
-rw-r--r--lwis_gpio.h2
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);
diff --git a/lwis_dt.c b/lwis_dt.c
index 87354b1..c448a51 100644
--- a/lwis_dt.c
+++ b/lwis_dt.c
@@ -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;