| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135 |
- /*
- * Copyright (c) 2006-2023, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2023-09-23 GuEe-GUI first version
- */
- #include "hwspinlock_dm.h"
- #define HWSPINLOCK_NUMBER 64
- #define HWSPINLOCK_STATUS_OFFSET(x) (0x4 * (x))
- #define HWSPINLOCK_OWNER_ID 0x1
- struct rockchip_hwspinlock
- {
- struct rt_hwspinlock_bank parent;
- void *regs;
- };
- static rt_err_t rockchip_hwspinlock_trylock(struct rt_hwspinlock *hwlock)
- {
- void *lock_regs = hwlock->priv;
- HWREG32(lock_regs) = HWSPINLOCK_OWNER_ID;
- /*
- * Get only first 4bits and compare to HWSPINLOCK_OWNER_ID:
- * when 4bits is 0, 4bits can be written with new value.
- * when 4bits is not 0, 4bits cannot be written.
- * when write data is 0x0000, 4bits clean to 0.
- */
- return ((HWREG32(lock_regs) & 0xf) == HWSPINLOCK_OWNER_ID);
- }
- static void rockchip_hwspinlock_unlock(struct rt_hwspinlock *hwlock)
- {
- void *lock_regs = hwlock->priv;
- HWREG32(lock_regs) = 0;
- }
- static const struct rt_hwspinlock_ops rk_hwspinlock_ops =
- {
- .trylock = rockchip_hwspinlock_trylock,
- .unlock = rockchip_hwspinlock_unlock,
- };
- static rt_err_t rockchip_hwspinlock_probe(struct rt_platform_device *pdev)
- {
- rt_err_t err;
- struct rt_hwspinlock *hwlock;
- struct rt_hwspinlock_bank *bank;
- struct rt_device *dev = &pdev->parent;
- struct rockchip_hwspinlock *rk_hwspinlock;
- rk_hwspinlock = hwspinlock_bank_alloc(rk_hwspinlock, HWSPINLOCK_NUMBER);
- if (!rk_hwspinlock)
- {
- return -RT_ENOMEM;
- }
- rk_hwspinlock->regs = rt_dm_dev_iomap(dev, 0);
- if (!rk_hwspinlock->regs)
- {
- err = -RT_EIO;
- goto _fail;
- }
- bank = &rk_hwspinlock->parent;
- hwlock = &bank->locks[0];
- for (int i = 0; i < HWSPINLOCK_NUMBER; ++i, ++hwlock)
- {
- hwlock->priv = rk_hwspinlock->regs + HWSPINLOCK_STATUS_OFFSET(i);
- }
- bank->dev = dev;
- bank->ops = &rk_hwspinlock_ops;
- bank->locks_nr = HWSPINLOCK_NUMBER;
- if ((err = rt_hwspinlock_bank_register(bank)))
- {
- goto _fail;
- }
- dev->user_data = rk_hwspinlock;
- return RT_EOK;
- _fail:
- if (rk_hwspinlock->regs)
- {
- rt_iounmap(rk_hwspinlock->regs);
- }
- rt_free(rk_hwspinlock);
- return err;
- }
- static rt_err_t rockchip_hwspinlock_remove(struct rt_platform_device *pdev)
- {
- struct rockchip_hwspinlock *rk_hwspinlock = pdev->parent.user_data;
- rt_hwspinlock_bank_unregister(&rk_hwspinlock->parent);
- rt_iounmap(rk_hwspinlock->regs);
- rt_free(rk_hwspinlock);
- return RT_EOK;
- }
- static const struct rt_ofw_node_id rockchip_hwspinlock_ofw_ids[] =
- {
- { .compatible = "rockchip,hwspinlock" },
- { /* sentinel */ }
- };
- static struct rt_platform_driver rockchip_hwspinlock_driver =
- {
- .name = "hwspinlock-rockchip",
- .ids = rockchip_hwspinlock_ofw_ids,
- .probe = rockchip_hwspinlock_probe,
- .remove = rockchip_hwspinlock_remove,
- };
- RT_PLATFORM_DRIVER_EXPORT(rockchip_hwspinlock_driver);
|