On Thu, 2019-10-03 at 06:49 -0700, Guenter Roeck wrote:
On 9/27/19 3:31 AM, Jiaxin Yu wrote:
<snip..>
+static int toprgu_reset_assert(struct reset_controller_dev *rcdev,
unsigned long id)
+{
- unsigned int tmp;
- unsigned long flags;
- struct toprgu_reset *data = container_of(rcdev,
struct toprgu_reset, rcdev);
- spin_lock_irqsave(&data->lock, flags);
- tmp = __raw_readl(data->toprgu_swrst_base + data->regofs);
- tmp |= BIT(id);
- tmp |= WDT_SWSYS_RST_KEY;
- writel(tmp, data->toprgu_swrst_base + data->regofs);
- spin_unlock_irqrestore(&data->lock, flags);
- return 0;
+}
+static int toprgu_reset_deassert(struct reset_controller_dev *rcdev,
unsigned long id)
+{
- unsigned int tmp;
- unsigned long flags;
- struct toprgu_reset *data = container_of(rcdev,
struct toprgu_reset, rcdev);
- spin_lock_irqsave(&data->lock, flags);
- tmp = __raw_readl(data->toprgu_swrst_base + data->regofs);
- tmp &= ~BIT(id);
- tmp |= WDT_SWSYS_RST_KEY;
- writel(tmp, data->toprgu_swrst_base + data->regofs);
- spin_unlock_irqrestore(&data->lock, flags);
- return 0;
+}
+static int toprgu_reset(struct reset_controller_dev *rcdev,
unsigned long id)
+{
- int ret;
- ret = toprgu_reset_assert(rcdev, id);
- if (ret)
return ret;
- return toprgu_reset_deassert(rcdev, id);
Unless there is additional synchronization elsewhere, parallel calls to the -> assert, and ->reset callbacks may result in the reset being deasserted while at least one caller (the one who called the ->assert function) believes that it is still asserted.
[ ... and if there _is_ additional synchronization elsewhere, the local spinlock would be unnecessary ]
I'm not sure if this count as additional synchronization, but you could get exclusive control to the reset by calling reset_control_get_exclusive so others won't try to reset the component while you are using it.
In this case, you still need spinlock because other drivers might trying to reset their components and they share same register.
Joe.C