* Re: [PATCH v7 07/20] clk: tegra: clk-periph: Add save and restore support
From: Dmitry Osipenko @ 2019-08-04 12:24 UTC (permalink / raw)
To: Sowjanya Komatineni, thierry.reding, jonathanh, tglx, jason,
marc.zyngier, linus.walleij, stefan, mark.rutland
Cc: pdeschrijver, pgaikwad, sboyd, linux-clk, linux-gpio, jckuo,
josephl, talho, linux-tegra, linux-kernel, mperttunen, spatra,
robh+dt, devicetree
In-Reply-To: <4dec8efb-bc3b-0275-8dea-7600a8f9e478@nvidia.com>
04.08.2019 2:44, Sowjanya Komatineni пишет:
>
> On 8/3/19 10:01 AM, Sowjanya Komatineni wrote:
>>
>> On 8/3/19 3:33 AM, Dmitry Osipenko wrote:
>>> 03.08.2019 2:51, Sowjanya Komatineni пишет:
>>>> On 8/2/19 2:15 PM, Dmitry Osipenko wrote:
>>>>> 02.08.2019 23:32, Sowjanya Komatineni пишет:
>>>>>> On 8/2/19 1:17 PM, Dmitry Osipenko wrote:
>>>>>>> 02.08.2019 23:13, Dmitry Osipenko пишет:
>>>>>>>> 02.08.2019 21:33, Sowjanya Komatineni пишет:
>>>>>>>>> On 8/2/19 5:38 AM, Dmitry Osipenko wrote:
>>>>>>>>>> 02.08.2019 2:49, Sowjanya Komatineni пишет:
>>>>>>>>>>> On 8/1/19 4:19 PM, Sowjanya Komatineni wrote:
>>>>>>>>>>>> On 8/1/19 2:30 PM, Sowjanya Komatineni wrote:
>>>>>>>>>>>>> On 8/1/19 1:54 PM, Dmitry Osipenko wrote:
>>>>>>>>>>>>>> 01.08.2019 23:31, Sowjanya Komatineni пишет:
>>>>>>>>>>>>>>> On 8/1/19 1:17 PM, Dmitry Osipenko wrote:
>>>>>>>>>>>>>>>> 01.08.2019 22:42, Sowjanya Komatineni пишет:
>>>>>>>>>>>>>>>>> On 8/1/19 12:00 PM, Dmitry Osipenko wrote:
>>>>>>>>>>>>>>>>>> 01.08.2019 20:58, Sowjanya Komatineni пишет:
>>>>>>>>>>>>>>>>>>> On 7/31/19 4:09 PM, Sowjanya Komatineni wrote:
>>>>>>>>>>>>>>>>>>>> On 7/31/19 3:44 AM, Dmitry Osipenko wrote:
>>>>>>>>>>>>>>>>>>>>> 31.07.2019 12:50, Dmitry Osipenko пишет:
>>>>>>>>>>>>>>>>>>>>>> 31.07.2019 3:20, Sowjanya Komatineni пишет:
>>>>>>>>>>>>>>>>>>>>>>> This patch implements save and restore context for
>>>>>>>>>>>>>>>>>>>>>>> peripheral
>>>>>>>>>>>>>>>>>>>>>>> fixed
>>>>>>>>>>>>>>>>>>>>>>> clock ops, peripheral gate clock ops, sdmmc mux clock
>>>>>>>>>>>>>>>>>>>>>>> ops, and
>>>>>>>>>>>>>>>>>>>>>>> peripheral clock ops.
>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>> During system suspend, core power goes off and
>>>>>>>>>>>>>>>>>>>>>>> looses the
>>>>>>>>>>>>>>>>>>>>>>> settings
>>>>>>>>>>>>>>>>>>>>>>> of the Tegra CAR controller registers.
>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>> So during suspend entry clock and reset state of
>>>>>>>>>>>>>>>>>>>>>>> peripherals is
>>>>>>>>>>>>>>>>>>>>>>> saved
>>>>>>>>>>>>>>>>>>>>>>> and on resume they are restored to have clocks back to
>>>>>>>>>>>>>>>>>>>>>>> same
>>>>>>>>>>>>>>>>>>>>>>> rate and
>>>>>>>>>>>>>>>>>>>>>>> state as before suspend.
>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>> Acked-by: Thierry Reding <treding@nvidia.com>
>>>>>>>>>>>>>>>>>>>>>>> Signed-off-by: Sowjanya Komatineni
>>>>>>>>>>>>>>>>>>>>>>> <skomatineni@nvidia.com>
>>>>>>>>>>>>>>>>>>>>>>> ---
>>>>>>>>>>>>>>>>>>>>>>> drivers/clk/tegra/clk-periph-fixed.c | 33
>>>>>>>>>>>>>>>>>>>>>>> ++++++++++++++++++++++++++++++++
>>>>>>>>>>>>>>>>>>>>>>> drivers/clk/tegra/clk-periph-gate.c | 34
>>>>>>>>>>>>>>>>>>>>>>> +++++++++++++++++++++++++++++++++
>>>>>>>>>>>>>>>>>>>>>>> drivers/clk/tegra/clk-periph.c | 37
>>>>>>>>>>>>>>>>>>>>>>> ++++++++++++++++++++++++++++++++++++
>>>>>>>>>>>>>>>>>>>>>>> drivers/clk/tegra/clk-sdmmc-mux.c | 28
>>>>>>>>>>>>>>>>>>>>>>> +++++++++++++++++++++++++++
>>>>>>>>>>>>>>>>>>>>>>> drivers/clk/tegra/clk.h | 6 ++++++
>>>>>>>>>>>>>>>>>>>>>>> 5 files changed, 138 insertions(+)
>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>> diff --git a/drivers/clk/tegra/clk-periph-fixed.c
>>>>>>>>>>>>>>>>>>>>>>> b/drivers/clk/tegra/clk-periph-fixed.c
>>>>>>>>>>>>>>>>>>>>>>> index c088e7a280df..21b24530fa00 100644
>>>>>>>>>>>>>>>>>>>>>>> --- a/drivers/clk/tegra/clk-periph-fixed.c
>>>>>>>>>>>>>>>>>>>>>>> +++ b/drivers/clk/tegra/clk-periph-fixed.c
>>>>>>>>>>>>>>>>>>>>>>> @@ -60,11 +60,44 @@
>>>>>>>>>>>>>>>>>>>>>>> tegra_clk_periph_fixed_recalc_rate(struct
>>>>>>>>>>>>>>>>>>>>>>> clk_hw *hw,
>>>>>>>>>>>>>>>>>>>>>>> return (unsigned long)rate;
>>>>>>>>>>>>>>>>>>>>>>> }
>>>>>>>>>>>>>>>>>>>>>>> +static int
>>>>>>>>>>>>>>>>>>>>>>> tegra_clk_periph_fixed_save_context(struct
>>>>>>>>>>>>>>>>>>>>>>> clk_hw
>>>>>>>>>>>>>>>>>>>>>>> *hw)
>>>>>>>>>>>>>>>>>>>>>>> +{
>>>>>>>>>>>>>>>>>>>>>>> + struct tegra_clk_periph_fixed *fixed =
>>>>>>>>>>>>>>>>>>>>>>> to_tegra_clk_periph_fixed(hw);
>>>>>>>>>>>>>>>>>>>>>>> + u32 mask = 1 << (fixed->num % 32);
>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>> + fixed->enb_ctx = readl_relaxed(fixed->base +
>>>>>>>>>>>>>>>>>>>>>>> fixed->regs->enb_reg) &
>>>>>>>>>>>>>>>>>>>>>>> + mask;
>>>>>>>>>>>>>>>>>>>>>>> + fixed->rst_ctx = readl_relaxed(fixed->base +
>>>>>>>>>>>>>>>>>>>>>>> fixed->regs->rst_reg) &
>>>>>>>>>>>>>>>>>>>>>>> + mask;
>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>> + return 0;
>>>>>>>>>>>>>>>>>>>>>>> +}
>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>> +static void
>>>>>>>>>>>>>>>>>>>>>>> tegra_clk_periph_fixed_restore_context(struct
>>>>>>>>>>>>>>>>>>>>>>> clk_hw
>>>>>>>>>>>>>>>>>>>>>>> *hw)
>>>>>>>>>>>>>>>>>>>>>>> +{
>>>>>>>>>>>>>>>>>>>>>>> + struct tegra_clk_periph_fixed *fixed =
>>>>>>>>>>>>>>>>>>>>>>> to_tegra_clk_periph_fixed(hw);
>>>>>>>>>>>>>>>>>>>>>>> + u32 mask = 1 << (fixed->num % 32);
>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>> + if (fixed->enb_ctx)
>>>>>>>>>>>>>>>>>>>>>>> + writel_relaxed(mask, fixed->base +
>>>>>>>>>>>>>>>>>>>>>>> fixed->regs->enb_set_reg);
>>>>>>>>>>>>>>>>>>>>>>> + else
>>>>>>>>>>>>>>>>>>>>>>> + writel_relaxed(mask, fixed->base +
>>>>>>>>>>>>>>>>>>>>>>> fixed->regs->enb_clr_reg);
>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>> + udelay(2);
>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>> + if (!fixed->rst_ctx) {
>>>>>>>>>>>>>>>>>>>>>>> + udelay(5); /* reset propogation delay */
>>>>>>>>>>>>>>>>>>>>>>> + writel_relaxed(mask, fixed->base +
>>>>>>>>>>>>>>>>>>>>>>> fixed->regs->rst_reg);
>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>> +}
>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>> static const struct clk_ops
>>>>>>>>>>>>>>>>>>>>>>> tegra_clk_periph_fixed_ops
>>>>>>>>>>>>>>>>>>>>>>> = {
>>>>>>>>>>>>>>>>>>>>>>> .is_enabled =
>>>>>>>>>>>>>>>>>>>>>>> tegra_clk_periph_fixed_is_enabled,
>>>>>>>>>>>>>>>>>>>>>>> .enable = tegra_clk_periph_fixed_enable,
>>>>>>>>>>>>>>>>>>>>>>> .disable = tegra_clk_periph_fixed_disable,
>>>>>>>>>>>>>>>>>>>>>>> .recalc_rate =
>>>>>>>>>>>>>>>>>>>>>>> tegra_clk_periph_fixed_recalc_rate,
>>>>>>>>>>>>>>>>>>>>>>> + .save_context =
>>>>>>>>>>>>>>>>>>>>>>> tegra_clk_periph_fixed_save_context,
>>>>>>>>>>>>>>>>>>>>>>> + .restore_context =
>>>>>>>>>>>>>>>>>>>>>>> tegra_clk_periph_fixed_restore_context,
>>>>>>>>>>>>>>>>>>>>>>> };
>>>>>>>>>>>>>>>>>>>>>>> struct clk
>>>>>>>>>>>>>>>>>>>>>>> *tegra_clk_register_periph_fixed(const
>>>>>>>>>>>>>>>>>>>>>>> char
>>>>>>>>>>>>>>>>>>>>>>> *name,
>>>>>>>>>>>>>>>>>>>>>>> diff --git a/drivers/clk/tegra/clk-periph-gate.c
>>>>>>>>>>>>>>>>>>>>>>> b/drivers/clk/tegra/clk-periph-gate.c
>>>>>>>>>>>>>>>>>>>>>>> index 4b31beefc9fc..6ba5b08e0787 100644
>>>>>>>>>>>>>>>>>>>>>>> --- a/drivers/clk/tegra/clk-periph-gate.c
>>>>>>>>>>>>>>>>>>>>>>> +++ b/drivers/clk/tegra/clk-periph-gate.c
>>>>>>>>>>>>>>>>>>>>>>> @@ -25,6 +25,8 @@ static
>>>>>>>>>>>>>>>>>>>>>>> DEFINE_SPINLOCK(periph_ref_lock);
>>>>>>>>>>>>>>>>>>>>>>> #define read_rst(gate) \
>>>>>>>>>>>>>>>>>>>>>>> readl_relaxed(gate->clk_base +
>>>>>>>>>>>>>>>>>>>>>>> (gate->regs->rst_reg))
>>>>>>>>>>>>>>>>>>>>>>> +#define write_rst_set(val, gate) \
>>>>>>>>>>>>>>>>>>>>>>> + writel_relaxed(val, gate->clk_base +
>>>>>>>>>>>>>>>>>>>>>>> (gate->regs->rst_set_reg))
>>>>>>>>>>>>>>>>>>>>>>> #define write_rst_clr(val, gate) \
>>>>>>>>>>>>>>>>>>>>>>> writel_relaxed(val, gate->clk_base +
>>>>>>>>>>>>>>>>>>>>>>> (gate->regs->rst_clr_reg))
>>>>>>>>>>>>>>>>>>>>>>> @@ -110,10 +112,42 @@ static void
>>>>>>>>>>>>>>>>>>>>>>> clk_periph_disable(struct
>>>>>>>>>>>>>>>>>>>>>>> clk_hw *hw)
>>>>>>>>>>>>>>>>>>>>>>> spin_unlock_irqrestore(&periph_ref_lock, flags);
>>>>>>>>>>>>>>>>>>>>>>> }
>>>>>>>>>>>>>>>>>>>>>>> +static int clk_periph_gate_save_context(struct
>>>>>>>>>>>>>>>>>>>>>>> clk_hw
>>>>>>>>>>>>>>>>>>>>>>> *hw)
>>>>>>>>>>>>>>>>>>>>>>> +{
>>>>>>>>>>>>>>>>>>>>>>> + struct tegra_clk_periph_gate *gate =
>>>>>>>>>>>>>>>>>>>>>>> to_clk_periph_gate(hw);
>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>> + gate->clk_state_ctx = read_enb(gate) &
>>>>>>>>>>>>>>>>>>>>>>> periph_clk_to_bit(gate);
>>>>>>>>>>>>>>>>>>>>>>> + gate->rst_state_ctx = read_rst(gate) &
>>>>>>>>>>>>>>>>>>>>>>> periph_clk_to_bit(gate);
>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>> + return 0;
>>>>>>>>>>>>>>>>>>>>>>> +}
>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>> +static void clk_periph_gate_restore_context(struct
>>>>>>>>>>>>>>>>>>>>>>> clk_hw
>>>>>>>>>>>>>>>>>>>>>>> *hw)
>>>>>>>>>>>>>>>>>>>>>>> +{
>>>>>>>>>>>>>>>>>>>>>>> + struct tegra_clk_periph_gate *gate =
>>>>>>>>>>>>>>>>>>>>>>> to_clk_periph_gate(hw);
>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>> + if (gate->clk_state_ctx)
>>>>>>>>>>>>>>>>>>>>>>> + write_enb_set(periph_clk_to_bit(gate), gate);
>>>>>>>>>>>>>>>>>>>>>>> + else
>>>>>>>>>>>>>>>>>>>>>>> + write_enb_clr(periph_clk_to_bit(gate), gate);
>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>> + udelay(5);
>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>> + if (!(gate->flags & TEGRA_PERIPH_NO_RESET) &&
>>>>>>>>>>>>>>>>>>>>>>> + !(gate->flags & TEGRA_PERIPH_MANUAL_RESET)) {
>>>>>>>>>>>>>>>>>>>>>>> + if (gate->rst_state_ctx)
>>>>>>>>>>>>>>>>>>>>>>> + write_rst_set(periph_clk_to_bit(gate), gate);
>>>>>>>>>>>>>>>>>>>>>>> + else
>>>>>>>>>>>>>>>>>>>>>>> + write_rst_clr(periph_clk_to_bit(gate), gate);
>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>> +}
>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>> const struct clk_ops
>>>>>>>>>>>>>>>>>>>>>>> tegra_clk_periph_gate_ops = {
>>>>>>>>>>>>>>>>>>>>>>> .is_enabled = clk_periph_is_enabled,
>>>>>>>>>>>>>>>>>>>>>>> .enable = clk_periph_enable,
>>>>>>>>>>>>>>>>>>>>>>> .disable = clk_periph_disable,
>>>>>>>>>>>>>>>>>>>>>>> + .save_context = clk_periph_gate_save_context,
>>>>>>>>>>>>>>>>>>>>>>> + .restore_context =
>>>>>>>>>>>>>>>>>>>>>>> clk_periph_gate_restore_context,
>>>>>>>>>>>>>>>>>>>>>>> };
>>>>>>>>>>>>>>>>>>>>>>> struct clk
>>>>>>>>>>>>>>>>>>>>>>> *tegra_clk_register_periph_gate(const
>>>>>>>>>>>>>>>>>>>>>>> char *name,
>>>>>>>>>>>>>>>>>>>>>>> diff --git a/drivers/clk/tegra/clk-periph.c
>>>>>>>>>>>>>>>>>>>>>>> b/drivers/clk/tegra/clk-periph.c
>>>>>>>>>>>>>>>>>>>>>>> index 58437da25156..06fb62955768 100644
>>>>>>>>>>>>>>>>>>>>>>> --- a/drivers/clk/tegra/clk-periph.c
>>>>>>>>>>>>>>>>>>>>>>> +++ b/drivers/clk/tegra/clk-periph.c
>>>>>>>>>>>>>>>>>>>>>>> @@ -99,6 +99,37 @@ static void
>>>>>>>>>>>>>>>>>>>>>>> clk_periph_disable(struct
>>>>>>>>>>>>>>>>>>>>>>> clk_hw
>>>>>>>>>>>>>>>>>>>>>>> *hw)
>>>>>>>>>>>>>>>>>>>>>>> gate_ops->disable(gate_hw);
>>>>>>>>>>>>>>>>>>>>>>> }
>>>>>>>>>>>>>>>>>>>>>>> +static int clk_periph_save_context(struct
>>>>>>>>>>>>>>>>>>>>>>> clk_hw *hw)
>>>>>>>>>>>>>>>>>>>>>>> +{
>>>>>>>>>>>>>>>>>>>>>>> + struct tegra_clk_periph *periph =
>>>>>>>>>>>>>>>>>>>>>>> to_clk_periph(hw);
>>>>>>>>>>>>>>>>>>>>>>> + const struct clk_ops *gate_ops = periph->gate_ops;
>>>>>>>>>>>>>>>>>>>>>>> + struct clk_hw *gate_hw = &periph->gate.hw;
>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>> + if (!(periph->gate.flags & TEGRA_PERIPH_NO_GATE))
>>>>>>>>>>>>>>>>>>>>>>> + gate_ops->save_context(gate_hw);
>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>> + periph->parent_ctx = clk_periph_get_parent(hw);
>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>> + return 0;
>>>>>>>>>>>>>>>>>>>>>>> +}
>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>> +static void clk_periph_restore_context(struct clk_hw
>>>>>>>>>>>>>>>>>>>>>>> *hw)
>>>>>>>>>>>>>>>>>>>>>>> +{
>>>>>>>>>>>>>>>>>>>>>>> + struct tegra_clk_periph *periph =
>>>>>>>>>>>>>>>>>>>>>>> to_clk_periph(hw);
>>>>>>>>>>>>>>>>>>>>>>> + const struct clk_ops *gate_ops = periph->gate_ops;
>>>>>>>>>>>>>>>>>>>>>>> + struct clk_hw *gate_hw = &periph->gate.hw;
>>>>>>>>>>>>>>>>>>>>>>> + const struct clk_ops *div_ops = periph->div_ops;
>>>>>>>>>>>>>>>>>>>>>>> + struct clk_hw *div_hw = &periph->divider.hw;
>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>> + clk_periph_set_parent(hw, periph->parent_ctx);
>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>> + if (!(periph->gate.flags & TEGRA_PERIPH_NO_DIV))
>>>>>>>>>>>>>>>>>>>>>>> + div_ops->restore_context(div_hw);
>>>>>>>>>>>>>>>>>>>>>> Could you please point to where the divider's
>>>>>>>>>>>>>>>>>>>>>> save_context()
>>>>>>>>>>>>>>>>>>>>>> happens?
>>>>>>>>>>>>>>>>>>>>>> Because I can't see it.
>>>>>>>>>>>>>>>>>>>>> Ah, I now see that there is no need to save the dividers
>>>>>>>>>>>>>>>>>>>>> context
>>>>>>>>>>>>>>>>>>>>> because
>>>>>>>>>>>>>>>>>>>>> clk itself has enough info that is needed for the
>>>>>>>>>>>>>>>>>>>>> context's
>>>>>>>>>>>>>>>>>>>>> restoring
>>>>>>>>>>>>>>>>>>>>> (like I pointed in the review to v6).
>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>> Looks like you could also implement a new
>>>>>>>>>>>>>>>>>>>>> clk_hw_get_parent_index()
>>>>>>>>>>>>>>>>>>>>> generic helper to get the index instead of storing it
>>>>>>>>>>>>>>>>>>>>> manually.
>>>>>>>>>>>>>>>>>>>> clk_periph_get_parent basically invokes existing
>>>>>>>>>>>>>>>>>>>> clk_mux_ops
>>>>>>>>>>>>>>>>>>>> get_parent() which is then saved in tegra_clk_periph.
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>> All existing drivers are using directly get_parent() from
>>>>>>>>>>>>>>>>>>>> clk_mux
>>>>>>>>>>>>>>>>>>>> which actually gets index from the register read.
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>> To have this more generic w.r.t save/restore context
>>>>>>>>>>>>>>>>>>>> point of
>>>>>>>>>>>>>>>>>>>> view,
>>>>>>>>>>>>>>>>>>>> probably instead of implementing new get_parent_index
>>>>>>>>>>>>>>>>>>>> helper,
>>>>>>>>>>>>>>>>>>>> I think
>>>>>>>>>>>>>>>>>>>> its better to implement save_context and
>>>>>>>>>>>>>>>>>>>> restore_context to
>>>>>>>>>>>>>>>>>>>> clk_mux_ops along with creating parent_index field into
>>>>>>>>>>>>>>>>>>>> clk_mux to
>>>>>>>>>>>>>>>>>>>> cache index during set_parent.
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>> So we just need to invoke mux_ops save_context and
>>>>>>>>>>>>>>>>>>>> restore_context.
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>> I hope its ok to add save/restore context to clk_mux_ops
>>>>>>>>>>>>>>>>>>> to be
>>>>>>>>>>>>>>>>>>> more
>>>>>>>>>>>>>>>>>>> generic w.r.t save/restore context rather than
>>>>>>>>>>>>>>>>>>> get_parent_index
>>>>>>>>>>>>>>>>>>> API.
>>>>>>>>>>>>>>>>>>> Please confirm if you agree.
>>>>>>>>>>>>>>>>>> Sounds like a good idea. I see that there is a 'restoring'
>>>>>>>>>>>>>>>>>> helper for
>>>>>>>>>>>>>>>>>> the generic clk_gate, seems something similar could be done
>>>>>>>>>>>>>>>>>> for the
>>>>>>>>>>>>>>>>>> clk_mux. And looks like anyway you'll need to associate the
>>>>>>>>>>>>>>>>>> parent
>>>>>>>>>>>>>>>>>> clock
>>>>>>>>>>>>>>>>>> with the hw index in order to restore the muxing.
>>>>>>>>>>>>>>>>> by 'restoring' helper for generic clk_gate, are you
>>>>>>>>>>>>>>>>> referring to
>>>>>>>>>>>>>>>>> clk_gate_restore_context API?
>>>>>>>>>>>>>>>> Yes.
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>> clk_gate_restore_context is API that's any clk drivers can
>>>>>>>>>>>>>>>>> use for
>>>>>>>>>>>>>>>>> clk_gate operation restore for custom gate clk_ops.
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>> But clk-periph is directly using generic clk_mux ops from
>>>>>>>>>>>>>>>>> clk_mux
>>>>>>>>>>>>>>>>> so I
>>>>>>>>>>>>>>>>> think we should add .restore_context to clk_mux_ops and then
>>>>>>>>>>>>>>>>> during
>>>>>>>>>>>>>>>>> clk-periph restore need to invoke mux_ops->restore_context.
>>>>>>>>>>>>>>>> I'm not sure whether it will be good for every driver that
>>>>>>>>>>>>>>>> uses
>>>>>>>>>>>>>>>> generic
>>>>>>>>>>>>>>>> clk_mux ops. Should be more flexible to have a generic helper
>>>>>>>>>>>>>>>> function
>>>>>>>>>>>>>>>> that any driver could use in order to restore the clock's
>>>>>>>>>>>>>>>> parent.
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> The clk-periph restoring also includes case of combining
>>>>>>>>>>>>>>>> divider
>>>>>>>>>>>>>>>> and
>>>>>>>>>>>>>>>> parent restoring, so generic helper could be useful in that
>>>>>>>>>>>>>>>> case
>>>>>>>>>>>>>>>> as well.
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> It also looks like you could actually use the
>>>>>>>>>>>>>>>> clk_gate_restore_context()
>>>>>>>>>>>>>>>> instead of manually saving the clock's enable-state, couldn't
>>>>>>>>>>>>>>>> you?
>>>>>>>>>>>>>>> ok for clk_mux, can add generic clk_mux_restore_context API
>>>>>>>>>>>>>>> rather
>>>>>>>>>>>>>>> than
>>>>>>>>>>>>>>> using restore_context in clk_ops and will invoke that during
>>>>>>>>>>>>>>> clk_periph
>>>>>>>>>>>>>>> restore.
>>>>>>>>>>>>>>>
>>>>>>>>>>> digging thru looks like for clk_periph source restore instead of
>>>>>>>>>>> clk_mux_restore_context, i can directly do clk_hw_get_parent and
>>>>>>>>>>> clk_set_parent with mux_hw as they invoke mux_ops get/set parent
>>>>>>>>>>> anyway.
>>>>>>>>>>> Will do this for periph clk mux
>>>> Just to be clear, clk_mux don't have cached parent. get_parent is by
>>>> register read. So, cant directly use get_parent and then set during
>>>> restore.
>>>>
>>>> So will create both clk_mux_save/restore_context in generic clk driver
>>>> and will invoke them during tegra peripheral clock suspend/resume.
>>> Why MUX clock doesn't have a cached parent? What MUX clock you're
>>> talking about?
>>>
>>> [snip]
>>
>> Please ignore got it.
>>
>> Will send next version after giving few more days for feedback.
>>
> Couple of issues:
>
> 1.) I see clk-tegra-periph driver periph_clks init_data entries for some
> peripherals are not correct for Tegra 114 and later chips.
>
> Eg I2C TEGRA_INIT_DATA_TABLE entries in clk-tegra-periph are used for all Tegra
> chipsets currently in the driver.
>
> These entries are using MUX shift of 30 and MUX mask only for 2 bits which is
> correct for T30 and prior.
> But for later Tegra chips, it should be MUX shift 29 and MASK(3).
>
> Also, I2C parent idx entries in mux_pllp_clkm_idx are different from Tegra114
> onwards.
>
> As we are using only PLLP and CLKM sources only for I2C, their corresponding mux
> values from register spec by using upper 2 bits for T114 onwards match actual 2
> bits of MUX value on T30 and prior.
>
> Not sure if this something known pending to port actual clock MUX table changes
> for Tegra114 onwards?
>
> Or
>
> Are we purposely using upper 2 bits only for clock source for T114 and later as
> the upper 2 bit values of the limited clock source we are using match with
> previous Tegra peripheral clock source mux values?
The actual hardware values are compatible on all Tegra SoCs and PLLC2 and PLLC3
are just unused on T114+, so should be okay.
> Peter/Thierry, Can you please help comment on this?
>
>
> 2.) Other issue is regarding using clk_set_parent directly during clk_peripheral
> restore is clk_core_set_parent checks new parent with current parent and if its
> same, it just returns as success which is good in normal operation.
>
> But during restore, we can't use clk_set_parent as new parent is from
> clk_get_parent on restore and this is same as cached parent.
>
> So clk_set_parent returns 0 but acutal register value for clk source is different
> as it gets reset on SC7 entry/exit and to restore need to invoke mux_ops
> set_parent with parent_index.
>
> So this need parent index for cached parent and without using context variable to
> store this, need an API like you were originally suggesting for get_parent_index
> to get parent index for the specified parent clk_hw.
>
> As we decided not to use save/restore for clk_mux ops as its generic for other
> drivers, looks like we need get_parent_index API to use for restoring peripheral
> source and use this with clk_mux_ops set_parent.
>
> clk core driver already has clk_fetch_parent_index but is it OK to export this?
>
> Otherwise, will create separate API in clk driver which returns parent index from
> parent clk_hw by using this existing clk_fetch_parent_index so this API can be
> used by other drivers.
The clk_fetch_parent_index can't be used directly as you can see because it uses
clk_core which is internal to clk.c, you'll need to make a wrapper for getting the
cached index.
Something like this:
int clk_hw_get_parent_index(struct clk_hw *hw, struct *parent_hw)
{
if (!hw || !parent_hw)
return -EINVAL;
return clk_fetch_parent_index(hw->core, parent_hw->core);
}
^ permalink raw reply
* Re: [PATCH v7 07/20] clk: tegra: clk-periph: Add save and restore support
From: Dmitry Osipenko @ 2019-08-04 12:31 UTC (permalink / raw)
To: Sowjanya Komatineni, thierry.reding, jonathanh, tglx, jason,
marc.zyngier, linus.walleij, stefan, mark.rutland
Cc: pdeschrijver, pgaikwad, sboyd, linux-clk, linux-gpio, jckuo,
josephl, talho, linux-tegra, linux-kernel, mperttunen, spatra,
robh+dt, devicetree
In-Reply-To: <2eab4f34-34be-e317-05bb-37749f2ef792@gmail.com>
04.08.2019 15:24, Dmitry Osipenko пишет:
> 04.08.2019 2:44, Sowjanya Komatineni пишет:
>>
>> On 8/3/19 10:01 AM, Sowjanya Komatineni wrote:
>>>
>>> On 8/3/19 3:33 AM, Dmitry Osipenko wrote:
>>>> 03.08.2019 2:51, Sowjanya Komatineni пишет:
>>>>> On 8/2/19 2:15 PM, Dmitry Osipenko wrote:
>>>>>> 02.08.2019 23:32, Sowjanya Komatineni пишет:
>>>>>>> On 8/2/19 1:17 PM, Dmitry Osipenko wrote:
>>>>>>>> 02.08.2019 23:13, Dmitry Osipenko пишет:
>>>>>>>>> 02.08.2019 21:33, Sowjanya Komatineni пишет:
>>>>>>>>>> On 8/2/19 5:38 AM, Dmitry Osipenko wrote:
>>>>>>>>>>> 02.08.2019 2:49, Sowjanya Komatineni пишет:
>>>>>>>>>>>> On 8/1/19 4:19 PM, Sowjanya Komatineni wrote:
>>>>>>>>>>>>> On 8/1/19 2:30 PM, Sowjanya Komatineni wrote:
>>>>>>>>>>>>>> On 8/1/19 1:54 PM, Dmitry Osipenko wrote:
>>>>>>>>>>>>>>> 01.08.2019 23:31, Sowjanya Komatineni пишет:
>>>>>>>>>>>>>>>> On 8/1/19 1:17 PM, Dmitry Osipenko wrote:
>>>>>>>>>>>>>>>>> 01.08.2019 22:42, Sowjanya Komatineni пишет:
>>>>>>>>>>>>>>>>>> On 8/1/19 12:00 PM, Dmitry Osipenko wrote:
>>>>>>>>>>>>>>>>>>> 01.08.2019 20:58, Sowjanya Komatineni пишет:
>>>>>>>>>>>>>>>>>>>> On 7/31/19 4:09 PM, Sowjanya Komatineni wrote:
>>>>>>>>>>>>>>>>>>>>> On 7/31/19 3:44 AM, Dmitry Osipenko wrote:
>>>>>>>>>>>>>>>>>>>>>> 31.07.2019 12:50, Dmitry Osipenko пишет:
>>>>>>>>>>>>>>>>>>>>>>> 31.07.2019 3:20, Sowjanya Komatineni пишет:
>>>>>>>>>>>>>>>>>>>>>>>> This patch implements save and restore context for
>>>>>>>>>>>>>>>>>>>>>>>> peripheral
>>>>>>>>>>>>>>>>>>>>>>>> fixed
>>>>>>>>>>>>>>>>>>>>>>>> clock ops, peripheral gate clock ops, sdmmc mux clock
>>>>>>>>>>>>>>>>>>>>>>>> ops, and
>>>>>>>>>>>>>>>>>>>>>>>> peripheral clock ops.
>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>> During system suspend, core power goes off and
>>>>>>>>>>>>>>>>>>>>>>>> looses the
>>>>>>>>>>>>>>>>>>>>>>>> settings
>>>>>>>>>>>>>>>>>>>>>>>> of the Tegra CAR controller registers.
>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>> So during suspend entry clock and reset state of
>>>>>>>>>>>>>>>>>>>>>>>> peripherals is
>>>>>>>>>>>>>>>>>>>>>>>> saved
>>>>>>>>>>>>>>>>>>>>>>>> and on resume they are restored to have clocks back to
>>>>>>>>>>>>>>>>>>>>>>>> same
>>>>>>>>>>>>>>>>>>>>>>>> rate and
>>>>>>>>>>>>>>>>>>>>>>>> state as before suspend.
>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>> Acked-by: Thierry Reding <treding@nvidia.com>
>>>>>>>>>>>>>>>>>>>>>>>> Signed-off-by: Sowjanya Komatineni
>>>>>>>>>>>>>>>>>>>>>>>> <skomatineni@nvidia.com>
>>>>>>>>>>>>>>>>>>>>>>>> ---
>>>>>>>>>>>>>>>>>>>>>>>> drivers/clk/tegra/clk-periph-fixed.c | 33
>>>>>>>>>>>>>>>>>>>>>>>> ++++++++++++++++++++++++++++++++
>>>>>>>>>>>>>>>>>>>>>>>> drivers/clk/tegra/clk-periph-gate.c | 34
>>>>>>>>>>>>>>>>>>>>>>>> +++++++++++++++++++++++++++++++++
>>>>>>>>>>>>>>>>>>>>>>>> drivers/clk/tegra/clk-periph.c | 37
>>>>>>>>>>>>>>>>>>>>>>>> ++++++++++++++++++++++++++++++++++++
>>>>>>>>>>>>>>>>>>>>>>>> drivers/clk/tegra/clk-sdmmc-mux.c | 28
>>>>>>>>>>>>>>>>>>>>>>>> +++++++++++++++++++++++++++
>>>>>>>>>>>>>>>>>>>>>>>> drivers/clk/tegra/clk.h | 6 ++++++
>>>>>>>>>>>>>>>>>>>>>>>> 5 files changed, 138 insertions(+)
>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>> diff --git a/drivers/clk/tegra/clk-periph-fixed.c
>>>>>>>>>>>>>>>>>>>>>>>> b/drivers/clk/tegra/clk-periph-fixed.c
>>>>>>>>>>>>>>>>>>>>>>>> index c088e7a280df..21b24530fa00 100644
>>>>>>>>>>>>>>>>>>>>>>>> --- a/drivers/clk/tegra/clk-periph-fixed.c
>>>>>>>>>>>>>>>>>>>>>>>> +++ b/drivers/clk/tegra/clk-periph-fixed.c
>>>>>>>>>>>>>>>>>>>>>>>> @@ -60,11 +60,44 @@
>>>>>>>>>>>>>>>>>>>>>>>> tegra_clk_periph_fixed_recalc_rate(struct
>>>>>>>>>>>>>>>>>>>>>>>> clk_hw *hw,
>>>>>>>>>>>>>>>>>>>>>>>> return (unsigned long)rate;
>>>>>>>>>>>>>>>>>>>>>>>> }
>>>>>>>>>>>>>>>>>>>>>>>> +static int
>>>>>>>>>>>>>>>>>>>>>>>> tegra_clk_periph_fixed_save_context(struct
>>>>>>>>>>>>>>>>>>>>>>>> clk_hw
>>>>>>>>>>>>>>>>>>>>>>>> *hw)
>>>>>>>>>>>>>>>>>>>>>>>> +{
>>>>>>>>>>>>>>>>>>>>>>>> + struct tegra_clk_periph_fixed *fixed =
>>>>>>>>>>>>>>>>>>>>>>>> to_tegra_clk_periph_fixed(hw);
>>>>>>>>>>>>>>>>>>>>>>>> + u32 mask = 1 << (fixed->num % 32);
>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>> + fixed->enb_ctx = readl_relaxed(fixed->base +
>>>>>>>>>>>>>>>>>>>>>>>> fixed->regs->enb_reg) &
>>>>>>>>>>>>>>>>>>>>>>>> + mask;
>>>>>>>>>>>>>>>>>>>>>>>> + fixed->rst_ctx = readl_relaxed(fixed->base +
>>>>>>>>>>>>>>>>>>>>>>>> fixed->regs->rst_reg) &
>>>>>>>>>>>>>>>>>>>>>>>> + mask;
>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>> + return 0;
>>>>>>>>>>>>>>>>>>>>>>>> +}
>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>> +static void
>>>>>>>>>>>>>>>>>>>>>>>> tegra_clk_periph_fixed_restore_context(struct
>>>>>>>>>>>>>>>>>>>>>>>> clk_hw
>>>>>>>>>>>>>>>>>>>>>>>> *hw)
>>>>>>>>>>>>>>>>>>>>>>>> +{
>>>>>>>>>>>>>>>>>>>>>>>> + struct tegra_clk_periph_fixed *fixed =
>>>>>>>>>>>>>>>>>>>>>>>> to_tegra_clk_periph_fixed(hw);
>>>>>>>>>>>>>>>>>>>>>>>> + u32 mask = 1 << (fixed->num % 32);
>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>> + if (fixed->enb_ctx)
>>>>>>>>>>>>>>>>>>>>>>>> + writel_relaxed(mask, fixed->base +
>>>>>>>>>>>>>>>>>>>>>>>> fixed->regs->enb_set_reg);
>>>>>>>>>>>>>>>>>>>>>>>> + else
>>>>>>>>>>>>>>>>>>>>>>>> + writel_relaxed(mask, fixed->base +
>>>>>>>>>>>>>>>>>>>>>>>> fixed->regs->enb_clr_reg);
>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>> + udelay(2);
>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>> + if (!fixed->rst_ctx) {
>>>>>>>>>>>>>>>>>>>>>>>> + udelay(5); /* reset propogation delay */
>>>>>>>>>>>>>>>>>>>>>>>> + writel_relaxed(mask, fixed->base +
>>>>>>>>>>>>>>>>>>>>>>>> fixed->regs->rst_reg);
>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>> +}
>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>> static const struct clk_ops
>>>>>>>>>>>>>>>>>>>>>>>> tegra_clk_periph_fixed_ops
>>>>>>>>>>>>>>>>>>>>>>>> = {
>>>>>>>>>>>>>>>>>>>>>>>> .is_enabled =
>>>>>>>>>>>>>>>>>>>>>>>> tegra_clk_periph_fixed_is_enabled,
>>>>>>>>>>>>>>>>>>>>>>>> .enable = tegra_clk_periph_fixed_enable,
>>>>>>>>>>>>>>>>>>>>>>>> .disable = tegra_clk_periph_fixed_disable,
>>>>>>>>>>>>>>>>>>>>>>>> .recalc_rate =
>>>>>>>>>>>>>>>>>>>>>>>> tegra_clk_periph_fixed_recalc_rate,
>>>>>>>>>>>>>>>>>>>>>>>> + .save_context =
>>>>>>>>>>>>>>>>>>>>>>>> tegra_clk_periph_fixed_save_context,
>>>>>>>>>>>>>>>>>>>>>>>> + .restore_context =
>>>>>>>>>>>>>>>>>>>>>>>> tegra_clk_periph_fixed_restore_context,
>>>>>>>>>>>>>>>>>>>>>>>> };
>>>>>>>>>>>>>>>>>>>>>>>> struct clk
>>>>>>>>>>>>>>>>>>>>>>>> *tegra_clk_register_periph_fixed(const
>>>>>>>>>>>>>>>>>>>>>>>> char
>>>>>>>>>>>>>>>>>>>>>>>> *name,
>>>>>>>>>>>>>>>>>>>>>>>> diff --git a/drivers/clk/tegra/clk-periph-gate.c
>>>>>>>>>>>>>>>>>>>>>>>> b/drivers/clk/tegra/clk-periph-gate.c
>>>>>>>>>>>>>>>>>>>>>>>> index 4b31beefc9fc..6ba5b08e0787 100644
>>>>>>>>>>>>>>>>>>>>>>>> --- a/drivers/clk/tegra/clk-periph-gate.c
>>>>>>>>>>>>>>>>>>>>>>>> +++ b/drivers/clk/tegra/clk-periph-gate.c
>>>>>>>>>>>>>>>>>>>>>>>> @@ -25,6 +25,8 @@ static
>>>>>>>>>>>>>>>>>>>>>>>> DEFINE_SPINLOCK(periph_ref_lock);
>>>>>>>>>>>>>>>>>>>>>>>> #define read_rst(gate) \
>>>>>>>>>>>>>>>>>>>>>>>> readl_relaxed(gate->clk_base +
>>>>>>>>>>>>>>>>>>>>>>>> (gate->regs->rst_reg))
>>>>>>>>>>>>>>>>>>>>>>>> +#define write_rst_set(val, gate) \
>>>>>>>>>>>>>>>>>>>>>>>> + writel_relaxed(val, gate->clk_base +
>>>>>>>>>>>>>>>>>>>>>>>> (gate->regs->rst_set_reg))
>>>>>>>>>>>>>>>>>>>>>>>> #define write_rst_clr(val, gate) \
>>>>>>>>>>>>>>>>>>>>>>>> writel_relaxed(val, gate->clk_base +
>>>>>>>>>>>>>>>>>>>>>>>> (gate->regs->rst_clr_reg))
>>>>>>>>>>>>>>>>>>>>>>>> @@ -110,10 +112,42 @@ static void
>>>>>>>>>>>>>>>>>>>>>>>> clk_periph_disable(struct
>>>>>>>>>>>>>>>>>>>>>>>> clk_hw *hw)
>>>>>>>>>>>>>>>>>>>>>>>> spin_unlock_irqrestore(&periph_ref_lock, flags);
>>>>>>>>>>>>>>>>>>>>>>>> }
>>>>>>>>>>>>>>>>>>>>>>>> +static int clk_periph_gate_save_context(struct
>>>>>>>>>>>>>>>>>>>>>>>> clk_hw
>>>>>>>>>>>>>>>>>>>>>>>> *hw)
>>>>>>>>>>>>>>>>>>>>>>>> +{
>>>>>>>>>>>>>>>>>>>>>>>> + struct tegra_clk_periph_gate *gate =
>>>>>>>>>>>>>>>>>>>>>>>> to_clk_periph_gate(hw);
>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>> + gate->clk_state_ctx = read_enb(gate) &
>>>>>>>>>>>>>>>>>>>>>>>> periph_clk_to_bit(gate);
>>>>>>>>>>>>>>>>>>>>>>>> + gate->rst_state_ctx = read_rst(gate) &
>>>>>>>>>>>>>>>>>>>>>>>> periph_clk_to_bit(gate);
>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>> + return 0;
>>>>>>>>>>>>>>>>>>>>>>>> +}
>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>> +static void clk_periph_gate_restore_context(struct
>>>>>>>>>>>>>>>>>>>>>>>> clk_hw
>>>>>>>>>>>>>>>>>>>>>>>> *hw)
>>>>>>>>>>>>>>>>>>>>>>>> +{
>>>>>>>>>>>>>>>>>>>>>>>> + struct tegra_clk_periph_gate *gate =
>>>>>>>>>>>>>>>>>>>>>>>> to_clk_periph_gate(hw);
>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>> + if (gate->clk_state_ctx)
>>>>>>>>>>>>>>>>>>>>>>>> + write_enb_set(periph_clk_to_bit(gate), gate);
>>>>>>>>>>>>>>>>>>>>>>>> + else
>>>>>>>>>>>>>>>>>>>>>>>> + write_enb_clr(periph_clk_to_bit(gate), gate);
>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>> + udelay(5);
>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>> + if (!(gate->flags & TEGRA_PERIPH_NO_RESET) &&
>>>>>>>>>>>>>>>>>>>>>>>> + !(gate->flags & TEGRA_PERIPH_MANUAL_RESET)) {
>>>>>>>>>>>>>>>>>>>>>>>> + if (gate->rst_state_ctx)
>>>>>>>>>>>>>>>>>>>>>>>> + write_rst_set(periph_clk_to_bit(gate), gate);
>>>>>>>>>>>>>>>>>>>>>>>> + else
>>>>>>>>>>>>>>>>>>>>>>>> + write_rst_clr(periph_clk_to_bit(gate), gate);
>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>> +}
>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>> const struct clk_ops
>>>>>>>>>>>>>>>>>>>>>>>> tegra_clk_periph_gate_ops = {
>>>>>>>>>>>>>>>>>>>>>>>> .is_enabled = clk_periph_is_enabled,
>>>>>>>>>>>>>>>>>>>>>>>> .enable = clk_periph_enable,
>>>>>>>>>>>>>>>>>>>>>>>> .disable = clk_periph_disable,
>>>>>>>>>>>>>>>>>>>>>>>> + .save_context = clk_periph_gate_save_context,
>>>>>>>>>>>>>>>>>>>>>>>> + .restore_context =
>>>>>>>>>>>>>>>>>>>>>>>> clk_periph_gate_restore_context,
>>>>>>>>>>>>>>>>>>>>>>>> };
>>>>>>>>>>>>>>>>>>>>>>>> struct clk
>>>>>>>>>>>>>>>>>>>>>>>> *tegra_clk_register_periph_gate(const
>>>>>>>>>>>>>>>>>>>>>>>> char *name,
>>>>>>>>>>>>>>>>>>>>>>>> diff --git a/drivers/clk/tegra/clk-periph.c
>>>>>>>>>>>>>>>>>>>>>>>> b/drivers/clk/tegra/clk-periph.c
>>>>>>>>>>>>>>>>>>>>>>>> index 58437da25156..06fb62955768 100644
>>>>>>>>>>>>>>>>>>>>>>>> --- a/drivers/clk/tegra/clk-periph.c
>>>>>>>>>>>>>>>>>>>>>>>> +++ b/drivers/clk/tegra/clk-periph.c
>>>>>>>>>>>>>>>>>>>>>>>> @@ -99,6 +99,37 @@ static void
>>>>>>>>>>>>>>>>>>>>>>>> clk_periph_disable(struct
>>>>>>>>>>>>>>>>>>>>>>>> clk_hw
>>>>>>>>>>>>>>>>>>>>>>>> *hw)
>>>>>>>>>>>>>>>>>>>>>>>> gate_ops->disable(gate_hw);
>>>>>>>>>>>>>>>>>>>>>>>> }
>>>>>>>>>>>>>>>>>>>>>>>> +static int clk_periph_save_context(struct
>>>>>>>>>>>>>>>>>>>>>>>> clk_hw *hw)
>>>>>>>>>>>>>>>>>>>>>>>> +{
>>>>>>>>>>>>>>>>>>>>>>>> + struct tegra_clk_periph *periph =
>>>>>>>>>>>>>>>>>>>>>>>> to_clk_periph(hw);
>>>>>>>>>>>>>>>>>>>>>>>> + const struct clk_ops *gate_ops = periph->gate_ops;
>>>>>>>>>>>>>>>>>>>>>>>> + struct clk_hw *gate_hw = &periph->gate.hw;
>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>> + if (!(periph->gate.flags & TEGRA_PERIPH_NO_GATE))
>>>>>>>>>>>>>>>>>>>>>>>> + gate_ops->save_context(gate_hw);
>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>> + periph->parent_ctx = clk_periph_get_parent(hw);
>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>> + return 0;
>>>>>>>>>>>>>>>>>>>>>>>> +}
>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>> +static void clk_periph_restore_context(struct clk_hw
>>>>>>>>>>>>>>>>>>>>>>>> *hw)
>>>>>>>>>>>>>>>>>>>>>>>> +{
>>>>>>>>>>>>>>>>>>>>>>>> + struct tegra_clk_periph *periph =
>>>>>>>>>>>>>>>>>>>>>>>> to_clk_periph(hw);
>>>>>>>>>>>>>>>>>>>>>>>> + const struct clk_ops *gate_ops = periph->gate_ops;
>>>>>>>>>>>>>>>>>>>>>>>> + struct clk_hw *gate_hw = &periph->gate.hw;
>>>>>>>>>>>>>>>>>>>>>>>> + const struct clk_ops *div_ops = periph->div_ops;
>>>>>>>>>>>>>>>>>>>>>>>> + struct clk_hw *div_hw = &periph->divider.hw;
>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>> + clk_periph_set_parent(hw, periph->parent_ctx);
>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>> + if (!(periph->gate.flags & TEGRA_PERIPH_NO_DIV))
>>>>>>>>>>>>>>>>>>>>>>>> + div_ops->restore_context(div_hw);
>>>>>>>>>>>>>>>>>>>>>>> Could you please point to where the divider's
>>>>>>>>>>>>>>>>>>>>>>> save_context()
>>>>>>>>>>>>>>>>>>>>>>> happens?
>>>>>>>>>>>>>>>>>>>>>>> Because I can't see it.
>>>>>>>>>>>>>>>>>>>>>> Ah, I now see that there is no need to save the dividers
>>>>>>>>>>>>>>>>>>>>>> context
>>>>>>>>>>>>>>>>>>>>>> because
>>>>>>>>>>>>>>>>>>>>>> clk itself has enough info that is needed for the
>>>>>>>>>>>>>>>>>>>>>> context's
>>>>>>>>>>>>>>>>>>>>>> restoring
>>>>>>>>>>>>>>>>>>>>>> (like I pointed in the review to v6).
>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>> Looks like you could also implement a new
>>>>>>>>>>>>>>>>>>>>>> clk_hw_get_parent_index()
>>>>>>>>>>>>>>>>>>>>>> generic helper to get the index instead of storing it
>>>>>>>>>>>>>>>>>>>>>> manually.
>>>>>>>>>>>>>>>>>>>>> clk_periph_get_parent basically invokes existing
>>>>>>>>>>>>>>>>>>>>> clk_mux_ops
>>>>>>>>>>>>>>>>>>>>> get_parent() which is then saved in tegra_clk_periph.
>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>> All existing drivers are using directly get_parent() from
>>>>>>>>>>>>>>>>>>>>> clk_mux
>>>>>>>>>>>>>>>>>>>>> which actually gets index from the register read.
>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>> To have this more generic w.r.t save/restore context
>>>>>>>>>>>>>>>>>>>>> point of
>>>>>>>>>>>>>>>>>>>>> view,
>>>>>>>>>>>>>>>>>>>>> probably instead of implementing new get_parent_index
>>>>>>>>>>>>>>>>>>>>> helper,
>>>>>>>>>>>>>>>>>>>>> I think
>>>>>>>>>>>>>>>>>>>>> its better to implement save_context and
>>>>>>>>>>>>>>>>>>>>> restore_context to
>>>>>>>>>>>>>>>>>>>>> clk_mux_ops along with creating parent_index field into
>>>>>>>>>>>>>>>>>>>>> clk_mux to
>>>>>>>>>>>>>>>>>>>>> cache index during set_parent.
>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>> So we just need to invoke mux_ops save_context and
>>>>>>>>>>>>>>>>>>>>> restore_context.
>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>> I hope its ok to add save/restore context to clk_mux_ops
>>>>>>>>>>>>>>>>>>>> to be
>>>>>>>>>>>>>>>>>>>> more
>>>>>>>>>>>>>>>>>>>> generic w.r.t save/restore context rather than
>>>>>>>>>>>>>>>>>>>> get_parent_index
>>>>>>>>>>>>>>>>>>>> API.
>>>>>>>>>>>>>>>>>>>> Please confirm if you agree.
>>>>>>>>>>>>>>>>>>> Sounds like a good idea. I see that there is a 'restoring'
>>>>>>>>>>>>>>>>>>> helper for
>>>>>>>>>>>>>>>>>>> the generic clk_gate, seems something similar could be done
>>>>>>>>>>>>>>>>>>> for the
>>>>>>>>>>>>>>>>>>> clk_mux. And looks like anyway you'll need to associate the
>>>>>>>>>>>>>>>>>>> parent
>>>>>>>>>>>>>>>>>>> clock
>>>>>>>>>>>>>>>>>>> with the hw index in order to restore the muxing.
>>>>>>>>>>>>>>>>>> by 'restoring' helper for generic clk_gate, are you
>>>>>>>>>>>>>>>>>> referring to
>>>>>>>>>>>>>>>>>> clk_gate_restore_context API?
>>>>>>>>>>>>>>>>> Yes.
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> clk_gate_restore_context is API that's any clk drivers can
>>>>>>>>>>>>>>>>>> use for
>>>>>>>>>>>>>>>>>> clk_gate operation restore for custom gate clk_ops.
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> But clk-periph is directly using generic clk_mux ops from
>>>>>>>>>>>>>>>>>> clk_mux
>>>>>>>>>>>>>>>>>> so I
>>>>>>>>>>>>>>>>>> think we should add .restore_context to clk_mux_ops and then
>>>>>>>>>>>>>>>>>> during
>>>>>>>>>>>>>>>>>> clk-periph restore need to invoke mux_ops->restore_context.
>>>>>>>>>>>>>>>>> I'm not sure whether it will be good for every driver that
>>>>>>>>>>>>>>>>> uses
>>>>>>>>>>>>>>>>> generic
>>>>>>>>>>>>>>>>> clk_mux ops. Should be more flexible to have a generic helper
>>>>>>>>>>>>>>>>> function
>>>>>>>>>>>>>>>>> that any driver could use in order to restore the clock's
>>>>>>>>>>>>>>>>> parent.
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>> The clk-periph restoring also includes case of combining
>>>>>>>>>>>>>>>>> divider
>>>>>>>>>>>>>>>>> and
>>>>>>>>>>>>>>>>> parent restoring, so generic helper could be useful in that
>>>>>>>>>>>>>>>>> case
>>>>>>>>>>>>>>>>> as well.
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>> It also looks like you could actually use the
>>>>>>>>>>>>>>>>> clk_gate_restore_context()
>>>>>>>>>>>>>>>>> instead of manually saving the clock's enable-state, couldn't
>>>>>>>>>>>>>>>>> you?
>>>>>>>>>>>>>>>> ok for clk_mux, can add generic clk_mux_restore_context API
>>>>>>>>>>>>>>>> rather
>>>>>>>>>>>>>>>> than
>>>>>>>>>>>>>>>> using restore_context in clk_ops and will invoke that during
>>>>>>>>>>>>>>>> clk_periph
>>>>>>>>>>>>>>>> restore.
>>>>>>>>>>>>>>>>
>>>>>>>>>>>> digging thru looks like for clk_periph source restore instead of
>>>>>>>>>>>> clk_mux_restore_context, i can directly do clk_hw_get_parent and
>>>>>>>>>>>> clk_set_parent with mux_hw as they invoke mux_ops get/set parent
>>>>>>>>>>>> anyway.
>>>>>>>>>>>> Will do this for periph clk mux
>>>>> Just to be clear, clk_mux don't have cached parent. get_parent is by
>>>>> register read. So, cant directly use get_parent and then set during
>>>>> restore.
>>>>>
>>>>> So will create both clk_mux_save/restore_context in generic clk driver
>>>>> and will invoke them during tegra peripheral clock suspend/resume.
>>>> Why MUX clock doesn't have a cached parent? What MUX clock you're
>>>> talking about?
>>>>
>>>> [snip]
>>>
>>> Please ignore got it.
>>>
>>> Will send next version after giving few more days for feedback.
>>>
>> Couple of issues:
>>
>> 1.) I see clk-tegra-periph driver periph_clks init_data entries for some
>> peripherals are not correct for Tegra 114 and later chips.
>>
>> Eg I2C TEGRA_INIT_DATA_TABLE entries in clk-tegra-periph are used for all Tegra
>> chipsets currently in the driver.
>>
>> These entries are using MUX shift of 30 and MUX mask only for 2 bits which is
>> correct for T30 and prior.
>> But for later Tegra chips, it should be MUX shift 29 and MASK(3).
>>
>> Also, I2C parent idx entries in mux_pllp_clkm_idx are different from Tegra114
>> onwards.
>>
>> As we are using only PLLP and CLKM sources only for I2C, their corresponding mux
>> values from register spec by using upper 2 bits for T114 onwards match actual 2
>> bits of MUX value on T30 and prior.
>>
>> Not sure if this something known pending to port actual clock MUX table changes
>> for Tegra114 onwards?
>>
>> Or
>>
>> Are we purposely using upper 2 bits only for clock source for T114 and later as
>> the upper 2 bit values of the limited clock source we are using match with
>> previous Tegra peripheral clock source mux values?
>
> The actual hardware values are compatible on all Tegra SoCs and PLLC2 and PLLC3
> are just unused on T114+, so should be okay.
>
>> Peter/Thierry, Can you please help comment on this?
>>
>>
>> 2.) Other issue is regarding using clk_set_parent directly during clk_peripheral
>> restore is clk_core_set_parent checks new parent with current parent and if its
>> same, it just returns as success which is good in normal operation.
>>
>> But during restore, we can't use clk_set_parent as new parent is from
>> clk_get_parent on restore and this is same as cached parent.
>>
>> So clk_set_parent returns 0 but acutal register value for clk source is different
>> as it gets reset on SC7 entry/exit and to restore need to invoke mux_ops
>> set_parent with parent_index.
>>
>> So this need parent index for cached parent and without using context variable to
>> store this, need an API like you were originally suggesting for get_parent_index
>> to get parent index for the specified parent clk_hw.
>>
>> As we decided not to use save/restore for clk_mux ops as its generic for other
>> drivers, looks like we need get_parent_index API to use for restoring peripheral
>> source and use this with clk_mux_ops set_parent.
>>
>> clk core driver already has clk_fetch_parent_index but is it OK to export this?
>>
>> Otherwise, will create separate API in clk driver which returns parent index from
>> parent clk_hw by using this existing clk_fetch_parent_index so this API can be
>> used by other drivers.
Actually, you probably meant exactly the same what I wrote below. So
yes, it should be good to extend the CCF API since likely that this case
will be useful for other drivers as well.
> The clk_fetch_parent_index can't be used directly as you can see because it uses
> clk_core which is internal to clk.c, you'll need to make a wrapper for getting the
> cached index.
>
> Something like this:
>
> int clk_hw_get_parent_index(struct clk_hw *hw, struct *parent_hw)
> {
> if (!hw || !parent_hw)
> return -EINVAL;
>
> return clk_fetch_parent_index(hw->core, parent_hw->core);
> }
>
^ permalink raw reply
* Re: [RFC PATCH 1/2] dt-bindings: net: macb: Add new property for PS SGMII only
From: Andrew Lunn @ 2019-08-04 14:56 UTC (permalink / raw)
To: Harini Katakam
Cc: nicolas.ferre, davem, claudiu.beznea, robh+dt, mark.rutland,
netdev, linux-kernel, michal.simek, harinikatakamlinux,
devicetree
In-Reply-To: <1564566033-676-2-git-send-email-harini.katakam@xilinx.com>
On Wed, Jul 31, 2019 at 03:10:32PM +0530, Harini Katakam wrote:
> Add a new property to indicate when PS SGMII is used with NO
> external PHY on board.
Hi Harini
What exactly is you use case? Are you connecting to a Ethernet switch?
To an SFP cage with a copper module?
Andrew
^ permalink raw reply
* Re: [PATCH] ARM: dts: meson8b: add ethernet fifo sizes
From: Aymeric @ 2019-08-04 19:38 UTC (permalink / raw)
To: Martin Blumenstingl, Jerome Brunet
Cc: Kevin Hilman, devicetree, linux-kernel, linux-amlogic
In-Reply-To: <CAFBinCBefuCvTL0E_zf=EQDLyTjE5sQD-TkHNj2vQ2UOCsmtkA@mail.gmail.com>
Le 23/07/2019 à 21:56, Martin Blumenstingl a écrit :
> On Thu, Jul 18, 2019 at 11:36 AM Jerome Brunet <jbrunet@baylibre.com> wrote:
>> If unspecified in DT, the fifo sizes are not automatically detected by
>> the dwmac1000 dma driver and the reported fifo sizes default to 0.
>> Because of this, flow control will be turned off on the device.
>>
>> Add the fifo sizes provided by the datasheet in the SoC in DT so
>> flow control may be enabled if necessary.
>>
>> Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
> Reviewed-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
>
> I wonder if this "fixes" some of the performance issues on Odroid-C1
> testing this is now on my TODO-list for the weekend
Good! and maybe that will fix the stability issue I'm seeing when using
the board with a 1 gigabit link! (cf
http://lists.infradead.org/pipermail/linux-amlogic/2019-June/012341.html)
I'll try that asap on my board too :)
Thanks.
--
Aymeric
^ permalink raw reply
* Re: [PATCH v4 4/4] ARM: dts: aspeed: Add Mihawk BMC platform
From: Andrew Jeffery @ 2019-08-05 0:32 UTC (permalink / raw)
To: Ben Pai, Rob Herring, mark.rutland, Joel Stanley, devicetree,
linux-arm-kernel, linux-aspeed, linux-kernel
Cc: wangat
In-Reply-To: <20190802083736.26783-1-Ben_Pai@wistron.com>
On Fri, 2 Aug 2019, at 18:07, Ben Pai wrote:
> The Mihawk BMC is an ASPEED ast2500 based BMC that is part of an
> OpenPower Power9 server.
>
> Signed-off-by: Ben Pai <Ben_Pai@wistron.com>
Reviewed-by: Andrew Jeffery <andrew@aj.id.au>
^ permalink raw reply
* Re: [RFC-ish PATCH 00/17] Clean up ASPEED devicetree warnings
From: Andrew Jeffery @ 2019-08-05 0:48 UTC (permalink / raw)
To: Joel Stanley
Cc: Rob Herring, linux-aspeed, Mark Rutland, devicetree,
moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
linux-kernel@vger.kernel.org, Adriana Kobylak,
Alexander A. Filippov, Arnd Bergmann,
YangBrianC.W 楊嘉偉 TAO, Corey Minyard,
Greg Kroah-Hartman, Haiyue Wang, John Wang, Ken Chen,
Linus Walleij
In-Reply-To: <CACPK8Xc4Vigeu1B1Su5392BSCSKfoEDqt_tiDtgKmNH5ucAvAg@mail.gmail.com>
On Fri, 2 Aug 2019, at 15:21, Joel Stanley wrote:
> On Tue, 30 Jul 2019 at 01:09, Andrew Jeffery <andrew@aj.id.au> wrote:
>
> > > > The bang-for-buck is in fixing up the KCS bindings which removes all-but-two of
> > > > the remaining warnings (which we can't feasibly remove), but doing so forces
> > > > code changes (which I'd avoided up until this point).
> > > >
> > > > Reflecting broadly on the fixes, I think I've made a mistake way back by using
> > > > syscon/simple-mfds to expose the innards of the SCU and LPC controllers in the
> > > > devicetree. This series cleans up what's currently there, but I have half a
> > > > mind to rev the SCU and LPC bindings to not use simple-mfd and instead have a
> > > > driver implementation that uses `platform_device_register_full()` or similar to
> > > > deal with the mess.
> > > >
> > > > Rob - I'm looking for your thoughts here and on the series, I've never felt
> > > > entirely comfortable with what I cooked up. Your advice would be appreciated.
> > >
> > > The series generally looks fine to me from a quick scan. As far as
> > > dropping 'simple-mfd', having less fine grained description in DT is
> > > generally my preference. It comes down to whether what you have
> > > defined is maintainable. As most of it is just additions, I think what
> > > you have is fine. Maybe keep all this in mind for the next chip
> > > depending how the SCU and LPC change.
> >
> > Okay, I think the timing of that suggestion is good given where things are with
> > the AST2600. I'll keep that in mind.
> >
> > Consensus so far seems to be that the series is fine. I'll split it up and send out
> > the sub-series to the relevant lists with the acks accumulated here.
>
> The series look good. I suggest posting the KCS bindings and driver
> changes as their own series to go through the IPMI tree.
Yeah, that was the plan.
>
> Please add my tag to all the patches except the OCC one, which I need
> to do some investigation in to.
>
> Reviewed-by: Joel Stanley <joel@jms.id.au>
Thanks, will do.
>
> The others can go via the aspeed tree. Perhaps post them as their own
> series too so I don't get confused and apply the wrong ones. That way
> if Rob wants to send his reviewed-by he can.
SGTM.
Cheers,
Andrew
^ permalink raw reply
* [PATCH v2 1/1] arm64: dts: rockchip: Add support for TB-96AI board
From: Elon Zhang @ 2019-08-05 1:57 UTC (permalink / raw)
To: heiko, mark.rutland, robh+dt
Cc: devicetree, linux-kernel, Elon Zhang, linux-rockchip,
manivannan.sadhasivam, linux-arm-kernel
Add devicetree support for RK3399Pro TB-96AI board, one of
the 96Boards family.
The TB-96AI board is a 96Boards Compute SOM design, launched
by Linaro, Rockchip and Beiqicloud.
More information can be obtained from the following websites:
1.https://www.96boards.org/product/tb-96ai/
2.http://t.rock-chips.com/
3.http://www.beiqicloud.com/
This patch add basic node for the board and support booting up
to Fedora.
Signed-off-by: Elon Zhang <zhangzj@rock-chips.com>
---
changes since v1:
- remove needless node
- using a standard LED formats for 96Boards
arch/arm64/boot/dts/rockchip/Makefile | 1 +
.../boot/dts/rockchip/rk3399pro-tb-96ai.dts | 560 ++++++++++++++++++
2 files changed, 561 insertions(+)
create mode 100644 arch/arm64/boot/dts/rockchip/rk3399pro-tb-96ai.dts
diff --git a/arch/arm64/boot/dts/rockchip/Makefile b/arch/arm64/boot/dts/rockchip/Makefile
index 5f2687acbf94..3d6c8d4363b5 100644
--- a/arch/arm64/boot/dts/rockchip/Makefile
+++ b/arch/arm64/boot/dts/rockchip/Makefile
@@ -27,3 +27,4 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-rock960.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-rockpro64.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-sapphire.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-sapphire-excavator.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399pro-tb-96ai.dtb
diff --git a/arch/arm64/boot/dts/rockchip/rk3399pro-tb-96ai.dts b/arch/arm64/boot/dts/rockchip/rk3399pro-tb-96ai.dts
new file mode 100644
index 000000000000..767b37b854ba
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3399pro-tb-96ai.dts
@@ -0,0 +1,560 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd.
+ */
+
+/dts-v1/;
+#include "rk3399pro.dtsi"
+#include "rk3399-opp.dtsi"
+
+/ {
+ compatible = "beiqi,rk3399pro-tb-96ai", "rockchip,rk3399pro";
+
+ chosen {
+ stdout-path = "serial2:1500000n8";
+ };
+
+ xin32k: xin32k {
+ compatible = "fixed-clock";
+ clock-frequency = <32768>;
+ clock-output-names = "xin32k";
+ #clock-cells = <0>;
+ };
+
+ vcc5v0_sys: vccsys {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc5v0_sys";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&work_led1>,<&work_led2>,<&work_led3>;
+
+ work_led1 {
+ gpios = <&gpio2 5 GPIO_ACTIVE_HIGH>;
+ label = "system_work_led1";
+ retain-state-suspended;
+ };
+
+ work_led2 {
+ gpios = <&gpio2 4 GPIO_ACTIVE_HIGH>;
+ label = "system_work_led2";
+ retain-state-suspended;
+ };
+
+ work_led3 {
+ gpios = <&gpio2 3 GPIO_ACTIVE_HIGH>;
+ label = "system_work_led3";
+ retain-state-suspended;
+ };
+ };
+};
+
+&cpu_l0 {
+ cpu-supply = <&vdd_cpu_l>;
+};
+
+&cpu_l1 {
+ cpu-supply = <&vdd_cpu_l>;
+};
+
+&cpu_l2 {
+ cpu-supply = <&vdd_cpu_l>;
+};
+
+&cpu_l3 {
+ cpu-supply = <&vdd_cpu_l>;
+};
+
+&cpu_b0 {
+ cpu-supply = <&vdd_cpu_b>;
+};
+
+&cpu_b1 {
+ cpu-supply = <&vdd_cpu_b>;
+};
+
+&emmc_phy {
+ status = "okay";
+};
+
+&i2c0 {
+ status = "okay";
+ i2c-scl-rising-time-ns = <180>;
+ i2c-scl-falling-time-ns = <30>;
+ clock-frequency = <400000>;
+
+ rk809: pmic@20 {
+ compatible = "rockchip,rk809";
+ reg = <0x20>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <RK_PC2 IRQ_TYPE_LEVEL_LOW>;
+ pinctrl-names = "default", "pmic-sleep",
+ "pmic-power-off", "pmic-reset";
+ pinctrl-0 = <&pmic_int_l>;
+ pinctrl-1 = <&soc_slppin_slp>, <&rk809_slppin_slp>;
+ pinctrl-2 = <&soc_slppin_gpio>, <&rk809_slppin_pwrdn>;
+ pinctrl-3 = <&soc_slppin_gpio>,<&rk809_slppin_null>;
+ rockchip,system-power-controller;
+ pmic-reset-func = <1>;
+ wakeup-source;
+ #clock-cells = <1>;
+ clock-output-names = "rk808-clkout1", "rk808-clkout2";
+
+ vcc1-supply = <&vcc5v0_sys>;
+ vcc2-supply = <&vcc5v0_sys>;
+ vcc3-supply = <&vcc5v0_sys>;
+ vcc4-supply = <&vcc5v0_sys>;
+ vcc5-supply = <&vcc_buck5>;
+ vcc6-supply = <&vcc_buck5>;
+ vcc7-supply = <&vcc3v3_sys>;
+ vcc8-supply = <&vcc3v3_sys>;
+ vcc9-supply = <&vcc5v0_sys>;
+
+ pwrkey {
+ status = "okay";
+ };
+
+ rtc {
+ status = "okay";
+ };
+
+ pinctrl_rk8xx: pinctrl_rk8xx {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ rk809_slppin_null: rk809_slppin_null {
+ pins = "gpio_slp";
+ function = "pin_fun0";
+ };
+
+ rk809_slppin_slp: rk809_slppin_slp {
+ pins = "gpio_slp";
+ function = "pin_fun1";
+ };
+
+ rk809_slppin_pwrdn: rk809_slppin_pwrdn {
+ pins = "gpio_slp";
+ function = "pin_fun2";
+ };
+
+ rk809_slppin_rst: rk809_slppin_rst {
+ pins = "gpio_slp";
+ function = "pin_fun3";
+ };
+ };
+
+ regulators {
+ vdd_center: DCDC_REG1 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-initial-mode = <0x2>;
+ regulator-name = "vdd_center";
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <900000>;
+ };
+ };
+
+ vdd_cpu_l: DCDC_REG2 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-ramp-delay = <6001>;
+ regulator-initial-mode = <0x2>;
+ regulator-name = "vdd_cpu_l";
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_ddr: DCDC_REG3 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-name = "vcc_ddr";
+ regulator-initial-mode = <0x2>;
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ };
+ };
+
+ vcc3v3_sys: DCDC_REG4 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-initial-mode = <0x2>;
+ regulator-name = "vcc3v3_sys";
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <3300000>;
+ };
+ };
+
+ vcc_buck5: DCDC_REG5 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <2200000>;
+ regulator-max-microvolt = <2200000>;
+ regulator-name = "vcc_buck5";
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <2200000>;
+ };
+ };
+
+ vcca_0v9: LDO_REG1 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <900000>;
+ regulator-name = "vcca_0v9";
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_1v8: LDO_REG2 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+
+ regulator-name = "vcc_1v8";
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <1800000>;
+ };
+ };
+
+ vcc0v9_soc: LDO_REG3 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <900000>;
+
+ regulator-name = "vcc0v9_soc";
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <900000>;
+ };
+ };
+
+ vcca_1v8: LDO_REG4 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+
+ regulator-name = "vcca_1v8";
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd1v5_dvp: LDO_REG5 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1500000>;
+ regulator-max-microvolt = <1500000>;
+
+ regulator-name = "vdd1v5_dvp";
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_1v5: LDO_REG6 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1500000>;
+ regulator-max-microvolt = <1500000>;
+
+ regulator-name = "vcc_1v5";
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_3v0: LDO_REG7 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+
+ regulator-name = "vcc_3v0";
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vccio_sd: LDO_REG8 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+
+ regulator-name = "vccio_sd";
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <3300000>;
+ };
+ };
+
+ vcc_sd: LDO_REG9 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+
+ regulator-name = "vcc_sd";
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <3300000>;
+ };
+ };
+
+ vcc5v0_usb: SWITCH_REG1 {
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+
+ regulator-name = "vcc5v0_usb";
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vccio_3v3: SWITCH_REG2 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+
+ regulator-name = "vccio_3v3";
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+ };
+ };
+
+ vdd_cpu_b: regulator@1c {
+ compatible = "fcs,fan53555";
+ reg = <0x1c>;
+ vin-supply = <&vcc5v0_sys>;
+ pinctrl-0 = <&vsel1_gpio>;
+ vsel-gpios = <&gpio1 RK_PC1 GPIO_ACTIVE_HIGH>;
+ regulator-name = "vdd_cpu_b";
+ regulator-min-microvolt = <712500>;
+ regulator-max-microvolt = <1500000>;
+ regulator-ramp-delay = <2300>;
+ fcs,suspend-voltage-selector = <1>;
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-initial-state = <3>;
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_gpu: regulator@10 {
+ compatible = "fcs,fan53555";
+ status = "okay";
+ reg = <0x10>;
+ vin-supply = <&vcc5v0_sys>;
+ pinctrl-0 = <&vsel2_gpio>;
+ vsel-gpios = <&gpio1 RK_PB6 GPIO_ACTIVE_HIGH>;
+ regulator-name = "vdd_gpu";
+ regulator-min-microvolt = <735000>;
+ regulator-max-microvolt = <1400000>;
+ regulator-ramp-delay = <2300>;
+ fcs,suspend-voltage-selector = <1>;
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+};
+
+&i2c8 {
+ status = "okay";
+ i2c-scl-rising-time-ns = <345>;
+ i2c-scl-falling-time-ns = <11>;
+ clock-frequency = <100000>;
+};
+
+&io_domains {
+ status = "okay";
+ bt656-supply = <&vcca_1v8>; /* APIO2_VDD */
+ audio-supply = <&vcca_1v8>; /* APIO5_VDD */
+ sdmmc-supply = <&vccio_sd>; /* SDMMC0_VDD */
+ gpio1830-supply = <&vcc_1v8>; /* APIO4_VDD */
+};
+
+&pinctrl {
+ pinctrl-names = "default";
+ pinctrl-0 = <&npu_ref_clk>;
+
+ leds {
+ work_led1: work_led1 {
+ rockchip,pins =
+ <2 5 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ work_led2: work_led2 {
+ rockchip,pins =
+ <2 4 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ work_led3: work_led3 {
+ rockchip,pins =
+ <2 3 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ npu_clk {
+ npu_ref_clk: npu-ref-clk {
+ rockchip,pins =
+ <0 RK_PA2 1 &pcfg_pull_none>;
+ };
+ };
+
+ pmic {
+ pmic_int_l: pmic-int-l {
+ rockchip,pins =
+ <1 RK_PC2 0 &pcfg_pull_up>;
+ };
+
+ soc_slppin_gpio: soc-slppin-gpio {
+ rockchip,pins =
+ <1 RK_PA5 0 &pcfg_output_low>;
+ };
+
+ soc_slppin_slp: soc-slppin-slp {
+ rockchip,pins =
+ <1 RK_PA5 1 &pcfg_pull_down>;
+ };
+
+ vsel1_gpio: vsel1-gpio {
+ rockchip,pins =
+ <1 RK_PC1 0 &pcfg_pull_down>;
+ };
+
+ vsel2_gpio: vsel2-gpio {
+ rockchip,pins =
+ <1 RK_PB6 0 &pcfg_pull_down>;
+ };
+ };
+
+ usb3 {
+ usb3_host_en: usb3-host-en {
+ rockchip,pins =
+ <2 RK_PA2 RK_FUNC_GPIO &pcfg_output_high>;
+ };
+ };
+};
+
+&pmu_io_domains {
+ status = "okay";
+ pmu1830-supply = <&vcc_1v8>;
+};
+
+&pwm0 {
+ status = "okay";
+};
+
+&pwm2 {
+ status = "okay";
+};
+
+&saradc {
+ status = "okay";
+ vref-supply = <&vcc_1v8>;
+};
+
+&sdhci {
+ bus-width = <8>;
+ mmc-hs400-1_8v;
+ non-removable;
+ keep-power-in-suspend;
+ mmc-hs400-enhanced-strobe;
+ status = "okay";
+};
+
+&tcphy1 {
+ status = "okay";
+};
+
+&tsadc {
+ rockchip,hw-tshut-mode = <1>; /* tshut mode 0:CRU 1:GPIO */
+ rockchip,hw-tshut-polarity = <1>; /* tshut polarity 0:LOW 1:HIGH */
+ status = "okay";
+};
+
+&u2phy1 {
+ status = "okay";
+
+ u2phy1_otg: otg-port {
+ status = "okay";
+ };
+
+ u2phy1_host: host-port {
+ phy-supply = <&vcc5v0_usb>;
+ status = "okay";
+ };
+};
+
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_xfer &uart0_cts>;
+ status = "okay";
+};
+
+&uart2 {
+ status = "okay";
+};
+
+&uart4 {
+ status = "okay";
+};
+
+&usb_host0_ehci {
+ status = "okay";
+};
+
+&usb_host1_ehci {
+ status = "okay";
+};
+
+&usb_host0_ohci {
+ status = "okay";
+};
+
+&usb_host1_ohci {
+ status = "okay";
+};
+
+&usbdrd3_1 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb3_host_en>;
+};
+
+&usbdrd_dwc3_0 {
+ status = "okay";
+};
+
+&usbdrd_dwc3_1 {
+ snps,dis-u3-autosuspend-quirk;
+ status = "okay";
+};
+
--
2.17.1
^ permalink raw reply related
* Re: [PATCH v16 1/2] spi: Add Renesas R-Car Gen3 RPC-IF SPI controller driver
From: masonccyang @ 2019-08-05 2:00 UTC (permalink / raw)
To: Sergei Shtylyov
Cc: broonie, devicetree, Geert Uytterhoeven, Simon Horman, juliensu,
lee.jones, linux-kernel, linux-renesas-soc, linux-spi,
marek.vasut, mark.rutland, miquel.raynal, robh+dt
In-Reply-To: <3d01957a-7318-274f-f3d5-6cd00850511b@cogentembedded.com>
Hi Sergei,
> > Add a driver for Renesas R-Car Gen3 RPC-IF SPI controller.
> >
> > Signed-off-by: Mason Yang <masonccyang@mxic.com.tw>
> > Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
> [...]
> > diff --git a/drivers/spi/spi-renesas-rpc.c
b/drivers/spi/spi-renesas-rpc.c
> > new file mode 100644
> > index 0000000..648d14e
> > --- /dev/null
> > +++ b/drivers/spi/spi-renesas-rpc.c
> > @@ -0,0 +1,754 @@
> [...]
> > +static void rpc_spi_hw_init(struct rpc_spi *rpc)
> > +{
> > + //
> > + // NOTE: The 0x260 are undocumented bits, but they must be set.
> > + // RPC_PHYCNT_STRTIM is strobe timing adjustment bit,
> > + // 0x0 : the delay is biggest,
> > + // 0x1 : the delay is 2nd biggest,
> > + // On H3 ES1.x, the value should be 0, while on others,
> > + // the value should be 6.
> > + //
> > + regmap_write(rpc->regmap, RPC_PHYCNT, RPC_PHYCNT_CAL |
> > + RPC_PHYCNT_STRTIM(6) | 0x260);
> > +
> > + //
> > + // NOTE: The 0x1511144 are undocumented bits, but they must be set
> > + // for RPC_PHYOFFSET1.
> > + // The 0x31 are undocumented bits, but they must be set
> > + // for RPC_PHYOFFSET2.
> > + //
> > + regmap_write(rpc->regmap, RPC_PHYOFFSET1, RPC_PHYOFFSET1_DDRTMG(3)
|
> > + 0x1511144);
> > + regmap_write(rpc->regmap, RPC_PHYOFFSET2, 0x31 |
> > + RPC_PHYOFFSET2_OCTTMG(4));
> > + regmap_write(rpc->regmap, RPC_SSLDR, RPC_SSLDR_SPNDL(7) |
> > + RPC_SSLDR_SLNDL(7) | RPC_SSLDR_SCKDL(7));
> > + regmap_write(rpc->regmap, RPC_CMNCR, RPC_CMNCR_MD | RPC_CMNCR_SFDE
|
> > + RPC_CMNCR_MOIIO_HIZ | RPC_CMNCR_IOFV_HIZ |
> > + RPC_CMNCR_BSZ(0));
> > +}
> [...]
> > +static int rpc_spi_io_xfer(struct rpc_spi *rpc,
> > + const void *tx_buf, void *rx_buf)
> > +{
> [...]
> > +err_out:
> > + return reset_control_reset(rpc->rstc);
>
> Don't toy need to call rpc_spi_hw_init(( here? The reset would spoil
> the PHY/etc register setup otherwise...
ummm, will fix to
-------------------------------------->
ret = reset_control_reset(rpc->rstc);
rpc_spi_hw_init(rpc);
return ret;
--------------------------------------<
thanks for your review.
>
> [...]
>
> MBR, Sergei
best regards,
Mason
CONFIDENTIALITY NOTE:
This e-mail and any attachments may contain confidential information
and/or personal data, which is protected by applicable laws. Please be
reminded that duplication, disclosure, distribution, or use of this e-mail
(and/or its attachments) or any part thereof is prohibited. If you receive
this e-mail in error, please notify us immediately and delete this mail as
well as its attachment(s) from your system. In addition, please be
informed that collection, processing, and/or use of personal data is
prohibited unless expressly permitted by personal data protection laws.
Thank you for your attention and cooperation.
Macronix International Co., Ltd.
=====================================================================
============================================================================
CONFIDENTIALITY NOTE:
This e-mail and any attachments may contain confidential information and/or personal data, which is protected by applicable laws. Please be reminded that duplication, disclosure, distribution, or use of this e-mail (and/or its attachments) or any part thereof is prohibited. If you receive this e-mail in error, please notify us immediately and delete this mail as well as its attachment(s) from your system. In addition, please be informed that collection, processing, and/or use of personal data is prohibited unless expressly permitted by personal data protection laws. Thank you for your attention and cooperation.
Macronix International Co., Ltd.
=====================================================================
^ permalink raw reply
* Re: [PATCH v3 1/2] dt-bindings: mmc: Document Aspeed SD controller
From: Andrew Jeffery @ 2019-08-05 2:10 UTC (permalink / raw)
To: Rob Herring
Cc: linux-mmc, Ulf Hansson, Mark Rutland, Joel Stanley, Adrian Hunter,
devicetree,
moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
linux-aspeed, linux-kernel@vger.kernel.org, Ryan Chen
In-Reply-To: <CAL_Jsq+oZRREV=VjYUxT3WphOa5tBaF1pvS_JKSphBY=3XB5MA@mail.gmail.com>
On Fri, 2 Aug 2019, at 08:29, Rob Herring wrote:
> On Tue, Jul 30, 2019 at 12:23 AM Andrew Jeffery <andrew@aj.id.au> wrote:
> >
> > The ASPEED SD/SDIO/eMMC controller exposes two slots implementing the
> > SDIO Host Specification v2.00, with 1 or 4 bit data buses, or an 8 bit
> > data bus if only a single slot is enabled.
> >
> > Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
> >
> > ---
> > v3:
> > * Fix compatible enums
> > * Add AST2600 compatibles
> > * Describe #address-cells / #size-cells
> > ---
> > .../devicetree/bindings/mmc/aspeed,sdhci.yaml | 100 ++++++++++++++++++
> > 1 file changed, 100 insertions(+)
> > create mode 100644 Documentation/devicetree/bindings/mmc/aspeed,sdhci.yaml
> >
> > diff --git a/Documentation/devicetree/bindings/mmc/aspeed,sdhci.yaml b/Documentation/devicetree/bindings/mmc/aspeed,sdhci.yaml
> > new file mode 100644
> > index 000000000000..dd2a00c59641
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/mmc/aspeed,sdhci.yaml
> > @@ -0,0 +1,100 @@
> > +# SPDX-License-Identifier: GPL-2.0-or-later
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/mmc/aspeed,sdhci.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: ASPEED SD/SDIO/eMMC Controller
> > +
> > +maintainers:
> > + - Andrew Jeffery <andrew@aj.id.au>
> > + - Ryan Chen <ryanchen.aspeed@gmail.com>
> > +
> > +description: |+
> > + The ASPEED SD/SDIO/eMMC controller exposes two slots implementing the SDIO
> > + Host Specification v2.00, with 1 or 4 bit data buses, or an 8 bit data bus if
> > + only a single slot is enabled.
> > +
> > + The two slots are supported by a common configuration area. As the SDHCIs for
> > + the slots are dependent on the common configuration area, they are described
> > + as child nodes.
> > +
> > +properties:
> > + compatible:
> > + enum:
> > + - aspeed,ast2400-sd-controller
> > + - aspeed,ast2500-sd-controller
> > + - aspeed,ast2600-sd-controller
> > + reg:
> > + maxItems: 1
> > + description: Common configuration registers
> > + "#address-cells":
> > + const: 1
> > + "#size-cells":
> > + const: 1
> > + ranges: true
> > + clocks:
> > + maxItems: 1
> > + description: The SD/SDIO controller clock gate
> > +
> > +patternProperties:
> > + "^sdhci@[0-9a-f]+$":
>
> This should probably have:
>
> allOf:
> - $ref: mmc-controller.yaml
>
> Another new thing in 5.3. :)
Ack.
>
> > + type: object
> > + properties:
> > + compatible:
> > + enum:
> > + - aspeed,ast2400-sdhci
> > + - aspeed,ast2500-sdhci
> > + - aspeed,ast2600-sdhci
> > + reg:
> > + maxItems: 1
> > + description: The SDHCI registers
> > + clocks:
> > + maxItems: 1
> > + description: The SD bus clock
> > + interrupts:
> > + maxItems: 1
> > + description: The SD interrupt shared between both slots
> > + required:
> > + - compatible
> > + - reg
> > + - clocks
> > + - interrupts
> > +
> > +additionalProperties: false
> > +
> > +required:
> > + - compatible
> > + - reg
> > + - "#address-cells"
> > + - "#size-cells"
> > + - ranges
> > + - clocks
> > +
> > +examples:
> > + - |
> > + #include <dt-bindings/clock/aspeed-clock.h>
> > + sdc@1e740000 {
> > + compatible = "aspeed,ast2500-sd-controller";
> > + reg = <0x1e740000 0x100>;
> > + #address-cells = <1>;
> > + #size-cells = <1>;
> > + ranges = <0 0x1e740000 0x10000>;
> > + clocks = <&syscon ASPEED_CLK_GATE_SDCLK>;
> > +
> > + sdhci0: sdhci@100 {
> > + compatible = "aspeed,ast2500-sdhci";
> > + reg = <0x100 0x100>;
> > + interrupts = <26>;
> > + sdhci,auto-cmd12;
>
> Not documented. Maybe should be common, but there's only a few users.
I'll document it locally for the moment.
Cheers,
Andrew
^ permalink raw reply
* [PATCH v1 1/1] dt-bindings: Add Vendor prefix for Beiqi
From: Elon Zhang @ 2019-08-05 2:39 UTC (permalink / raw)
To: robh+dt, mark.rutland
Cc: manivannan.sadhasivam, linux-kernel, devicetree, luowz,
Elon Zhang
Add devicetree vendor prefix for Beiqi.
http://www.beiqicloud.com/
Signed-off-by: Elon Zhang <zhangzj@rock-chips.com>
---
Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
index 1acf806b62bf..1092360d8868 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
@@ -135,6 +135,8 @@ patternProperties:
description: Shenzhen AZW Technology Co., Ltd.
"^bananapi,.*":
description: BIPAI KEJI LIMITED
+ "^beiqi,.*":
+ description: Xiamen Beiqi Technology Co., Ltd.
"^bhf,.*":
description: Beckhoff Automation GmbH & Co. KG
"^bitmain,.*":
--
2.17.1
^ permalink raw reply related
* [PATCH v4 0/2] mmc: Add support for the ASPEED SD controller
From: Andrew Jeffery @ 2019-08-05 2:51 UTC (permalink / raw)
To: linux-mmc
Cc: Andrew Jeffery, ulf.hansson, robh+dt, mark.rutland, joel,
adrian.hunter, devicetree, linux-arm-kernel, linux-aspeed,
linux-kernel, ryanchen.aspeed
Hello,
v4 of the ASPEED SDHCI driver addresses Rob's comments on the binding, making
it utilise the new mmc-controller schema and describing the sdhci,auto-cmd12
property.
v3 can be found here:
http://patchwork.ozlabs.org/cover/1138793/
Please review!
Andrew
Andrew Jeffery (2):
dt-bindings: mmc: Document Aspeed SD controller
mmc: Add support for the ASPEED SD controller
.../devicetree/bindings/mmc/aspeed,sdhci.yaml | 105 ++++++
drivers/mmc/host/Kconfig | 12 +
drivers/mmc/host/Makefile | 1 +
drivers/mmc/host/sdhci-of-aspeed.c | 328 ++++++++++++++++++
4 files changed, 446 insertions(+)
create mode 100644 Documentation/devicetree/bindings/mmc/aspeed,sdhci.yaml
create mode 100644 drivers/mmc/host/sdhci-of-aspeed.c
--
2.20.1
^ permalink raw reply
* [PATCH v4 1/2] dt-bindings: mmc: Document Aspeed SD controller
From: Andrew Jeffery @ 2019-08-05 2:51 UTC (permalink / raw)
To: linux-mmc
Cc: Andrew Jeffery, ulf.hansson, robh+dt, mark.rutland, joel,
adrian.hunter, devicetree, linux-arm-kernel, linux-aspeed,
linux-kernel, ryanchen.aspeed
In-Reply-To: <20190805025155.9020-1-andrew@aj.id.au>
The ASPEED SD/SDIO/MMC controller exposes two slots implementing the
SDIO Host Specification v2.00, with 1 or 4 bit data buses, or an 8 bit
data bus if only a single slot is enabled.
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
---
v3:
* Make use of mmc-controller.yaml
* Document sdhci,auto-cmd12
v2:
* Fix compatible enums
* Add AST2600 compatibles
* Describe #address-cells / #size-cells
---
.../devicetree/bindings/mmc/aspeed,sdhci.yaml | 105 ++++++++++++++++++
1 file changed, 105 insertions(+)
create mode 100644 Documentation/devicetree/bindings/mmc/aspeed,sdhci.yaml
diff --git a/Documentation/devicetree/bindings/mmc/aspeed,sdhci.yaml b/Documentation/devicetree/bindings/mmc/aspeed,sdhci.yaml
new file mode 100644
index 000000000000..ca8684f47962
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/aspeed,sdhci.yaml
@@ -0,0 +1,105 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mmc/aspeed,sdhci.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: ASPEED SD/SDIO/eMMC Controller
+
+maintainers:
+ - Andrew Jeffery <andrew@aj.id.au>
+ - Ryan Chen <ryanchen.aspeed@gmail.com>
+
+description: |+
+ The ASPEED SD/SDIO/eMMC controller exposes two slots implementing the SDIO
+ Host Specification v2.00, with 1 or 4 bit data buses, or an 8 bit data bus if
+ only a single slot is enabled.
+
+ The two slots are supported by a common configuration area. As the SDHCIs for
+ the slots are dependent on the common configuration area, they are described
+ as child nodes.
+
+properties:
+ compatible:
+ enum:
+ - aspeed,ast2400-sd-controller
+ - aspeed,ast2500-sd-controller
+ - aspeed,ast2600-sd-controller
+ reg:
+ maxItems: 1
+ description: Common configuration registers
+ "#address-cells":
+ const: 1
+ "#size-cells":
+ const: 1
+ ranges: true
+ clocks:
+ maxItems: 1
+ description: The SD/SDIO controller clock gate
+
+patternProperties:
+ "^sdhci@[0-9a-f]+$":
+ type: object
+ allOf:
+ - $ref: mmc-controller.yaml
+ properties:
+ compatible:
+ enum:
+ - aspeed,ast2400-sdhci
+ - aspeed,ast2500-sdhci
+ - aspeed,ast2600-sdhci
+ reg:
+ maxItems: 1
+ description: The SDHCI registers
+ clocks:
+ maxItems: 1
+ description: The SD bus clock
+ interrupts:
+ maxItems: 1
+ description: The SD interrupt shared between both slots
+ sdhci,auto-cmd12:
+ type: boolean
+ description: Specifies that controller should use auto CMD12
+ required:
+ - compatible
+ - reg
+ - clocks
+ - interrupts
+
+additionalProperties: false
+
+required:
+ - compatible
+ - reg
+ - "#address-cells"
+ - "#size-cells"
+ - ranges
+ - clocks
+
+examples:
+ - |
+ #include <dt-bindings/clock/aspeed-clock.h>
+ sdc@1e740000 {
+ compatible = "aspeed,ast2500-sd-controller";
+ reg = <0x1e740000 0x100>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0x1e740000 0x10000>;
+ clocks = <&syscon ASPEED_CLK_GATE_SDCLK>;
+
+ sdhci0: sdhci@100 {
+ compatible = "aspeed,ast2500-sdhci";
+ reg = <0x100 0x100>;
+ interrupts = <26>;
+ sdhci,auto-cmd12;
+ clocks = <&syscon ASPEED_CLK_SDIO>;
+ };
+
+ sdhci1: sdhci@200 {
+ compatible = "aspeed,ast2500-sdhci";
+ reg = <0x200 0x100>;
+ interrupts = <26>;
+ sdhci,auto-cmd12;
+ clocks = <&syscon ASPEED_CLK_SDIO>;
+ };
+ };
--
2.20.1
^ permalink raw reply related
* [PATCH v4 2/2] mmc: Add support for the ASPEED SD controller
From: Andrew Jeffery @ 2019-08-05 2:51 UTC (permalink / raw)
To: linux-mmc
Cc: Andrew Jeffery, ulf.hansson, robh+dt, mark.rutland, joel,
adrian.hunter, devicetree, linux-arm-kernel, linux-aspeed,
linux-kernel, ryanchen.aspeed
In-Reply-To: <20190805025155.9020-1-andrew@aj.id.au>
Add a minimal driver for ASPEED's SD controller, which exposes two
SDHCIs.
The ASPEED design implements a common register set for the SDHCIs, and
moves some of the standard configuration elements out to this common
area (e.g. 8-bit mode, and card detect configuration which is not
currently supported).
The SD controller has a dedicated hardware interrupt that is shared
between the slots. The common register set exposes information on which
slot triggered the interrupt; early revisions of the patch introduced an
irqchip for the register, but reality is it doesn't behave as an
irqchip, and the result fits awkwardly into the irqchip APIs. Instead
I've taken the simple approach of using the IRQ as a shared IRQ with
some minor performance impact for the second slot.
Ryan was the original author of the patch - I've taken his work and
massaged it to drop the irqchip support and rework the devicetree
integration. The driver has been smoke tested under qemu against a
minimal SD controller model and lightly tested on an ast2500-evb.
Signed-off-by: Ryan Chen <ryanchen.aspeed@gmail.com>
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
---
v3: No change
v2:
* Add AST2600 compatible
* Drop SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN
* Ensure slot number is valid
* Fix build with CONFIG_MODULES
* Fix module license string
* Non-PCI devices won't die
* Rename aspeed_sdc_configure_8bit_mode()
* Rename aspeed_sdhci_pdata
* Switch to sdhci_enable_clk()
* Use PTR_ERR() on the right `struct platform_device *`
---
drivers/mmc/host/Kconfig | 12 ++
drivers/mmc/host/Makefile | 1 +
drivers/mmc/host/sdhci-of-aspeed.c | 328 +++++++++++++++++++++++++++++
3 files changed, 341 insertions(+)
create mode 100644 drivers/mmc/host/sdhci-of-aspeed.c
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 14d89a108edd..0f8a230de2f3 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -154,6 +154,18 @@ config MMC_SDHCI_OF_ARASAN
If unsure, say N.
+config MMC_SDHCI_OF_ASPEED
+ tristate "SDHCI OF support for the ASPEED SDHCI controller"
+ depends on MMC_SDHCI_PLTFM
+ depends on OF
+ help
+ This selects the ASPEED Secure Digital Host Controller Interface.
+
+ If you have a controller with this interface, say Y or M here. You
+ also need to enable an appropriate bus interface.
+
+ If unsure, say N.
+
config MMC_SDHCI_OF_AT91
tristate "SDHCI OF support for the Atmel SDMMC controller"
depends on MMC_SDHCI_PLTFM
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index 73578718f119..390ee162fe71 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -84,6 +84,7 @@ obj-$(CONFIG_MMC_SDHCI_ESDHC_IMX) += sdhci-esdhc-imx.o
obj-$(CONFIG_MMC_SDHCI_DOVE) += sdhci-dove.o
obj-$(CONFIG_MMC_SDHCI_TEGRA) += sdhci-tegra.o
obj-$(CONFIG_MMC_SDHCI_OF_ARASAN) += sdhci-of-arasan.o
+obj-$(CONFIG_MMC_SDHCI_OF_ASPEED) += sdhci-of-aspeed.o
obj-$(CONFIG_MMC_SDHCI_OF_AT91) += sdhci-of-at91.o
obj-$(CONFIG_MMC_SDHCI_OF_ESDHC) += sdhci-of-esdhc.o
obj-$(CONFIG_MMC_SDHCI_OF_HLWD) += sdhci-of-hlwd.o
diff --git a/drivers/mmc/host/sdhci-of-aspeed.c b/drivers/mmc/host/sdhci-of-aspeed.c
new file mode 100644
index 000000000000..d31785ec90d7
--- /dev/null
+++ b/drivers/mmc/host/sdhci-of-aspeed.c
@@ -0,0 +1,328 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* Copyright (C) 2019 ASPEED Technology Inc. */
+/* Copyright (C) 2019 IBM Corp. */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/mmc/host.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+
+#include "sdhci-pltfm.h"
+
+#define ASPEED_SDC_INFO 0x00
+#define ASPEED_SDC_S1MMC8 BIT(25)
+#define ASPEED_SDC_S0MMC8 BIT(24)
+
+struct aspeed_sdc {
+ struct clk *clk;
+ struct resource *res;
+
+ spinlock_t lock;
+ void __iomem *regs;
+};
+
+struct aspeed_sdhci {
+ struct aspeed_sdc *parent;
+ u32 width_mask;
+};
+
+static void aspeed_sdc_configure_8bit_mode(struct aspeed_sdc *sdc,
+ struct aspeed_sdhci *sdhci,
+ bool bus8)
+{
+ u32 info;
+
+ /* Set/clear 8 bit mode */
+ spin_lock(&sdc->lock);
+ info = readl(sdc->regs + ASPEED_SDC_INFO);
+ if (bus8)
+ info |= sdhci->width_mask;
+ else
+ info &= ~sdhci->width_mask;
+ writel(info, sdc->regs + ASPEED_SDC_INFO);
+ spin_unlock(&sdc->lock);
+}
+
+static void aspeed_sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
+{
+ int div;
+ u16 clk;
+
+ if (clock == host->clock)
+ return;
+
+ sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
+
+ if (clock == 0)
+ goto out;
+
+ for (div = 1; div < 256; div *= 2) {
+ if ((host->max_clk / div) <= clock)
+ break;
+ }
+ div >>= 1;
+
+ clk = div << SDHCI_DIVIDER_SHIFT;
+
+ sdhci_enable_clk(host, clk);
+
+out:
+ host->clock = clock;
+}
+
+static void aspeed_sdhci_set_bus_width(struct sdhci_host *host, int width)
+{
+ struct sdhci_pltfm_host *pltfm_priv;
+ struct aspeed_sdhci *aspeed_sdhci;
+ struct aspeed_sdc *aspeed_sdc;
+ u8 ctrl;
+
+ pltfm_priv = sdhci_priv(host);
+ aspeed_sdhci = sdhci_pltfm_priv(pltfm_priv);
+ aspeed_sdc = aspeed_sdhci->parent;
+
+ /* Set/clear 8-bit mode */
+ aspeed_sdc_configure_8bit_mode(aspeed_sdc, aspeed_sdhci,
+ width == MMC_BUS_WIDTH_8);
+
+ /* Set/clear 1 or 4 bit mode */
+ ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
+ if (width == MMC_BUS_WIDTH_4)
+ ctrl |= SDHCI_CTRL_4BITBUS;
+ else
+ ctrl &= ~SDHCI_CTRL_4BITBUS;
+ sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
+}
+
+static const struct sdhci_ops aspeed_sdhci_ops = {
+ .set_clock = aspeed_sdhci_set_clock,
+ .get_max_clock = sdhci_pltfm_clk_get_max_clock,
+ .set_bus_width = aspeed_sdhci_set_bus_width,
+ .get_timeout_clock = sdhci_pltfm_clk_get_max_clock,
+ .reset = sdhci_reset,
+ .set_uhs_signaling = sdhci_set_uhs_signaling,
+};
+
+static const struct sdhci_pltfm_data aspeed_sdhci_pdata = {
+ .ops = &aspeed_sdhci_ops,
+ .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
+};
+
+static inline int aspeed_sdhci_calculate_slot(struct aspeed_sdhci *dev,
+ struct resource *res)
+{
+ resource_size_t delta;
+
+ if (!res || resource_type(res) != IORESOURCE_MEM)
+ return -EINVAL;
+
+ if (res->start < dev->parent->res->start)
+ return -EINVAL;
+
+ delta = res->start - dev->parent->res->start;
+ if (delta & (0x100 - 1))
+ return -EINVAL;
+
+ return (delta / 0x100) - 1;
+}
+
+static int aspeed_sdhci_probe(struct platform_device *pdev)
+{
+ struct sdhci_pltfm_host *pltfm_host;
+ struct aspeed_sdhci *dev;
+ struct sdhci_host *host;
+ struct resource *res;
+ int slot;
+ int ret;
+
+ host = sdhci_pltfm_init(pdev, &aspeed_sdhci_pdata, sizeof(*dev));
+ if (IS_ERR(host))
+ return PTR_ERR(host);
+
+ pltfm_host = sdhci_priv(host);
+ dev = sdhci_pltfm_priv(pltfm_host);
+ dev->parent = dev_get_drvdata(pdev->dev.parent);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ slot = aspeed_sdhci_calculate_slot(dev, res);
+
+ if (slot < 0)
+ return slot;
+ else if (slot >= 2)
+ return -EINVAL;
+
+ dev_info(&pdev->dev, "Configuring for slot %d\n", slot);
+ dev->width_mask = !slot ? ASPEED_SDC_S0MMC8 : ASPEED_SDC_S1MMC8;
+
+ sdhci_get_of_property(pdev);
+
+ pltfm_host->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(pltfm_host->clk))
+ return PTR_ERR(pltfm_host->clk);
+
+ ret = clk_prepare_enable(pltfm_host->clk);
+ if (ret) {
+ dev_err(&pdev->dev, "Unable to enable SDIO clock\n");
+ goto err_pltfm_free;
+ }
+
+ ret = mmc_of_parse(host->mmc);
+ if (ret)
+ goto err_sdhci_add;
+
+ ret = sdhci_add_host(host);
+ if (ret)
+ goto err_sdhci_add;
+
+ return 0;
+
+err_sdhci_add:
+ clk_disable_unprepare(pltfm_host->clk);
+err_pltfm_free:
+ sdhci_pltfm_free(pdev);
+ return ret;
+}
+
+static int aspeed_sdhci_remove(struct platform_device *pdev)
+{
+ struct sdhci_pltfm_host *pltfm_host;
+ struct sdhci_host *host;
+ int dead = 0;
+
+ host = platform_get_drvdata(pdev);
+ pltfm_host = sdhci_priv(host);
+
+ sdhci_remove_host(host, dead);
+
+ clk_disable_unprepare(pltfm_host->clk);
+
+ sdhci_pltfm_free(pdev);
+
+ return 0;
+}
+
+static const struct of_device_id aspeed_sdhci_of_match[] = {
+ { .compatible = "aspeed,ast2400-sdhci", },
+ { .compatible = "aspeed,ast2500-sdhci", },
+ { .compatible = "aspeed,ast2600-sdhci", },
+ { }
+};
+
+static struct platform_driver aspeed_sdhci_driver = {
+ .driver = {
+ .name = "sdhci-aspeed",
+ .of_match_table = aspeed_sdhci_of_match,
+ },
+ .probe = aspeed_sdhci_probe,
+ .remove = aspeed_sdhci_remove,
+};
+
+static int aspeed_sdc_probe(struct platform_device *pdev)
+
+{
+ struct device_node *parent, *child;
+ struct aspeed_sdc *sdc;
+ int ret;
+
+ sdc = devm_kzalloc(&pdev->dev, sizeof(*sdc), GFP_KERNEL);
+ if (!sdc)
+ return -ENOMEM;
+
+ spin_lock_init(&sdc->lock);
+
+ sdc->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(sdc->clk))
+ return PTR_ERR(sdc->clk);
+
+ ret = clk_prepare_enable(sdc->clk);
+ if (ret) {
+ dev_err(&pdev->dev, "Unable to enable SDCLK\n");
+ return ret;
+ }
+
+ sdc->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ sdc->regs = devm_ioremap_resource(&pdev->dev, sdc->res);
+ if (IS_ERR(sdc->regs)) {
+ ret = PTR_ERR(sdc->regs);
+ goto err_clk;
+ }
+
+ dev_set_drvdata(&pdev->dev, sdc);
+
+ parent = pdev->dev.of_node;
+ for_each_available_child_of_node(parent, child) {
+ struct platform_device *cpdev;
+
+ cpdev = of_platform_device_create(child, NULL, &pdev->dev);
+ if (IS_ERR(cpdev)) {
+ of_node_put(child);
+ ret = PTR_ERR(cpdev);
+ goto err_clk;
+ }
+ }
+
+ return 0;
+
+err_clk:
+ clk_disable_unprepare(sdc->clk);
+ return ret;
+}
+
+static int aspeed_sdc_remove(struct platform_device *pdev)
+{
+ struct aspeed_sdc *sdc = dev_get_drvdata(&pdev->dev);
+
+ clk_disable_unprepare(sdc->clk);
+
+ return 0;
+}
+
+static const struct of_device_id aspeed_sdc_of_match[] = {
+ { .compatible = "aspeed,ast2400-sd-controller", },
+ { .compatible = "aspeed,ast2500-sd-controller", },
+ { .compatible = "aspeed,ast2600-sd-controller", },
+ { }
+};
+
+MODULE_DEVICE_TABLE(of, aspeed_sdc_of_match);
+
+static struct platform_driver aspeed_sdc_driver = {
+ .driver = {
+ .name = "sd-controller-aspeed",
+ .pm = &sdhci_pltfm_pmops,
+ .of_match_table = aspeed_sdc_of_match,
+ },
+ .probe = aspeed_sdc_probe,
+ .remove = aspeed_sdc_remove,
+};
+
+static int __init aspeed_sdc_init(void)
+{
+ int rc;
+
+ rc = platform_driver_register(&aspeed_sdhci_driver);
+ if (rc < 0)
+ return rc;
+
+ return platform_driver_register(&aspeed_sdc_driver);
+}
+module_init(aspeed_sdc_init);
+
+static void __exit aspeed_sdc_exit(void)
+{
+ platform_driver_unregister(&aspeed_sdc_driver);
+ platform_driver_unregister(&aspeed_sdhci_driver);
+}
+module_exit(aspeed_sdc_exit);
+
+MODULE_DESCRIPTION("Driver for the ASPEED SD/SDIO/SDHCI Controllers");
+MODULE_AUTHOR("Ryan Chen <ryan_chen@aspeedtech.com>");
+MODULE_AUTHOR("Andrew Jeffery <andrew@aj.id.au>");
+MODULE_LICENSE("GPL");
--
2.20.1
^ permalink raw reply related
* Re: [PATCH v3 02/11] dt-bindings: clock: imx-lpcg: add support to parse clocks from device tree
From: Dong Aisheng @ 2019-08-05 3:27 UTC (permalink / raw)
To: Shawn Guo
Cc: Dong Aisheng, devicetree, sboyd, Michael Turquette, Rob Herring,
dl-linux-imx, Sascha Hauer, Fabio Estevam, linux-clk,
moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
In-Reply-To: <20190803135048.GL8870@X250.getinternet.no>
On Sun, Aug 4, 2019 at 11:45 AM Shawn Guo <shawnguo@kernel.org> wrote:
>
> On Tue, Jul 16, 2019 at 11:00:56PM +0800, Dong Aisheng wrote:
> > MX8QM and MX8QXP LPCG Clocks are mostly the same except they may reside
> > in different subsystems across CPUs and also vary a bit on the availability.
> >
> > Same as SCU clock, we want to move the clock definition into device tree
> > which can fully decouple the dependency of Clock ID definition from device
> > tree and make us be able to write a fully generic lpcg clock driver.
> >
> > And we can also use the existence of clock nodes in device tree to address
> > the device and clock availability differences across different SoCs.
> >
> > Cc: Rob Herring <robh+dt@kernel.org>
> > Cc: Stephen Boyd <sboyd@kernel.org>
> > Cc: Shawn Guo <shawnguo@kernel.org>
> > Cc: Sascha Hauer <kernel@pengutronix.de>
> > Cc: Michael Turquette <mturquette@baylibre.com>
> > Cc: devicetree@vger.kernel.org
> > Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
> > ---
> > ChangeLog:
> > v2->v3:
> > * no changes
> > v1->v2:
> > * Update example
> > * Add power domain property
> > ---
> > .../devicetree/bindings/clock/imx8qxp-lpcg.txt | 34 ++++++++++++++++++----
> > 1 file changed, 28 insertions(+), 6 deletions(-)
> >
> > diff --git a/Documentation/devicetree/bindings/clock/imx8qxp-lpcg.txt b/Documentation/devicetree/bindings/clock/imx8qxp-lpcg.txt
> > index 965cfa4..6fc2fd8 100644
> > --- a/Documentation/devicetree/bindings/clock/imx8qxp-lpcg.txt
> > +++ b/Documentation/devicetree/bindings/clock/imx8qxp-lpcg.txt
> > @@ -11,6 +11,21 @@ enabled by these control bits, it might still not be running based
> > on the base resource.
> >
> > Required properties:
> > +- compatible: Should be one of:
> > + "fsl,imx8qxp-lpcg"
> > + "fsl,imx8qm-lpcg" followed by "fsl,imx8qxp-lpcg".
> > +- reg: Address and length of the register set.
> > +- #clock-cells: Should be 1. One LPCG supports multiple clocks.
> > +- clocks: Input parent clocks phandle array for each clock.
> > +- bit-offset: An integer array indicating the bit offset for each clock.
>
> I guess that the driver should be able to figure bit offset from
> 'clock-indices' property.
>
Yes, it can be done in theory.
Then the binding may look like:
sdhc0_lpcg: clock-controller@5b200000 {
...
#clock-cells = <1>;
clocks = <&sdhc0_clk IMX_SC_PM_CLK_PER>,
<&conn_ipg_clk>, <&conn_axi_clk>;
clock-indices = <0>, <16>, <20>;
clock-output-names = "sdhc0_lpcg_per_clk",
"sdhc0_lpcg_ipg_clk",
"sdhc0_lpcg_ahb_clk";
power-domains = <&pd IMX_SC_R_SDHC_0>;
};
usdhc1: mmc@5b010000 {
...
clocks = <&sdhc0_lpcg 16>,
<&sdhc0_lpcg 0>,
<&sdhc0_lpcg 20>;
clock-names = "ipg", "per", "ahb";
};
However, after trying, i found one limitation if using clock-indices
that users have to do a secondary search for the indices value from clock names
which is not very friendly.
Formerly from the clock output names, user can easily get the clock
index as they're
in fixed orders as output names, so very easily to use.
e.g.
clocks = <&sdhc0_lpcg 1>,
<&sdhc0_lpcg 0>,
<&sdhc0_lpcg 2>;
If using clock-indices, users have no way to know it's clock index
from clock output names order
unless they do a secondary search from the clock-indice array accordingly.
For example, for "sdhc0_lpcg_ahb_clk", user can easily know its
reference is <&sdhc0_lpcg 2>.
But if using clock-indice, we need search clock-indices array to find
its reference
becomes <&sdhc0_lpcg 20>. So this seems like a drawback if using clock-indices.
Therefore, personally i'm still a bit intend to the original way which
is more simple and
straightforward from user point of view, unless there's a strong
objections on define another
vendor private property.
Shawn,
How do you think?
Should we enforce the complexity to users?
> > +- hw-autogate: Boolean array indicating whether supports HW autogate for
> > + each clock.
>
> Not sure why it needs to be a property in DT. Or asking it different
> way, when it should be true and when false?
>
It is one LPCG feature.
For some specific device LPCGs, it may support clock auto gating. (depends on
IP's capability. e.g. uSDHC).
So we define this feature in DT as well in case if user may want to
use it in the future.
But AFAIK, there's still no one using it. Most drivers reply on runtime PM to do
clock management. Did not use LPCG auto gate off feature.
But the current LPCG driver API does support this parameter.
If you think it's unnecessary to define it in DT as there're still no
users, i can remove it
and disabling autogate in driver by default.
Regards
Aisheng
> Shawn
>
> > +- clock-output-names: Shall be the corresponding names of the outputs.
> > + NOTE this property must be specified in the same order
> > + as the clock bit-offset and hw-autogate property.
> > +- power-domains: Should contain the power domain used by this clock.
> > +
> > +Legacy binding (DEPRECATED):
> > - compatible: Should be one of:
> > "fsl,imx8qxp-lpcg-adma",
> > "fsl,imx8qxp-lpcg-conn",
> > @@ -33,10 +48,17 @@ Examples:
> >
> > #include <dt-bindings/clock/imx8qxp-clock.h>
> >
> > -conn_lpcg: clock-controller@5b200000 {
> > - compatible = "fsl,imx8qxp-lpcg-conn";
> > - reg = <0x5b200000 0xb0000>;
> > +sdhc0_lpcg: clock-controller@5b200000 {
> > + compatible = "fsl,imx8qxp-lpcg";
> > + reg = <0x5b200000 0x10000>;
> > #clock-cells = <1>;
> > + clocks = <&sdhc0_clk IMX_SC_PM_CLK_PER>,
> > + <&conn_ipg_clk>, <&conn_axi_clk>;
> > + bit-offset = <0 16 20>;
> > + clock-output-names = "sdhc0_lpcg_per_clk",
> > + "sdhc0_lpcg_ipg_clk",
> > + "sdhc0_lpcg_ahb_clk";
> > + power-domains = <&pd IMX_SC_R_SDHC_0>;
> > };
> >
> > usdhc1: mmc@5b010000 {
> > @@ -44,8 +66,8 @@ usdhc1: mmc@5b010000 {
> > interrupt-parent = <&gic>;
> > interrupts = <GIC_SPI 232 IRQ_TYPE_LEVEL_HIGH>;
> > reg = <0x5b010000 0x10000>;
> > - clocks = <&conn_lpcg IMX8QXP_CONN_LPCG_SDHC0_IPG_CLK>,
> > - <&conn_lpcg IMX8QXP_CONN_LPCG_SDHC0_PER_CLK>,
> > - <&conn_lpcg IMX8QXP_CONN_LPCG_SDHC0_HCLK>;
> > + clocks = <&sdhc0_lpcg 1>,
> > + <&sdhc0_lpcg 0>,
> > + <&sdhc0_lpcg 2>;
> > clock-names = "ipg", "per", "ahb";
> > };
> > --
> > 2.7.4
> >
^ permalink raw reply
* Re: [PATCH v3 01/11] dt-bindings: firmware: imx-scu: new binding to parse clocks from device tree
From: Dong Aisheng @ 2019-08-05 3:48 UTC (permalink / raw)
To: Shawn Guo
Cc: Dong Aisheng, devicetree, sboyd, Michael Turquette, Rob Herring,
dl-linux-imx, Sascha Hauer, Fabio Estevam, linux-clk,
moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
In-Reply-To: <20190803144246.GM8870@X250.getinternet.no>
On Sun, Aug 4, 2019 at 11:49 AM Shawn Guo <shawnguo@kernel.org> wrote:
>
> On Tue, Jul 16, 2019 at 11:00:55PM +0800, Dong Aisheng wrote:
> > There's a few limitations on the original one cell clock binding
> > (#clock-cells = <1>) that we have to define some SW clock IDs for device
> > tree to reference. This may cause troubles if we want to use common
> > clock IDs for multi platforms support when the clock of those platforms
> > are mostly the same.
> > e.g. Current clock IDs name are defined with SS prefix.
> >
> > However the device may reside in different SS across CPUs, that means the
> > SS prefix may not valid anymore for a new SoC. Furthermore, the device
> > availability of those clocks may also vary a bit.
> >
> > For such situation, we want to eliminate the using of SW Clock IDs and
> > change to use a more close to HW one instead.
> > For SCU clocks usage, only two params required: Resource id + Clock Type.
>
> If this is how SCU firmware addresses the clock, I agree that it's worth
> witching to this new bindings, which describes the hardware (SCU
> firmware in this case) better, IMO.
>
> > Both parameters are platform independent. So we could use two cells binding
> > to pass those parameters,
> >
> > Cc: Rob Herring <robh+dt@kernel.org>
> > Cc: Stephen Boyd <sboyd@kernel.org>
> > Cc: Shawn Guo <shawnguo@kernel.org>
> > Cc: Sascha Hauer <kernel@pengutronix.de>
> > Cc: Michael Turquette <mturquette@baylibre.com>
> > Cc: devicetree@vger.kernel.org
> > Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
> > ---
> > ChangeLog:
> > v2->v3:
> > * Changed to two cells binding and register all clocks in driver
> > instead of parse from device tree.
> > v1->v2:
> > * changed to one cell binding inspired by arm,scpi.txt
> > Documentation/devicetree/bindings/arm/arm,scpi.txt
> > Resource ID is encoded in 'reg' property.
> > Clock type is encoded in generic clock-indices property.
> > Then we don't have to search all the DT nodes to fetch
> > those two value to construct clocks which is relatively
> > low efficiency.
> > * Add required power-domain property as well.
> > ---
> > .../devicetree/bindings/arm/freescale/fsl,scu.txt | 12 +++++++-----
> > include/dt-bindings/firmware/imx/rsrc.h | 17 +++++++++++++++++
> > 2 files changed, 24 insertions(+), 5 deletions(-)
> >
> > diff --git a/Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt b/Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt
> > index 5d7dbab..351d335 100644
> > --- a/Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt
> > +++ b/Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt
> > @@ -89,7 +89,10 @@ Required properties:
> > "fsl,imx8qm-clock"
> > "fsl,imx8qxp-clock"
> > followed by "fsl,scu-clk"
> > -- #clock-cells: Should be 1. Contains the Clock ID value.
> > +- #clock-cells: Should be either
> > + 2: Contains the Resource and Clock ID value.
> > + or
> > + 1: Contains the Clock ID value. (DEPRECATED)
> > - clocks: List of clock specifiers, must contain an entry for
> > each required entry in clock-names
> > - clock-names: Should include entries "xtal_32KHz", "xtal_24MHz"
> > @@ -162,7 +165,7 @@ firmware {
> >
> > clk: clk {
> > compatible = "fsl,imx8qxp-clk", "fsl,scu-clk";
> > - #clock-cells = <1>;
> > + #clock-cells = <2>;
> > };
> >
> > iomuxc {
> > @@ -192,8 +195,7 @@ serial@5a060000 {
> > ...
> > pinctrl-names = "default";
> > pinctrl-0 = <&pinctrl_lpuart0>;
> > - clocks = <&clk IMX8QXP_UART0_CLK>,
> > - <&clk IMX8QXP_UART0_IPG_CLK>;
> > - clock-names = "per", "ipg";
> > + clocks = <&uart0_clk IMX_SC_R_UART_0 IMX_SC_PM_CLK_PER>;
> > + clock-names = "ipg";
> > power-domains = <&pd IMX_SC_R_UART_0>;
> > };
> > diff --git a/include/dt-bindings/firmware/imx/rsrc.h b/include/dt-bindings/firmware/imx/rsrc.h
> > index 4e61f64..fbeaca7 100644
> > --- a/include/dt-bindings/firmware/imx/rsrc.h
> > +++ b/include/dt-bindings/firmware/imx/rsrc.h
> > @@ -547,4 +547,21 @@
> > #define IMX_SC_R_ATTESTATION 545
> > #define IMX_SC_R_LAST 546
> >
> > +/*
> > + * Defines for SC PM CLK
> > + */
> > +#define IMX_SC_PM_CLK_SLV_BUS 0 /* Slave bus clock */
> > +#define IMX_SC_PM_CLK_MST_BUS 1 /* Master bus clock */
> > +#define IMX_SC_PM_CLK_PER 2 /* Peripheral clock */
> > +#define IMX_SC_PM_CLK_PHY 3 /* Phy clock */
> > +#define IMX_SC_PM_CLK_MISC 4 /* Misc clock */
This is for typical device resource.
> > +#define IMX_SC_PM_CLK_MISC0 0 /* Misc 0 clock */
> > +#define IMX_SC_PM_CLK_MISC1 1 /* Misc 1 clock */
> > +#define IMX_SC_PM_CLK_MISC2 2 /* Misc 2 clock */
> > +#define IMX_SC_PM_CLK_MISC3 3 /* Misc 3 clock */
> > +#define IMX_SC_PM_CLK_MISC4 4 /* Misc 4 clock */
This is for some special clock types which do not belong to above
normal clock types.
Used very rare in SCU firmware.
e.g.
enet0_mac0_rxclk SC_R_ENE T_0 / SC_PM_CL K_MISC0
> > +#define IMX_SC_PM_CLK_CPU 2 /* CPU clock */
> > +#define IMX_SC_PM_CLK_PLL 4 /* PLL */
> > +#define IMX_SC_PM_CLK_BYPASS 4 /* Bypass clock */
They're for specific clock types for CPU/PLL/BYPASS only.
>
> It seems that there are several sets of clock type which apply to
> different resources/devices? If so, can you separate them a bit with
> some comments to make the list easier for readers?
>
Yes, i could add comments as above.
Thanks for the suggestions.
Aisheng
> Shawn
>
> > +
> > #endif /* __DT_BINDINGS_RSCRC_IMX_H */
> > --
> > 2.7.4
> >
^ permalink raw reply
* [PATCHv2 1/3] dt-bindings: pci: layerscape-pci: add compatible strings "fsl, ls1028a-pcie"
From: Xiaowei Bao @ 2019-08-05 4:04 UTC (permalink / raw)
To: bhelgaas, robh+dt, mark.rutland, shawnguo, leoyang.li, kishon,
lorenzo.pieralisi, arnd, gregkh, minghuan.Lian, mingkai.hu,
zhiqiang.hou, roy.zang, kstewart, pombredanne, shawn.lin,
linux-pci, devicetree, linux-kernel, linux-arm-kernel,
linuxppc-dev
Cc: Xiaowei Bao
Add the PCIe compatible string for LS1028A
Signed-off-by: Xiaowei Bao <xiaowei.bao@nxp.com>
---
v2:
- no change.
Documentation/devicetree/bindings/pci/layerscape-pci.txt | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/pci/layerscape-pci.txt b/Documentation/devicetree/bindings/pci/layerscape-pci.txt
index e20ceaa..99a386e 100644
--- a/Documentation/devicetree/bindings/pci/layerscape-pci.txt
+++ b/Documentation/devicetree/bindings/pci/layerscape-pci.txt
@@ -21,6 +21,7 @@ Required properties:
"fsl,ls1046a-pcie"
"fsl,ls1043a-pcie"
"fsl,ls1012a-pcie"
+ "fsl,ls1028a-pcie"
EP mode:
"fsl,ls1046a-pcie-ep", "fsl,ls-pcie-ep"
- reg: base addresses and lengths of the PCIe controller register blocks.
--
2.9.5
^ permalink raw reply related
* [PATCHv2 2/3] arm64: dts: ls1028a: Add PCIe controller DT nodes
From: Xiaowei Bao @ 2019-08-05 4:04 UTC (permalink / raw)
To: bhelgaas, robh+dt, mark.rutland, shawnguo, leoyang.li, kishon,
lorenzo.pieralisi, arnd, gregkh, minghuan.Lian, mingkai.hu,
zhiqiang.hou, roy.zang, kstewart, pombredanne, shawn.lin,
linux-pci, devicetree, linux-kernel, linux-arm-kernel,
linuxppc-dev
Cc: Xiaowei Bao
In-Reply-To: <20190805040453.48009-1-xiaowei.bao@nxp.com>
LS1028a implements 2 PCIe 3.0 controllers.
Signed-off-by: Xiaowei Bao <xiaowei.bao@nxp.com>
---
v2:
- Fix up the legacy INTx allocate failed issue.
arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi | 52 ++++++++++++++++++++++++++
1 file changed, 52 insertions(+)
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi
index aef5b06..0b542ed 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi
@@ -503,6 +503,58 @@
status = "disabled";
};
+ pcie@3400000 {
+ compatible = "fsl,ls1028a-pcie";
+ reg = <0x00 0x03400000 0x0 0x00100000 /* controller registers */
+ 0x80 0x00000000 0x0 0x00002000>; /* configuration space */
+ reg-names = "regs", "config";
+ interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>, /* PME interrupt */
+ <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>; /* aer interrupt */
+ interrupt-names = "pme", "aer";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
+ dma-coherent;
+ num-lanes = <4>;
+ bus-range = <0x0 0xff>;
+ ranges = <0x81000000 0x0 0x00000000 0x80 0x00010000 0x0 0x00010000 /* downstream I/O */
+ 0x82000000 0x0 0x40000000 0x80 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
+ msi-parent = <&its>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0000 0 0 1 &gic 0 0 GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>,
+ <0000 0 0 2 &gic 0 0 GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>,
+ <0000 0 0 3 &gic 0 0 GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>,
+ <0000 0 0 4 &gic 0 0 GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ pcie@3500000 {
+ compatible = "fsl,ls1028a-pcie";
+ reg = <0x00 0x03500000 0x0 0x00100000 /* controller registers */
+ 0x88 0x00000000 0x0 0x00002000>; /* configuration space */
+ reg-names = "regs", "config";
+ interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "pme", "aer";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
+ dma-coherent;
+ num-lanes = <4>;
+ bus-range = <0x0 0xff>;
+ ranges = <0x81000000 0x0 0x00000000 0x88 0x00010000 0x0 0x00010000 /* downstream I/O */
+ 0x82000000 0x0 0x40000000 0x88 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
+ msi-parent = <&its>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0000 0 0 1 &gic 0 0 GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>,
+ <0000 0 0 2 &gic 0 0 GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>,
+ <0000 0 0 3 &gic 0 0 GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>,
+ <0000 0 0 4 &gic 0 0 GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
pcie@1f0000000 { /* Integrated Endpoint Root Complex */
compatible = "pci-host-ecam-generic";
reg = <0x01 0xf0000000 0x0 0x100000>;
--
2.9.5
^ permalink raw reply related
* [PATCHv2 3/3] PCI: layerscape: Add LS1028a support
From: Xiaowei Bao @ 2019-08-05 4:04 UTC (permalink / raw)
To: bhelgaas, robh+dt, mark.rutland, shawnguo, leoyang.li, kishon,
lorenzo.pieralisi, arnd, gregkh, minghuan.Lian, mingkai.hu,
zhiqiang.hou, roy.zang, kstewart, pombredanne, shawn.lin,
linux-pci, devicetree, linux-kernel, linux-arm-kernel,
linuxppc-dev
Cc: Xiaowei Bao
In-Reply-To: <20190805040453.48009-1-xiaowei.bao@nxp.com>
Add support for the LS1028a PCIe controller.
Signed-off-by: Xiaowei Bao <xiaowei.bao@nxp.com>
---
v2:
- no change.
drivers/pci/controller/dwc/pci-layerscape.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/drivers/pci/controller/dwc/pci-layerscape.c b/drivers/pci/controller/dwc/pci-layerscape.c
index 3a5fa26..8c556e1 100644
--- a/drivers/pci/controller/dwc/pci-layerscape.c
+++ b/drivers/pci/controller/dwc/pci-layerscape.c
@@ -236,6 +236,14 @@ static const struct ls_pcie_drvdata ls1043_drvdata = {
.dw_pcie_ops = &dw_ls_pcie_ops,
};
+static const struct ls_pcie_drvdata ls1028a_drvdata = {
+ .lut_offset = 0x80000,
+ .ltssm_shift = 0,
+ .lut_dbg = 0x407fc,
+ .ops = &ls_pcie_host_ops,
+ .dw_pcie_ops = &dw_ls_pcie_ops,
+};
+
static const struct ls_pcie_drvdata ls1046_drvdata = {
.lut_offset = 0x80000,
.ltssm_shift = 24,
@@ -263,6 +271,7 @@ static const struct ls_pcie_drvdata ls2088_drvdata = {
static const struct of_device_id ls_pcie_of_match[] = {
{ .compatible = "fsl,ls1012a-pcie", .data = &ls1046_drvdata },
{ .compatible = "fsl,ls1021a-pcie", .data = &ls1021_drvdata },
+ { .compatible = "fsl,ls1028a-pcie", .data = &ls1028a_drvdata },
{ .compatible = "fsl,ls1043a-pcie", .data = &ls1043_drvdata },
{ .compatible = "fsl,ls1046a-pcie", .data = &ls1046_drvdata },
{ .compatible = "fsl,ls2080a-pcie", .data = &ls2080_drvdata },
--
2.9.5
^ permalink raw reply related
* [PATCH v4 00/10] Add Support for MediaTek PMIC MT6358
From: Hsin-Hsiung Wang @ 2019-08-05 5:21 UTC (permalink / raw)
To: Lee Jones, Rob Herring, Matthias Brugger, Mark Brown
Cc: Mark Rutland, Liam Girdwood, Eddie Huang, Sean Wang,
Alessandro Zummo, Alexandre Belloni, Hsin-Hsiung Wang,
Thomas Gleixner, Richard Fontana, Kate Stewart, Allison Randal,
devicetree, linux-arm-kernel, linux-mediatek, linux-kernel,
linux-rtc, srv_heupstream
This patchset including refactoring interrupt add support to MT6358 PMIC.
MT6358 is the primary PMIC for MT8183 platform.
changes since v3:
- refine some coding style in the mt6358 interrupt setting for better
code quality.
- refine some coding style in the mt6358 regulstor for better code
quality.
- fix correct voltage register for vgpu.
- remove useless define in mt6397-core.c.
- add rtc node in 6358.dtsi.
Hsin-Hsiung Wang (8):
mfd: mt6397: clean up code
mfd: mt6397: extract irq related code from core driver
mfd: mt6397: modify suspend/resume behavior
dt-bindings: mfd: Add compatible for the MediaTek MT6358 PMIC
regulator: Add document for MT6358 regulator
mfd: Add support for the MediaTek MT6358 PMIC
regulator: mt6358: Add support for MT6358 regulator
arm64: dts: mt6358: add PMIC MT6358 related nodes
Ran Bi (2):
rtc: mt6397: fix alarm register overwrite
rtc: Add support for the MediaTek MT6358 RTC
Documentation/devicetree/bindings/mfd/mt6397.txt | 11 +-
.../bindings/regulator/mt6358-regulator.txt | 358 +++++++++++++
arch/arm64/boot/dts/mediatek/mt6358.dtsi | 362 +++++++++++++
drivers/mfd/Makefile | 4 +-
drivers/mfd/mt6358-irq.c | 229 ++++++++
drivers/mfd/mt6397-core.c | 281 +++-------
drivers/mfd/mt6397-irq.c | 214 ++++++++
drivers/regulator/Kconfig | 9 +
drivers/regulator/Makefile | 1 +
drivers/regulator/mt6358-regulator.c | 580 +++++++++++++++++++++
drivers/rtc/rtc-mt6397.c | 90 +++-
include/linux/mfd/mt6358/core.h | 158 ++++++
include/linux/mfd/mt6358/registers.h | 282 ++++++++++
include/linux/mfd/mt6397/core.h | 15 +
include/linux/regulator/mt6358-regulator.h | 56 ++
15 files changed, 2428 insertions(+), 222 deletions(-)
create mode 100644 Documentation/devicetree/bindings/regulator/mt6358-regulator.txt
create mode 100644 arch/arm64/boot/dts/mediatek/mt6358.dtsi
create mode 100644 drivers/mfd/mt6358-irq.c
create mode 100644 drivers/mfd/mt6397-irq.c
create mode 100644 drivers/regulator/mt6358-regulator.c
create mode 100644 include/linux/mfd/mt6358/core.h
create mode 100644 include/linux/mfd/mt6358/registers.h
create mode 100644 include/linux/regulator/mt6358-regulator.h
--
2.6.4
^ permalink raw reply
* [PATCH v4 01/10] mfd: mt6397: clean up code
From: Hsin-Hsiung Wang @ 2019-08-05 5:21 UTC (permalink / raw)
To: Lee Jones, Rob Herring, Matthias Brugger, Mark Brown
Cc: Mark Rutland, Alessandro Zummo, Alexandre Belloni,
srv_heupstream-NuS5LvNUpcJWk0Htik3J/w,
devicetree-u79uwXL29TY76Z2rM5mHXA, Kate Stewart, Sean Wang,
Liam Girdwood, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
Richard Fontana, linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Allison Randal, linux-rtc-u79uwXL29TY76Z2rM5mHXA, Thomas Gleixner,
Eddie Huang, Hsin-Hsiung Wang,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <1564982518-32163-1-git-send-email-hsin-hsiung.wang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
refine some variable name for more readable
Acked-for-mfd-by: Lee Jones <lee.jones-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Signed-off-by: Hsin-Hsiung Wang <hsin-hsiung.wang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
---
drivers/mfd/mt6397-core.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/drivers/mfd/mt6397-core.c b/drivers/mfd/mt6397-core.c
index 337bccc..c070862 100644
--- a/drivers/mfd/mt6397-core.c
+++ b/drivers/mfd/mt6397-core.c
@@ -10,17 +10,17 @@
#include <linux/of_irq.h>
#include <linux/regmap.h>
#include <linux/mfd/core.h>
-#include <linux/mfd/mt6397/core.h>
#include <linux/mfd/mt6323/core.h>
-#include <linux/mfd/mt6397/registers.h>
+#include <linux/mfd/mt6397/core.h>
#include <linux/mfd/mt6323/registers.h>
+#include <linux/mfd/mt6397/registers.h>
#define MT6397_RTC_BASE 0xe000
#define MT6397_RTC_SIZE 0x3e
-#define MT6323_CID_CODE 0x23
-#define MT6391_CID_CODE 0x91
-#define MT6397_CID_CODE 0x97
+#define MT6323_CHIP_ID 0x23
+#define MT6391_CHIP_ID 0x91
+#define MT6397_CHIP_ID 0x97
static const struct resource mt6397_rtc_resources[] = {
{
@@ -290,7 +290,7 @@ static int mt6397_probe(struct platform_device *pdev)
return pmic->irq;
switch (id & 0xff) {
- case MT6323_CID_CODE:
+ case MT6323_CHIP_ID:
pmic->int_con[0] = MT6323_INT_CON0;
pmic->int_con[1] = MT6323_INT_CON1;
pmic->int_status[0] = MT6323_INT_STATUS0;
@@ -304,8 +304,8 @@ static int mt6397_probe(struct platform_device *pdev)
0, pmic->irq_domain);
break;
- case MT6397_CID_CODE:
- case MT6391_CID_CODE:
+ case MT6391_CHIP_ID:
+ case MT6397_CHIP_ID:
pmic->int_con[0] = MT6397_INT_CON0;
pmic->int_con[1] = MT6397_INT_CON1;
pmic->int_status[0] = MT6397_INT_STATUS0;
--
2.6.4
^ permalink raw reply related
* [PATCH v4 02/10] mfd: mt6397: extract irq related code from core driver
From: Hsin-Hsiung Wang @ 2019-08-05 5:21 UTC (permalink / raw)
To: Lee Jones, Rob Herring, Matthias Brugger, Mark Brown
Cc: Mark Rutland, Liam Girdwood, Eddie Huang, Sean Wang,
Alessandro Zummo, Alexandre Belloni, Hsin-Hsiung Wang,
Thomas Gleixner, Richard Fontana, Kate Stewart, Allison Randal,
devicetree, linux-arm-kernel, linux-mediatek, linux-kernel,
linux-rtc, srv_heupstream
In-Reply-To: <1564982518-32163-1-git-send-email-hsin-hsiung.wang@mediatek.com>
In order to support different types of irq design, we decide to add
separate irq drivers for different design and keep mt6397 mfd core
simple and reusable to all generations of PMICs so far.
Signed-off-by: Hsin-Hsiung Wang <hsin-hsiung.wang@mediatek.com>
---
drivers/mfd/Makefile | 3 +-
drivers/mfd/mt6397-core.c | 146 --------------------------------
drivers/mfd/mt6397-irq.c | 181 ++++++++++++++++++++++++++++++++++++++++
include/linux/mfd/mt6397/core.h | 9 ++
4 files changed, 192 insertions(+), 147 deletions(-)
create mode 100644 drivers/mfd/mt6397-irq.c
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index f026ada..9a96325 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -241,7 +241,8 @@ obj-$(CONFIG_INTEL_SOC_PMIC) += intel-soc-pmic.o
obj-$(CONFIG_INTEL_SOC_PMIC_BXTWC) += intel_soc_pmic_bxtwc.o
obj-$(CONFIG_INTEL_SOC_PMIC_CHTWC) += intel_soc_pmic_chtwc.o
obj-$(CONFIG_INTEL_SOC_PMIC_CHTDC_TI) += intel_soc_pmic_chtdc_ti.o
-obj-$(CONFIG_MFD_MT6397) += mt6397-core.o
+mt6397-objs := mt6397-core.o mt6397-irq.o
+obj-$(CONFIG_MFD_MT6397) += mt6397.o
obj-$(CONFIG_MFD_ALTERA_A10SR) += altera-a10sr.o
obj-$(CONFIG_MFD_ALTERA_SYSMGR) += altera-sysmgr.o
diff --git a/drivers/mfd/mt6397-core.c b/drivers/mfd/mt6397-core.c
index c070862..93c8881 100644
--- a/drivers/mfd/mt6397-core.c
+++ b/drivers/mfd/mt6397-core.c
@@ -18,10 +18,6 @@
#define MT6397_RTC_BASE 0xe000
#define MT6397_RTC_SIZE 0x3e
-#define MT6323_CHIP_ID 0x23
-#define MT6391_CHIP_ID 0x91
-#define MT6397_CHIP_ID 0x97
-
static const struct resource mt6397_rtc_resources[] = {
{
.start = MT6397_RTC_BASE,
@@ -86,148 +82,6 @@ static const struct mfd_cell mt6397_devs[] = {
}
};
-static void mt6397_irq_lock(struct irq_data *data)
-{
- struct mt6397_chip *mt6397 = irq_data_get_irq_chip_data(data);
-
- mutex_lock(&mt6397->irqlock);
-}
-
-static void mt6397_irq_sync_unlock(struct irq_data *data)
-{
- struct mt6397_chip *mt6397 = irq_data_get_irq_chip_data(data);
-
- regmap_write(mt6397->regmap, mt6397->int_con[0],
- mt6397->irq_masks_cur[0]);
- regmap_write(mt6397->regmap, mt6397->int_con[1],
- mt6397->irq_masks_cur[1]);
-
- mutex_unlock(&mt6397->irqlock);
-}
-
-static void mt6397_irq_disable(struct irq_data *data)
-{
- struct mt6397_chip *mt6397 = irq_data_get_irq_chip_data(data);
- int shift = data->hwirq & 0xf;
- int reg = data->hwirq >> 4;
-
- mt6397->irq_masks_cur[reg] &= ~BIT(shift);
-}
-
-static void mt6397_irq_enable(struct irq_data *data)
-{
- struct mt6397_chip *mt6397 = irq_data_get_irq_chip_data(data);
- int shift = data->hwirq & 0xf;
- int reg = data->hwirq >> 4;
-
- mt6397->irq_masks_cur[reg] |= BIT(shift);
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int mt6397_irq_set_wake(struct irq_data *irq_data, unsigned int on)
-{
- struct mt6397_chip *mt6397 = irq_data_get_irq_chip_data(irq_data);
- int shift = irq_data->hwirq & 0xf;
- int reg = irq_data->hwirq >> 4;
-
- if (on)
- mt6397->wake_mask[reg] |= BIT(shift);
- else
- mt6397->wake_mask[reg] &= ~BIT(shift);
-
- return 0;
-}
-#else
-#define mt6397_irq_set_wake NULL
-#endif
-
-static struct irq_chip mt6397_irq_chip = {
- .name = "mt6397-irq",
- .irq_bus_lock = mt6397_irq_lock,
- .irq_bus_sync_unlock = mt6397_irq_sync_unlock,
- .irq_enable = mt6397_irq_enable,
- .irq_disable = mt6397_irq_disable,
- .irq_set_wake = mt6397_irq_set_wake,
-};
-
-static void mt6397_irq_handle_reg(struct mt6397_chip *mt6397, int reg,
- int irqbase)
-{
- unsigned int status;
- int i, irq, ret;
-
- ret = regmap_read(mt6397->regmap, reg, &status);
- if (ret) {
- dev_err(mt6397->dev, "Failed to read irq status: %d\n", ret);
- return;
- }
-
- for (i = 0; i < 16; i++) {
- if (status & BIT(i)) {
- irq = irq_find_mapping(mt6397->irq_domain, irqbase + i);
- if (irq)
- handle_nested_irq(irq);
- }
- }
-
- regmap_write(mt6397->regmap, reg, status);
-}
-
-static irqreturn_t mt6397_irq_thread(int irq, void *data)
-{
- struct mt6397_chip *mt6397 = data;
-
- mt6397_irq_handle_reg(mt6397, mt6397->int_status[0], 0);
- mt6397_irq_handle_reg(mt6397, mt6397->int_status[1], 16);
-
- return IRQ_HANDLED;
-}
-
-static int mt6397_irq_domain_map(struct irq_domain *d, unsigned int irq,
- irq_hw_number_t hw)
-{
- struct mt6397_chip *mt6397 = d->host_data;
-
- irq_set_chip_data(irq, mt6397);
- irq_set_chip_and_handler(irq, &mt6397_irq_chip, handle_level_irq);
- irq_set_nested_thread(irq, 1);
- irq_set_noprobe(irq);
-
- return 0;
-}
-
-static const struct irq_domain_ops mt6397_irq_domain_ops = {
- .map = mt6397_irq_domain_map,
-};
-
-static int mt6397_irq_init(struct mt6397_chip *mt6397)
-{
- int ret;
-
- mutex_init(&mt6397->irqlock);
-
- /* Mask all interrupt sources */
- regmap_write(mt6397->regmap, mt6397->int_con[0], 0x0);
- regmap_write(mt6397->regmap, mt6397->int_con[1], 0x0);
-
- mt6397->irq_domain = irq_domain_add_linear(mt6397->dev->of_node,
- MT6397_IRQ_NR, &mt6397_irq_domain_ops, mt6397);
- if (!mt6397->irq_domain) {
- dev_err(mt6397->dev, "could not create irq domain\n");
- return -ENOMEM;
- }
-
- ret = devm_request_threaded_irq(mt6397->dev, mt6397->irq, NULL,
- mt6397_irq_thread, IRQF_ONESHOT, "mt6397-pmic", mt6397);
- if (ret) {
- dev_err(mt6397->dev, "failed to register irq=%d; err: %d\n",
- mt6397->irq, ret);
- return ret;
- }
-
- return 0;
-}
-
#ifdef CONFIG_PM_SLEEP
static int mt6397_irq_suspend(struct device *dev)
{
diff --git a/drivers/mfd/mt6397-irq.c b/drivers/mfd/mt6397-irq.c
new file mode 100644
index 0000000..b2d3ce1
--- /dev/null
+++ b/drivers/mfd/mt6397-irq.c
@@ -0,0 +1,181 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (c) 2019 MediaTek Inc.
+
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/mfd/mt6323/core.h>
+#include <linux/mfd/mt6323/registers.h>
+#include <linux/mfd/mt6397/core.h>
+#include <linux/mfd/mt6397/registers.h>
+
+static void mt6397_irq_lock(struct irq_data *data)
+{
+ struct mt6397_chip *mt6397 = irq_data_get_irq_chip_data(data);
+
+ mutex_lock(&mt6397->irqlock);
+}
+
+static void mt6397_irq_sync_unlock(struct irq_data *data)
+{
+ struct mt6397_chip *mt6397 = irq_data_get_irq_chip_data(data);
+
+ regmap_write(mt6397->regmap, mt6397->int_con[0],
+ mt6397->irq_masks_cur[0]);
+ regmap_write(mt6397->regmap, mt6397->int_con[1],
+ mt6397->irq_masks_cur[1]);
+
+ mutex_unlock(&mt6397->irqlock);
+}
+
+static void mt6397_irq_disable(struct irq_data *data)
+{
+ struct mt6397_chip *mt6397 = irq_data_get_irq_chip_data(data);
+ int shift = data->hwirq & 0xf;
+ int reg = data->hwirq >> 4;
+
+ mt6397->irq_masks_cur[reg] &= ~BIT(shift);
+}
+
+static void mt6397_irq_enable(struct irq_data *data)
+{
+ struct mt6397_chip *mt6397 = irq_data_get_irq_chip_data(data);
+ int shift = data->hwirq & 0xf;
+ int reg = data->hwirq >> 4;
+
+ mt6397->irq_masks_cur[reg] |= BIT(shift);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int mt6397_irq_set_wake(struct irq_data *irq_data, unsigned int on)
+{
+ struct mt6397_chip *mt6397 = irq_data_get_irq_chip_data(irq_data);
+ int shift = irq_data->hwirq & 0xf;
+ int reg = irq_data->hwirq >> 4;
+
+ if (on)
+ mt6397->wake_mask[reg] |= BIT(shift);
+ else
+ mt6397->wake_mask[reg] &= ~BIT(shift);
+
+ return 0;
+}
+#else
+#define mt6397_irq_set_wake NULL
+#endif
+
+static struct irq_chip mt6397_irq_chip = {
+ .name = "mt6397-irq",
+ .irq_bus_lock = mt6397_irq_lock,
+ .irq_bus_sync_unlock = mt6397_irq_sync_unlock,
+ .irq_enable = mt6397_irq_enable,
+ .irq_disable = mt6397_irq_disable,
+ .irq_set_wake = mt6397_irq_set_wake,
+};
+
+static void mt6397_irq_handle_reg(struct mt6397_chip *mt6397, int reg,
+ int irqbase)
+{
+ unsigned int status;
+ int i, irq, ret;
+
+ ret = regmap_read(mt6397->regmap, reg, &status);
+ if (ret) {
+ dev_err(mt6397->dev, "Failed to read irq status: %d\n", ret);
+ return;
+ }
+
+ for (i = 0; i < 16; i++) {
+ if (status & BIT(i)) {
+ irq = irq_find_mapping(mt6397->irq_domain, irqbase + i);
+ if (irq)
+ handle_nested_irq(irq);
+ }
+ }
+
+ regmap_write(mt6397->regmap, reg, status);
+}
+
+static irqreturn_t mt6397_irq_thread(int irq, void *data)
+{
+ struct mt6397_chip *mt6397 = data;
+
+ mt6397_irq_handle_reg(mt6397, mt6397->int_status[0], 0);
+ mt6397_irq_handle_reg(mt6397, mt6397->int_status[1], 16);
+
+ return IRQ_HANDLED;
+}
+
+static int mt6397_irq_domain_map(struct irq_domain *d, unsigned int irq,
+ irq_hw_number_t hw)
+{
+ struct mt6397_chip *mt6397 = d->host_data;
+
+ irq_set_chip_data(irq, mt6397);
+ irq_set_chip_and_handler(irq, &mt6397_irq_chip, handle_level_irq);
+ irq_set_nested_thread(irq, 1);
+ irq_set_noprobe(irq);
+
+ return 0;
+}
+
+static const struct irq_domain_ops mt6397_irq_domain_ops = {
+ .map = mt6397_irq_domain_map,
+};
+
+int mt6397_irq_init(struct mt6397_chip *chip)
+{
+ int ret;
+
+ mutex_init(&chip->irqlock);
+
+ switch (chip->chip_id) {
+ case MT6323_CHIP_ID:
+ chip->int_con[0] = MT6323_INT_CON0;
+ chip->int_con[1] = MT6323_INT_CON1;
+ chip->int_status[0] = MT6323_INT_STATUS0;
+ chip->int_status[1] = MT6323_INT_STATUS1;
+ break;
+
+ case MT6391_CHIP_ID:
+ case MT6397_CHIP_ID:
+ chip->int_con[0] = MT6397_INT_CON0;
+ chip->int_con[1] = MT6397_INT_CON1;
+ chip->int_status[0] = MT6397_INT_STATUS0;
+ chip->int_status[1] = MT6397_INT_STATUS1;
+ break;
+
+ default:
+ dev_err(chip->dev, "unsupported chip: 0x%x\n", chip->chip_id);
+ return -ENODEV;
+ }
+
+ /* Mask all interrupt sources */
+ regmap_write(chip->regmap, chip->int_con[0], 0x0);
+ regmap_write(chip->regmap, chip->int_con[1], 0x0);
+
+ chip->irq_domain = irq_domain_add_linear(chip->dev->of_node,
+ MT6397_IRQ_NR,
+ &mt6397_irq_domain_ops,
+ chip);
+ if (!chip->irq_domain) {
+ dev_err(chip->dev, "could not create irq domain\n");
+ return -ENOMEM;
+ }
+
+ ret = devm_request_threaded_irq(chip->dev, chip->irq, NULL,
+ mt6397_irq_thread, IRQF_ONESHOT,
+ "mt6397-pmic", chip);
+ if (ret) {
+ dev_err(chip->dev, "failed to register irq=%d; err: %d\n",
+ chip->irq, ret);
+ return ret;
+ }
+
+ return 0;
+}
diff --git a/include/linux/mfd/mt6397/core.h b/include/linux/mfd/mt6397/core.h
index 25a95e7..9320c2a 100644
--- a/include/linux/mfd/mt6397/core.h
+++ b/include/linux/mfd/mt6397/core.h
@@ -7,6 +7,12 @@
#ifndef __MFD_MT6397_CORE_H__
#define __MFD_MT6397_CORE_H__
+enum chip_id {
+ MT6323_CHIP_ID = 0x23,
+ MT6391_CHIP_ID = 0x91,
+ MT6397_CHIP_ID = 0x97,
+};
+
enum mt6397_irq_numbers {
MT6397_IRQ_SPKL_AB = 0,
MT6397_IRQ_SPKR_AB,
@@ -54,6 +60,9 @@ struct mt6397_chip {
u16 irq_masks_cache[2];
u16 int_con[2];
u16 int_status[2];
+ u16 chip_id;
};
+int mt6397_irq_init(struct mt6397_chip *chip);
+
#endif /* __MFD_MT6397_CORE_H__ */
--
2.6.4
^ permalink raw reply related
* [PATCH v4 03/10] mfd: mt6397: modify suspend/resume behavior
From: Hsin-Hsiung Wang @ 2019-08-05 5:21 UTC (permalink / raw)
To: Lee Jones, Rob Herring, Matthias Brugger, Mark Brown
Cc: Mark Rutland, Liam Girdwood, Eddie Huang, Sean Wang,
Alessandro Zummo, Alexandre Belloni, Hsin-Hsiung Wang,
Thomas Gleixner, Richard Fontana, Kate Stewart, Allison Randal,
devicetree, linux-arm-kernel, linux-mediatek, linux-kernel,
linux-rtc, srv_heupstream
In-Reply-To: <1564982518-32163-1-git-send-email-hsin-hsiung.wang@mediatek.com>
Some pmics don't need backup interrupt settings, so we change to use
pm notifier for the pmics which are necessary to store settings.
Signed-off-by: Hsin-Hsiung Wang <hsin-hsiung.wang@mediatek.com>
---
drivers/mfd/mt6397-core.c | 89 +++++++++++++++++------------------------
drivers/mfd/mt6397-irq.c | 33 +++++++++++++++
include/linux/mfd/mt6397/core.h | 3 ++
3 files changed, 73 insertions(+), 52 deletions(-)
diff --git a/drivers/mfd/mt6397-core.c b/drivers/mfd/mt6397-core.c
index 93c8881..8f94187 100644
--- a/drivers/mfd/mt6397-core.c
+++ b/drivers/mfd/mt6397-core.c
@@ -4,7 +4,6 @@
* Author: Flora Fu, MediaTek
*/
-#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/of_irq.h>
@@ -82,40 +81,27 @@ static const struct mfd_cell mt6397_devs[] = {
}
};
-#ifdef CONFIG_PM_SLEEP
-static int mt6397_irq_suspend(struct device *dev)
-{
- struct mt6397_chip *chip = dev_get_drvdata(dev);
-
- regmap_write(chip->regmap, chip->int_con[0], chip->wake_mask[0]);
- regmap_write(chip->regmap, chip->int_con[1], chip->wake_mask[1]);
-
- enable_irq_wake(chip->irq);
-
- return 0;
-}
-
-static int mt6397_irq_resume(struct device *dev)
-{
- struct mt6397_chip *chip = dev_get_drvdata(dev);
-
- regmap_write(chip->regmap, chip->int_con[0], chip->irq_masks_cur[0]);
- regmap_write(chip->regmap, chip->int_con[1], chip->irq_masks_cur[1]);
-
- disable_irq_wake(chip->irq);
+struct chip_data {
+ u32 cid_addr;
+ u32 cid_shift;
+};
- return 0;
-}
-#endif
+static const struct chip_data mt6323_core = {
+ .cid_addr = MT6323_CID,
+ .cid_shift = 0,
+};
-static SIMPLE_DEV_PM_OPS(mt6397_pm_ops, mt6397_irq_suspend,
- mt6397_irq_resume);
+static const struct chip_data mt6397_core = {
+ .cid_addr = MT6397_CID,
+ .cid_shift = 0,
+};
static int mt6397_probe(struct platform_device *pdev)
{
int ret;
unsigned int id;
struct mt6397_chip *pmic;
+ const struct chip_data *pmic_core;
pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL);
if (!pmic)
@@ -131,28 +117,30 @@ static int mt6397_probe(struct platform_device *pdev)
if (!pmic->regmap)
return -ENODEV;
- platform_set_drvdata(pdev, pmic);
+ pmic_core = of_device_get_match_data(&pdev->dev);
+ if (!pmic_core)
+ return -ENODEV;
- ret = regmap_read(pmic->regmap, MT6397_CID, &id);
+ ret = regmap_read(pmic->regmap, pmic_core->cid_addr, &id);
if (ret) {
- dev_err(pmic->dev, "Failed to read chip id: %d\n", ret);
+ dev_err(&pdev->dev, "Failed to read chip id: %d\n", ret);
return ret;
}
+ pmic->chip_id = (id >> pmic_core->cid_shift) & 0xff;
+
+ platform_set_drvdata(pdev, pmic);
+
pmic->irq = platform_get_irq(pdev, 0);
if (pmic->irq <= 0)
return pmic->irq;
- switch (id & 0xff) {
- case MT6323_CHIP_ID:
- pmic->int_con[0] = MT6323_INT_CON0;
- pmic->int_con[1] = MT6323_INT_CON1;
- pmic->int_status[0] = MT6323_INT_STATUS0;
- pmic->int_status[1] = MT6323_INT_STATUS1;
- ret = mt6397_irq_init(pmic);
- if (ret)
- return ret;
+ ret = mt6397_irq_init(pmic);
+ if (ret)
+ return ret;
+ switch (pmic->chip_id) {
+ case MT6323_CHIP_ID:
ret = devm_mfd_add_devices(&pdev->dev, -1, mt6323_devs,
ARRAY_SIZE(mt6323_devs), NULL,
0, pmic->irq_domain);
@@ -160,21 +148,13 @@ static int mt6397_probe(struct platform_device *pdev)
case MT6391_CHIP_ID:
case MT6397_CHIP_ID:
- pmic->int_con[0] = MT6397_INT_CON0;
- pmic->int_con[1] = MT6397_INT_CON1;
- pmic->int_status[0] = MT6397_INT_STATUS0;
- pmic->int_status[1] = MT6397_INT_STATUS1;
- ret = mt6397_irq_init(pmic);
- if (ret)
- return ret;
-
ret = devm_mfd_add_devices(&pdev->dev, -1, mt6397_devs,
ARRAY_SIZE(mt6397_devs), NULL,
0, pmic->irq_domain);
break;
default:
- dev_err(&pdev->dev, "unsupported chip: %d\n", id);
+ dev_err(&pdev->dev, "unsupported chip: %d\n", pmic->chip_id);
return -ENODEV;
}
@@ -187,9 +167,15 @@ static int mt6397_probe(struct platform_device *pdev)
}
static const struct of_device_id mt6397_of_match[] = {
- { .compatible = "mediatek,mt6397" },
- { .compatible = "mediatek,mt6323" },
- { }
+ {
+ .compatible = "mediatek,mt6323",
+ .data = &mt6323_core,
+ }, {
+ .compatible = "mediatek,mt6397",
+ .data = &mt6397_core,
+ }, {
+ /* sentinel */
+ }
};
MODULE_DEVICE_TABLE(of, mt6397_of_match);
@@ -204,7 +190,6 @@ static struct platform_driver mt6397_driver = {
.driver = {
.name = "mt6397",
.of_match_table = of_match_ptr(mt6397_of_match),
- .pm = &mt6397_pm_ops,
},
.id_table = mt6397_id,
};
diff --git a/drivers/mfd/mt6397-irq.c b/drivers/mfd/mt6397-irq.c
index b2d3ce1..669e93d 100644
--- a/drivers/mfd/mt6397-irq.c
+++ b/drivers/mfd/mt6397-irq.c
@@ -9,6 +9,7 @@
#include <linux/of_irq.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
+#include <linux/suspend.h>
#include <linux/mfd/mt6323/core.h>
#include <linux/mfd/mt6323/registers.h>
#include <linux/mfd/mt6397/core.h>
@@ -128,6 +129,36 @@ static const struct irq_domain_ops mt6397_irq_domain_ops = {
.map = mt6397_irq_domain_map,
};
+static int mt6397_irq_pm_notifier(struct notifier_block *notifier,
+ unsigned long pm_event, void *unused)
+{
+ struct mt6397_chip *chip =
+ container_of(notifier, struct mt6397_chip, pm_nb);
+
+ switch (pm_event) {
+ case PM_SUSPEND_PREPARE:
+ regmap_write(chip->regmap,
+ chip->int_con[0], chip->wake_mask[0]);
+ regmap_write(chip->regmap,
+ chip->int_con[1], chip->wake_mask[1]);
+ enable_irq_wake(chip->irq);
+ break;
+
+ case PM_POST_SUSPEND:
+ regmap_write(chip->regmap,
+ chip->int_con[0], chip->irq_masks_cur[0]);
+ regmap_write(chip->regmap,
+ chip->int_con[1], chip->irq_masks_cur[1]);
+ disable_irq_wake(chip->irq);
+ break;
+
+ default:
+ break;
+ }
+
+ return NOTIFY_DONE;
+}
+
int mt6397_irq_init(struct mt6397_chip *chip)
{
int ret;
@@ -159,6 +190,7 @@ int mt6397_irq_init(struct mt6397_chip *chip)
regmap_write(chip->regmap, chip->int_con[0], 0x0);
regmap_write(chip->regmap, chip->int_con[1], 0x0);
+ chip->pm_nb.notifier_call = mt6397_irq_pm_notifier;
chip->irq_domain = irq_domain_add_linear(chip->dev->of_node,
MT6397_IRQ_NR,
&mt6397_irq_domain_ops,
@@ -177,5 +209,6 @@ int mt6397_irq_init(struct mt6397_chip *chip)
return ret;
}
+ register_pm_notifier(&chip->pm_nb);
return 0;
}
diff --git a/include/linux/mfd/mt6397/core.h b/include/linux/mfd/mt6397/core.h
index 9320c2a..23e21da 100644
--- a/include/linux/mfd/mt6397/core.h
+++ b/include/linux/mfd/mt6397/core.h
@@ -7,6 +7,8 @@
#ifndef __MFD_MT6397_CORE_H__
#define __MFD_MT6397_CORE_H__
+#include <linux/notifier.h>
+
enum chip_id {
MT6323_CHIP_ID = 0x23,
MT6391_CHIP_ID = 0x91,
@@ -52,6 +54,7 @@ enum mt6397_irq_numbers {
struct mt6397_chip {
struct device *dev;
struct regmap *regmap;
+ struct notifier_block pm_nb;
int irq;
struct irq_domain *irq_domain;
struct mutex irqlock;
--
2.6.4
^ permalink raw reply related
* [PATCH v4 04/10] dt-bindings: mfd: Add compatible for the MediaTek MT6358 PMIC
From: Hsin-Hsiung Wang @ 2019-08-05 5:21 UTC (permalink / raw)
To: Lee Jones, Rob Herring, Matthias Brugger, Mark Brown
Cc: Mark Rutland, Liam Girdwood, Eddie Huang, Sean Wang,
Alessandro Zummo, Alexandre Belloni, Hsin-Hsiung Wang,
Thomas Gleixner, Richard Fontana, Kate Stewart, Allison Randal,
devicetree, linux-arm-kernel, linux-mediatek, linux-kernel,
linux-rtc, srv_heupstream
In-Reply-To: <1564982518-32163-1-git-send-email-hsin-hsiung.wang@mediatek.com>
This adds compatible for the MediaTek MT6358 PMIC.
Acked-for-mfd-by: Lee Jones <lee.jones@linaro.org>
Reviewed-by: Rob Herring <robh@kernel.org>
Signed-off-by: Hsin-Hsiung Wang <hsin-hsiung.wang@mediatek.com>
---
Documentation/devicetree/bindings/mfd/mt6397.txt | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/Documentation/devicetree/bindings/mfd/mt6397.txt b/Documentation/devicetree/bindings/mfd/mt6397.txt
index 0ebd08a..62f1c17 100644
--- a/Documentation/devicetree/bindings/mfd/mt6397.txt
+++ b/Documentation/devicetree/bindings/mfd/mt6397.txt
@@ -17,22 +17,27 @@ Documentation/devicetree/bindings/soc/mediatek/pwrap.txt
This document describes the binding for MFD device and its sub module.
Required properties:
-compatible: "mediatek,mt6397" or "mediatek,mt6323"
+compatible:
+ "mediatek,mt6323" for PMIC MT6323
+ "mediatek,mt6358" for PMIC MT6358
+ "mediatek,mt6397" for PMIC MT6397
Optional subnodes:
- rtc
Required properties:
- - compatible: "mediatek,mt6397-rtc"
+ - compatible: "mediatek,mt6397-rtc" or "mediatek,mt6358-rtc"
- regulators
Required properties:
- compatible: "mediatek,mt6397-regulator"
see Documentation/devicetree/bindings/regulator/mt6397-regulator.txt
+ - compatible: "mediatek,mt6358-regulator"
+ see Documentation/devicetree/bindings/regulator/mt6358-regulator.txt
- compatible: "mediatek,mt6323-regulator"
see Documentation/devicetree/bindings/regulator/mt6323-regulator.txt
- codec
Required properties:
- - compatible: "mediatek,mt6397-codec"
+ - compatible: "mediatek,mt6397-codec" or "mediatek,mt6358-sound"
- clk
Required properties:
- compatible: "mediatek,mt6397-clk"
--
2.6.4
^ permalink raw reply related
* [PATCH v4 05/10] regulator: Add document for MT6358 regulator
From: Hsin-Hsiung Wang @ 2019-08-05 5:21 UTC (permalink / raw)
To: Lee Jones, Rob Herring, Matthias Brugger, Mark Brown
Cc: Mark Rutland, Liam Girdwood, Eddie Huang, Sean Wang,
Alessandro Zummo, Alexandre Belloni, Hsin-Hsiung Wang,
Thomas Gleixner, Richard Fontana, Kate Stewart, Allison Randal,
devicetree, linux-arm-kernel, linux-mediatek, linux-kernel,
linux-rtc, srv_heupstream
In-Reply-To: <1564982518-32163-1-git-send-email-hsin-hsiung.wang@mediatek.com>
add dt-binding document for MediaTek MT6358 PMIC
Reviewed-by: Rob Herring <robh@kernel.org>
Signed-off-by: Hsin-Hsiung Wang <hsin-hsiung.wang@mediatek.com>
---
.../bindings/regulator/mt6358-regulator.txt | 358 +++++++++++++++++++++
1 file changed, 358 insertions(+)
create mode 100644 Documentation/devicetree/bindings/regulator/mt6358-regulator.txt
diff --git a/Documentation/devicetree/bindings/regulator/mt6358-regulator.txt b/Documentation/devicetree/bindings/regulator/mt6358-regulator.txt
new file mode 100644
index 0000000..9a90a92
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/mt6358-regulator.txt
@@ -0,0 +1,358 @@
+MediaTek MT6358 Regulator
+
+All voltage regulators provided by the MT6358 PMIC are described as the
+subnodes of the MT6358 regulators node. Each regulator is named according
+to its regulator type, buck_<name> and ldo_<name>. The definition for each
+of these nodes is defined using the standard binding for regulators at
+Documentation/devicetree/bindings/regulator/regulator.txt.
+
+The valid names for regulators are::
+BUCK:
+ buck_vdram1, buck_vcore, buck_vpa, buck_vproc11, buck_vproc12, buck_vgpu,
+ buck_vs2, buck_vmodem, buck_vs1
+LDO:
+ ldo_vdram2, ldo_vsim1, ldo_vibr, ldo_vrf12, ldo_vio18, ldo_vusb, ldo_vcamio,
+ ldo_vcamd, ldo_vcn18, ldo_vfe28, ldo_vsram_proc11, ldo_vcn28, ldo_vsram_others,
+ ldo_vsram_gpu, ldo_vxo22, ldo_vefuse, ldo_vaux18, ldo_vmch, ldo_vbif28,
+ ldo_vsram_proc12, ldo_vcama1, ldo_vemc, ldo_vio28, ldo_va12, ldo_vrf18,
+ ldo_vcn33_bt, ldo_vcn33_wifi, ldo_vcama2, ldo_vmc, ldo_vldo28, ldo_vaud28,
+ ldo_vsim2
+
+Example:
+
+ pmic {
+ compatible = "mediatek,mt6358";
+
+ mt6358regulator: mt6358regulator {
+ compatible = "mediatek,mt6358-regulator";
+
+ mt6358_vdram1_reg: buck_vdram1 {
+ regulator-compatible = "buck_vdram1";
+ regulator-name = "vdram1";
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <2087500>;
+ regulator-ramp-delay = <12500>;
+ regulator-enable-ramp-delay = <0>;
+ regulator-always-on;
+ };
+
+ mt6358_vcore_reg: buck_vcore {
+ regulator-name = "vcore";
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <1293750>;
+ regulator-ramp-delay = <6250>;
+ regulator-enable-ramp-delay = <200>;
+ regulator-always-on;
+ };
+
+ mt6358_vpa_reg: buck_vpa {
+ regulator-name = "vpa";
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <3650000>;
+ regulator-ramp-delay = <50000>;
+ regulator-enable-ramp-delay = <250>;
+ };
+
+ mt6358_vproc11_reg: buck_vproc11 {
+ regulator-name = "vproc11";
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <1293750>;
+ regulator-ramp-delay = <6250>;
+ regulator-enable-ramp-delay = <200>;
+ regulator-always-on;
+ };
+
+ mt6358_vproc12_reg: buck_vproc12 {
+ regulator-name = "vproc12";
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <1293750>;
+ regulator-ramp-delay = <6250>;
+ regulator-enable-ramp-delay = <200>;
+ regulator-always-on;
+ };
+
+ mt6358_vgpu_reg: buck_vgpu {
+ regulator-name = "vgpu";
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <1293750>;
+ regulator-ramp-delay = <6250>;
+ regulator-enable-ramp-delay = <200>;
+ };
+
+ mt6358_vs2_reg: buck_vs2 {
+ regulator-name = "vs2";
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <2087500>;
+ regulator-ramp-delay = <12500>;
+ regulator-enable-ramp-delay = <0>;
+ regulator-always-on;
+ };
+
+ mt6358_vmodem_reg: buck_vmodem {
+ regulator-name = "vmodem";
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <1293750>;
+ regulator-ramp-delay = <6250>;
+ regulator-enable-ramp-delay = <900>;
+ regulator-always-on;
+ };
+
+ mt6358_vs1_reg: buck_vs1 {
+ regulator-name = "vs1";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <2587500>;
+ regulator-ramp-delay = <12500>;
+ regulator-enable-ramp-delay = <0>;
+ regulator-always-on;
+ };
+
+ mt6358_vdram2_reg: ldo_vdram2 {
+ regulator-name = "vdram2";
+ regulator-min-microvolt = <600000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-enable-ramp-delay = <3300>;
+ };
+
+ mt6358_vsim1_reg: ldo_vsim1 {
+ regulator-name = "vsim1";
+ regulator-min-microvolt = <1700000>;
+ regulator-max-microvolt = <3100000>;
+ regulator-enable-ramp-delay = <540>;
+ };
+
+ mt6358_vibr_reg: ldo_vibr {
+ regulator-name = "vibr";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-enable-ramp-delay = <60>;
+ };
+
+ mt6358_vrf12_reg: ldo_vrf12 {
+ compatible = "regulator-fixed";
+ regulator-name = "vrf12";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-enable-ramp-delay = <120>;
+ };
+
+ mt6358_vio18_reg: ldo_vio18 {
+ compatible = "regulator-fixed";
+ regulator-name = "vio18";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-enable-ramp-delay = <2700>;
+ regulator-always-on;
+ };
+
+ mt6358_vusb_reg: ldo_vusb {
+ regulator-name = "vusb";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3100000>;
+ regulator-enable-ramp-delay = <270>;
+ regulator-always-on;
+ };
+
+ mt6358_vcamio_reg: ldo_vcamio {
+ compatible = "regulator-fixed";
+ regulator-name = "vcamio";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-enable-ramp-delay = <270>;
+ };
+
+ mt6358_vcamd_reg: ldo_vcamd {
+ regulator-name = "vcamd";
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-enable-ramp-delay = <270>;
+ };
+
+ mt6358_vcn18_reg: ldo_vcn18 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcn18";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-enable-ramp-delay = <270>;
+ };
+
+ mt6358_vfe28_reg: ldo_vfe28 {
+ compatible = "regulator-fixed";
+ regulator-name = "vfe28";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-enable-ramp-delay = <270>;
+ };
+
+ mt6358_vsram_proc11_reg: ldo_vsram_proc11 {
+ regulator-name = "vsram_proc11";
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <1293750>;
+ regulator-ramp-delay = <6250>;
+ regulator-enable-ramp-delay = <240>;
+ regulator-always-on;
+ };
+
+ mt6358_vcn28_reg: ldo_vcn28 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcn28";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-enable-ramp-delay = <270>;
+ };
+
+ mt6358_vsram_others_reg: ldo_vsram_others {
+ regulator-name = "vsram_others";
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <1293750>;
+ regulator-ramp-delay = <6250>;
+ regulator-enable-ramp-delay = <240>;
+ regulator-always-on;
+ };
+
+ mt6358_vsram_gpu_reg: ldo_vsram_gpu {
+ regulator-name = "vsram_gpu";
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <1293750>;
+ regulator-ramp-delay = <6250>;
+ regulator-enable-ramp-delay = <240>;
+ };
+
+ mt6358_vxo22_reg: ldo_vxo22 {
+ compatible = "regulator-fixed";
+ regulator-name = "vxo22";
+ regulator-min-microvolt = <2200000>;
+ regulator-max-microvolt = <2200000>;
+ regulator-enable-ramp-delay = <120>;
+ regulator-always-on;
+ };
+
+ mt6358_vefuse_reg: ldo_vefuse {
+ regulator-name = "vefuse";
+ regulator-min-microvolt = <1700000>;
+ regulator-max-microvolt = <1900000>;
+ regulator-enable-ramp-delay = <270>;
+ };
+
+ mt6358_vaux18_reg: ldo_vaux18 {
+ compatible = "regulator-fixed";
+ regulator-name = "vaux18";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-enable-ramp-delay = <270>;
+ };
+
+ mt6358_vmch_reg: ldo_vmch {
+ regulator-name = "vmch";
+ regulator-min-microvolt = <2900000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-enable-ramp-delay = <60>;
+ };
+
+ mt6358_vbif28_reg: ldo_vbif28 {
+ compatible = "regulator-fixed";
+ regulator-name = "vbif28";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-enable-ramp-delay = <270>;
+ };
+
+ mt6358_vsram_proc12_reg: ldo_vsram_proc12 {
+ regulator-name = "vsram_proc12";
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <1293750>;
+ regulator-ramp-delay = <6250>;
+ regulator-enable-ramp-delay = <240>;
+ regulator-always-on;
+ };
+
+ mt6358_vcama1_reg: ldo_vcama1 {
+ regulator-name = "vcama1";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-enable-ramp-delay = <270>;
+ };
+
+ mt6358_vemc_reg: ldo_vemc {
+ regulator-name = "vemc";
+ regulator-min-microvolt = <2900000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-enable-ramp-delay = <60>;
+ regulator-always-on;
+ };
+
+ mt6358_vio28_reg: ldo_vio28 {
+ compatible = "regulator-fixed";
+ regulator-name = "vio28";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-enable-ramp-delay = <270>;
+ };
+
+ mt6358_va12_reg: ldo_va12 {
+ compatible = "regulator-fixed";
+ regulator-name = "va12";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-enable-ramp-delay = <270>;
+ regulator-always-on;
+ };
+
+ mt6358_vrf18_reg: ldo_vrf18 {
+ compatible = "regulator-fixed";
+ regulator-name = "vrf18";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-enable-ramp-delay = <120>;
+ };
+
+ mt6358_vcn33_bt_reg: ldo_vcn33_bt {
+ regulator-name = "vcn33_bt";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3500000>;
+ regulator-enable-ramp-delay = <270>;
+ };
+
+ mt6358_vcn33_wifi_reg: ldo_vcn33_wifi {
+ regulator-name = "vcn33_wifi";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3500000>;
+ regulator-enable-ramp-delay = <270>;
+ };
+
+ mt6358_vcama2_reg: ldo_vcama2 {
+ regulator-name = "vcama2";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-enable-ramp-delay = <270>;
+ };
+
+ mt6358_vmc_reg: ldo_vmc {
+ regulator-name = "vmc";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-enable-ramp-delay = <60>;
+ };
+
+ mt6358_vldo28_reg: ldo_vldo28 {
+ regulator-name = "vldo28";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-enable-ramp-delay = <270>;
+ };
+
+ mt6358_vaud28_reg: ldo_vaud28 {
+ compatible = "regulator-fixed";
+ regulator-name = "vaud28";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-enable-ramp-delay = <270>;
+ };
+
+ mt6358_vsim2_reg: ldo_vsim2 {
+ regulator-name = "vsim2";
+ regulator-min-microvolt = <1700000>;
+ regulator-max-microvolt = <3100000>;
+ regulator-enable-ramp-delay = <540>;
+ };
+ };
+ };
--
2.6.4
^ permalink raw reply related
* [PATCH v4 06/10] mfd: Add support for the MediaTek MT6358 PMIC
From: Hsin-Hsiung Wang @ 2019-08-05 5:21 UTC (permalink / raw)
To: Lee Jones, Rob Herring, Matthias Brugger, Mark Brown
Cc: Mark Rutland, Liam Girdwood, Eddie Huang, Sean Wang,
Alessandro Zummo, Alexandre Belloni, Hsin-Hsiung Wang,
Thomas Gleixner, Richard Fontana, Kate Stewart, Allison Randal,
devicetree, linux-arm-kernel, linux-mediatek, linux-kernel,
linux-rtc, srv_heupstream
In-Reply-To: <1564982518-32163-1-git-send-email-hsin-hsiung.wang@mediatek.com>
This adds support for the MediaTek MT6358 PMIC. This is a
multifunction device with the following sub modules:
- Regulator
- RTC
- Codec
- Interrupt
It is interfaced to the host controller using SPI interface
by a proprietary hardware called PMIC wrapper or pwrap.
MT6358 MFD is a child device of the pwrap.
Signed-off-by: Hsin-Hsiung Wang <hsin-hsiung.wang@mediatek.com>
---
drivers/mfd/Makefile | 3 +-
drivers/mfd/mt6358-irq.c | 229 ++++++++++++++++++++++++++++
drivers/mfd/mt6397-core.c | 52 ++++++-
include/linux/mfd/mt6358/core.h | 158 ++++++++++++++++++++
include/linux/mfd/mt6358/registers.h | 282 +++++++++++++++++++++++++++++++++++
include/linux/mfd/mt6397/core.h | 3 +
6 files changed, 725 insertions(+), 2 deletions(-)
create mode 100644 drivers/mfd/mt6358-irq.c
create mode 100644 include/linux/mfd/mt6358/core.h
create mode 100644 include/linux/mfd/mt6358/registers.h
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 9a96325..36d088b 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -241,7 +241,8 @@ obj-$(CONFIG_INTEL_SOC_PMIC) += intel-soc-pmic.o
obj-$(CONFIG_INTEL_SOC_PMIC_BXTWC) += intel_soc_pmic_bxtwc.o
obj-$(CONFIG_INTEL_SOC_PMIC_CHTWC) += intel_soc_pmic_chtwc.o
obj-$(CONFIG_INTEL_SOC_PMIC_CHTDC_TI) += intel_soc_pmic_chtdc_ti.o
-mt6397-objs := mt6397-core.o mt6397-irq.o
+
+mt6397-objs := mt6397-core.o mt6397-irq.o mt6358-irq.o
obj-$(CONFIG_MFD_MT6397) += mt6397.o
obj-$(CONFIG_MFD_ALTERA_A10SR) += altera-a10sr.o
diff --git a/drivers/mfd/mt6358-irq.c b/drivers/mfd/mt6358-irq.c
new file mode 100644
index 0000000..2f55079
--- /dev/null
+++ b/drivers/mfd/mt6358-irq.c
@@ -0,0 +1,229 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (c) 2019 MediaTek Inc.
+
+#include <linux/interrupt.h>
+#include <linux/mfd/mt6358/core.h>
+#include <linux/mfd/mt6358/registers.h>
+#include <linux/mfd/mt6397/core.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+static struct irq_top_t mt6358_ints[] = {
+ MT6358_TOP_GEN(BUCK),
+ MT6358_TOP_GEN(LDO),
+ MT6358_TOP_GEN(PSC),
+ MT6358_TOP_GEN(SCK),
+ MT6358_TOP_GEN(BM),
+ MT6358_TOP_GEN(HK),
+ MT6358_TOP_GEN(AUD),
+ MT6358_TOP_GEN(MISC),
+};
+
+static void pmic_irq_enable(struct irq_data *data)
+{
+ unsigned int hwirq = irqd_to_hwirq(data);
+ struct mt6397_chip *chip = irq_data_get_irq_chip_data(data);
+ struct pmic_irq_data *irqd = chip->irq_data;
+
+ irqd->enable_hwirq[hwirq] = true;
+}
+
+static void pmic_irq_disable(struct irq_data *data)
+{
+ unsigned int hwirq = irqd_to_hwirq(data);
+ struct mt6397_chip *chip = irq_data_get_irq_chip_data(data);
+ struct pmic_irq_data *irqd = chip->irq_data;
+
+ irqd->enable_hwirq[hwirq] = false;
+}
+
+static void pmic_irq_lock(struct irq_data *data)
+{
+ struct mt6397_chip *chip = irq_data_get_irq_chip_data(data);
+
+ mutex_lock(&chip->irqlock);
+}
+
+static void pmic_irq_sync_unlock(struct irq_data *data)
+{
+ unsigned int i, top_gp, en_reg, int_regs, shift;
+ struct mt6397_chip *chip = irq_data_get_irq_chip_data(data);
+ struct pmic_irq_data *irqd = chip->irq_data;
+
+ for (i = 0; i < irqd->num_pmic_irqs; i++) {
+ if (irqd->enable_hwirq[i] == irqd->cache_hwirq[i])
+ continue;
+
+ top_gp = 0;
+ while ((top_gp + 1) < ARRAY_SIZE(mt6358_ints) &&
+ i >= mt6358_ints[top_gp + 1].hwirq_base)
+ top_gp++;
+
+ if (top_gp >= ARRAY_SIZE(mt6358_ints)) {
+ mutex_unlock(&chip->irqlock);
+ dev_err(chip->dev,
+ "Failed to get top_group: %d\n", top_gp);
+ return;
+ }
+
+ int_regs = (i - mt6358_ints[top_gp].hwirq_base) /
+ MT6358_REG_WIDTH;
+ en_reg = mt6358_ints[top_gp].en_reg +
+ mt6358_ints[top_gp].en_reg_shift * int_regs;
+ shift = (i - mt6358_ints[top_gp].hwirq_base) % MT6358_REG_WIDTH;
+ regmap_update_bits(chip->regmap, en_reg, BIT(shift),
+ irqd->enable_hwirq[i] << shift);
+ irqd->cache_hwirq[i] = irqd->enable_hwirq[i];
+ }
+ mutex_unlock(&chip->irqlock);
+}
+
+static struct irq_chip mt6358_irq_chip = {
+ .name = "mt6358-irq",
+ .flags = IRQCHIP_SKIP_SET_WAKE,
+ .irq_enable = pmic_irq_enable,
+ .irq_disable = pmic_irq_disable,
+ .irq_bus_lock = pmic_irq_lock,
+ .irq_bus_sync_unlock = pmic_irq_sync_unlock,
+};
+
+static void mt6358_irq_sp_handler(struct mt6397_chip *chip,
+ unsigned int top_gp)
+{
+ unsigned int sta_reg, irq_status;
+ unsigned int hwirq, virq;
+ int ret, i, j;
+
+ for (i = 0; i < mt6358_ints[top_gp].num_int_regs; i++) {
+ sta_reg = mt6358_ints[top_gp].sta_reg +
+ mt6358_ints[top_gp].sta_reg_shift * i;
+ ret = regmap_read(chip->regmap, sta_reg, &irq_status);
+ if (ret) {
+ dev_err(chip->dev,
+ "Failed to read irq status: %d\n", ret);
+ return;
+ }
+
+ if (!irq_status)
+ continue;
+
+ for (j = 0; j < MT6358_REG_WIDTH ; j++) {
+ if ((irq_status & BIT(j)) == 0)
+ continue;
+ hwirq = mt6358_ints[top_gp].hwirq_base +
+ MT6358_REG_WIDTH * i + j;
+ virq = irq_find_mapping(chip->irq_domain, hwirq);
+ if (virq)
+ handle_nested_irq(virq);
+ }
+
+ regmap_write(chip->regmap, sta_reg, irq_status);
+ }
+}
+
+static irqreturn_t mt6358_irq_handler(int irq, void *data)
+{
+ struct mt6397_chip *chip = data;
+ struct pmic_irq_data *mt6358_irq_data = chip->irq_data;
+ unsigned int top_irq_status;
+ unsigned int i;
+ int ret;
+
+ ret = regmap_read(chip->regmap,
+ mt6358_irq_data->top_int_status_reg,
+ &top_irq_status);
+ if (ret) {
+ dev_err(chip->dev, "Can't read TOP_INT_STATUS ret=%d\n", ret);
+ return IRQ_NONE;
+ }
+
+ for (i = 0; i < mt6358_irq_data->num_top; i++) {
+ if (top_irq_status & BIT(mt6358_ints[i].top_offset))
+ mt6358_irq_sp_handler(chip, i);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int pmic_irq_domain_map(struct irq_domain *d, unsigned int irq,
+ irq_hw_number_t hw)
+{
+ struct mt6397_chip *mt6397 = d->host_data;
+
+ irq_set_chip_data(irq, mt6397);
+ irq_set_chip_and_handler(irq, &mt6358_irq_chip, handle_level_irq);
+ irq_set_nested_thread(irq, 1);
+ irq_set_noprobe(irq);
+
+ return 0;
+}
+
+static const struct irq_domain_ops mt6358_irq_domain_ops = {
+ .map = pmic_irq_domain_map,
+ .xlate = irq_domain_xlate_twocell,
+};
+
+int mt6358_irq_init(struct mt6397_chip *chip)
+{
+ int i, j, ret;
+ struct pmic_irq_data *irqd;
+
+ irqd = devm_kzalloc(chip->dev, sizeof(struct pmic_irq_data *),
+ GFP_KERNEL);
+ if (!irqd)
+ return -ENOMEM;
+
+ chip->irq_data = irqd;
+
+ mutex_init(&chip->irqlock);
+ irqd->top_int_status_reg = MT6358_TOP_INT_STATUS0;
+ irqd->num_pmic_irqs = MT6358_IRQ_NR;
+ irqd->num_top = ARRAY_SIZE(mt6358_ints);
+
+ irqd->enable_hwirq = devm_kcalloc(chip->dev,
+ irqd->num_pmic_irqs,
+ sizeof(bool),
+ GFP_KERNEL);
+ if (!irqd->enable_hwirq)
+ return -ENOMEM;
+
+ irqd->cache_hwirq = devm_kcalloc(chip->dev,
+ irqd->num_pmic_irqs,
+ sizeof(bool),
+ GFP_KERNEL);
+ if (!irqd->cache_hwirq)
+ return -ENOMEM;
+
+ /* Disable all interrupt for initializing */
+ for (i = 0; i < irqd->num_top; i++) {
+ for (j = 0; j < mt6358_ints[i].num_int_regs; j++)
+ regmap_write(chip->regmap,
+ mt6358_ints[i].en_reg +
+ mt6358_ints[i].en_reg_shift * j, 0);
+ }
+
+ chip->irq_domain = irq_domain_add_linear(chip->dev->of_node,
+ irqd->num_pmic_irqs,
+ &mt6358_irq_domain_ops, chip);
+ if (!chip->irq_domain) {
+ dev_err(chip->dev, "could not create irq domain\n");
+ return -ENODEV;
+ }
+
+ ret = devm_request_threaded_irq(chip->dev, chip->irq, NULL,
+ mt6358_irq_handler, IRQF_ONESHOT,
+ mt6358_irq_chip.name, chip);
+ if (ret) {
+ dev_err(chip->dev, "failed to register irq=%d; err: %d\n",
+ chip->irq, ret);
+ return ret;
+ }
+
+ enable_irq_wake(chip->irq);
+ return ret;
+}
diff --git a/drivers/mfd/mt6397-core.c b/drivers/mfd/mt6397-core.c
index 8f94187..815d83c 100644
--- a/drivers/mfd/mt6397-core.c
+++ b/drivers/mfd/mt6397-core.c
@@ -10,13 +10,30 @@
#include <linux/regmap.h>
#include <linux/mfd/core.h>
#include <linux/mfd/mt6323/core.h>
+#include <linux/mfd/mt6358/core.h>
#include <linux/mfd/mt6397/core.h>
#include <linux/mfd/mt6323/registers.h>
+#include <linux/mfd/mt6358/registers.h>
#include <linux/mfd/mt6397/registers.h>
+#define MT6358_RTC_BASE 0x0588
+#define MT6358_RTC_SIZE 0x3c
#define MT6397_RTC_BASE 0xe000
#define MT6397_RTC_SIZE 0x3e
+static const struct resource mt6358_rtc_resources[] = {
+ {
+ .start = MT6358_RTC_BASE,
+ .end = MT6358_RTC_BASE + MT6358_RTC_SIZE,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MT6358_IRQ_RTC,
+ .end = MT6358_IRQ_RTC,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
static const struct resource mt6397_rtc_resources[] = {
{
.start = MT6397_RTC_BASE,
@@ -55,6 +72,21 @@ static const struct mfd_cell mt6323_devs[] = {
},
};
+static const struct mfd_cell mt6358_devs[] = {
+ {
+ .name = "mt6358-regulator",
+ .of_compatible = "mediatek,mt6358-regulator"
+ }, {
+ .name = "mt6397-rtc",
+ .num_resources = ARRAY_SIZE(mt6358_rtc_resources),
+ .resources = mt6358_rtc_resources,
+ .of_compatible = "mediatek,mt6358-rtc",
+ }, {
+ .name = "mt6358-sound",
+ .of_compatible = "mediatek,mt6358-sound"
+ },
+};
+
static const struct mfd_cell mt6397_devs[] = {
{
.name = "mt6397-rtc",
@@ -91,6 +123,11 @@ static const struct chip_data mt6323_core = {
.cid_shift = 0,
};
+static const struct chip_data mt6358_core = {
+ .cid_addr = MT6358_SWCID,
+ .cid_shift = 8,
+};
+
static const struct chip_data mt6397_core = {
.cid_addr = MT6397_CID,
.cid_shift = 0,
@@ -135,7 +172,11 @@ static int mt6397_probe(struct platform_device *pdev)
if (pmic->irq <= 0)
return pmic->irq;
- ret = mt6397_irq_init(pmic);
+ if (pmic->chip_id == MT6358_CHIP_ID)
+ ret = mt6358_irq_init(pmic);
+ else
+ ret = mt6397_irq_init(pmic);
+
if (ret)
return ret;
@@ -146,6 +187,12 @@ static int mt6397_probe(struct platform_device *pdev)
0, pmic->irq_domain);
break;
+ case MT6358_CHIP_ID:
+ ret = devm_mfd_add_devices(&pdev->dev, -1, mt6358_devs,
+ ARRAY_SIZE(mt6358_devs), NULL,
+ 0, pmic->irq_domain);
+ break;
+
case MT6391_CHIP_ID:
case MT6397_CHIP_ID:
ret = devm_mfd_add_devices(&pdev->dev, -1, mt6397_devs,
@@ -171,6 +218,9 @@ static const struct of_device_id mt6397_of_match[] = {
.compatible = "mediatek,mt6323",
.data = &mt6323_core,
}, {
+ .compatible = "mediatek,mt6358",
+ .data = &mt6358_core,
+ }, {
.compatible = "mediatek,mt6397",
.data = &mt6397_core,
}, {
diff --git a/include/linux/mfd/mt6358/core.h b/include/linux/mfd/mt6358/core.h
new file mode 100644
index 0000000..05108617
--- /dev/null
+++ b/include/linux/mfd/mt6358/core.h
@@ -0,0 +1,158 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef __MFD_MT6358_CORE_H__
+#define __MFD_MT6358_CORE_H__
+
+#define MT6358_REG_WIDTH 16
+
+struct irq_top_t {
+ int hwirq_base;
+ unsigned int num_int_regs;
+ unsigned int num_int_bits;
+ unsigned int en_reg;
+ unsigned int en_reg_shift;
+ unsigned int sta_reg;
+ unsigned int sta_reg_shift;
+ unsigned int top_offset;
+};
+
+struct pmic_irq_data {
+ unsigned int num_top;
+ unsigned int num_pmic_irqs;
+ unsigned short top_int_status_reg;
+ bool *enable_hwirq;
+ bool *cache_hwirq;
+};
+
+enum mt6358_irq_top_status_shift {
+ MT6358_BUCK_TOP = 0,
+ MT6358_LDO_TOP,
+ MT6358_PSC_TOP,
+ MT6358_SCK_TOP,
+ MT6358_BM_TOP,
+ MT6358_HK_TOP,
+ MT6358_AUD_TOP,
+ MT6358_MISC_TOP,
+};
+
+enum mt6358_irq_numbers {
+ MT6358_IRQ_VPROC11_OC = 0,
+ MT6358_IRQ_VPROC12_OC,
+ MT6358_IRQ_VCORE_OC,
+ MT6358_IRQ_VGPU_OC,
+ MT6358_IRQ_VMODEM_OC,
+ MT6358_IRQ_VDRAM1_OC,
+ MT6358_IRQ_VS1_OC,
+ MT6358_IRQ_VS2_OC,
+ MT6358_IRQ_VPA_OC,
+ MT6358_IRQ_VCORE_PREOC,
+ MT6358_IRQ_VFE28_OC = 16,
+ MT6358_IRQ_VXO22_OC,
+ MT6358_IRQ_VRF18_OC,
+ MT6358_IRQ_VRF12_OC,
+ MT6358_IRQ_VEFUSE_OC,
+ MT6358_IRQ_VCN33_OC,
+ MT6358_IRQ_VCN28_OC,
+ MT6358_IRQ_VCN18_OC,
+ MT6358_IRQ_VCAMA1_OC,
+ MT6358_IRQ_VCAMA2_OC,
+ MT6358_IRQ_VCAMD_OC,
+ MT6358_IRQ_VCAMIO_OC,
+ MT6358_IRQ_VLDO28_OC,
+ MT6358_IRQ_VA12_OC,
+ MT6358_IRQ_VAUX18_OC,
+ MT6358_IRQ_VAUD28_OC,
+ MT6358_IRQ_VIO28_OC,
+ MT6358_IRQ_VIO18_OC,
+ MT6358_IRQ_VSRAM_PROC11_OC,
+ MT6358_IRQ_VSRAM_PROC12_OC,
+ MT6358_IRQ_VSRAM_OTHERS_OC,
+ MT6358_IRQ_VSRAM_GPU_OC,
+ MT6358_IRQ_VDRAM2_OC,
+ MT6358_IRQ_VMC_OC,
+ MT6358_IRQ_VMCH_OC,
+ MT6358_IRQ_VEMC_OC,
+ MT6358_IRQ_VSIM1_OC,
+ MT6358_IRQ_VSIM2_OC,
+ MT6358_IRQ_VIBR_OC,
+ MT6358_IRQ_VUSB_OC,
+ MT6358_IRQ_VBIF28_OC,
+ MT6358_IRQ_PWRKEY = 48,
+ MT6358_IRQ_HOMEKEY,
+ MT6358_IRQ_PWRKEY_R,
+ MT6358_IRQ_HOMEKEY_R,
+ MT6358_IRQ_NI_LBAT_INT,
+ MT6358_IRQ_CHRDET,
+ MT6358_IRQ_CHRDET_EDGE,
+ MT6358_IRQ_VCDT_HV_DET,
+ MT6358_IRQ_RTC = 64,
+ MT6358_IRQ_FG_BAT0_H = 80,
+ MT6358_IRQ_FG_BAT0_L,
+ MT6358_IRQ_FG_CUR_H,
+ MT6358_IRQ_FG_CUR_L,
+ MT6358_IRQ_FG_ZCV,
+ MT6358_IRQ_FG_BAT1_H,
+ MT6358_IRQ_FG_BAT1_L,
+ MT6358_IRQ_FG_N_CHARGE_L,
+ MT6358_IRQ_FG_IAVG_H,
+ MT6358_IRQ_FG_IAVG_L,
+ MT6358_IRQ_FG_TIME_H,
+ MT6358_IRQ_FG_DISCHARGE,
+ MT6358_IRQ_FG_CHARGE,
+ MT6358_IRQ_BATON_LV = 96,
+ MT6358_IRQ_BATON_HT,
+ MT6358_IRQ_BATON_BAT_IN,
+ MT6358_IRQ_BATON_BAT_OUT,
+ MT6358_IRQ_BIF,
+ MT6358_IRQ_BAT_H = 112,
+ MT6358_IRQ_BAT_L,
+ MT6358_IRQ_BAT2_H,
+ MT6358_IRQ_BAT2_L,
+ MT6358_IRQ_BAT_TEMP_H,
+ MT6358_IRQ_BAT_TEMP_L,
+ MT6358_IRQ_AUXADC_IMP,
+ MT6358_IRQ_NAG_C_DLTV,
+ MT6358_IRQ_AUDIO = 128,
+ MT6358_IRQ_ACCDET = 133,
+ MT6358_IRQ_ACCDET_EINT0,
+ MT6358_IRQ_ACCDET_EINT1,
+ MT6358_IRQ_SPI_CMD_ALERT = 144,
+ MT6358_IRQ_NR,
+};
+
+#define MT6358_IRQ_BUCK_BASE MT6358_IRQ_VPROC11_OC
+#define MT6358_IRQ_LDO_BASE MT6358_IRQ_VFE28_OC
+#define MT6358_IRQ_PSC_BASE MT6358_IRQ_PWRKEY
+#define MT6358_IRQ_SCK_BASE MT6358_IRQ_RTC
+#define MT6358_IRQ_BM_BASE MT6358_IRQ_FG_BAT0_H
+#define MT6358_IRQ_HK_BASE MT6358_IRQ_BAT_H
+#define MT6358_IRQ_AUD_BASE MT6358_IRQ_AUDIO
+#define MT6358_IRQ_MISC_BASE MT6358_IRQ_SPI_CMD_ALERT
+
+#define MT6358_IRQ_BUCK_BITS (MT6358_IRQ_VCORE_PREOC - MT6358_IRQ_BUCK_BASE + 1)
+#define MT6358_IRQ_LDO_BITS (MT6358_IRQ_VBIF28_OC - MT6358_IRQ_LDO_BASE + 1)
+#define MT6358_IRQ_PSC_BITS (MT6358_IRQ_VCDT_HV_DET - MT6358_IRQ_PSC_BASE + 1)
+#define MT6358_IRQ_SCK_BITS (MT6358_IRQ_RTC - MT6358_IRQ_SCK_BASE + 1)
+#define MT6358_IRQ_BM_BITS (MT6358_IRQ_BIF - MT6358_IRQ_BM_BASE + 1)
+#define MT6358_IRQ_HK_BITS (MT6358_IRQ_NAG_C_DLTV - MT6358_IRQ_HK_BASE + 1)
+#define MT6358_IRQ_AUD_BITS (MT6358_IRQ_ACCDET_EINT1 - MT6358_IRQ_AUD_BASE + 1)
+#define MT6358_IRQ_MISC_BITS \
+ (MT6358_IRQ_SPI_CMD_ALERT - MT6358_IRQ_MISC_BASE + 1)
+
+#define MT6358_TOP_GEN(sp) \
+{ \
+ .hwirq_base = MT6358_IRQ_##sp##_BASE, \
+ .num_int_regs = \
+ ((MT6358_IRQ_##sp##_BITS - 1) / MT6358_REG_WIDTH) + 1, \
+ .num_int_bits = MT6358_IRQ_##sp##_BITS, \
+ .en_reg = MT6358_##sp##_TOP_INT_CON0, \
+ .en_reg_shift = 0x6, \
+ .sta_reg = MT6358_##sp##_TOP_INT_STATUS0, \
+ .sta_reg_shift = 0x2, \
+ .top_offset = MT6358_##sp##_TOP, \
+}
+
+#endif /* __MFD_MT6358_CORE_H__ */
diff --git a/include/linux/mfd/mt6358/registers.h b/include/linux/mfd/mt6358/registers.h
new file mode 100644
index 0000000..ff5645b
--- /dev/null
+++ b/include/linux/mfd/mt6358/registers.h
@@ -0,0 +1,282 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef __MFD_MT6358_REGISTERS_H__
+#define __MFD_MT6358_REGISTERS_H__
+
+/* PMIC Registers */
+#define MT6358_SWCID 0xa
+#define MT6358_MISC_TOP_INT_CON0 0x188
+#define MT6358_MISC_TOP_INT_STATUS0 0x194
+#define MT6358_TOP_INT_STATUS0 0x19e
+#define MT6358_SCK_TOP_INT_CON0 0x52e
+#define MT6358_SCK_TOP_INT_STATUS0 0x53a
+#define MT6358_EOSC_CALI_CON0 0x540
+#define MT6358_EOSC_CALI_CON1 0x542
+#define MT6358_RTC_MIX_CON0 0x544
+#define MT6358_RTC_MIX_CON1 0x546
+#define MT6358_RTC_MIX_CON2 0x548
+#define MT6358_RTC_DSN_ID 0x580
+#define MT6358_RTC_DSN_REV0 0x582
+#define MT6358_RTC_DBI 0x584
+#define MT6358_RTC_DXI 0x586
+#define MT6358_RTC_BBPU 0x588
+#define MT6358_RTC_IRQ_STA 0x58a
+#define MT6358_RTC_IRQ_EN 0x58c
+#define MT6358_RTC_CII_EN 0x58e
+#define MT6358_RTC_AL_MASK 0x590
+#define MT6358_RTC_TC_SEC 0x592
+#define MT6358_RTC_TC_MIN 0x594
+#define MT6358_RTC_TC_HOU 0x596
+#define MT6358_RTC_TC_DOM 0x598
+#define MT6358_RTC_TC_DOW 0x59a
+#define MT6358_RTC_TC_MTH 0x59c
+#define MT6358_RTC_TC_YEA 0x59e
+#define MT6358_RTC_AL_SEC 0x5a0
+#define MT6358_RTC_AL_MIN 0x5a2
+#define MT6358_RTC_AL_HOU 0x5a4
+#define MT6358_RTC_AL_DOM 0x5a6
+#define MT6358_RTC_AL_DOW 0x5a8
+#define MT6358_RTC_AL_MTH 0x5aa
+#define MT6358_RTC_AL_YEA 0x5ac
+#define MT6358_RTC_OSC32CON 0x5ae
+#define MT6358_RTC_POWERKEY1 0x5b0
+#define MT6358_RTC_POWERKEY2 0x5b2
+#define MT6358_RTC_PDN1 0x5b4
+#define MT6358_RTC_PDN2 0x5b6
+#define MT6358_RTC_SPAR0 0x5b8
+#define MT6358_RTC_SPAR1 0x5ba
+#define MT6358_RTC_PROT 0x5bc
+#define MT6358_RTC_DIFF 0x5be
+#define MT6358_RTC_CALI 0x5c0
+#define MT6358_RTC_WRTGR 0x5c2
+#define MT6358_RTC_CON 0x5c4
+#define MT6358_RTC_SEC_CTRL 0x5c6
+#define MT6358_RTC_INT_CNT 0x5c8
+#define MT6358_RTC_SEC_DAT0 0x5ca
+#define MT6358_RTC_SEC_DAT1 0x5cc
+#define MT6358_RTC_SEC_DAT2 0x5ce
+#define MT6358_RTC_SEC_DSN_ID 0x600
+#define MT6358_RTC_SEC_DSN_REV0 0x602
+#define MT6358_RTC_SEC_DBI 0x604
+#define MT6358_RTC_SEC_DXI 0x606
+#define MT6358_RTC_TC_SEC_SEC 0x608
+#define MT6358_RTC_TC_MIN_SEC 0x60a
+#define MT6358_RTC_TC_HOU_SEC 0x60c
+#define MT6358_RTC_TC_DOM_SEC 0x60e
+#define MT6358_RTC_TC_DOW_SEC 0x610
+#define MT6358_RTC_TC_MTH_SEC 0x612
+#define MT6358_RTC_TC_YEA_SEC 0x614
+#define MT6358_RTC_SEC_CK_PDN 0x616
+#define MT6358_RTC_SEC_WRTGR 0x618
+#define MT6358_PSC_TOP_INT_CON0 0x910
+#define MT6358_PSC_TOP_INT_STATUS0 0x91c
+#define MT6358_BM_TOP_INT_CON0 0xc32
+#define MT6358_BM_TOP_INT_CON1 0xc38
+#define MT6358_BM_TOP_INT_STATUS0 0xc4a
+#define MT6358_BM_TOP_INT_STATUS1 0xc4c
+#define MT6358_HK_TOP_INT_CON0 0xf92
+#define MT6358_HK_TOP_INT_STATUS0 0xf9e
+#define MT6358_BUCK_TOP_INT_CON0 0x1318
+#define MT6358_BUCK_TOP_INT_STATUS0 0x1324
+#define MT6358_BUCK_VPROC11_CON0 0x1388
+#define MT6358_BUCK_VPROC11_DBG0 0x139e
+#define MT6358_BUCK_VPROC11_DBG1 0x13a0
+#define MT6358_BUCK_VPROC11_ELR0 0x13a6
+#define MT6358_BUCK_VPROC12_CON0 0x1408
+#define MT6358_BUCK_VPROC12_DBG0 0x141e
+#define MT6358_BUCK_VPROC12_DBG1 0x1420
+#define MT6358_BUCK_VPROC12_ELR0 0x1426
+#define MT6358_BUCK_VCORE_CON0 0x1488
+#define MT6358_BUCK_VCORE_DBG0 0x149e
+#define MT6358_BUCK_VCORE_DBG1 0x14a0
+#define MT6358_BUCK_VCORE_ELR0 0x14aa
+#define MT6358_BUCK_VGPU_CON0 0x1508
+#define MT6358_BUCK_VGPU_DBG0 0x151e
+#define MT6358_BUCK_VGPU_DBG1 0x1520
+#define MT6358_BUCK_VGPU_ELR0 0x1526
+#define MT6358_BUCK_VMODEM_CON0 0x1588
+#define MT6358_BUCK_VMODEM_DBG0 0x159e
+#define MT6358_BUCK_VMODEM_DBG1 0x15a0
+#define MT6358_BUCK_VMODEM_ELR0 0x15a6
+#define MT6358_BUCK_VDRAM1_CON0 0x1608
+#define MT6358_BUCK_VDRAM1_DBG0 0x161e
+#define MT6358_BUCK_VDRAM1_DBG1 0x1620
+#define MT6358_BUCK_VDRAM1_ELR0 0x1626
+#define MT6358_BUCK_VS1_CON0 0x1688
+#define MT6358_BUCK_VS1_DBG0 0x169e
+#define MT6358_BUCK_VS1_DBG1 0x16a0
+#define MT6358_BUCK_VS1_ELR0 0x16ae
+#define MT6358_BUCK_VS2_CON0 0x1708
+#define MT6358_BUCK_VS2_DBG0 0x171e
+#define MT6358_BUCK_VS2_DBG1 0x1720
+#define MT6358_BUCK_VS2_ELR0 0x172e
+#define MT6358_BUCK_VPA_CON0 0x1788
+#define MT6358_BUCK_VPA_CON1 0x178a
+#define MT6358_BUCK_VPA_ELR0 MT6358_BUCK_VPA_CON1
+#define MT6358_BUCK_VPA_DBG0 0x1792
+#define MT6358_BUCK_VPA_DBG1 0x1794
+#define MT6358_VPROC_ANA_CON0 0x180c
+#define MT6358_VCORE_VGPU_ANA_CON0 0x1828
+#define MT6358_VMODEM_ANA_CON0 0x1888
+#define MT6358_VDRAM1_ANA_CON0 0x1896
+#define MT6358_VS1_ANA_CON0 0x18a2
+#define MT6358_VS2_ANA_CON0 0x18ae
+#define MT6358_VPA_ANA_CON0 0x18ba
+#define MT6358_LDO_TOP_INT_CON0 0x1a50
+#define MT6358_LDO_TOP_INT_CON1 0x1a56
+#define MT6358_LDO_TOP_INT_STATUS0 0x1a68
+#define MT6358_LDO_TOP_INT_STATUS1 0x1a6a
+#define MT6358_LDO_VXO22_CON0 0x1a88
+#define MT6358_LDO_VXO22_CON1 0x1a96
+#define MT6358_LDO_VA12_CON0 0x1a9c
+#define MT6358_LDO_VA12_CON1 0x1aaa
+#define MT6358_LDO_VAUX18_CON0 0x1ab0
+#define MT6358_LDO_VAUX18_CON1 0x1abe
+#define MT6358_LDO_VAUD28_CON0 0x1ac4
+#define MT6358_LDO_VAUD28_CON1 0x1ad2
+#define MT6358_LDO_VIO28_CON0 0x1ad8
+#define MT6358_LDO_VIO28_CON1 0x1ae6
+#define MT6358_LDO_VIO18_CON0 0x1aec
+#define MT6358_LDO_VIO18_CON1 0x1afa
+#define MT6358_LDO_VDRAM2_CON0 0x1b08
+#define MT6358_LDO_VDRAM2_CON1 0x1b16
+#define MT6358_LDO_VEMC_CON0 0x1b1c
+#define MT6358_LDO_VEMC_CON1 0x1b2a
+#define MT6358_LDO_VUSB_CON0_0 0x1b30
+#define MT6358_LDO_VUSB_CON1 0x1b40
+#define MT6358_LDO_VSRAM_PROC11_CON0 0x1b46
+#define MT6358_LDO_VSRAM_PROC11_DBG0 0x1b60
+#define MT6358_LDO_VSRAM_PROC11_DBG1 0x1b62
+#define MT6358_LDO_VSRAM_PROC11_TRACKING_CON0 0x1b64
+#define MT6358_LDO_VSRAM_PROC11_TRACKING_CON1 0x1b66
+#define MT6358_LDO_VSRAM_PROC11_TRACKING_CON2 0x1b68
+#define MT6358_LDO_VSRAM_PROC11_TRACKING_CON3 0x1b6a
+#define MT6358_LDO_VSRAM_PROC12_TRACKING_CON0 0x1b6c
+#define MT6358_LDO_VSRAM_PROC12_TRACKING_CON1 0x1b6e
+#define MT6358_LDO_VSRAM_PROC12_TRACKING_CON2 0x1b70
+#define MT6358_LDO_VSRAM_PROC12_TRACKING_CON3 0x1b72
+#define MT6358_LDO_VSRAM_WAKEUP_CON0 0x1b74
+#define MT6358_LDO_GON1_ELR_NUM 0x1b76
+#define MT6358_LDO_VDRAM2_ELR0 0x1b78
+#define MT6358_LDO_VSRAM_PROC12_CON0 0x1b88
+#define MT6358_LDO_VSRAM_PROC12_DBG0 0x1ba2
+#define MT6358_LDO_VSRAM_PROC12_DBG1 0x1ba4
+#define MT6358_LDO_VSRAM_OTHERS_CON0 0x1ba6
+#define MT6358_LDO_VSRAM_OTHERS_DBG0 0x1bc0
+#define MT6358_LDO_VSRAM_OTHERS_DBG1 0x1bc2
+#define MT6358_LDO_VSRAM_GPU_CON0 0x1bc8
+#define MT6358_LDO_VSRAM_GPU_DBG0 0x1be2
+#define MT6358_LDO_VSRAM_GPU_DBG1 0x1be4
+#define MT6358_LDO_VSRAM_CON0 0x1bee
+#define MT6358_LDO_VSRAM_CON1 0x1bf0
+#define MT6358_LDO_VSRAM_CON2 0x1bf2
+#define MT6358_LDO_VSRAM_CON3 0x1bf4
+#define MT6358_LDO_VFE28_CON0 0x1c08
+#define MT6358_LDO_VFE28_CON1 0x1c16
+#define MT6358_LDO_VFE28_CON2 0x1c18
+#define MT6358_LDO_VFE28_CON3 0x1c1a
+#define MT6358_LDO_VRF18_CON0 0x1c1c
+#define MT6358_LDO_VRF18_CON1 0x1c2a
+#define MT6358_LDO_VRF18_CON2 0x1c2c
+#define MT6358_LDO_VRF18_CON3 0x1c2e
+#define MT6358_LDO_VRF12_CON0 0x1c30
+#define MT6358_LDO_VRF12_CON1 0x1c3e
+#define MT6358_LDO_VRF12_CON2 0x1c40
+#define MT6358_LDO_VRF12_CON3 0x1c42
+#define MT6358_LDO_VEFUSE_CON0 0x1c44
+#define MT6358_LDO_VEFUSE_CON1 0x1c52
+#define MT6358_LDO_VEFUSE_CON2 0x1c54
+#define MT6358_LDO_VEFUSE_CON3 0x1c56
+#define MT6358_LDO_VCN18_CON0 0x1c58
+#define MT6358_LDO_VCN18_CON1 0x1c66
+#define MT6358_LDO_VCN18_CON2 0x1c68
+#define MT6358_LDO_VCN18_CON3 0x1c6a
+#define MT6358_LDO_VCAMA1_CON0 0x1c6c
+#define MT6358_LDO_VCAMA1_CON1 0x1c7a
+#define MT6358_LDO_VCAMA1_CON2 0x1c7c
+#define MT6358_LDO_VCAMA1_CON3 0x1c7e
+#define MT6358_LDO_VCAMA2_CON0 0x1c88
+#define MT6358_LDO_VCAMA2_CON1 0x1c96
+#define MT6358_LDO_VCAMA2_CON2 0x1c98
+#define MT6358_LDO_VCAMA2_CON3 0x1c9a
+#define MT6358_LDO_VCAMD_CON0 0x1c9c
+#define MT6358_LDO_VCAMD_CON1 0x1caa
+#define MT6358_LDO_VCAMD_CON2 0x1cac
+#define MT6358_LDO_VCAMD_CON3 0x1cae
+#define MT6358_LDO_VCAMIO_CON0 0x1cb0
+#define MT6358_LDO_VCAMIO_CON1 0x1cbe
+#define MT6358_LDO_VCAMIO_CON2 0x1cc0
+#define MT6358_LDO_VCAMIO_CON3 0x1cc2
+#define MT6358_LDO_VMC_CON0 0x1cc4
+#define MT6358_LDO_VMC_CON1 0x1cd2
+#define MT6358_LDO_VMC_CON2 0x1cd4
+#define MT6358_LDO_VMC_CON3 0x1cd6
+#define MT6358_LDO_VMCH_CON0 0x1cd8
+#define MT6358_LDO_VMCH_CON1 0x1ce6
+#define MT6358_LDO_VMCH_CON2 0x1ce8
+#define MT6358_LDO_VMCH_CON3 0x1cea
+#define MT6358_LDO_VIBR_CON0 0x1d08
+#define MT6358_LDO_VIBR_CON1 0x1d16
+#define MT6358_LDO_VIBR_CON2 0x1d18
+#define MT6358_LDO_VIBR_CON3 0x1d1a
+#define MT6358_LDO_VCN33_CON0_0 0x1d1c
+#define MT6358_LDO_VCN33_CON0_1 0x1d2a
+#define MT6358_LDO_VCN33_CON1 0x1d2c
+#define MT6358_LDO_VCN33_BT_CON1 MT6358_LDO_VCN33_CON1
+#define MT6358_LDO_VCN33_WIFI_CON1 MT6358_LDO_VCN33_CON1
+#define MT6358_LDO_VCN33_CON2 0x1d2e
+#define MT6358_LDO_VCN33_CON3 0x1d30
+#define MT6358_LDO_VLDO28_CON0_0 0x1d32
+#define MT6358_LDO_VLDO28_CON0_1 0x1d40
+#define MT6358_LDO_VLDO28_CON1 0x1d42
+#define MT6358_LDO_VLDO28_CON2 0x1d44
+#define MT6358_LDO_VLDO28_CON3 0x1d46
+#define MT6358_LDO_VSIM1_CON0 0x1d48
+#define MT6358_LDO_VSIM1_CON1 0x1d56
+#define MT6358_LDO_VSIM1_CON2 0x1d58
+#define MT6358_LDO_VSIM1_CON3 0x1d5a
+#define MT6358_LDO_VSIM2_CON0 0x1d5c
+#define MT6358_LDO_VSIM2_CON1 0x1d6a
+#define MT6358_LDO_VSIM2_CON2 0x1d6c
+#define MT6358_LDO_VSIM2_CON3 0x1d6e
+#define MT6358_LDO_VCN28_CON0 0x1d88
+#define MT6358_LDO_VCN28_CON1 0x1d96
+#define MT6358_LDO_VCN28_CON2 0x1d98
+#define MT6358_LDO_VCN28_CON3 0x1d9a
+#define MT6358_VRTC28_CON0 0x1d9c
+#define MT6358_LDO_VBIF28_CON0 0x1d9e
+#define MT6358_LDO_VBIF28_CON1 0x1dac
+#define MT6358_LDO_VBIF28_CON2 0x1dae
+#define MT6358_LDO_VBIF28_CON3 0x1db0
+#define MT6358_VCAMA1_ANA_CON0 0x1e08
+#define MT6358_VCAMA2_ANA_CON0 0x1e0c
+#define MT6358_VCN33_ANA_CON0 0x1e28
+#define MT6358_VSIM1_ANA_CON0 0x1e2c
+#define MT6358_VSIM2_ANA_CON0 0x1e30
+#define MT6358_VUSB_ANA_CON0 0x1e34
+#define MT6358_VEMC_ANA_CON0 0x1e38
+#define MT6358_VLDO28_ANA_CON0 0x1e3c
+#define MT6358_VIO28_ANA_CON0 0x1e40
+#define MT6358_VIBR_ANA_CON0 0x1e44
+#define MT6358_VMCH_ANA_CON0 0x1e48
+#define MT6358_VMC_ANA_CON0 0x1e4c
+#define MT6358_VRF18_ANA_CON0 0x1e88
+#define MT6358_VCN18_ANA_CON0 0x1e8c
+#define MT6358_VCAMIO_ANA_CON0 0x1e90
+#define MT6358_VIO18_ANA_CON0 0x1e94
+#define MT6358_VEFUSE_ANA_CON0 0x1e98
+#define MT6358_VRF12_ANA_CON0 0x1e9c
+#define MT6358_VSRAM_PROC11_ANA_CON0 0x1ea0
+#define MT6358_VSRAM_PROC12_ANA_CON0 0x1ea4
+#define MT6358_VSRAM_OTHERS_ANA_CON0 0x1ea6
+#define MT6358_VSRAM_GPU_ANA_CON0 0x1ea8
+#define MT6358_VDRAM2_ANA_CON0 0x1eaa
+#define MT6358_VCAMD_ANA_CON0 0x1eae
+#define MT6358_VA12_ANA_CON0 0x1eb2
+#define MT6358_AUD_TOP_INT_CON0 0x2228
+#define MT6358_AUD_TOP_INT_STATUS0 0x2234
+
+#endif /* __MFD_MT6358_REGISTERS_H__ */
diff --git a/include/linux/mfd/mt6397/core.h b/include/linux/mfd/mt6397/core.h
index 23e21da..cd73438 100644
--- a/include/linux/mfd/mt6397/core.h
+++ b/include/linux/mfd/mt6397/core.h
@@ -11,6 +11,7 @@
enum chip_id {
MT6323_CHIP_ID = 0x23,
+ MT6358_CHIP_ID = 0x58,
MT6391_CHIP_ID = 0x91,
MT6397_CHIP_ID = 0x97,
};
@@ -64,8 +65,10 @@ struct mt6397_chip {
u16 int_con[2];
u16 int_status[2];
u16 chip_id;
+ void *irq_data;
};
+int mt6358_irq_init(struct mt6397_chip *chip);
int mt6397_irq_init(struct mt6397_chip *chip);
#endif /* __MFD_MT6397_CORE_H__ */
--
2.6.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox