<commit_before>/*
 * Copyright (c) 2016 Intel Corporation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <errno.h>

#include <device.h>
#include <drivers/ioapic.h>
#include <gpio.h>
#include <init.h>
#include <nanokernel.h>
#include <sys_io.h>

#include "qm_gpio.h"
#include "gpio_utils.h"
#include "qm_isr.h"
#include "clk.h"
#include <power.h>

struct gpio_qmsi_config {
	qm_gpio_t gpio;
	uint8_t num_pins;
};

struct gpio_qmsi_runtime {
	sys_slist_t callbacks;
	uint32_t pin_callbacks;
#ifdef CONFIG_GPIO_QMSI_API_REENTRANCY
	struct nano_sem sem;
#endif /* CONFIG_GPIO_QMSI_API_REENTRANCY */
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
	uint32_t device_power_state;
#endif
};

#ifdef CONFIG_GPIO_QMSI_API_REENTRANCY
#define RP_GET(dev) (&((struct gpio_qmsi_runtime *)(dev->driver_data))->sem)
static const int reentrancy_protection = 1;
#else
#define RP_GET(context) (NULL)
static const int reentrancy_protection;
#endif /* CONFIG_GPIO_QMSI_API_REENTRANCY */

static void gpio_reentrancy_init(struct device *dev)
{
	if (!reentrancy_protection) {
		return;
	}

	nano_sem_init(RP_GET(dev));
	nano_sem_give(RP_GET(dev));
}

static void gpio_critical_region_start(struct device *dev)
{
	if (!reentrancy_protection) {
		return;
	}

	nano_sem_take(RP_GET(dev), TICKS_UNLIMITED);
}

static void gpio_critical_region_end(struct device *dev)
{
	if (!reentrancy_protection) {
		return;
	}

	nano_sem_give(RP_GET(dev));
}

int gpio_qmsi_init(struct device *dev);

#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
static void gpio_qmsi_set_power_state(struct device *dev, uint32_t power_state)
{
	struct gpio_qmsi_runtime *context = dev->driver_data;

	context->device_power_state = power_state;
}

static uint32_t gpio_qmsi_get_power_state(struct device *dev)
{
	struct gpio_qmsi_runtime *context = dev->driver_data;

	return context->device_power_state;
}
#else
#define gpio_qmsi_set_power_state(...)
#endif


#ifdef CONFIG_GPIO_QMSI_0
static struct gpio_qmsi_config gpio_0_config = {
	.gpio = QM_GPIO_0,
	.num_pins = QM_NUM_GPIO_PINS,
};

static struct gpio_qmsi_runtime gpio_0_runtime;

#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
QM_RW uint32_t save_reg[10];
static uint32_t int_gpio_mask_save;

static int gpio_suspend_device(struct device *dev)
{
	int_gpio_mask_save = REG_VAL(&QM_SCSS_INT->int_gpio_mask);
	save_reg[0] = REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_swporta_dr);
	save_reg[1] = REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_swporta_ddr);
	save_reg[2] = REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_swporta_ctl);
	save_reg[3] = REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_inten);
	save_reg[4] = REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_intmask);
	save_reg[5] = REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_inttype_level);
	save_reg[6] = REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_int_polarity);
	save_reg[7] = REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_debounce);
	save_reg[8] = REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_ls_sync);
	save_reg[9] = REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_int_bothedge);

	gpio_qmsi_set_power_state(dev, DEVICE_PM_SUSPEND_STATE);

	return 0;
}

static int gpio_resume_device_from_suspend(struct device *dev)
{
	REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_swporta_dr) = save_reg[0];
	REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_swporta_ddr) = save_reg[1];
	REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_swporta_ctl) = save_reg[2];
	REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_inten) = save_reg[3];
	REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_intmask) = save_reg[4];
	REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_inttype_level) = save_reg[5];
	REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_int_polarity) = save_reg[6];
	REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_debounce) = save_reg[7];
	REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_ls_sync) = save_reg[8];
	REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_int_bothedge) = save_reg[9];
	REG_VAL(&QM_SCSS_INT->int_gpio_mask) = int_gpio_mask_save;

	gpio_qmsi_set_power_state(dev, DEVICE_PM_ACTIVE_STATE);

	return 0;
}

/*
* Implements the driver control management functionality
* the *context may include IN data or/and OUT data
*/
static int gpio_qmsi_device_ctrl(struct device *port, uint32_t ctrl_command,
				 void *context)
{
	if (ctrl_command == DEVICE_PM_SET_POWER_STATE) {
		if (*((uint32_t *)context) == DEVICE_PM_SUSPEND_STATE) {
			return gpio_suspend_device(port);
		} else if (*((uint32_t *)context) == DEVICE_PM_ACTIVE_STATE) {
			return gpio_resume_device_from_suspend(port);
		}
	} else if (ctrl_command == DEVICE_PM_GET_POWER_STATE) {
		*((uint32_t *)context) = gpio_qmsi_get_power_state(port);
		return 0;
	}
	return 0;
}
#endif

DEVICE_DEFINE(gpio_0, CONFIG_GPIO_QMSI_0_NAME, &gpio_qmsi_init,
	      gpio_qmsi_device_ctrl, &gpio_0_runtime, &gpio_0_config,
	      SECONDARY, CONFIG_GPIO_QMSI_INIT_PRIORITY, NULL);

#endif /* CONFIG_GPIO_QMSI_0 */

#ifdef CONFIG_GPIO_QMSI_1
static struct gpio_qmsi_config gpio_aon_config = {
	.gpio = QM_AON_GPIO_0,
	.num_pins = QM_NUM_AON_GPIO_PINS,
};

static struct gpio_qmsi_runtime gpio_aon_runtime;


#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
static uint32_t int_gpio_aon_mask_save;

static int gpio_aon_suspend_device(struct device *dev)
{
	int_gpio_aon_mask_save = REG_VAL(&QM_SCSS_INT->int_aon_gpio_mask);
	gpio_qmsi_set_power_state(dev, DEVICE_PM_SUSPEND_STATE);
	return 0;
}

static int gpio_aon_resume_device_from_suspend(struct device *dev)
{
	REG_VAL(&QM_SCSS_INT->int_aon_gpio_mask) = int_gpio_aon_mask_save;<commit_msg>gpio: qmsi: Make driver config_info structure const.<commit_after>/*
 * Copyright (c) 2016 Intel Corporation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <errno.h>

#include <device.h>
#include <drivers/ioapic.h>
#include <gpio.h>
#include <init.h>
#include <nanokernel.h>
#include <sys_io.h>

#include "qm_gpio.h"
#include "gpio_utils.h"
#include "qm_isr.h"
#include "clk.h"
#include <power.h>

struct gpio_qmsi_config {
	qm_gpio_t gpio;
	uint8_t num_pins;
};

struct gpio_qmsi_runtime {
	sys_slist_t callbacks;
	uint32_t pin_callbacks;
#ifdef CONFIG_GPIO_QMSI_API_REENTRANCY
	struct nano_sem sem;
#endif /* CONFIG_GPIO_QMSI_API_REENTRANCY */
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
	uint32_t device_power_state;
#endif
};

#ifdef CONFIG_GPIO_QMSI_API_REENTRANCY
#define RP_GET(dev) (&((struct gpio_qmsi_runtime *)(dev->driver_data))->sem)
static const int reentrancy_protection = 1;
#else
#define RP_GET(context) (NULL)
static const int reentrancy_protection;
#endif /* CONFIG_GPIO_QMSI_API_REENTRANCY */

static void gpio_reentrancy_init(struct device *dev)
{
	if (!reentrancy_protection) {
		return;
	}

	nano_sem_init(RP_GET(dev));
	nano_sem_give(RP_GET(dev));
}

static void gpio_critical_region_start(struct device *dev)
{
	if (!reentrancy_protection) {
		return;
	}

	nano_sem_take(RP_GET(dev), TICKS_UNLIMITED);
}

static void gpio_critical_region_end(struct device *dev)
{
	if (!reentrancy_protection) {
		return;
	}

	nano_sem_give(RP_GET(dev));
}

int gpio_qmsi_init(struct device *dev);

#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
static void gpio_qmsi_set_power_state(struct device *dev, uint32_t power_state)
{
	struct gpio_qmsi_runtime *context = dev->driver_data;

	context->device_power_state = power_state;
}

static uint32_t gpio_qmsi_get_power_state(struct device *dev)
{
	struct gpio_qmsi_runtime *context = dev->driver_data;

	return context->device_power_state;
}
#else
#define gpio_qmsi_set_power_state(...)
#endif


#ifdef CONFIG_GPIO_QMSI_0
static const struct gpio_qmsi_config gpio_0_config = {
	.gpio = QM_GPIO_0,
	.num_pins = QM_NUM_GPIO_PINS,
};

static struct gpio_qmsi_runtime gpio_0_runtime;

#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
QM_RW uint32_t save_reg[10];
static uint32_t int_gpio_mask_save;

static int gpio_suspend_device(struct device *dev)
{
	int_gpio_mask_save = REG_VAL(&QM_SCSS_INT->int_gpio_mask);
	save_reg[0] = REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_swporta_dr);
	save_reg[1] = REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_swporta_ddr);
	save_reg[2] = REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_swporta_ctl);
	save_reg[3] = REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_inten);
	save_reg[4] = REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_intmask);
	save_reg[5] = REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_inttype_level);
	save_reg[6] = REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_int_polarity);
	save_reg[7] = REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_debounce);
	save_reg[8] = REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_ls_sync);
	save_reg[9] = REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_int_bothedge);

	gpio_qmsi_set_power_state(dev, DEVICE_PM_SUSPEND_STATE);

	return 0;
}

static int gpio_resume_device_from_suspend(struct device *dev)
{
	REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_swporta_dr) = save_reg[0];
	REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_swporta_ddr) = save_reg[1];
	REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_swporta_ctl) = save_reg[2];
	REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_inten) = save_reg[3];
	REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_intmask) = save_reg[4];
	REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_inttype_level) = save_reg[5];
	REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_int_polarity) = save_reg[6];
	REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_debounce) = save_reg[7];
	REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_ls_sync) = save_reg[8];
	REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_int_bothedge) = save_reg[9];
	REG_VAL(&QM_SCSS_INT->int_gpio_mask) = int_gpio_mask_save;

	gpio_qmsi_set_power_state(dev, DEVICE_PM_ACTIVE_STATE);

	return 0;
}

/*
* Implements the driver control management functionality
* the *context may include IN data or/and OUT data
*/
static int gpio_qmsi_device_ctrl(struct device *port, uint32_t ctrl_command,
				 void *context)
{
	if (ctrl_command == DEVICE_PM_SET_POWER_STATE) {
		if (*((uint32_t *)context) == DEVICE_PM_SUSPEND_STATE) {
			return gpio_suspend_device(port);
		} else if (*((uint32_t *)context) == DEVICE_PM_ACTIVE_STATE) {
			return gpio_resume_device_from_suspend(port);
		}
	} else if (ctrl_command == DEVICE_PM_GET_POWER_STATE) {
		*((uint32_t *)context) = gpio_qmsi_get_power_state(port);
		return 0;
	}
	return 0;
}
#endif

DEVICE_DEFINE(gpio_0, CONFIG_GPIO_QMSI_0_NAME, &gpio_qmsi_init,
	      gpio_qmsi_device_ctrl, &gpio_0_runtime, &gpio_0_config,
	      SECONDARY, CONFIG_GPIO_QMSI_INIT_PRIORITY, NULL);

#endif /* CONFIG_GPIO_QMSI_0 */

#ifdef CONFIG_GPIO_QMSI_1
static const struct gpio_qmsi_config gpio_aon_config = {
	.gpio = QM_AON_GPIO_0,
	.num_pins = QM_NUM_AON_GPIO_PINS,
};

static struct gpio_qmsi_runtime gpio_aon_runtime;


#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
static uint32_t int_gpio_aon_mask_save;

static int gpio_aon_suspend_device(struct device *dev)
{
	int_gpio_aon_mask_save = REG_VAL(&QM_SCSS_INT->int_aon_gpio_mask);
	gpio_qmsi_set_power_state(dev, DEVICE_PM_SUSPEND_STATE);
	return 0;
}

static int gpio_aon_resume_device_from_suspend(struct device *dev)
{
	REG_VAL(&QM_SCSS_INT->int_aon_gpio_mask) = int_gpio_aon_mask_save;
{'fraction_non_alphanumeric': 0.11160906662070154, 'fraction_numerical': 0.01551322933724037, 'mean_word_length': 6.883152173913044, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 79, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2609351', 'n_tokens_mistral': 4951, 'n_tokens_neox': 4875, 'n_words': 809}