drm/tegra: Changes for v5.2-rc1
This contains a fix for the usage of shared resets that previously generated a WARN on boot. In addition, there's a fix for CPU cache maintenance of GEM buffers allocated using get_pages(). -----BEGIN PGP SIGNATURE----- iQJHBAABCAAxFiEEiOrDCAFJzPfAjcif3SOs138+s6EFAly4k7gTHHRyZWRpbmdA bnZpZGlhLmNvbQAKCRDdI6zXfz6zoUqkD/oC21pwikg0nYh1LoiH7GbmA3NPm56o Ei0cx9p8KyHUT0ongxmr0wfvyfCjwCqlFPWJOZrFOXjUmIupUooTbsqnAiHwEQE8 6m2FaZXRpYc8VYk7+uW4u1MhmWr7fStuxVs/GKVZBK7jaxn3MXouL6fP3cOc8QK1 GZdek2hxMDkvK1PnDc0MRx+COxsi3pMRL8hwBj++1EWPh3SGuOBsaj8S9dxXwSXH TrNCIpGV6BOL6y9g9uDGmqDM6lef90Dx0mRneuWK3pQoCbQJDMUsdVuNEKYI+wqZ hrfG9TZWeamK42OSX5GDM/DJwtb2K1z58Z410dlmc1IK9Inw7LcpYDHdoZQSmBgv 5KwYgeqjQSYV9Ok1D0SY3grdroufg6PSHuE+VgD4SpQ4pbBrBvPUqxpi4icY0re9 Td3FBzHzEMB14QWXIKWXfG7fd9pAKSesxaRaI3G9mtJrI1kIeRa3/0z8MQtSwbOg fxAZYXkCS2aeo9h6Owmhqm/lgYuv/SJ/1NOwLVJ6tgoI1rN0ukMe2OCPCOFmY7AJ ehiVBfXY7bjVYW3yhCUdm4w5ju/lmO5g2N4nqdpmcpvOz4QZE0aviPqcA5hiMfMQ 5WKakqrJ1NGVMTQtKJxGgUq3BXEFqnMpKUkUMT+KVQinMjZOEu1klxlg4ScyZVdd Ly0z3PjsUbv+6g== =nA5m -----END PGP SIGNATURE----- Merge tag 'drm/tegra/for-5.2-rc1' of git://anongit.freedesktop.org/tegra/linux into drm-next drm/tegra: Changes for v5.2-rc1 This contains a fix for the usage of shared resets that previously generated a WARN on boot. In addition, there's a fix for CPU cache maintenance of GEM buffers allocated using get_pages(). (airlied: contains a merge from a shared tegra tree) Signed-off-by: Dave Airlie <airlied@redhat.com> From: Thierry Reding <thierry.reding@gmail.com> Link: https://patchwork.freedesktop.org/patch/msgid/20190418151447.9430-1-thierry.reding@gmail.com
This commit is contained in:
commit
6e865c7230
|
@ -204,7 +204,7 @@ static void tegra_bo_free(struct drm_device *drm, struct tegra_bo *bo)
|
||||||
{
|
{
|
||||||
if (bo->pages) {
|
if (bo->pages) {
|
||||||
dma_unmap_sg(drm->dev, bo->sgt->sgl, bo->sgt->nents,
|
dma_unmap_sg(drm->dev, bo->sgt->sgl, bo->sgt->nents,
|
||||||
DMA_BIDIRECTIONAL);
|
DMA_FROM_DEVICE);
|
||||||
drm_gem_put_pages(&bo->gem, bo->pages, true, true);
|
drm_gem_put_pages(&bo->gem, bo->pages, true, true);
|
||||||
sg_free_table(bo->sgt);
|
sg_free_table(bo->sgt);
|
||||||
kfree(bo->sgt);
|
kfree(bo->sgt);
|
||||||
|
@ -230,7 +230,7 @@ static int tegra_bo_get_pages(struct drm_device *drm, struct tegra_bo *bo)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = dma_map_sg(drm->dev, bo->sgt->sgl, bo->sgt->nents,
|
err = dma_map_sg(drm->dev, bo->sgt->sgl, bo->sgt->nents,
|
||||||
DMA_BIDIRECTIONAL);
|
DMA_FROM_DEVICE);
|
||||||
if (err == 0) {
|
if (err == 0) {
|
||||||
err = -EFAULT;
|
err = -EFAULT;
|
||||||
goto free_sgt;
|
goto free_sgt;
|
||||||
|
|
|
@ -2871,6 +2871,13 @@ static int tegra_sor_init(struct host1x_client *client)
|
||||||
* kernel is possible.
|
* kernel is possible.
|
||||||
*/
|
*/
|
||||||
if (sor->rst) {
|
if (sor->rst) {
|
||||||
|
err = reset_control_acquire(sor->rst);
|
||||||
|
if (err < 0) {
|
||||||
|
dev_err(sor->dev, "failed to acquire SOR reset: %d\n",
|
||||||
|
err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
err = reset_control_assert(sor->rst);
|
err = reset_control_assert(sor->rst);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
dev_err(sor->dev, "failed to assert SOR reset: %d\n",
|
dev_err(sor->dev, "failed to assert SOR reset: %d\n",
|
||||||
|
@ -2894,6 +2901,8 @@ static int tegra_sor_init(struct host1x_client *client)
|
||||||
err);
|
err);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reset_control_release(sor->rst);
|
||||||
}
|
}
|
||||||
|
|
||||||
err = clk_prepare_enable(sor->clk_safe);
|
err = clk_prepare_enable(sor->clk_safe);
|
||||||
|
@ -3331,7 +3340,7 @@ static int tegra_sor_probe(struct platform_device *pdev)
|
||||||
goto remove;
|
goto remove;
|
||||||
}
|
}
|
||||||
|
|
||||||
sor->rst = devm_reset_control_get(&pdev->dev, "sor");
|
sor->rst = devm_reset_control_get_exclusive_released(&pdev->dev, "sor");
|
||||||
if (IS_ERR(sor->rst)) {
|
if (IS_ERR(sor->rst)) {
|
||||||
err = PTR_ERR(sor->rst);
|
err = PTR_ERR(sor->rst);
|
||||||
|
|
||||||
|
@ -3519,6 +3528,8 @@ static int tegra_sor_suspend(struct device *dev)
|
||||||
dev_err(dev, "failed to assert reset: %d\n", err);
|
dev_err(dev, "failed to assert reset: %d\n", err);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reset_control_release(sor->rst);
|
||||||
}
|
}
|
||||||
|
|
||||||
usleep_range(1000, 2000);
|
usleep_range(1000, 2000);
|
||||||
|
@ -3542,9 +3553,17 @@ static int tegra_sor_resume(struct device *dev)
|
||||||
usleep_range(1000, 2000);
|
usleep_range(1000, 2000);
|
||||||
|
|
||||||
if (sor->rst) {
|
if (sor->rst) {
|
||||||
|
err = reset_control_acquire(sor->rst);
|
||||||
|
if (err < 0) {
|
||||||
|
dev_err(dev, "failed to acquire reset: %d\n", err);
|
||||||
|
clk_disable_unprepare(sor->clk);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
err = reset_control_deassert(sor->rst);
|
err = reset_control_deassert(sor->rst);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
dev_err(dev, "failed to deassert reset: %d\n", err);
|
dev_err(dev, "failed to deassert reset: %d\n", err);
|
||||||
|
reset_control_release(sor->rst);
|
||||||
clk_disable_unprepare(sor->clk);
|
clk_disable_unprepare(sor->clk);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ static LIST_HEAD(reset_lookup_list);
|
||||||
* @id: ID of the reset controller in the reset
|
* @id: ID of the reset controller in the reset
|
||||||
* controller device
|
* controller device
|
||||||
* @refcnt: Number of gets of this reset_control
|
* @refcnt: Number of gets of this reset_control
|
||||||
|
* @acquired: Only one reset_control may be acquired for a given rcdev and id.
|
||||||
* @shared: Is this a shared (1), or an exclusive (0) reset_control?
|
* @shared: Is this a shared (1), or an exclusive (0) reset_control?
|
||||||
* @deassert_cnt: Number of times this reset line has been deasserted
|
* @deassert_cnt: Number of times this reset line has been deasserted
|
||||||
* @triggered_count: Number of times this reset line has been reset. Currently
|
* @triggered_count: Number of times this reset line has been reset. Currently
|
||||||
|
@ -45,6 +46,7 @@ struct reset_control {
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
unsigned int id;
|
unsigned int id;
|
||||||
struct kref refcnt;
|
struct kref refcnt;
|
||||||
|
bool acquired;
|
||||||
bool shared;
|
bool shared;
|
||||||
bool array;
|
bool array;
|
||||||
atomic_t deassert_count;
|
atomic_t deassert_count;
|
||||||
|
@ -63,6 +65,17 @@ struct reset_control_array {
|
||||||
struct reset_control *rstc[];
|
struct reset_control *rstc[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const char *rcdev_name(struct reset_controller_dev *rcdev)
|
||||||
|
{
|
||||||
|
if (rcdev->dev)
|
||||||
|
return dev_name(rcdev->dev);
|
||||||
|
|
||||||
|
if (rcdev->of_node)
|
||||||
|
return rcdev->of_node->full_name;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* of_reset_simple_xlate - translate reset_spec to the reset line number
|
* of_reset_simple_xlate - translate reset_spec to the reset line number
|
||||||
* @rcdev: a pointer to the reset controller device
|
* @rcdev: a pointer to the reset controller device
|
||||||
|
@ -232,6 +245,34 @@ err:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int reset_control_array_acquire(struct reset_control_array *resets)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
for (i = 0; i < resets->num_rstcs; i++) {
|
||||||
|
err = reset_control_acquire(resets->rstc[i]);
|
||||||
|
if (err < 0)
|
||||||
|
goto release;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
release:
|
||||||
|
while (i--)
|
||||||
|
reset_control_release(resets->rstc[i]);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void reset_control_array_release(struct reset_control_array *resets)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
for (i = 0; i < resets->num_rstcs; i++)
|
||||||
|
reset_control_release(resets->rstc[i]);
|
||||||
|
}
|
||||||
|
|
||||||
static inline bool reset_control_is_array(struct reset_control *rstc)
|
static inline bool reset_control_is_array(struct reset_control *rstc)
|
||||||
{
|
{
|
||||||
return rstc->array;
|
return rstc->array;
|
||||||
|
@ -272,6 +313,9 @@ int reset_control_reset(struct reset_control *rstc)
|
||||||
|
|
||||||
if (atomic_inc_return(&rstc->triggered_count) != 1)
|
if (atomic_inc_return(&rstc->triggered_count) != 1)
|
||||||
return 0;
|
return 0;
|
||||||
|
} else {
|
||||||
|
if (!rstc->acquired)
|
||||||
|
return -EPERM;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = rstc->rcdev->ops->reset(rstc->rcdev, rstc->id);
|
ret = rstc->rcdev->ops->reset(rstc->rcdev, rstc->id);
|
||||||
|
@ -334,6 +378,12 @@ int reset_control_assert(struct reset_control *rstc)
|
||||||
*/
|
*/
|
||||||
if (!rstc->rcdev->ops->assert)
|
if (!rstc->rcdev->ops->assert)
|
||||||
return -ENOTSUPP;
|
return -ENOTSUPP;
|
||||||
|
|
||||||
|
if (!rstc->acquired) {
|
||||||
|
WARN(1, "reset %s (ID: %u) is not acquired\n",
|
||||||
|
rcdev_name(rstc->rcdev), rstc->id);
|
||||||
|
return -EPERM;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return rstc->rcdev->ops->assert(rstc->rcdev, rstc->id);
|
return rstc->rcdev->ops->assert(rstc->rcdev, rstc->id);
|
||||||
|
@ -369,6 +419,12 @@ int reset_control_deassert(struct reset_control *rstc)
|
||||||
|
|
||||||
if (atomic_inc_return(&rstc->deassert_count) != 1)
|
if (atomic_inc_return(&rstc->deassert_count) != 1)
|
||||||
return 0;
|
return 0;
|
||||||
|
} else {
|
||||||
|
if (!rstc->acquired) {
|
||||||
|
WARN(1, "reset %s (ID: %u) is not acquired\n",
|
||||||
|
rcdev_name(rstc->rcdev), rstc->id);
|
||||||
|
return -EPERM;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -406,9 +462,87 @@ int reset_control_status(struct reset_control *rstc)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(reset_control_status);
|
EXPORT_SYMBOL_GPL(reset_control_status);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* reset_control_acquire() - acquires a reset control for exclusive use
|
||||||
|
* @rstc: reset control
|
||||||
|
*
|
||||||
|
* This is used to explicitly acquire a reset control for exclusive use. Note
|
||||||
|
* that exclusive resets are requested as acquired by default. In order for a
|
||||||
|
* second consumer to be able to control the reset, the first consumer has to
|
||||||
|
* release it first. Typically the easiest way to achieve this is to call the
|
||||||
|
* reset_control_get_exclusive_released() to obtain an instance of the reset
|
||||||
|
* control. Such reset controls are not acquired by default.
|
||||||
|
*
|
||||||
|
* Consumers implementing shared access to an exclusive reset need to follow
|
||||||
|
* a specific protocol in order to work together. Before consumers can change
|
||||||
|
* a reset they must acquire exclusive access using reset_control_acquire().
|
||||||
|
* After they are done operating the reset, they must release exclusive access
|
||||||
|
* with a call to reset_control_release(). Consumers are not granted exclusive
|
||||||
|
* access to the reset as long as another consumer hasn't released a reset.
|
||||||
|
*
|
||||||
|
* See also: reset_control_release()
|
||||||
|
*/
|
||||||
|
int reset_control_acquire(struct reset_control *rstc)
|
||||||
|
{
|
||||||
|
struct reset_control *rc;
|
||||||
|
|
||||||
|
if (!rstc)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (WARN_ON(IS_ERR(rstc)))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (reset_control_is_array(rstc))
|
||||||
|
return reset_control_array_acquire(rstc_to_array(rstc));
|
||||||
|
|
||||||
|
mutex_lock(&reset_list_mutex);
|
||||||
|
|
||||||
|
if (rstc->acquired) {
|
||||||
|
mutex_unlock(&reset_list_mutex);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
list_for_each_entry(rc, &rstc->rcdev->reset_control_head, list) {
|
||||||
|
if (rstc != rc && rstc->id == rc->id) {
|
||||||
|
if (rc->acquired) {
|
||||||
|
mutex_unlock(&reset_list_mutex);
|
||||||
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rstc->acquired = true;
|
||||||
|
|
||||||
|
mutex_unlock(&reset_list_mutex);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(reset_control_acquire);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* reset_control_release() - releases exclusive access to a reset control
|
||||||
|
* @rstc: reset control
|
||||||
|
*
|
||||||
|
* Releases exclusive access right to a reset control previously obtained by a
|
||||||
|
* call to reset_control_acquire(). Until a consumer calls this function, no
|
||||||
|
* other consumers will be granted exclusive access.
|
||||||
|
*
|
||||||
|
* See also: reset_control_acquire()
|
||||||
|
*/
|
||||||
|
void reset_control_release(struct reset_control *rstc)
|
||||||
|
{
|
||||||
|
if (!rstc || WARN_ON(IS_ERR(rstc)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (reset_control_is_array(rstc))
|
||||||
|
reset_control_array_release(rstc_to_array(rstc));
|
||||||
|
else
|
||||||
|
rstc->acquired = false;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(reset_control_release);
|
||||||
|
|
||||||
static struct reset_control *__reset_control_get_internal(
|
static struct reset_control *__reset_control_get_internal(
|
||||||
struct reset_controller_dev *rcdev,
|
struct reset_controller_dev *rcdev,
|
||||||
unsigned int index, bool shared)
|
unsigned int index, bool shared, bool acquired)
|
||||||
{
|
{
|
||||||
struct reset_control *rstc;
|
struct reset_control *rstc;
|
||||||
|
|
||||||
|
@ -416,6 +550,14 @@ static struct reset_control *__reset_control_get_internal(
|
||||||
|
|
||||||
list_for_each_entry(rstc, &rcdev->reset_control_head, list) {
|
list_for_each_entry(rstc, &rcdev->reset_control_head, list) {
|
||||||
if (rstc->id == index) {
|
if (rstc->id == index) {
|
||||||
|
/*
|
||||||
|
* Allow creating a secondary exclusive reset_control
|
||||||
|
* that is initially not acquired for an already
|
||||||
|
* controlled reset line.
|
||||||
|
*/
|
||||||
|
if (!rstc->shared && !shared && !acquired)
|
||||||
|
break;
|
||||||
|
|
||||||
if (WARN_ON(!rstc->shared || !shared))
|
if (WARN_ON(!rstc->shared || !shared))
|
||||||
return ERR_PTR(-EBUSY);
|
return ERR_PTR(-EBUSY);
|
||||||
|
|
||||||
|
@ -434,6 +576,7 @@ static struct reset_control *__reset_control_get_internal(
|
||||||
list_add(&rstc->list, &rcdev->reset_control_head);
|
list_add(&rstc->list, &rcdev->reset_control_head);
|
||||||
rstc->id = index;
|
rstc->id = index;
|
||||||
kref_init(&rstc->refcnt);
|
kref_init(&rstc->refcnt);
|
||||||
|
rstc->acquired = acquired;
|
||||||
rstc->shared = shared;
|
rstc->shared = shared;
|
||||||
|
|
||||||
return rstc;
|
return rstc;
|
||||||
|
@ -461,7 +604,7 @@ static void __reset_control_put_internal(struct reset_control *rstc)
|
||||||
|
|
||||||
struct reset_control *__of_reset_control_get(struct device_node *node,
|
struct reset_control *__of_reset_control_get(struct device_node *node,
|
||||||
const char *id, int index, bool shared,
|
const char *id, int index, bool shared,
|
||||||
bool optional)
|
bool optional, bool acquired)
|
||||||
{
|
{
|
||||||
struct reset_control *rstc;
|
struct reset_control *rstc;
|
||||||
struct reset_controller_dev *r, *rcdev;
|
struct reset_controller_dev *r, *rcdev;
|
||||||
|
@ -514,7 +657,7 @@ struct reset_control *__of_reset_control_get(struct device_node *node,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* reset_list_mutex also protects the rcdev's reset_control list */
|
/* reset_list_mutex also protects the rcdev's reset_control list */
|
||||||
rstc = __reset_control_get_internal(rcdev, rstc_id, shared);
|
rstc = __reset_control_get_internal(rcdev, rstc_id, shared, acquired);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
mutex_unlock(&reset_list_mutex);
|
mutex_unlock(&reset_list_mutex);
|
||||||
|
@ -544,7 +687,7 @@ __reset_controller_by_name(const char *name)
|
||||||
|
|
||||||
static struct reset_control *
|
static struct reset_control *
|
||||||
__reset_control_get_from_lookup(struct device *dev, const char *con_id,
|
__reset_control_get_from_lookup(struct device *dev, const char *con_id,
|
||||||
bool shared, bool optional)
|
bool shared, bool optional, bool acquired)
|
||||||
{
|
{
|
||||||
const struct reset_control_lookup *lookup;
|
const struct reset_control_lookup *lookup;
|
||||||
struct reset_controller_dev *rcdev;
|
struct reset_controller_dev *rcdev;
|
||||||
|
@ -574,7 +717,7 @@ __reset_control_get_from_lookup(struct device *dev, const char *con_id,
|
||||||
|
|
||||||
rstc = __reset_control_get_internal(rcdev,
|
rstc = __reset_control_get_internal(rcdev,
|
||||||
lookup->index,
|
lookup->index,
|
||||||
shared);
|
shared, acquired);
|
||||||
mutex_unlock(&reset_list_mutex);
|
mutex_unlock(&reset_list_mutex);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -589,13 +732,18 @@ __reset_control_get_from_lookup(struct device *dev, const char *con_id,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct reset_control *__reset_control_get(struct device *dev, const char *id,
|
struct reset_control *__reset_control_get(struct device *dev, const char *id,
|
||||||
int index, bool shared, bool optional)
|
int index, bool shared, bool optional,
|
||||||
|
bool acquired)
|
||||||
{
|
{
|
||||||
|
if (WARN_ON(shared && acquired))
|
||||||
|
return ERR_PTR(-EINVAL);
|
||||||
|
|
||||||
if (dev->of_node)
|
if (dev->of_node)
|
||||||
return __of_reset_control_get(dev->of_node, id, index, shared,
|
return __of_reset_control_get(dev->of_node, id, index, shared,
|
||||||
optional);
|
optional, acquired);
|
||||||
|
|
||||||
return __reset_control_get_from_lookup(dev, id, shared, optional);
|
return __reset_control_get_from_lookup(dev, id, shared, optional,
|
||||||
|
acquired);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(__reset_control_get);
|
EXPORT_SYMBOL_GPL(__reset_control_get);
|
||||||
|
|
||||||
|
@ -636,7 +784,7 @@ static void devm_reset_control_release(struct device *dev, void *res)
|
||||||
|
|
||||||
struct reset_control *__devm_reset_control_get(struct device *dev,
|
struct reset_control *__devm_reset_control_get(struct device *dev,
|
||||||
const char *id, int index, bool shared,
|
const char *id, int index, bool shared,
|
||||||
bool optional)
|
bool optional, bool acquired)
|
||||||
{
|
{
|
||||||
struct reset_control **ptr, *rstc;
|
struct reset_control **ptr, *rstc;
|
||||||
|
|
||||||
|
@ -645,7 +793,7 @@ struct reset_control *__devm_reset_control_get(struct device *dev,
|
||||||
if (!ptr)
|
if (!ptr)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
rstc = __reset_control_get(dev, id, index, shared, optional);
|
rstc = __reset_control_get(dev, id, index, shared, optional, acquired);
|
||||||
if (!IS_ERR(rstc)) {
|
if (!IS_ERR(rstc)) {
|
||||||
*ptr = rstc;
|
*ptr = rstc;
|
||||||
devres_add(dev, ptr);
|
devres_add(dev, ptr);
|
||||||
|
@ -672,7 +820,7 @@ int __device_reset(struct device *dev, bool optional)
|
||||||
struct reset_control *rstc;
|
struct reset_control *rstc;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
rstc = __reset_control_get(dev, NULL, 0, 0, optional);
|
rstc = __reset_control_get(dev, NULL, 0, 0, optional, true);
|
||||||
if (IS_ERR(rstc))
|
if (IS_ERR(rstc))
|
||||||
return PTR_ERR(rstc);
|
return PTR_ERR(rstc);
|
||||||
|
|
||||||
|
@ -716,12 +864,15 @@ static int of_reset_control_get_count(struct device_node *node)
|
||||||
* @np: device node for the device that requests the reset controls array
|
* @np: device node for the device that requests the reset controls array
|
||||||
* @shared: whether reset controls are shared or not
|
* @shared: whether reset controls are shared or not
|
||||||
* @optional: whether it is optional to get the reset controls
|
* @optional: whether it is optional to get the reset controls
|
||||||
|
* @acquired: only one reset control may be acquired for a given controller
|
||||||
|
* and ID
|
||||||
*
|
*
|
||||||
* Returns pointer to allocated reset_control_array on success or
|
* Returns pointer to allocated reset_control_array on success or
|
||||||
* error on failure
|
* error on failure
|
||||||
*/
|
*/
|
||||||
struct reset_control *
|
struct reset_control *
|
||||||
of_reset_control_array_get(struct device_node *np, bool shared, bool optional)
|
of_reset_control_array_get(struct device_node *np, bool shared, bool optional,
|
||||||
|
bool acquired)
|
||||||
{
|
{
|
||||||
struct reset_control_array *resets;
|
struct reset_control_array *resets;
|
||||||
struct reset_control *rstc;
|
struct reset_control *rstc;
|
||||||
|
@ -736,7 +887,8 @@ of_reset_control_array_get(struct device_node *np, bool shared, bool optional)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
for (i = 0; i < num; i++) {
|
for (i = 0; i < num; i++) {
|
||||||
rstc = __of_reset_control_get(np, NULL, i, shared, optional);
|
rstc = __of_reset_control_get(np, NULL, i, shared, optional,
|
||||||
|
acquired);
|
||||||
if (IS_ERR(rstc))
|
if (IS_ERR(rstc))
|
||||||
goto err_rst;
|
goto err_rst;
|
||||||
resets->rstc[i] = rstc;
|
resets->rstc[i] = rstc;
|
||||||
|
@ -783,7 +935,7 @@ devm_reset_control_array_get(struct device *dev, bool shared, bool optional)
|
||||||
if (!devres)
|
if (!devres)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
rstc = of_reset_control_array_get(dev->of_node, shared, optional);
|
rstc = of_reset_control_array_get(dev->of_node, shared, optional, true);
|
||||||
if (IS_ERR(rstc)) {
|
if (IS_ERR(rstc)) {
|
||||||
devres_free(devres);
|
devres_free(devres);
|
||||||
return rstc;
|
return rstc;
|
||||||
|
|
|
@ -107,7 +107,8 @@ static int dwc3_of_simple_probe(struct platform_device *pdev)
|
||||||
simple->pulse_resets = true;
|
simple->pulse_resets = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
simple->resets = of_reset_control_array_get(np, shared_resets, true);
|
simple->resets = of_reset_control_array_get(np, shared_resets, true,
|
||||||
|
true);
|
||||||
if (IS_ERR(simple->resets)) {
|
if (IS_ERR(simple->resets)) {
|
||||||
ret = PTR_ERR(simple->resets);
|
ret = PTR_ERR(simple->resets);
|
||||||
dev_err(dev, "failed to get device resets, err=%d\n", ret);
|
dev_err(dev, "failed to get device resets, err=%d\n", ret);
|
||||||
|
|
|
@ -14,23 +14,26 @@ int reset_control_reset(struct reset_control *rstc);
|
||||||
int reset_control_assert(struct reset_control *rstc);
|
int reset_control_assert(struct reset_control *rstc);
|
||||||
int reset_control_deassert(struct reset_control *rstc);
|
int reset_control_deassert(struct reset_control *rstc);
|
||||||
int reset_control_status(struct reset_control *rstc);
|
int reset_control_status(struct reset_control *rstc);
|
||||||
|
int reset_control_acquire(struct reset_control *rstc);
|
||||||
|
void reset_control_release(struct reset_control *rstc);
|
||||||
|
|
||||||
struct reset_control *__of_reset_control_get(struct device_node *node,
|
struct reset_control *__of_reset_control_get(struct device_node *node,
|
||||||
const char *id, int index, bool shared,
|
const char *id, int index, bool shared,
|
||||||
bool optional);
|
bool optional, bool acquired);
|
||||||
struct reset_control *__reset_control_get(struct device *dev, const char *id,
|
struct reset_control *__reset_control_get(struct device *dev, const char *id,
|
||||||
int index, bool shared,
|
int index, bool shared,
|
||||||
bool optional);
|
bool optional, bool acquired);
|
||||||
void reset_control_put(struct reset_control *rstc);
|
void reset_control_put(struct reset_control *rstc);
|
||||||
int __device_reset(struct device *dev, bool optional);
|
int __device_reset(struct device *dev, bool optional);
|
||||||
struct reset_control *__devm_reset_control_get(struct device *dev,
|
struct reset_control *__devm_reset_control_get(struct device *dev,
|
||||||
const char *id, int index, bool shared,
|
const char *id, int index, bool shared,
|
||||||
bool optional);
|
bool optional, bool acquired);
|
||||||
|
|
||||||
struct reset_control *devm_reset_control_array_get(struct device *dev,
|
struct reset_control *devm_reset_control_array_get(struct device *dev,
|
||||||
bool shared, bool optional);
|
bool shared, bool optional);
|
||||||
struct reset_control *of_reset_control_array_get(struct device_node *np,
|
struct reset_control *of_reset_control_array_get(struct device_node *np,
|
||||||
bool shared, bool optional);
|
bool shared, bool optional,
|
||||||
|
bool acquired);
|
||||||
|
|
||||||
int reset_control_get_count(struct device *dev);
|
int reset_control_get_count(struct device *dev);
|
||||||
|
|
||||||
|
@ -56,6 +59,15 @@ static inline int reset_control_status(struct reset_control *rstc)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int reset_control_acquire(struct reset_control *rstc)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void reset_control_release(struct reset_control *rstc)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
static inline void reset_control_put(struct reset_control *rstc)
|
static inline void reset_control_put(struct reset_control *rstc)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -68,21 +80,23 @@ static inline int __device_reset(struct device *dev, bool optional)
|
||||||
static inline struct reset_control *__of_reset_control_get(
|
static inline struct reset_control *__of_reset_control_get(
|
||||||
struct device_node *node,
|
struct device_node *node,
|
||||||
const char *id, int index, bool shared,
|
const char *id, int index, bool shared,
|
||||||
bool optional)
|
bool optional, bool acquired)
|
||||||
{
|
{
|
||||||
return optional ? NULL : ERR_PTR(-ENOTSUPP);
|
return optional ? NULL : ERR_PTR(-ENOTSUPP);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct reset_control *__reset_control_get(
|
static inline struct reset_control *__reset_control_get(
|
||||||
struct device *dev, const char *id,
|
struct device *dev, const char *id,
|
||||||
int index, bool shared, bool optional)
|
int index, bool shared, bool optional,
|
||||||
|
bool acquired)
|
||||||
{
|
{
|
||||||
return optional ? NULL : ERR_PTR(-ENOTSUPP);
|
return optional ? NULL : ERR_PTR(-ENOTSUPP);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct reset_control *__devm_reset_control_get(
|
static inline struct reset_control *__devm_reset_control_get(
|
||||||
struct device *dev, const char *id,
|
struct device *dev, const char *id,
|
||||||
int index, bool shared, bool optional)
|
int index, bool shared, bool optional,
|
||||||
|
bool acquired)
|
||||||
{
|
{
|
||||||
return optional ? NULL : ERR_PTR(-ENOTSUPP);
|
return optional ? NULL : ERR_PTR(-ENOTSUPP);
|
||||||
}
|
}
|
||||||
|
@ -94,7 +108,8 @@ devm_reset_control_array_get(struct device *dev, bool shared, bool optional)
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct reset_control *
|
static inline struct reset_control *
|
||||||
of_reset_control_array_get(struct device_node *np, bool shared, bool optional)
|
of_reset_control_array_get(struct device_node *np, bool shared, bool optional,
|
||||||
|
bool acquired)
|
||||||
{
|
{
|
||||||
return optional ? NULL : ERR_PTR(-ENOTSUPP);
|
return optional ? NULL : ERR_PTR(-ENOTSUPP);
|
||||||
}
|
}
|
||||||
|
@ -134,7 +149,28 @@ static inline int device_reset_optional(struct device *dev)
|
||||||
static inline struct reset_control *
|
static inline struct reset_control *
|
||||||
__must_check reset_control_get_exclusive(struct device *dev, const char *id)
|
__must_check reset_control_get_exclusive(struct device *dev, const char *id)
|
||||||
{
|
{
|
||||||
return __reset_control_get(dev, id, 0, false, false);
|
return __reset_control_get(dev, id, 0, false, false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* reset_control_get_exclusive_released - Lookup and obtain a temoprarily
|
||||||
|
* exclusive reference to a reset
|
||||||
|
* controller.
|
||||||
|
* @dev: device to be reset by the controller
|
||||||
|
* @id: reset line name
|
||||||
|
*
|
||||||
|
* Returns a struct reset_control or IS_ERR() condition containing errno.
|
||||||
|
* reset-controls returned by this function must be acquired via
|
||||||
|
* reset_control_acquire() before they can be used and should be released
|
||||||
|
* via reset_control_release() afterwards.
|
||||||
|
*
|
||||||
|
* Use of id names is optional.
|
||||||
|
*/
|
||||||
|
static inline struct reset_control *
|
||||||
|
__must_check reset_control_get_exclusive_released(struct device *dev,
|
||||||
|
const char *id)
|
||||||
|
{
|
||||||
|
return __reset_control_get(dev, id, 0, false, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -162,19 +198,19 @@ __must_check reset_control_get_exclusive(struct device *dev, const char *id)
|
||||||
static inline struct reset_control *reset_control_get_shared(
|
static inline struct reset_control *reset_control_get_shared(
|
||||||
struct device *dev, const char *id)
|
struct device *dev, const char *id)
|
||||||
{
|
{
|
||||||
return __reset_control_get(dev, id, 0, true, false);
|
return __reset_control_get(dev, id, 0, true, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct reset_control *reset_control_get_optional_exclusive(
|
static inline struct reset_control *reset_control_get_optional_exclusive(
|
||||||
struct device *dev, const char *id)
|
struct device *dev, const char *id)
|
||||||
{
|
{
|
||||||
return __reset_control_get(dev, id, 0, false, true);
|
return __reset_control_get(dev, id, 0, false, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct reset_control *reset_control_get_optional_shared(
|
static inline struct reset_control *reset_control_get_optional_shared(
|
||||||
struct device *dev, const char *id)
|
struct device *dev, const char *id)
|
||||||
{
|
{
|
||||||
return __reset_control_get(dev, id, 0, true, true);
|
return __reset_control_get(dev, id, 0, true, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -190,7 +226,7 @@ static inline struct reset_control *reset_control_get_optional_shared(
|
||||||
static inline struct reset_control *of_reset_control_get_exclusive(
|
static inline struct reset_control *of_reset_control_get_exclusive(
|
||||||
struct device_node *node, const char *id)
|
struct device_node *node, const char *id)
|
||||||
{
|
{
|
||||||
return __of_reset_control_get(node, id, 0, false, false);
|
return __of_reset_control_get(node, id, 0, false, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -215,7 +251,7 @@ static inline struct reset_control *of_reset_control_get_exclusive(
|
||||||
static inline struct reset_control *of_reset_control_get_shared(
|
static inline struct reset_control *of_reset_control_get_shared(
|
||||||
struct device_node *node, const char *id)
|
struct device_node *node, const char *id)
|
||||||
{
|
{
|
||||||
return __of_reset_control_get(node, id, 0, true, false);
|
return __of_reset_control_get(node, id, 0, true, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -232,7 +268,7 @@ static inline struct reset_control *of_reset_control_get_shared(
|
||||||
static inline struct reset_control *of_reset_control_get_exclusive_by_index(
|
static inline struct reset_control *of_reset_control_get_exclusive_by_index(
|
||||||
struct device_node *node, int index)
|
struct device_node *node, int index)
|
||||||
{
|
{
|
||||||
return __of_reset_control_get(node, NULL, index, false, false);
|
return __of_reset_control_get(node, NULL, index, false, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -260,7 +296,7 @@ static inline struct reset_control *of_reset_control_get_exclusive_by_index(
|
||||||
static inline struct reset_control *of_reset_control_get_shared_by_index(
|
static inline struct reset_control *of_reset_control_get_shared_by_index(
|
||||||
struct device_node *node, int index)
|
struct device_node *node, int index)
|
||||||
{
|
{
|
||||||
return __of_reset_control_get(node, NULL, index, true, false);
|
return __of_reset_control_get(node, NULL, index, true, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -279,7 +315,26 @@ static inline struct reset_control *
|
||||||
__must_check devm_reset_control_get_exclusive(struct device *dev,
|
__must_check devm_reset_control_get_exclusive(struct device *dev,
|
||||||
const char *id)
|
const char *id)
|
||||||
{
|
{
|
||||||
return __devm_reset_control_get(dev, id, 0, false, false);
|
return __devm_reset_control_get(dev, id, 0, false, false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* devm_reset_control_get_exclusive_released - resource managed
|
||||||
|
* reset_control_get_exclusive_released()
|
||||||
|
* @dev: device to be reset by the controller
|
||||||
|
* @id: reset line name
|
||||||
|
*
|
||||||
|
* Managed reset_control_get_exclusive_released(). For reset controllers
|
||||||
|
* returned from this function, reset_control_put() is called automatically on
|
||||||
|
* driver detach.
|
||||||
|
*
|
||||||
|
* See reset_control_get_exclusive_released() for more information.
|
||||||
|
*/
|
||||||
|
static inline struct reset_control *
|
||||||
|
__must_check devm_reset_control_get_exclusive_released(struct device *dev,
|
||||||
|
const char *id)
|
||||||
|
{
|
||||||
|
return __devm_reset_control_get(dev, id, 0, false, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -294,19 +349,19 @@ __must_check devm_reset_control_get_exclusive(struct device *dev,
|
||||||
static inline struct reset_control *devm_reset_control_get_shared(
|
static inline struct reset_control *devm_reset_control_get_shared(
|
||||||
struct device *dev, const char *id)
|
struct device *dev, const char *id)
|
||||||
{
|
{
|
||||||
return __devm_reset_control_get(dev, id, 0, true, false);
|
return __devm_reset_control_get(dev, id, 0, true, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct reset_control *devm_reset_control_get_optional_exclusive(
|
static inline struct reset_control *devm_reset_control_get_optional_exclusive(
|
||||||
struct device *dev, const char *id)
|
struct device *dev, const char *id)
|
||||||
{
|
{
|
||||||
return __devm_reset_control_get(dev, id, 0, false, true);
|
return __devm_reset_control_get(dev, id, 0, false, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct reset_control *devm_reset_control_get_optional_shared(
|
static inline struct reset_control *devm_reset_control_get_optional_shared(
|
||||||
struct device *dev, const char *id)
|
struct device *dev, const char *id)
|
||||||
{
|
{
|
||||||
return __devm_reset_control_get(dev, id, 0, true, true);
|
return __devm_reset_control_get(dev, id, 0, true, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -324,7 +379,7 @@ static inline struct reset_control *devm_reset_control_get_optional_shared(
|
||||||
static inline struct reset_control *
|
static inline struct reset_control *
|
||||||
devm_reset_control_get_exclusive_by_index(struct device *dev, int index)
|
devm_reset_control_get_exclusive_by_index(struct device *dev, int index)
|
||||||
{
|
{
|
||||||
return __devm_reset_control_get(dev, NULL, index, false, false);
|
return __devm_reset_control_get(dev, NULL, index, false, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -340,7 +395,7 @@ devm_reset_control_get_exclusive_by_index(struct device *dev, int index)
|
||||||
static inline struct reset_control *
|
static inline struct reset_control *
|
||||||
devm_reset_control_get_shared_by_index(struct device *dev, int index)
|
devm_reset_control_get_shared_by_index(struct device *dev, int index)
|
||||||
{
|
{
|
||||||
return __devm_reset_control_get(dev, NULL, index, true, false);
|
return __devm_reset_control_get(dev, NULL, index, true, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -412,24 +467,30 @@ devm_reset_control_array_get_optional_shared(struct device *dev)
|
||||||
static inline struct reset_control *
|
static inline struct reset_control *
|
||||||
of_reset_control_array_get_exclusive(struct device_node *node)
|
of_reset_control_array_get_exclusive(struct device_node *node)
|
||||||
{
|
{
|
||||||
return of_reset_control_array_get(node, false, false);
|
return of_reset_control_array_get(node, false, false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct reset_control *
|
||||||
|
of_reset_control_array_get_exclusive_released(struct device_node *node)
|
||||||
|
{
|
||||||
|
return of_reset_control_array_get(node, false, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct reset_control *
|
static inline struct reset_control *
|
||||||
of_reset_control_array_get_shared(struct device_node *node)
|
of_reset_control_array_get_shared(struct device_node *node)
|
||||||
{
|
{
|
||||||
return of_reset_control_array_get(node, true, false);
|
return of_reset_control_array_get(node, true, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct reset_control *
|
static inline struct reset_control *
|
||||||
of_reset_control_array_get_optional_exclusive(struct device_node *node)
|
of_reset_control_array_get_optional_exclusive(struct device_node *node)
|
||||||
{
|
{
|
||||||
return of_reset_control_array_get(node, false, true);
|
return of_reset_control_array_get(node, false, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct reset_control *
|
static inline struct reset_control *
|
||||||
of_reset_control_array_get_optional_shared(struct device_node *node)
|
of_reset_control_array_get_optional_shared(struct device_node *node)
|
||||||
{
|
{
|
||||||
return of_reset_control_array_get(node, true, true);
|
return of_reset_control_array_get(node, true, true, true);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue