mirror of
https://github.com/torvalds/linux.git
synced 2026-07-31 03:27:03 +02:00
Merge "coresight-cti: Add gpio trigin and trigout support"
This commit is contained in:
commit
bede146f94
|
|
@ -15,9 +15,11 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
|
||||
#include "coresight-priv.h"
|
||||
#include "coresight-cti.h"
|
||||
|
|
@ -346,6 +348,98 @@ int cti_add_default_connection(struct device *dev, struct cti_drvdata *drvdata)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int cti_trigin_gpio_enable(struct cti_drvdata *drvdata)
|
||||
{
|
||||
int ret;
|
||||
struct pinctrl *pctrl;
|
||||
struct pinctrl_state *pctrl_state;
|
||||
|
||||
if (drvdata->gpio_trigin->pctrl)
|
||||
return 0;
|
||||
|
||||
pctrl = devm_pinctrl_get(drvdata->csdev->dev.parent);
|
||||
if (IS_ERR(pctrl)) {
|
||||
dev_err(&drvdata->csdev->dev, "pinctrl get failed\n");
|
||||
return PTR_ERR(pctrl);
|
||||
}
|
||||
|
||||
pctrl_state = pinctrl_lookup_state(pctrl, "cti-trigin-pctrl");
|
||||
if (IS_ERR(pctrl_state)) {
|
||||
dev_err(&drvdata->csdev->dev,
|
||||
"pinctrl get state failed\n");
|
||||
ret = PTR_ERR(pctrl_state);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = pinctrl_select_state(pctrl, pctrl_state);
|
||||
if (ret) {
|
||||
dev_err(&drvdata->csdev->dev,
|
||||
"pinctrl enable state failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
drvdata->gpio_trigin->pctrl = pctrl;
|
||||
return 0;
|
||||
err:
|
||||
devm_pinctrl_put(pctrl);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cti_trigout_gpio_enable(struct cti_drvdata *drvdata)
|
||||
{
|
||||
int ret;
|
||||
struct pinctrl *pctrl;
|
||||
struct pinctrl_state *pctrl_state;
|
||||
|
||||
if (drvdata->gpio_trigout->pctrl)
|
||||
return 0;
|
||||
|
||||
pctrl = devm_pinctrl_get(drvdata->csdev->dev.parent);
|
||||
if (IS_ERR(pctrl)) {
|
||||
dev_err(&drvdata->csdev->dev, "pinctrl get failed\n");
|
||||
return PTR_ERR(pctrl);
|
||||
}
|
||||
|
||||
pctrl_state = pinctrl_lookup_state(pctrl, "cti-trigout-pctrl");
|
||||
if (IS_ERR(pctrl_state)) {
|
||||
dev_err(&drvdata->csdev->dev,
|
||||
"pinctrl get state failed\n");
|
||||
ret = PTR_ERR(pctrl_state);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = pinctrl_select_state(pctrl, pctrl_state);
|
||||
if (ret) {
|
||||
dev_err(&drvdata->csdev->dev,
|
||||
"pinctrl enable state failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
drvdata->gpio_trigout->pctrl = pctrl;
|
||||
return 0;
|
||||
err:
|
||||
devm_pinctrl_put(pctrl);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void cti_trigin_gpio_disable(struct cti_drvdata *drvdata)
|
||||
{
|
||||
if (!drvdata->gpio_trigin->pctrl)
|
||||
return;
|
||||
|
||||
devm_pinctrl_put(drvdata->gpio_trigin->pctrl);
|
||||
drvdata->gpio_trigin->pctrl = NULL;
|
||||
}
|
||||
|
||||
void cti_trigout_gpio_disable(struct cti_drvdata *drvdata)
|
||||
{
|
||||
if (!drvdata->gpio_trigout->pctrl)
|
||||
return;
|
||||
|
||||
devm_pinctrl_put(drvdata->gpio_trigout->pctrl);
|
||||
drvdata->gpio_trigout->pctrl = NULL;
|
||||
}
|
||||
|
||||
/** cti channel api **/
|
||||
/* attach/detach channel from trigger - write through if enabled. */
|
||||
int cti_channel_trig_op(struct device *dev, enum cti_chan_op op,
|
||||
|
|
@ -401,6 +495,22 @@ int cti_channel_trig_op(struct device *dev, enum cti_chan_op op,
|
|||
else
|
||||
config->ctiouten[trigger_idx] = reg_value;
|
||||
|
||||
if (op == CTI_CHAN_ATTACH) {
|
||||
if (direction == CTI_TRIG_IN &&
|
||||
drvdata->gpio_trigin->trig == trigger_idx)
|
||||
cti_trigin_gpio_enable(drvdata);
|
||||
else if (direction == CTI_TRIG_OUT &&
|
||||
drvdata->gpio_trigout->trig == trigger_idx)
|
||||
cti_trigout_gpio_enable(drvdata);
|
||||
} else {
|
||||
if (direction == CTI_TRIG_IN &&
|
||||
drvdata->gpio_trigin->trig == trigger_idx)
|
||||
cti_trigin_gpio_disable(drvdata);
|
||||
else if (direction == CTI_TRIG_OUT &&
|
||||
drvdata->gpio_trigout->trig == trigger_idx)
|
||||
cti_trigout_gpio_disable(drvdata);
|
||||
}
|
||||
|
||||
/* write through if enabled */
|
||||
if (cti_active(config))
|
||||
cti_write_single_reg(drvdata, reg_offset, reg_value);
|
||||
|
|
@ -886,6 +996,41 @@ static bool is_extended_cti(struct device *dev)
|
|||
return fwnode_property_present(dev->fwnode, "qcom,extended_cti");
|
||||
}
|
||||
|
||||
static int cti_parse_gpio(struct cti_drvdata *drvdata, struct amba_device *adev)
|
||||
{
|
||||
int ret;
|
||||
int trig;
|
||||
|
||||
drvdata->gpio_trigin = devm_kzalloc(&adev->dev,
|
||||
sizeof(struct cti_pctrl), GFP_KERNEL);
|
||||
if (!drvdata->gpio_trigin)
|
||||
return -ENOMEM;
|
||||
|
||||
drvdata->gpio_trigin->trig = -1;
|
||||
ret = of_property_read_u32(adev->dev.of_node,
|
||||
"qcom,cti-gpio-trigin", &trig);
|
||||
if (!ret)
|
||||
drvdata->gpio_trigin->trig = trig;
|
||||
else if (ret != -EINVAL)
|
||||
return ret;
|
||||
|
||||
drvdata->gpio_trigout = devm_kzalloc(&adev->dev,
|
||||
sizeof(struct cti_pctrl), GFP_KERNEL);
|
||||
if (!drvdata->gpio_trigout)
|
||||
return -ENOMEM;
|
||||
|
||||
drvdata->gpio_trigout->trig = -1;
|
||||
ret = of_property_read_u32(adev->dev.of_node,
|
||||
"qcom,cti-gpio-trigout", &trig);
|
||||
|
||||
if (!ret)
|
||||
drvdata->gpio_trigout->trig = trig;
|
||||
else if (ret != -EINVAL)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cti_probe(struct amba_device *adev, const struct amba_id *id)
|
||||
{
|
||||
int ret = 0;
|
||||
|
|
@ -940,6 +1085,10 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
|
|||
if (!cti_desc.name)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = cti_parse_gpio(drvdata, adev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* setup CPU power management handling for CPU bound CTI devices. */
|
||||
ret = cti_pm_setup(drvdata);
|
||||
if (ret)
|
||||
|
|
|
|||
|
|
@ -987,6 +987,11 @@ static ssize_t chan_xtrigs_reset_store(struct device *dev,
|
|||
for (i = 0; i < config->nr_trig_max; i++) {
|
||||
config->ctiinen[i] = 0;
|
||||
config->ctiouten[i] = 0;
|
||||
|
||||
if (drvdata->gpio_trigin->trig == i)
|
||||
cti_trigin_gpio_disable(drvdata);
|
||||
if (drvdata->gpio_trigout->trig == i)
|
||||
cti_trigout_gpio_disable(drvdata);
|
||||
}
|
||||
|
||||
/* clear the other regs */
|
||||
|
|
|
|||
|
|
@ -185,6 +185,11 @@ struct cti_config {
|
|||
u32 asicctl;
|
||||
};
|
||||
|
||||
struct cti_pctrl {
|
||||
struct pinctrl *pctrl;
|
||||
int trig;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cti_drvdata - specifics for the CTI device
|
||||
* @base: Memory mapped base address for this component..
|
||||
|
|
@ -204,6 +209,8 @@ struct cti_drvdata {
|
|||
struct list_head node;
|
||||
void (*csdev_release)(struct device *dev);
|
||||
bool extended_cti;
|
||||
struct cti_pctrl *gpio_trigin;
|
||||
struct cti_pctrl *gpio_trigout;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -242,6 +249,8 @@ struct cti_trig_con *cti_allocate_trig_con(struct device *dev, int in_sigs,
|
|||
int out_sigs);
|
||||
int cti_enable(struct coresight_device *csdev);
|
||||
int cti_disable(struct coresight_device *csdev);
|
||||
void cti_trigin_gpio_disable(struct cti_drvdata *drvdata);
|
||||
void cti_trigout_gpio_disable(struct cti_drvdata *drvdata);
|
||||
void cti_write_all_hw_regs(struct cti_drvdata *drvdata);
|
||||
void cti_write_intack(struct device *dev, u32 ackval);
|
||||
void cti_write_single_reg(struct cti_drvdata *drvdata, int offset, u32 value);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user