On 20-07-30 11:39:22, Philipp Zabel wrote: > On Thu, 2020-07-30 at 11:55 +0300, Abel Vesa wrote: > > On 20-07-29 14:46:28, Philipp Zabel wrote: > > > Hi Abel, > > > > > > On Wed, 2020-07-29 at 15:07 +0300, Abel Vesa wrote: > > > > On i.MX8MP, there is a new type of IP which is called BLK_CTRL in > > > > [...] > > > > > > + > > > > +static int imx_blk_ctrl_reset_set(struct reset_controller_dev *rcdev, > > > > + unsigned long id, bool assert) > > > > +{ > > > > + struct imx_blk_ctrl_drvdata *drvdata = container_of(rcdev, > > > > + struct imx_blk_ctrl_drvdata, rcdev); > > > > + unsigned int offset = drvdata->rst_hws[id].offset; > > > > + unsigned int shift = drvdata->rst_hws[id].shift; > > > > + unsigned int mask = drvdata->rst_hws[id].mask; > > > > + void __iomem *reg_addr = drvdata->base + offset; > > > > + unsigned long flags; > > > > + u32 reg; > > > > + > > > > + if (assert) { > > > > + pm_runtime_get_sync(rcdev->dev); > > > > + spin_lock_irqsave(&drvdata->lock, flags); > > > > + reg = readl(reg_addr); > > > > + writel(reg & ~(mask << shift), reg_addr); > > > > + spin_unlock_irqrestore(&drvdata->lock, flags); > > > > + } else { > > > > + spin_lock_irqsave(&drvdata->lock, flags); > > > > + reg = readl(reg_addr); > > > > + writel(reg | (mask << shift), reg_addr); > > > > + spin_unlock_irqrestore(&drvdata->lock, flags); > > > > + pm_runtime_put(rcdev->dev); > > > > > > This still has the issue of potentially letting exclusive reset control > > > users break the device usage counter. > > > > > > Also shared reset control users start with deassert(), and you end probe > > > with pm_runtime_put(), so the first shared reset control user that > > > deasserts its reset will decrement the dev->power.usage_count to -1 ? > > > For multiple resets being initially deasserted this would decrement > > > multiple times. > > > > > > I think you'll have to track the (number of) asserted reset bits in this > > > reset controller and limit when to call pm_runtime_get/put_sync(). > > > > > > > Yes, you're right. > > > > I'll add a mask, and for each assert, the according bit will get set, and > > for each deasssert the same bit will get cleared. > > > And when the mask has at least one bit set, the pm_runtime_get gets called > > ^ When the mask was 0 before but now has a bit set. > > > and when the mask is 0, the pm_runtime_put_sync will be called. > > ^ When the mask had a bit set but now is 0. > > > Does that sound OK ? > > And the mask starts out as 0, as after the pm_runtime_put() in probe all > reset lines are deasserted? > Yes, that is correct. > > > > + } > > > > + > > > > + return 0; > > > > +} > > > > + > > > > +static int imx_blk_ctrl_reset_reset(struct reset_controller_dev *rcdev, > > > > + unsigned long id) > > > > +{ > > > > + imx_blk_ctrl_reset_set(rcdev, id, true); > > > > + return imx_blk_ctrl_reset_set(rcdev, id, false); > > > > > > Does this work for all peripherals? Are there none that require the > > > reset line to be asserted for a certain number of bus clocks or similar? > > > > As of now, there is no user that calls reset. All the users call the assert > > and then deassert. As for the number of clocks for reset, I'll try to have a > > chat to the HW design team and then come back with the information. > > Ok. If this is not required or can't be guaranteed to work, it may be > better to just leave it out. > > regards > Philipp