mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 17:25:35 +03:00
media: tegra: cdi-mgr: support interrupt timeouts
Add support for configurable interrupt timers and event notification queues to SIPL Device Block to mirror the CDAC (QNX) pulse channel interface. The CDI_MGR_IOCTL_INTR_CONFIG IOCTL is added to set the timeout duration at initialization, and existing GPIO interrupt code is refactored. Also removes the GPIO index limitation to the range of [0,31] by returning the complete indices one at a time instead of a bit flag. Jira CAMERASW-11100 Jira CAMERASW-11385 Jira CAMERASW-9366 Bug 3902416 Bug 3792904 Signed-off-by: Vincent Chung <vincentc@nvidia.com> Change-Id: I62b6c0bd8be18922ab1fe5d40485a69274f2a18e Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/2893327 Reviewed-by: Semi Malinen <smalinen@nvidia.com> Reviewed-by: Shiva Dubey <sdubey@nvidia.com> GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
This commit is contained in:
committed by
mobile promotions
parent
5dcd80a533
commit
be01df015d
@@ -1,10 +1,11 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
// Copyright (c) 2015-2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
// Copyright (c) 2015-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||||
|
|
||||||
#ifndef __CDI_MGR_PRIV_H__
|
#ifndef __CDI_MGR_PRIV_H__
|
||||||
#define __CDI_MGR_PRIV_H__
|
#define __CDI_MGR_PRIV_H__
|
||||||
|
|
||||||
#include <linux/cdev.h>
|
#include <linux/cdev.h>
|
||||||
|
#include <linux/hrtimer.h>
|
||||||
#include <media/cdi-mgr.h>
|
#include <media/cdi-mgr.h>
|
||||||
#include "cdi-tca-priv.h"
|
#include "cdi-tca-priv.h"
|
||||||
|
|
||||||
@@ -12,17 +13,37 @@
|
|||||||
#define CDI_MGR_TCA9539_REGISTER_COUNT (8)
|
#define CDI_MGR_TCA9539_REGISTER_COUNT (8)
|
||||||
#define CDI_MGR_TCA9539_BASE_REG_ADDR (0x00)
|
#define CDI_MGR_TCA9539_BASE_REG_ADDR (0x00)
|
||||||
|
|
||||||
|
#define CDI_MGR_GPIO_EVENT_QUEUE_SIZE (8)
|
||||||
|
#define CDI_MGR_GPIO_TIMER_QUEUE_SIZE (4)
|
||||||
|
|
||||||
enum cam_gpio_direction {
|
enum cam_gpio_direction {
|
||||||
CAM_DEVBLK_GPIO_UNSUSED = 0,
|
CAM_DEVBLK_GPIO_UNUSED = 0,
|
||||||
CAM_DEVBLK_GPIO_INPUT_INTERRUPT,
|
CAM_DEVBLK_GPIO_INPUT_INTR,
|
||||||
CAM_DEVBLK_GPIO_OUTPUT
|
CAM_DEVBLK_GPIO_OUTPUT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct cam_gpio_timer_queue {
|
||||||
|
struct hrtimer timer;
|
||||||
|
ktime_t expires[CDI_MGR_GPIO_TIMER_QUEUE_SIZE];
|
||||||
|
u32 head;
|
||||||
|
u32 count;
|
||||||
|
};
|
||||||
|
|
||||||
struct cam_gpio_config {
|
struct cam_gpio_config {
|
||||||
int index;
|
struct cdi_mgr_priv *mgr;
|
||||||
|
u32 idx;
|
||||||
enum cam_gpio_direction gpio_dir;
|
enum cam_gpio_direction gpio_dir;
|
||||||
struct gpio_desc *desc;
|
struct gpio_desc *desc;
|
||||||
int gpio_intr_irq;
|
int intr_irq;
|
||||||
|
struct cam_gpio_timer_queue timers;
|
||||||
|
ktime_t timeout;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cam_gpio_event_queue {
|
||||||
|
wait_queue_head_t wait;
|
||||||
|
struct cdi_mgr_gpio_intr events[CDI_MGR_GPIO_EVENT_QUEUE_SIZE];
|
||||||
|
u32 head;
|
||||||
|
u32 count;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cdi_mgr_priv {
|
struct cdi_mgr_priv {
|
||||||
@@ -46,14 +67,13 @@ struct cdi_mgr_priv {
|
|||||||
u32 pwr_state;
|
u32 pwr_state;
|
||||||
atomic_t irq_in_use;
|
atomic_t irq_in_use;
|
||||||
struct pwm_device *pwm;
|
struct pwm_device *pwm;
|
||||||
wait_queue_head_t err_queue;
|
|
||||||
bool err_irq_reported;
|
|
||||||
u8 des_pwr_method;
|
u8 des_pwr_method;
|
||||||
u8 des_pwr_i2c_addr;
|
u8 des_pwr_i2c_addr;
|
||||||
struct tca9539_priv tca9539;
|
struct tca9539_priv tca9539;
|
||||||
struct cam_gpio_config gpio_arr[MAX_CDI_GPIOS];
|
struct cam_gpio_config gpios[MAX_CDI_GPIOS];
|
||||||
uint32_t gpio_count;
|
uint32_t num_gpios;
|
||||||
uint32_t err_irq_recvd_status_mask;
|
bool intrs_enable;
|
||||||
|
struct cam_gpio_event_queue gpio_events;
|
||||||
bool stop_err_irq_wait;
|
bool stop_err_irq_wait;
|
||||||
u8 cim_ver; /* 1 - P3714 A01, 2 - P3714 A02/A03 */
|
u8 cim_ver; /* 1 - P3714 A01, 2 - P3714 A02/A03 */
|
||||||
u32 cim_frsync[3]; /* FRSYNC source selection for each muxer */
|
u32 cim_frsync[3]; /* FRSYNC source selection for each muxer */
|
||||||
|
|||||||
@@ -223,24 +223,168 @@ int cdi_mgr_debugfs_remove(struct cdi_mgr_priv *cdi_mgr)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int cdi_mgr_gpio_eq_event(
|
||||||
|
struct cdi_mgr_priv *cdi_mgr, struct cdi_mgr_gpio_intr evt)
|
||||||
|
{
|
||||||
|
struct cam_gpio_event_queue *queue;
|
||||||
|
u32 queue_cap;
|
||||||
|
|
||||||
|
if (!cdi_mgr)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
queue = &cdi_mgr->gpio_events;
|
||||||
|
queue_cap = ARRAY_SIZE(queue->events);
|
||||||
|
|
||||||
|
if (queue->count >= queue_cap) {
|
||||||
|
dev_err(cdi_mgr->dev,
|
||||||
|
"%s: failed to enqueue interrupt event, overflow\n",
|
||||||
|
__func__);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
queue->events[(queue->head+queue->count)%queue_cap] = evt;
|
||||||
|
queue->count++;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cdi_mgr_gpio_dq_event(
|
||||||
|
struct cdi_mgr_priv *cdi_mgr, struct cdi_mgr_gpio_intr *evt)
|
||||||
|
{
|
||||||
|
struct cam_gpio_event_queue *queue;
|
||||||
|
u32 queue_cap;
|
||||||
|
|
||||||
|
if (!cdi_mgr || !evt)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
queue = &cdi_mgr->gpio_events;
|
||||||
|
queue_cap = ARRAY_SIZE(queue->events);
|
||||||
|
|
||||||
|
if (queue->count == 0)
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
|
*evt = queue->events[queue->head];
|
||||||
|
queue->head = (queue->head+1) % queue_cap;
|
||||||
|
queue->count--;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cdi_mgr_gpio_eq_intr_timer(
|
||||||
|
struct cam_gpio_config *pin)
|
||||||
|
{
|
||||||
|
struct cdi_mgr_priv *cdi_mgr;
|
||||||
|
struct cam_gpio_timer_queue *queue;
|
||||||
|
u32 queue_cap;
|
||||||
|
ktime_t timeout_abs;
|
||||||
|
|
||||||
|
if (!pin || !pin->mgr)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* Skip enqueue if timeout is disabled */
|
||||||
|
if (ktime_to_ms(pin->timeout) <= 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
cdi_mgr = pin->mgr;
|
||||||
|
queue = &pin->timers;
|
||||||
|
queue_cap = ARRAY_SIZE(queue->expires);
|
||||||
|
|
||||||
|
if (queue->count >= queue_cap) {
|
||||||
|
dev_err(cdi_mgr->dev,
|
||||||
|
"%s: failed to enqueue interrupt timer, overflow\n",
|
||||||
|
__func__);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
timeout_abs = ktime_add(ktime_get(), pin->timeout);
|
||||||
|
|
||||||
|
if (!hrtimer_active(&queue->timer)) {
|
||||||
|
/* Start the interrupt timer immediately */
|
||||||
|
hrtimer_start(&queue->timer, timeout_abs, HRTIMER_MODE_ABS);
|
||||||
|
} else {
|
||||||
|
/* Enqueue interrupt timer */
|
||||||
|
queue->expires[(queue->head+queue->count)%queue_cap] = timeout_abs;
|
||||||
|
queue->count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cdi_mgr_gpio_dq_intr_timer(
|
||||||
|
struct cam_gpio_config *pin)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
struct cdi_mgr_priv *cdi_mgr;
|
||||||
|
struct cam_gpio_timer_queue *queue;
|
||||||
|
u32 queue_cap;
|
||||||
|
ktime_t *expire;
|
||||||
|
struct cdi_mgr_gpio_intr event;
|
||||||
|
|
||||||
|
if (!pin || !pin->mgr)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
cdi_mgr = pin->mgr;
|
||||||
|
queue = &pin->timers;
|
||||||
|
queue_cap = ARRAY_SIZE(queue->expires);
|
||||||
|
|
||||||
|
spin_lock_irqsave(&cdi_mgr->spinlock, flags);
|
||||||
|
|
||||||
|
/* Report timer expiry */
|
||||||
|
event.idx = pin->idx;
|
||||||
|
event.code = CDI_MGR_GPIO_INTR_TIMEOUT;
|
||||||
|
if (cdi_mgr_gpio_eq_event(cdi_mgr, event) != 0)
|
||||||
|
dev_err(cdi_mgr->dev,
|
||||||
|
"%s: failed to enqueue interrupt timeout event, "
|
||||||
|
"idx %d\n", __func__, pin->idx);
|
||||||
|
|
||||||
|
/* Dequeue next interrupt timer */
|
||||||
|
if (queue->count == 0)
|
||||||
|
goto unlock;
|
||||||
|
|
||||||
|
expire = &queue->expires[queue->head];
|
||||||
|
hrtimer_start(&queue->timer, *expire, HRTIMER_MODE_ABS);
|
||||||
|
queue->head = (queue->head+1) % queue_cap;
|
||||||
|
queue->count--;
|
||||||
|
|
||||||
|
unlock:
|
||||||
|
spin_unlock_irqrestore(&cdi_mgr->spinlock, flags);
|
||||||
|
|
||||||
|
wake_up_interruptible(&cdi_mgr->gpio_events.wait);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static irqreturn_t cdi_mgr_isr(int irq, void *data)
|
static irqreturn_t cdi_mgr_isr(int irq, void *data)
|
||||||
{
|
{
|
||||||
struct cdi_mgr_priv *cdi_mgr;
|
struct cdi_mgr_priv *cdi_mgr;
|
||||||
int ret;
|
int ret;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int i = 0, gpio_mask = 0;
|
int i = 0;
|
||||||
|
struct cam_gpio_config *pin;
|
||||||
|
struct cdi_mgr_gpio_intr event;
|
||||||
|
|
||||||
if (data) {
|
if (data) {
|
||||||
cdi_mgr = (struct cdi_mgr_priv *)data;
|
cdi_mgr = (struct cdi_mgr_priv *)data;
|
||||||
|
if (!cdi_mgr->intrs_enable)
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
|
||||||
spin_lock_irqsave(&cdi_mgr->spinlock, flags);
|
spin_lock_irqsave(&cdi_mgr->spinlock, flags);
|
||||||
for (i = 0; i < cdi_mgr->gpio_count; i++) {
|
for (i = 0; i < cdi_mgr->num_gpios; i++) {
|
||||||
if (irq == cdi_mgr->gpio_arr[i].gpio_intr_irq)
|
pin = &cdi_mgr->gpios[i];
|
||||||
gpio_mask |= (1 << cdi_mgr->gpio_arr[i].index);
|
if (irq != pin->intr_irq)
|
||||||
|
continue;
|
||||||
|
event.idx = pin->idx;
|
||||||
|
event.code = CDI_MGR_GPIO_INTR;
|
||||||
|
if (cdi_mgr_gpio_eq_event(cdi_mgr, event) != 0)
|
||||||
|
pr_err("Failed to enqueue interrupt event, "
|
||||||
|
"idx %d\n", pin->idx);
|
||||||
|
if (cdi_mgr_gpio_eq_intr_timer(pin) != 0)
|
||||||
|
pr_err("Failed to enqueue interrupt timer, "
|
||||||
|
"idx %d\n", pin->idx);
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&cdi_mgr->spinlock, flags);
|
spin_unlock_irqrestore(&cdi_mgr->spinlock, flags);
|
||||||
cdi_mgr->err_irq_recvd_status_mask = gpio_mask;
|
|
||||||
wake_up_interruptible(&cdi_mgr->err_queue);
|
wake_up_interruptible(&cdi_mgr->gpio_events.wait);
|
||||||
|
|
||||||
spin_lock_irqsave(&cdi_mgr->spinlock, flags);
|
spin_lock_irqsave(&cdi_mgr->spinlock, flags);
|
||||||
if (cdi_mgr->sinfo.si_signo && cdi_mgr->t) {
|
if (cdi_mgr->sinfo.si_signo && cdi_mgr->t) {
|
||||||
@@ -250,9 +394,6 @@ static irqreturn_t cdi_mgr_isr(int irq, void *data)
|
|||||||
cdi_mgr->t);
|
cdi_mgr->t);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
pr_err("error sending signal\n");
|
pr_err("error sending signal\n");
|
||||||
spin_unlock_irqrestore(&cdi_mgr->spinlock,
|
|
||||||
flags);
|
|
||||||
return IRQ_HANDLED;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&cdi_mgr->spinlock, flags);
|
spin_unlock_irqrestore(&cdi_mgr->spinlock, flags);
|
||||||
@@ -261,6 +402,29 @@ static irqreturn_t cdi_mgr_isr(int irq, void *data)
|
|||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static enum hrtimer_restart cdi_mgr_intr_timer(struct hrtimer *timer)
|
||||||
|
{
|
||||||
|
struct cam_gpio_timer_queue *queue;
|
||||||
|
struct cam_gpio_config *pin;
|
||||||
|
|
||||||
|
if (timer == NULL)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
queue = container_of(timer, struct cam_gpio_timer_queue, timer);
|
||||||
|
pin = container_of(queue, struct cam_gpio_config, timers);
|
||||||
|
|
||||||
|
if (cdi_mgr_gpio_dq_intr_timer(pin) != 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
error:
|
||||||
|
pr_err("Failed to handle GPIO interrupt timer expiry\n");
|
||||||
|
|
||||||
|
done:
|
||||||
|
return HRTIMER_NORESTART;
|
||||||
|
}
|
||||||
|
|
||||||
int cdi_delete_lst(struct device *dev, struct i2c_client *client)
|
int cdi_delete_lst(struct device *dev, struct i2c_client *client)
|
||||||
{
|
{
|
||||||
struct cdi_mgr_priv *cdi_mgr;
|
struct cdi_mgr_priv *cdi_mgr;
|
||||||
@@ -658,51 +822,191 @@ static int cdi_mgr_pwm_config(
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cdi_mgr_wait_err(
|
static u32 gpio_to_idx(
|
||||||
struct cdi_mgr_priv *cdi_mgr, void __user *arg)
|
struct cdi_mgr_priv *cdi_mgr, u32 idx)
|
||||||
{
|
{
|
||||||
int err = 0, i = 0;
|
int i;
|
||||||
uint32_t gpio_irq_monitor_mask = 0;
|
|
||||||
uint32_t gpio_irq_status_mask = 0;
|
|
||||||
|
|
||||||
if (!atomic_xchg(&cdi_mgr->irq_in_use, 1)) {
|
for (i = 0; i < cdi_mgr->num_gpios; i++)
|
||||||
for (i = 0; i < cdi_mgr->gpio_count; i++) {
|
if (cdi_mgr->gpios[i].idx == idx)
|
||||||
if ((cdi_mgr->gpio_arr[i].gpio_dir == CAM_DEVBLK_GPIO_INPUT_INTERRUPT) &&
|
return i;
|
||||||
cdi_mgr->gpio_arr[i].gpio_intr_irq >= 0)
|
|
||||||
enable_irq(cdi_mgr->gpio_arr[i].gpio_intr_irq);
|
|
||||||
}
|
|
||||||
cdi_mgr->err_irq_recvd_status_mask = 0;
|
|
||||||
cdi_mgr->stop_err_irq_wait = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (get_user(gpio_irq_monitor_mask, (uint32_t __user *)arg)) {
|
return MAX_CDI_GPIOS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cdi_mgr_gpio_config(
|
||||||
|
struct cdi_mgr_priv *cdi_mgr, const void __user *arg)
|
||||||
|
{
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
struct cdi_mgr_gpio_info config;
|
||||||
|
u32 idx;
|
||||||
|
struct cam_gpio_config *pin;
|
||||||
|
|
||||||
|
if (!cdi_mgr)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (copy_from_user(&config, arg, sizeof(config))) {
|
||||||
dev_err(cdi_mgr->pdev,
|
dev_err(cdi_mgr->pdev,
|
||||||
"%s: failed to get_user\n", __func__);
|
"%s: failed to copy from user\n", __func__);
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
idx = gpio_to_idx(cdi_mgr, config.idx);
|
||||||
err = wait_event_interruptible(cdi_mgr->err_queue,
|
if (idx >= MAX_CDI_GPIOS) {
|
||||||
(cdi_mgr->err_irq_recvd_status_mask & gpio_irq_monitor_mask) != 0);
|
dev_err(cdi_mgr->pdev, "%s: unknown gpio idx %u\n",
|
||||||
if (err < 0) {
|
__func__, config.idx);
|
||||||
dev_err(cdi_mgr->pdev, "%s: wait_event_interruptible failed\n", __func__);
|
/* WAR: nvbugs/4087689 */
|
||||||
break;
|
/* return -EFAULT; */
|
||||||
}
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
gpio_irq_status_mask = cdi_mgr->err_irq_recvd_status_mask & gpio_irq_monitor_mask;
|
pin = &cdi_mgr->gpios[idx];
|
||||||
|
|
||||||
if (!cdi_mgr->stop_err_irq_wait &&
|
/* Interrupt timeout */
|
||||||
put_user(gpio_irq_status_mask, (u32 __user *) arg)) {
|
if ((config.timeout_ms > 0) &&
|
||||||
dev_err(cdi_mgr->pdev,
|
(pin->gpio_dir != CAM_DEVBLK_GPIO_INPUT_INTR))
|
||||||
"%s: failed to put_user\n", __func__);
|
dev_warn(cdi_mgr->pdev,
|
||||||
return -EFAULT;
|
"%s: gpio idx %u setting timeout for non-interrupt "
|
||||||
}
|
"type pin has no effect\n", __func__, idx);
|
||||||
cdi_mgr->err_irq_recvd_status_mask = 0;
|
|
||||||
} while (cdi_mgr->err_irq_reported == false);
|
pin->timeout = ms_to_ktime(config.timeout_ms);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int cdi_mgr_gpio_intr_arm(
|
||||||
|
struct cdi_mgr_priv *cdi_mgr)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct cam_gpio_config *pin;
|
||||||
|
|
||||||
|
if (!cdi_mgr)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (!atomic_xchg(&cdi_mgr->irq_in_use, 1))
|
||||||
|
for (i = 0; i < cdi_mgr->num_gpios; i++) {
|
||||||
|
pin = &cdi_mgr->gpios[i];
|
||||||
|
if ((pin->gpio_dir == CAM_DEVBLK_GPIO_INPUT_INTR) &&
|
||||||
|
(pin->intr_irq >= 0))
|
||||||
|
enable_irq(pin->intr_irq);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cdi_mgr_gpio_intr_reset(struct cdi_mgr_priv *cdi_mgr)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
int i;
|
||||||
|
struct cam_gpio_config *pin;
|
||||||
|
struct cam_gpio_event_queue *evts_queue;
|
||||||
|
struct cam_gpio_timer_queue *tmrs_queue;
|
||||||
|
|
||||||
|
if (!cdi_mgr)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
evts_queue = &cdi_mgr->gpio_events;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&cdi_mgr->spinlock, flags);
|
||||||
|
|
||||||
|
// Reset GPIO pin timer queues
|
||||||
|
for (i = 0; i < cdi_mgr->num_gpios; i++) {
|
||||||
|
pin = &cdi_mgr->gpios[i];
|
||||||
|
tmrs_queue = &pin->timers;
|
||||||
|
(void)hrtimer_try_to_cancel(&tmrs_queue->timer);
|
||||||
|
tmrs_queue->head = 0;
|
||||||
|
tmrs_queue->count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset GPIO events queue
|
||||||
|
evts_queue->head = 0;
|
||||||
|
evts_queue->count = 0;
|
||||||
|
|
||||||
|
cdi_mgr->intrs_enable = false;
|
||||||
|
cdi_mgr->stop_err_irq_wait = false;
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&cdi_mgr->spinlock, flags);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cdi_mgr_gpio_intr_wait(
|
||||||
|
struct cdi_mgr_priv *cdi_mgr, void __user *arg)
|
||||||
|
{
|
||||||
|
int err = 0;
|
||||||
|
int ret;
|
||||||
|
unsigned long flags;
|
||||||
|
struct cdi_mgr_gpio_intr event;
|
||||||
|
|
||||||
|
if (!cdi_mgr) {
|
||||||
|
err = -EINVAL;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = cdi_mgr_gpio_intr_arm(cdi_mgr);
|
||||||
|
if (err != 0) {
|
||||||
|
dev_err(cdi_mgr->pdev,
|
||||||
|
"%s: cdi_mgr_gpio_intr_arm failed %d\n",
|
||||||
|
__func__, err);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = wait_event_interruptible(cdi_mgr->gpio_events.wait,
|
||||||
|
(cdi_mgr->stop_err_irq_wait
|
||||||
|
|| (cdi_mgr->gpio_events.count > 0)));
|
||||||
|
if (ret < 0) {
|
||||||
|
err = ret;
|
||||||
|
dev_err(cdi_mgr->pdev,
|
||||||
|
"%s: wait_event_interruptible failed %d\n",
|
||||||
|
__func__, err);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cdi_mgr->stop_err_irq_wait) {
|
||||||
|
event.idx = 0;
|
||||||
|
event.code = CDI_MGR_GPIO_INTR_UNBLOCK;
|
||||||
|
if (copy_to_user(arg, &event, sizeof(event))) {
|
||||||
|
err = -EFAULT;
|
||||||
|
dev_err(cdi_mgr->pdev,
|
||||||
|
"%s: failed to copy to user\n", __func__);
|
||||||
|
}
|
||||||
|
cdi_mgr->stop_err_irq_wait = false;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
spin_lock_irqsave(&cdi_mgr->spinlock, flags);
|
||||||
|
ret = cdi_mgr_gpio_dq_event(cdi_mgr, &event);
|
||||||
|
spin_unlock_irqrestore(&cdi_mgr->spinlock, flags);
|
||||||
|
if (ret != 0) {
|
||||||
|
err = ret;
|
||||||
|
dev_err(cdi_mgr->pdev,
|
||||||
|
"%s: failed to dequeue interrupt event\n", __func__);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (copy_to_user(arg, &event, sizeof(event))) {
|
||||||
|
err = -EFAULT;
|
||||||
|
dev_err(cdi_mgr->pdev,
|
||||||
|
"%s: failed to copy to user\n", __func__);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cdi_mgr_gpio_intr_wait_abort(struct cdi_mgr_priv *cdi_mgr)
|
||||||
|
{
|
||||||
|
if (!cdi_mgr)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
cdi_mgr->stop_err_irq_wait = true;
|
||||||
|
wake_up_interruptible(&cdi_mgr->gpio_events.wait);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int cdi_mgr_des_power(
|
static int cdi_mgr_des_power(
|
||||||
struct cdi_mgr_priv *cdi_mgr, bool enable)
|
struct cdi_mgr_priv *cdi_mgr, bool enable)
|
||||||
{
|
{
|
||||||
@@ -771,11 +1075,11 @@ static long cdi_mgr_ioctl(
|
|||||||
* and then register PID
|
* and then register PID
|
||||||
*/
|
*/
|
||||||
if (!atomic_xchg(&cdi_mgr->irq_in_use, 1)) {
|
if (!atomic_xchg(&cdi_mgr->irq_in_use, 1)) {
|
||||||
for (i = 0; i < cdi_mgr->gpio_count; i++) {
|
for (i = 0; i < cdi_mgr->num_gpios; i++) {
|
||||||
if ((cdi_mgr->gpio_arr[i].gpio_dir ==
|
if ((cdi_mgr->gpios[i].gpio_dir ==
|
||||||
CAM_DEVBLK_GPIO_INPUT_INTERRUPT) &&
|
CAM_DEVBLK_GPIO_INPUT_INTR) &&
|
||||||
cdi_mgr->gpio_arr[i].gpio_intr_irq >= 0)
|
cdi_mgr->gpios[i].intr_irq >= 0)
|
||||||
enable_irq(cdi_mgr->gpio_arr[i].gpio_intr_irq);
|
enable_irq(cdi_mgr->gpios[i].intr_irq);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -812,17 +1116,18 @@ static long cdi_mgr_ioctl(
|
|||||||
case CDI_MGR_IOCTL_PWM_CONFIG:
|
case CDI_MGR_IOCTL_PWM_CONFIG:
|
||||||
err = cdi_mgr_pwm_config(cdi_mgr, (const void __user *)arg);
|
err = cdi_mgr_pwm_config(cdi_mgr, (const void __user *)arg);
|
||||||
break;
|
break;
|
||||||
case CDI_MGR_IOCTL_WAIT_ERR:
|
case CDI_MGR_IOCTL_INTR_CONFIG:
|
||||||
err = cdi_mgr_wait_err(cdi_mgr, (void __user *)arg);
|
err = cdi_mgr_gpio_config(cdi_mgr, (const void __user *)arg);
|
||||||
break;
|
break;
|
||||||
case CDI_MGR_IOCTL_ABORT_WAIT_ERR:
|
case CDI_MGR_IOCTL_INTR_ENABLE:
|
||||||
cdi_mgr->err_irq_recvd_status_mask = CDI_MGR_STOP_GPIO_INTR_EVENT_WAIT;
|
err = cdi_mgr_gpio_intr_reset(cdi_mgr);
|
||||||
cdi_mgr->err_irq_reported = true;
|
cdi_mgr->intrs_enable = true;
|
||||||
cdi_mgr->stop_err_irq_wait = true;
|
|
||||||
wake_up_interruptible(&cdi_mgr->err_queue);
|
|
||||||
break;
|
break;
|
||||||
case CDI_MGR_IOCTL_ENABLE_ERROR_REPORT:
|
case CDI_MGR_IOCTL_INTR_WAIT:
|
||||||
cdi_mgr->err_irq_reported = true;
|
err = cdi_mgr_gpio_intr_wait(cdi_mgr, (void __user *)arg);
|
||||||
|
break;
|
||||||
|
case CDI_MGR_IOCTL_INTR_WAIT_ABORT:
|
||||||
|
err = cdi_mgr_gpio_intr_wait_abort(cdi_mgr);
|
||||||
break;
|
break;
|
||||||
case CDI_MGR_IOCTL_GET_PWR_INFO:
|
case CDI_MGR_IOCTL_GET_PWR_INFO:
|
||||||
err = cdi_mgr_get_pwr_ctrl_info(cdi_mgr, (void __user *)arg);
|
err = cdi_mgr_get_pwr_ctrl_info(cdi_mgr, (void __user *)arg);
|
||||||
@@ -854,11 +1159,11 @@ static int cdi_mgr_open(struct inode *inode, struct file *file)
|
|||||||
if (atomic_xchg(&cdi_mgr->in_use, 1))
|
if (atomic_xchg(&cdi_mgr->in_use, 1))
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
|
||||||
cdi_mgr->err_irq_reported = false;
|
|
||||||
|
|
||||||
dev_dbg(cdi_mgr->pdev, "%s\n", __func__);
|
dev_dbg(cdi_mgr->pdev, "%s\n", __func__);
|
||||||
file->private_data = cdi_mgr;
|
file->private_data = cdi_mgr;
|
||||||
|
|
||||||
|
cdi_mgr->stop_err_irq_wait = false;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -868,7 +1173,6 @@ static int cdi_mgr_release(struct inode *inode, struct file *file)
|
|||||||
int i = 0;
|
int i = 0;
|
||||||
struct cdi_mgr_priv *cdi_mgr = file->private_data;
|
struct cdi_mgr_priv *cdi_mgr = file->private_data;
|
||||||
|
|
||||||
cdi_mgr->err_irq_reported = true;
|
|
||||||
if (cdi_mgr->tca9539.enable) {
|
if (cdi_mgr->tca9539.enable) {
|
||||||
if (down_timeout(&tca9539_sem,
|
if (down_timeout(&tca9539_sem,
|
||||||
usecs_to_jiffies(TIMEOUT_US)) != 0)
|
usecs_to_jiffies(TIMEOUT_US)) != 0)
|
||||||
@@ -898,15 +1202,15 @@ static int cdi_mgr_release(struct inode *inode, struct file *file)
|
|||||||
cdi_mgr_mcdi_ctrl(cdi_mgr, false);
|
cdi_mgr_mcdi_ctrl(cdi_mgr, false);
|
||||||
|
|
||||||
/* disable irq if irq is in use, when device is closed */
|
/* disable irq if irq is in use, when device is closed */
|
||||||
|
(void)cdi_mgr_gpio_intr_reset(cdi_mgr);
|
||||||
if (atomic_xchg(&cdi_mgr->irq_in_use, 0)) {
|
if (atomic_xchg(&cdi_mgr->irq_in_use, 0)) {
|
||||||
for (i = 0; i < cdi_mgr->gpio_count; i++) {
|
for (i = 0; i < cdi_mgr->num_gpios; i++) {
|
||||||
if ((cdi_mgr->gpio_arr[i].gpio_dir == CAM_DEVBLK_GPIO_INPUT_INTERRUPT) &&
|
if ((cdi_mgr->gpios[i].gpio_dir == CAM_DEVBLK_GPIO_INPUT_INTR) &&
|
||||||
cdi_mgr->gpio_arr[i].gpio_intr_irq >= 0)
|
cdi_mgr->gpios[i].intr_irq >= 0)
|
||||||
disable_irq(cdi_mgr->gpio_arr[i].gpio_intr_irq);
|
disable_irq(cdi_mgr->gpios[i].intr_irq);
|
||||||
}
|
}
|
||||||
cdi_mgr->err_irq_recvd_status_mask = CDI_MGR_STOP_GPIO_INTR_EVENT_WAIT;
|
|
||||||
cdi_mgr->stop_err_irq_wait = true;
|
cdi_mgr->stop_err_irq_wait = true;
|
||||||
wake_up_interruptible(&cdi_mgr->err_queue);
|
wake_up_interruptible(&cdi_mgr->gpio_events.wait);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if runtime_pwrctrl_off is not true, power off all here */
|
/* if runtime_pwrctrl_off is not true, power off all here */
|
||||||
@@ -954,8 +1258,8 @@ static void cdi_mgr_del(struct cdi_mgr_priv *cdi_mgr)
|
|||||||
i2c_put_adapter(cdi_mgr->adap);
|
i2c_put_adapter(cdi_mgr->adap);
|
||||||
|
|
||||||
for (i = 0; i < MAX_CDI_GPIOS; i++) {
|
for (i = 0; i < MAX_CDI_GPIOS; i++) {
|
||||||
if (cdi_mgr->gpio_arr[i].desc)
|
if (cdi_mgr->gpios[i].desc)
|
||||||
devm_gpiod_put(cdi_mgr->dev, cdi_mgr->gpio_arr[i].desc);
|
devm_gpiod_put(cdi_mgr->dev, cdi_mgr->gpios[i].desc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1251,32 +1555,32 @@ static int cdi_mgr_setup_gpio_interrupt(struct device *dev, struct cdi_mgr_priv
|
|||||||
int ret = 0;
|
int ret = 0;
|
||||||
int gpio_irq = 0;
|
int gpio_irq = 0;
|
||||||
|
|
||||||
ret = gpiod_direction_input(cdi_mgr->gpio_arr[idx].desc);
|
ret = gpiod_direction_input(cdi_mgr->gpios[idx].desc);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(dev, "%s Failed to gpio direction : input 0\n",
|
dev_err(dev, "%s Failed to gpio direction : input 0\n",
|
||||||
__func__);
|
__func__);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
gpio_irq = gpiod_to_irq(cdi_mgr->gpio_arr[idx].desc);
|
gpio_irq = gpiod_to_irq(cdi_mgr->gpios[idx].desc);
|
||||||
if (gpio_irq < 0) {
|
if (gpio_irq < 0) {
|
||||||
dev_err(dev, "gpiod_to_irq() failed: %d\n", gpio_irq);
|
dev_err(dev, "gpiod_to_irq() failed: %d\n", gpio_irq);
|
||||||
return gpio_irq;
|
return gpio_irq;
|
||||||
}
|
}
|
||||||
|
|
||||||
cdi_mgr->gpio_arr[idx].gpio_intr_irq = gpio_irq;
|
cdi_mgr->gpios[idx].intr_irq = gpio_irq;
|
||||||
ret = devm_request_irq(dev,
|
ret = devm_request_irq(dev,
|
||||||
cdi_mgr->gpio_arr[idx].gpio_intr_irq,
|
cdi_mgr->gpios[idx].intr_irq,
|
||||||
cdi_mgr_isr, intr_edge, dev_name(dev), cdi_mgr);
|
cdi_mgr_isr, intr_edge, dev_name(dev), cdi_mgr);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(dev, "devm_request_irq failed with err %d\n", ret);
|
dev_err(dev, "devm_request_irq failed with err %d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
disable_irq(cdi_mgr->gpio_arr[idx].gpio_intr_irq);
|
disable_irq(cdi_mgr->gpios[idx].intr_irq);
|
||||||
atomic_set(&cdi_mgr->irq_in_use, 0);
|
atomic_set(&cdi_mgr->irq_in_use, 0);
|
||||||
|
|
||||||
cdi_mgr->gpio_arr[idx].gpio_dir = CAM_DEVBLK_GPIO_INPUT_INTERRUPT;
|
cdi_mgr->gpios[idx].gpio_dir = CAM_DEVBLK_GPIO_INPUT_INTR;
|
||||||
cdi_mgr->gpio_arr[idx].index = gpio_idx;
|
cdi_mgr->gpios[idx].idx = gpio_idx;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1284,7 +1588,7 @@ static int cdi_mgr_setup_gpio_interrupt(struct device *dev, struct cdi_mgr_priv
|
|||||||
static int cdi_mgr_configure_gpios(struct device *dev, struct cdi_mgr_priv *cdi_mgr)
|
static int cdi_mgr_configure_gpios(struct device *dev, struct cdi_mgr_priv *cdi_mgr)
|
||||||
{
|
{
|
||||||
struct device_node *node = NULL;
|
struct device_node *node = NULL;
|
||||||
int gpio_count = 0;
|
int num_gpios = 0;
|
||||||
uint32_t i = 0, j = 0;
|
uint32_t i = 0, j = 0;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
@@ -1296,13 +1600,13 @@ static int cdi_mgr_configure_gpios(struct device *dev, struct cdi_mgr_priv *cdi_
|
|||||||
if (node != NULL) {
|
if (node != NULL) {
|
||||||
struct device_node *child = NULL;
|
struct device_node *child = NULL;
|
||||||
|
|
||||||
gpio_count = of_get_child_count(node);
|
num_gpios = of_get_child_count(node);
|
||||||
if (!gpio_count || gpio_count > MAX_CDI_GPIOS) {
|
if (!num_gpios || num_gpios > MAX_CDI_GPIOS) {
|
||||||
dev_err(dev, "%s Invalid number of gpios : %d\n",
|
dev_err(dev, "%s Invalid number of gpios : %d\n",
|
||||||
__func__, gpio_count);
|
__func__, num_gpios);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
dev_dbg(dev, "%s gpio node count : %d\n", __func__, gpio_count);
|
dev_dbg(dev, "%s gpio node count : %d\n", __func__, num_gpios);
|
||||||
|
|
||||||
for_each_child_of_node(node, child) {
|
for_each_child_of_node(node, child) {
|
||||||
uint32_t gpio_index = 0;
|
uint32_t gpio_index = 0;
|
||||||
@@ -1320,22 +1624,22 @@ static int cdi_mgr_configure_gpios(struct device *dev, struct cdi_mgr_priv *cdi_
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (j = 0; j < cdi_mgr->gpio_count; j++) {
|
for (j = 0; j < cdi_mgr->num_gpios; j++) {
|
||||||
if (cdi_mgr->gpio_arr[j].index == gpio_index) {
|
if (cdi_mgr->gpios[j].idx == gpio_index) {
|
||||||
dev_err(dev, "%s GPIO already in use\n", __func__);
|
dev_err(dev, "%s GPIO already in use\n", __func__);
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 2, 0)
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 2, 0)
|
||||||
cdi_mgr->gpio_arr[i].desc = devm_fwnode_get_gpiod_from_child(dev,
|
cdi_mgr->gpios[i].desc = devm_fwnode_get_gpiod_from_child(dev,
|
||||||
"devblk", &child->fwnode, GPIOD_ASIS, NULL);
|
"devblk", &child->fwnode, GPIOD_ASIS, NULL);
|
||||||
#else
|
#else
|
||||||
cdi_mgr->gpio_arr[i].desc = devm_fwnode_gpiod_get_index(dev,
|
cdi_mgr->gpios[i].desc = devm_fwnode_gpiod_get_index(dev,
|
||||||
&child->fwnode, "devblk", 0, GPIOD_ASIS, NULL);
|
&child->fwnode, "devblk", 0, GPIOD_ASIS, NULL);
|
||||||
#endif
|
#endif
|
||||||
if (IS_ERR(cdi_mgr->gpio_arr[i].desc)) {
|
if (IS_ERR(cdi_mgr->gpios[i].desc)) {
|
||||||
ret = PTR_ERR(cdi_mgr->gpio_arr[i].desc);
|
ret = PTR_ERR(cdi_mgr->gpios[i].desc);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
dev_err(dev, "%s Failed to allocate gpio desc\n",
|
dev_err(dev, "%s Failed to allocate gpio desc\n",
|
||||||
__func__);
|
__func__);
|
||||||
@@ -1365,7 +1669,7 @@ static int cdi_mgr_configure_gpios(struct device *dev, struct cdi_mgr_priv *cdi_
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
cdi_mgr->gpio_count++;
|
cdi_mgr->num_gpios++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -1422,6 +1726,7 @@ static int cdi_mgr_probe(struct platform_device *pdev)
|
|||||||
struct cdi_mgr_priv *cdi_mgr;
|
struct cdi_mgr_priv *cdi_mgr;
|
||||||
struct cdi_mgr_platform_data *pd;
|
struct cdi_mgr_platform_data *pd;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
struct cam_gpio_config *pin = NULL;
|
||||||
struct device_node *child = NULL;
|
struct device_node *child = NULL;
|
||||||
struct device_node *child_tca9539 = NULL;
|
struct device_node *child_tca9539 = NULL;
|
||||||
|
|
||||||
@@ -1439,11 +1744,17 @@ static int cdi_mgr_probe(struct platform_device *pdev)
|
|||||||
atomic_set(&cdi_mgr->in_use, 0);
|
atomic_set(&cdi_mgr->in_use, 0);
|
||||||
INIT_LIST_HEAD(&cdi_mgr->dev_list);
|
INIT_LIST_HEAD(&cdi_mgr->dev_list);
|
||||||
mutex_init(&cdi_mgr->mutex);
|
mutex_init(&cdi_mgr->mutex);
|
||||||
init_waitqueue_head(&cdi_mgr->err_queue);
|
init_waitqueue_head(&cdi_mgr->gpio_events.wait);
|
||||||
cdi_mgr->err_irq_recvd_status_mask = 0;
|
|
||||||
cdi_mgr->err_irq_reported = false;
|
|
||||||
cdi_mgr->pwm = NULL;
|
cdi_mgr->pwm = NULL;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(cdi_mgr->gpios); i++) {
|
||||||
|
pin = &cdi_mgr->gpios[i];
|
||||||
|
pin->mgr = cdi_mgr;
|
||||||
|
hrtimer_init(&pin->timers.timer, CLOCK_MONOTONIC,
|
||||||
|
HRTIMER_MODE_ABS);
|
||||||
|
pin->timers.timer.function = &cdi_mgr_intr_timer;
|
||||||
|
}
|
||||||
|
|
||||||
if (pdev->dev.of_node) {
|
if (pdev->dev.of_node) {
|
||||||
pd = of_cdi_mgr_pdata(pdev);
|
pd = of_cdi_mgr_pdata(pdev);
|
||||||
if (IS_ERR(pd))
|
if (IS_ERR(pd))
|
||||||
|
|||||||
@@ -7,22 +7,23 @@
|
|||||||
#include <linux/ioctl.h>
|
#include <linux/ioctl.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
|
||||||
#define CDI_MGR_IOCTL_PWR_DN _IOW('o', 1, __s16)
|
#define CDI_MGR_IOCTL_PWR_DN _IOW('o', 1, __s16)
|
||||||
#define CDI_MGR_IOCTL_PWR_UP _IOR('o', 2, __s16)
|
#define CDI_MGR_IOCTL_PWR_UP _IOR('o', 2, __s16)
|
||||||
#define CDI_MGR_IOCTL_SET_PID _IOW('o', 3, struct cdi_mgr_sinfo)
|
#define CDI_MGR_IOCTL_SET_PID _IOW('o', 3, struct cdi_mgr_sinfo)
|
||||||
#define CDI_MGR_IOCTL_SIGNAL _IOW('o', 4, int)
|
#define CDI_MGR_IOCTL_SIGNAL _IOW('o', 4, int)
|
||||||
#define CDI_MGR_IOCTL_DEV_ADD _IOW('o', 5, struct cdi_mgr_new_dev)
|
#define CDI_MGR_IOCTL_DEV_ADD _IOW('o', 5, struct cdi_mgr_new_dev)
|
||||||
#define CDI_MGR_IOCTL_DEV_DEL _IOW('o', 6, int)
|
#define CDI_MGR_IOCTL_DEV_DEL _IOW('o', 6, int)
|
||||||
#define CDI_MGR_IOCTL_PWR_INFO _IOW('o', 7, struct cdi_mgr_pwr_info)
|
#define CDI_MGR_IOCTL_PWR_INFO _IOW('o', 7, struct cdi_mgr_pwr_info)
|
||||||
#define CDI_MGR_IOCTL_PWM_ENABLE _IOW('o', 8, int)
|
#define CDI_MGR_IOCTL_PWM_ENABLE _IOW('o', 8, int)
|
||||||
#define CDI_MGR_IOCTL_PWM_CONFIG _IOW('o', 9, struct cdi_mgr_pwm_info)
|
#define CDI_MGR_IOCTL_PWM_CONFIG _IOW('o', 9, struct cdi_mgr_pwm_info)
|
||||||
#define CDI_MGR_IOCTL_WAIT_ERR _IOWR('o', 10, __u32)
|
#define CDI_MGR_IOCTL_INTR_CONFIG _IOW('o', 10, struct cdi_mgr_gpio_info)
|
||||||
#define CDI_MGR_IOCTL_ABORT_WAIT_ERR _IO('o', 11)
|
#define CDI_MGR_IOCTL_INTR_ENABLE _IO('o', 11)
|
||||||
#define CDI_MGR_IOCTL_GET_EXT_PWR_CTRL _IOR('o', 12, __u8)
|
#define CDI_MGR_IOCTL_INTR_WAIT _IOR('o', 12, __u32)
|
||||||
#define CDI_MGR_IOCTL_ENABLE_ERROR_REPORT _IO('o', 13)
|
#define CDI_MGR_IOCTL_INTR_WAIT_ABORT _IO('o', 13)
|
||||||
#define CDI_MGR_IOCTL_GET_PWR_INFO _IOW('o', 14, struct cdi_mgr_pwr_ctrl_info)
|
#define CDI_MGR_IOCTL_GET_EXT_PWR_CTRL _IOR('o', 14, __u8)
|
||||||
#define CDI_MGR_IOCTL_ENABLE_DES_POWER _IO('o', 15)
|
#define CDI_MGR_IOCTL_GET_PWR_INFO _IOW('o', 15, struct cdi_mgr_pwr_ctrl_info)
|
||||||
#define CDI_MGR_IOCTL_DISABLE_DES_POWER _IO('o', 16)
|
#define CDI_MGR_IOCTL_ENABLE_DES_POWER _IO('o', 16)
|
||||||
|
#define CDI_MGR_IOCTL_DISABLE_DES_POWER _IO('o', 17)
|
||||||
|
|
||||||
#define CDI_MGR_POWER_ALL 5
|
#define CDI_MGR_POWER_ALL 5
|
||||||
#define MAX_CDI_NAME_LENGTH 32
|
#define MAX_CDI_NAME_LENGTH 32
|
||||||
@@ -57,14 +58,26 @@ struct cdi_mgr_pwr_ctrl_info {
|
|||||||
__s8 des_pwr_i2c_addr;
|
__s8 des_pwr_i2c_addr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct cdi_mgr_gpio_info {
|
||||||
|
__u32 idx;
|
||||||
|
__u32 timeout_ms;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cdi_mgr_gpio_intr {
|
||||||
|
__u32 idx;
|
||||||
|
__u32 code;
|
||||||
|
};
|
||||||
|
|
||||||
struct cdi_mgr_pwm_info {
|
struct cdi_mgr_pwm_info {
|
||||||
__u64 duty_ns;
|
__u64 duty_ns;
|
||||||
__u64 period_ns;
|
__u64 period_ns;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
CDI_MGR_PWM_DISABLE = 0,
|
CDI_MGR_GPIO_INTR_UNBLOCK = 0,
|
||||||
CDI_MGR_PWM_ENABLE,
|
CDI_MGR_GPIO_INTR,
|
||||||
|
CDI_MGR_GPIO_INTR_TIMEOUT,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@@ -72,4 +85,9 @@ enum {
|
|||||||
CDI_MGR_SIGNAL_SUSPEND,
|
CDI_MGR_SIGNAL_SUSPEND,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
CDI_MGR_PWM_DISABLE = 0,
|
||||||
|
CDI_MGR_PWM_ENABLE,
|
||||||
|
};
|
||||||
|
|
||||||
#endif /* __UAPI_TEGRA_CDI_MGR_H__ */
|
#endif /* __UAPI_TEGRA_CDI_MGR_H__ */
|
||||||
|
|||||||
Reference in New Issue
Block a user