summaryrefslogtreecommitdiff
path: root/drivers/hwspinlock/omap_hwspinlock.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hwspinlock/omap_hwspinlock.c')
-rw-r--r--drivers/hwspinlock/omap_hwspinlock.c115
1 files changed, 42 insertions, 73 deletions
diff --git a/drivers/hwspinlock/omap_hwspinlock.c b/drivers/hwspinlock/omap_hwspinlock.c
index 292869cc9034..27b47b8623c0 100644
--- a/drivers/hwspinlock/omap_hwspinlock.c
+++ b/drivers/hwspinlock/omap_hwspinlock.c
@@ -1,20 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* OMAP hardware spinlock driver
*
- * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com
+ * Copyright (C) 2010-2021 Texas Instruments Incorporated - https://www.ti.com
*
* Contact: Simon Que <sque@ti.com>
* Hari Kanigeri <h-kanigeri2@ti.com>
* Ohad Ben-Cohen <ohad@wizery.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
+ * Suman Anna <s-anna@ti.com>
*/
#include <linux/kernel.h>
@@ -27,6 +20,7 @@
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/hwspinlock.h>
+#include <linux/of.h>
#include <linux/platform_device.h>
#include "hwspinlock_internal.h"
@@ -80,93 +74,68 @@ static const struct hwspinlock_ops omap_hwspinlock_ops = {
static int omap_hwspinlock_probe(struct platform_device *pdev)
{
- struct hwspinlock_pdata *pdata = pdev->dev.platform_data;
struct hwspinlock_device *bank;
- struct hwspinlock *hwlock;
- struct resource *res;
void __iomem *io_base;
int num_locks, i, ret;
+ /* Only a single hwspinlock block device is supported */
+ int base_id = 0;
- if (!pdata)
- return -ENODEV;
+ io_base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(io_base))
+ return PTR_ERR(io_base);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- return -ENODEV;
-
- io_base = ioremap(res->start, resource_size(res));
- if (!io_base)
- return -ENOMEM;
+ /*
+ * make sure the module is enabled and clocked before reading
+ * the module SYSSTATUS register
+ */
+ devm_pm_runtime_enable(&pdev->dev);
+ ret = pm_runtime_resume_and_get(&pdev->dev);
+ if (ret < 0)
+ return ret;
/* Determine number of locks */
i = readl(io_base + SYSSTATUS_OFFSET);
i >>= SPINLOCK_NUMLOCKS_BIT_OFFSET;
- /* one of the four lsb's must be set, and nothing else */
- if (hweight_long(i & 0xf) != 1 || i > 8) {
- ret = -EINVAL;
- goto iounmap_base;
- }
-
- num_locks = i * 32; /* actual number of locks in this device */
-
- bank = kzalloc(sizeof(*bank) + num_locks * sizeof(*hwlock), GFP_KERNEL);
- if (!bank) {
- ret = -ENOMEM;
- goto iounmap_base;
- }
-
- platform_set_drvdata(pdev, bank);
-
- for (i = 0, hwlock = &bank->lock[0]; i < num_locks; i++, hwlock++)
- hwlock->priv = io_base + LOCK_BASE_OFFSET + sizeof(u32) * i;
-
/*
* runtime PM will make sure the clock of this module is
- * enabled iff at least one lock is requested
+ * enabled again iff at least one lock is requested
*/
- pm_runtime_enable(&pdev->dev);
-
- ret = hwspin_lock_register(bank, &pdev->dev, &omap_hwspinlock_ops,
- pdata->base_id, num_locks);
- if (ret)
- goto reg_fail;
-
- return 0;
+ ret = pm_runtime_put(&pdev->dev);
+ if (ret < 0)
+ return ret;
-reg_fail:
- pm_runtime_disable(&pdev->dev);
- kfree(bank);
-iounmap_base:
- iounmap(io_base);
- return ret;
-}
+ /* one of the four lsb's must be set, and nothing else */
+ if (hweight_long(i & 0xf) != 1 || i > 8)
+ return -EINVAL;
-static int omap_hwspinlock_remove(struct platform_device *pdev)
-{
- struct hwspinlock_device *bank = platform_get_drvdata(pdev);
- void __iomem *io_base = bank->lock[0].priv - LOCK_BASE_OFFSET;
- int ret;
+ num_locks = i * 32; /* actual number of locks in this device */
- ret = hwspin_lock_unregister(bank);
- if (ret) {
- dev_err(&pdev->dev, "%s failed: %d\n", __func__, ret);
- return ret;
- }
+ bank = devm_kzalloc(&pdev->dev, struct_size(bank, lock, num_locks),
+ GFP_KERNEL);
+ if (!bank)
+ return -ENOMEM;
- pm_runtime_disable(&pdev->dev);
- iounmap(io_base);
- kfree(bank);
+ for (i = 0; i < num_locks; i++)
+ bank->lock[i].priv = io_base + LOCK_BASE_OFFSET + sizeof(u32) * i;
- return 0;
+ return devm_hwspin_lock_register(&pdev->dev, bank, &omap_hwspinlock_ops,
+ base_id, num_locks);
}
+static const struct of_device_id omap_hwspinlock_of_match[] = {
+ { .compatible = "ti,omap4-hwspinlock", },
+ { .compatible = "ti,am64-hwspinlock", },
+ { .compatible = "ti,am654-hwspinlock", },
+ { /* end */ },
+};
+MODULE_DEVICE_TABLE(of, omap_hwspinlock_of_match);
+
static struct platform_driver omap_hwspinlock_driver = {
.probe = omap_hwspinlock_probe,
- .remove = omap_hwspinlock_remove,
.driver = {
.name = "omap_hwspinlock",
- .owner = THIS_MODULE,
+ .of_match_table = omap_hwspinlock_of_match,
},
};