-
Notifications
You must be signed in to change notification settings - Fork 5.3k
[dm][hwspinlock] support hwspinlock #11030
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| menuconfig RT_USING_HWSPINLOCK | ||
| bool "Using Hardware Spinlock device drivers" | ||
| depends on RT_USING_DM | ||
| depends on RT_USING_OFW | ||
| select RT_USING_ADT | ||
| select RT_USING_ADT_REF | ||
| default n | ||
| help | ||
| Hardware spinlock modules provide hardware assistance for | ||
| synchronization and mutual exclusion between heterogeneous processors | ||
| and those not operating under a single, shared operating system. | ||
|
|
||
| if RT_USING_HWSPINLOCK | ||
| osource "$(SOC_DM_HWSPINLOCK_DIR)/Kconfig" | ||
| endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| from building import * | ||
|
|
||
| group = [] | ||
|
|
||
| if not GetDepend(['RT_USING_HWSPINLOCK']): | ||
| Return('group') | ||
|
|
||
| cwd = GetCurrentDir() | ||
| CPPPATH = [cwd + '/../include'] | ||
|
|
||
| src = ['hwspinlock.c'] | ||
|
|
||
| group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH) | ||
|
|
||
| Return('group') |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,319 @@ | ||||||
| /* | ||||||
| * 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 <rtthread.h> | ||||||
|
|
||||||
| #include <cpuport.h> | ||||||
|
|
||||||
| #define DBG_TAG "rtdm.hwspinlock" | ||||||
| #define DBG_LVL DBG_INFO | ||||||
| #include <rtdbg.h> | ||||||
|
|
||||||
| #include "hwspinlock_dm.h" | ||||||
|
|
||||||
| static RT_DEFINE_SPINLOCK(hwspinlock_ops_lock); | ||||||
| static rt_list_t hwspinlock_bank_nodes = RT_LIST_OBJECT_INIT(hwspinlock_bank_nodes); | ||||||
|
|
||||||
| rt_err_t rt_hwspinlock_bank_register(struct rt_hwspinlock_bank *bank) | ||||||
| { | ||||||
| struct rt_hwspinlock *hwlock; | ||||||
|
|
||||||
| if (!bank || !bank->ops || bank->locks_nr <= 0 || !bank->dev) | ||||||
| { | ||||||
| return -RT_EINVAL; | ||||||
| } | ||||||
|
|
||||||
| rt_list_init(&bank->list); | ||||||
| rt_ref_init(&bank->ref); | ||||||
|
|
||||||
| hwlock = &bank->locks[0]; | ||||||
|
|
||||||
| for (int i = 0; i < bank->locks_nr; ++i, ++hwlock) | ||||||
| { | ||||||
GuEe-GUI marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
| hwlock->bank = bank; | ||||||
| hwlock->used = RT_FALSE; | ||||||
| rt_spin_lock_init(&hwlock->lock); | ||||||
| } | ||||||
|
|
||||||
| rt_spin_lock(&hwspinlock_ops_lock); | ||||||
| rt_list_insert_after(&hwspinlock_bank_nodes, &bank->list); | ||||||
| rt_spin_unlock(&hwspinlock_ops_lock); | ||||||
|
|
||||||
| rt_dm_dev_bind_fwdata(bank->dev, RT_NULL, bank); | ||||||
|
|
||||||
| return RT_EOK; | ||||||
| } | ||||||
|
|
||||||
| rt_err_t rt_hwspinlock_bank_unregister(struct rt_hwspinlock_bank *bank) | ||||||
| { | ||||||
| rt_err_t err; | ||||||
|
|
||||||
| if (!bank) | ||||||
| { | ||||||
| return -RT_EINVAL; | ||||||
| } | ||||||
|
|
||||||
| rt_spin_lock(&hwspinlock_ops_lock); | ||||||
|
|
||||||
| if (rt_ref_read(&bank->ref) == 1) | ||||||
| { | ||||||
GuEe-GUI marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
| rt_list_remove(&bank->list); | ||||||
| rt_dm_dev_unbind_fwdata(bank->dev, RT_NULL); | ||||||
|
|
||||||
| err = RT_EOK; | ||||||
| } | ||||||
| else | ||||||
| { | ||||||
| err = -RT_EBUSY; | ||||||
| } | ||||||
|
|
||||||
| rt_spin_unlock(&hwspinlock_ops_lock); | ||||||
|
|
||||||
| return err; | ||||||
| } | ||||||
|
|
||||||
| rt_err_t rt_hwspin_trylock_raw(struct rt_hwspinlock *hwlock, | ||||||
| rt_ubase_t *out_irq_level) | ||||||
| { | ||||||
| rt_err_t err; | ||||||
|
|
||||||
| if (!hwlock) | ||||||
| { | ||||||
| return -RT_EINVAL; | ||||||
| } | ||||||
|
|
||||||
| if (out_irq_level) | ||||||
| { | ||||||
| *out_irq_level = rt_spin_lock_irqsave(&hwlock->lock); | ||||||
| } | ||||||
| else | ||||||
| { | ||||||
| rt_spin_lock(&hwlock->lock); | ||||||
| } | ||||||
|
|
||||||
| err = hwlock->bank->ops->trylock(hwlock); | ||||||
|
|
||||||
| if (err) | ||||||
| { | ||||||
| if (out_irq_level) | ||||||
| { | ||||||
| rt_spin_unlock_irqrestore(&hwlock->lock, *out_irq_level); | ||||||
| } | ||||||
| else | ||||||
| { | ||||||
| rt_spin_unlock(&hwlock->lock); | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| rt_hw_dmb(); | ||||||
|
|
||||||
| return err; | ||||||
| } | ||||||
|
|
||||||
| rt_err_t rt_hwspin_lock_timeout_raw(struct rt_hwspinlock *hwlock, | ||||||
| rt_uint32_t timeout_ms, rt_ubase_t *out_irq_level) | ||||||
| { | ||||||
| rt_err_t err; | ||||||
| rt_tick_t timeout = rt_tick_get() + rt_tick_from_millisecond(timeout_ms); | ||||||
|
|
||||||
| for (;;) | ||||||
| { | ||||||
| err = rt_hwspin_trylock_raw(hwlock, out_irq_level); | ||||||
|
|
||||||
| if (err != -RT_EBUSY) | ||||||
| { | ||||||
| break; | ||||||
| } | ||||||
|
|
||||||
| if (timeout < rt_tick_get()) | ||||||
GuEe-GUI marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
| { | ||||||
| return -RT_ETIMEOUT; | ||||||
| } | ||||||
|
|
||||||
| if (hwlock->bank->ops->relax) | ||||||
| { | ||||||
| hwlock->bank->ops->relax(hwlock); | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| return err; | ||||||
| } | ||||||
|
|
||||||
| void rt_hwspin_unlock_raw(struct rt_hwspinlock *hwlock, | ||||||
| rt_ubase_t *out_irq_level) | ||||||
| { | ||||||
| if (!hwlock) | ||||||
| { | ||||||
| return; | ||||||
| } | ||||||
|
|
||||||
| rt_hw_dmb(); | ||||||
|
|
||||||
| hwlock->bank->ops->unlock(hwlock); | ||||||
|
|
||||||
| if (out_irq_level) | ||||||
| { | ||||||
| rt_spin_unlock_irqrestore(&hwlock->lock, *out_irq_level); | ||||||
| } | ||||||
| else | ||||||
| { | ||||||
| rt_spin_unlock(&hwlock->lock); | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| static struct rt_hwspinlock *hwspinlock_get(struct rt_hwspinlock_bank *bank, int id) | ||||||
| { | ||||||
| struct rt_hwspinlock *hwlock = RT_NULL; | ||||||
|
|
||||||
| if (bank) | ||||||
| { | ||||||
| int offset = id - bank->base_id; | ||||||
|
|
||||||
| if (!bank->locks[offset].used) | ||||||
|
||||||
| if (!bank->locks[offset].used) | |
| if (offset >= 0 && offset < bank->locks_nr && !bank->locks[offset].used) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🟡 [PR Title/PR 标题]: PR title needs improvement / PR 标题需要改进
English: The PR title
[dm][hwspinlock] support hwspinlockfollows the correct prefix format[module][subsystem], but the description "support hwspinlock" is too vague. It should be more specific about what is being added.中文: PR 标题
[dm][hwspinlock] support hwspinlock遵循了正确的前缀格式[模块][子系统],但描述 "support hwspinlock" 过于模糊。应该更具体地说明正在添加什么。Suggested title / 建议标题:
[dm][hwspinlock] Add hardware spinlock driver frameworkor / 或
[dm][hwspinlock] Implement hwspinlock driver managementNote: This follows the RT-Thread guideline that titles should be specific and avoid vague terms like "support" or "add support for".