diff options
Diffstat (limited to 'drivers/hwspinlock/omap_hwspinlock.c')
| -rw-r--r-- | drivers/hwspinlock/omap_hwspinlock.c | 115 |
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, }, }; |
