linux/drivers/hwspinlock/omap_hwspinlock.c
Linus Torvalds bdbddf72a2 soc: driver updates for 7.0
There are are a number of to firmware drivers, in particular the TEE
 subsystem:
 
   - a bus callback for TEE firmware that device drivers can register to
   - sysfs support for tee firmware information
   - minor updates to platform specific TEE drivers for AMD, NXP, Qualcomm
     and the generic optee driver
   - ARM SCMI firmware refactoring to improve the protocol discover
     among other fixes and cleanups
   - ARM FF-A firmware interoperability improvements
 
 The reset controller and memory controller subsystems gain support for
 additional hardware platforms from Mediatek, Renesas, NXP, Canaan and
 SpacemiT.
 
 Most of the other changes are for random drivers/soc code. Among
 a number of cleanups and newly added hardware support, including:
 
  - Mediatek MT8196 DVFS power management and mailbox support
 
  - Qualcomm SCM firmware and MDT loader refactoring, as part of
    the new Glymur platform support.
 
  - NXP i.MX9 System Manager firmware support for accessing the
    syslog
 
  - Minor updates for TI, Renesas, Samsung, Apple, Marvell and AMD
    SoCs.
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEo6/YBQwIrVS28WGKmmx57+YAGNkFAmmLWqkACgkQmmx57+YA
 GNmbPRAAt4qSMkLvVjGkjjuI3phIjEk9oCNBWDNRUtwdTpnP97cbFXI0jVo2vG7X
 aKatSjHeqYe66QT1YFW+JXjJiPXQxtlZtquHomcShHQRd/fS34A1ip9l0sR/RbFV
 qP8qMBWWlyND0DsUcE7ymRX/j74yOobdcjG/vG48X81wFxxFOHoNSwItRx5zIq+6
 3KenZMoP6+uEQk4uq1USpr0mYAoIUPl0opV9UCjVUSzmYdYW2l/pJWlIqFuj8QZ7
 X09qQg070GtYMSOwZfPwvSeV01tEZevIDW7ZF6tJuUNiHE8QMOUoNEWXj1L7hhOY
 PUWfDJSKenzzqhMZzM0Vbds/MtGkG7BtCGjJc6zGTaDtO4ucBZcF3tL2KA5k6kp1
 9domNvrAT4HGPC1DeWYYRf5RWe63253ev+UDFgEHIwdxj5jE9q9YrnRNvuKvTHcZ
 FTYIiBakSMwnjVQt5x9Cm3F1JuQ7LpIN2Fkrq3AY3m85+mHnjdSWVN8jCB9Ko3xX
 91ONHnxVyC2bU47yVmLXugWO1MhNeNKuZFKcgqlGImeBixEhT43P8j9b3NeMTVyA
 P5iVMZw9om/3XtF5hVHz5ABHlOcFCY5QcKsSJZ9PMyPnjUyzg7Ige7pkZZknNJnb
 wcYDQr/sEn83WU6uRRLm3qDbWmGR5tYFcgYYa9U4e8tsO7ZXaqw=
 =rUYH
 -----END PGP SIGNATURE-----

Merge tag 'soc-drivers-7.0' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc

Pull SoC driver updates from Arnd Bergmann:
 "There are are a number of to firmware drivers, in particular the TEE
  subsystem:

   - a bus callback for TEE firmware that device drivers can register to

   - sysfs support for tee firmware information

   - minor updates to platform specific TEE drivers for AMD, NXP,
     Qualcomm and the generic optee driver

   - ARM SCMI firmware refactoring to improve the protocol discover
     among other fixes and cleanups

   - ARM FF-A firmware interoperability improvements

  The reset controller and memory controller subsystems gain support for
  additional hardware platforms from Mediatek, Renesas, NXP, Canaan and
  SpacemiT.

  Most of the other changes are for random drivers/soc code. Among a
  number of cleanups and newly added hardware support, including:

   - Mediatek MT8196 DVFS power management and mailbox support

   - Qualcomm SCM firmware and MDT loader refactoring, as part of the
     new Glymur platform support.

   - NXP i.MX9 System Manager firmware support for accessing the syslog

   - Minor updates for TI, Renesas, Samsung, Apple, Marvell and AMD
     SoCs"

* tag 'soc-drivers-7.0' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc: (171 commits)
  bus: fsl-mc: fix an error handling in fsl_mc_device_add()
  reset: spacemit: Add SpacemiT K3 reset driver
  reset: spacemit: Extract common K1 reset code
  reset: Create subdirectory for SpacemiT drivers
  dt-bindings: soc: spacemit: Add K3 reset support and IDs
  reset: canaan: k230: drop OF dependency and enable by default
  reset: rzg2l-usbphy-ctrl: Add suspend/resume support
  reset: rzg2l-usbphy-ctrl: Propagate the return value of regmap_field_update_bits()
  reset: gpio: check the return value of gpiod_set_value_cansleep()
  reset: imx8mp-audiomix: Support i.MX8ULP SIM LPAV
  reset: imx8mp-audiomix: Extend the driver usage
  reset: imx8mp-audiomix: Switch to using regmap API
  reset: imx8mp-audiomix: Drop unneeded macros
  soc: fsl: qe: qe_ports_ic: Consolidate chained IRQ handler install/remove
  soc: mediatek: mtk-cmdq: Add mminfra_offset adjustment for DRAM addresses
  soc: mediatek: mtk-cmdq: Extend cmdq_pkt_write API for SoCs without subsys ID
  soc: mediatek: mtk-cmdq: Add pa_base parsing for hardware without subsys ID support
  soc: mediatek: mtk-cmdq: Add cmdq_get_mbox_priv() in cmdq_pkt_create()
  mailbox: mtk-cmdq: Add driver data to support for MT8196
  mailbox: mtk-cmdq: Add mminfra_offset configuration for DRAM transaction
  ...
2026-02-10 20:45:30 -08:00

159 lines
4.2 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* OMAP hardware spinlock driver
*
* 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>
* Suman Anna <s-anna@ti.com>
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/bitops.h>
#include <linux/pm_runtime.h>
#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"
/* Spinlock register offsets */
#define SYSSTATUS_OFFSET 0x0014
#define LOCK_BASE_OFFSET 0x0800
#define SPINLOCK_NUMLOCKS_BIT_OFFSET (24)
/* Possible values of SPINLOCK_LOCK_REG */
#define SPINLOCK_NOTTAKEN (0) /* free */
#define SPINLOCK_TAKEN (1) /* locked */
static int omap_hwspinlock_trylock(struct hwspinlock *lock)
{
void __iomem *lock_addr = lock->priv;
/* attempt to acquire the lock by reading its value */
return (SPINLOCK_NOTTAKEN == readl(lock_addr));
}
static void omap_hwspinlock_unlock(struct hwspinlock *lock)
{
void __iomem *lock_addr = lock->priv;
/* release the lock by writing 0 to it */
writel(SPINLOCK_NOTTAKEN, lock_addr);
}
/*
* relax the OMAP interconnect while spinning on it.
*
* The specs recommended that the retry delay time will be
* just over half of the time that a requester would be
* expected to hold the lock.
*
* The number below is taken from an hardware specs example,
* obviously it is somewhat arbitrary.
*/
static void omap_hwspinlock_relax(struct hwspinlock *lock)
{
ndelay(50);
}
static const struct hwspinlock_ops omap_hwspinlock_ops = {
.trylock = omap_hwspinlock_trylock,
.unlock = omap_hwspinlock_unlock,
.relax = omap_hwspinlock_relax,
};
static int omap_hwspinlock_probe(struct platform_device *pdev)
{
struct hwspinlock_device *bank;
void __iomem *io_base;
int num_locks, i, ret;
/* Only a single hwspinlock block device is supported */
int base_id = 0;
io_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(io_base))
return PTR_ERR(io_base);
/*
* make sure the module is enabled and clocked before reading
* the module SYSSTATUS register
*/
ret = devm_pm_runtime_enable(&pdev->dev);
if (ret)
return ret;
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;
/*
* runtime PM will make sure the clock of this module is
* enabled again iff at least one lock is requested
*/
pm_runtime_put(&pdev->dev);
/* one of the four lsb's must be set, and nothing else */
if (hweight_long(i & 0xf) != 1 || i > 8)
return -EINVAL;
num_locks = i * 32; /* actual number of locks in this device */
bank = devm_kzalloc(&pdev->dev, struct_size(bank, lock, num_locks),
GFP_KERNEL);
if (!bank)
return -ENOMEM;
for (i = 0; i < num_locks; i++)
bank->lock[i].priv = io_base + LOCK_BASE_OFFSET + sizeof(u32) * i;
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,
.driver = {
.name = "omap_hwspinlock",
.of_match_table = omap_hwspinlock_of_match,
},
};
static int __init omap_hwspinlock_init(void)
{
return platform_driver_register(&omap_hwspinlock_driver);
}
/* board init code might need to reserve hwspinlocks for predefined purposes */
postcore_initcall(omap_hwspinlock_init);
static void __exit omap_hwspinlock_exit(void)
{
platform_driver_unregister(&omap_hwspinlock_driver);
}
module_exit(omap_hwspinlock_exit);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("Hardware spinlock driver for OMAP");
MODULE_AUTHOR("Simon Que <sque@ti.com>");
MODULE_AUTHOR("Hari Kanigeri <h-kanigeri2@ti.com>");
MODULE_AUTHOR("Ohad Ben-Cohen <ohad@wizery.com>");