Devicetree
 help / color / mirror / Atom feed
* Re: [PATCHv2 01/10] mmc: dw_mmc: display the real register value on debugfs
From: Shawn Lin @ 2016-11-16  9:04 UTC (permalink / raw)
  To: Jaehoon Chung
  Cc: linux-mmc-u79uwXL29TY76Z2rM5mHXA,
	shawn.lin-TNX95d0MmH7DzftRWevZcw,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	ulf.hansson-QSEj5FYQhm4dnm+yROfE0A, heiko-4mtYJXux2i+zQB+pC5nmwQ,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A
In-Reply-To: <20161115101232.3854-2-jh80.chung-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>

在 2016/11/15 18:12, Jaehoon Chung 写道:
> Developer wants to see the real register value, not register offset.
> This patch fixed to display the real value of register.
>

IIRC, you had submited some similar patch but I don't remember
why it wasn't merged?

Anyway,

Reviewed-by: Shawn Lin <shawn.lin-TNX95d0MmH7DzftRWevZcw@public.gmane.org>

> Signed-off-by: Jaehoon Chung <jh80.chung-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
> Tested-by: Heiko Stuebner <heiko-4mtYJXux2i+zQB+pC5nmwQ@public.gmane.org>
> ---
>  drivers/mmc/host/dw_mmc.c | 14 ++++++++------
>  1 file changed, 8 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
> index a16c537..e53899e 100644
> --- a/drivers/mmc/host/dw_mmc.c
> +++ b/drivers/mmc/host/dw_mmc.c
> @@ -165,12 +165,14 @@ static const struct file_operations dw_mci_req_fops = {
>
>  static int dw_mci_regs_show(struct seq_file *s, void *v)
>  {
> -	seq_printf(s, "STATUS:\t0x%08x\n", SDMMC_STATUS);
> -	seq_printf(s, "RINTSTS:\t0x%08x\n", SDMMC_RINTSTS);
> -	seq_printf(s, "CMD:\t0x%08x\n", SDMMC_CMD);
> -	seq_printf(s, "CTRL:\t0x%08x\n", SDMMC_CTRL);
> -	seq_printf(s, "INTMASK:\t0x%08x\n", SDMMC_INTMASK);
> -	seq_printf(s, "CLKENA:\t0x%08x\n", SDMMC_CLKENA);
> +	struct dw_mci *host = s->private;
> +
> +	seq_printf(s, "STATUS:\t0x%08x\n", mci_readl(host, STATUS));
> +	seq_printf(s, "RINTSTS:\t0x%08x\n", mci_readl(host, RINTSTS));
> +	seq_printf(s, "CMD:\t0x%08x\n", mci_readl(host, CMD));
> +	seq_printf(s, "CTRL:\t0x%08x\n", mci_readl(host, CTRL));
> +	seq_printf(s, "INTMASK:\t0x%08x\n", mci_readl(host, INTMASK));
> +	seq_printf(s, "CLKENA:\t0x%08x\n", mci_readl(host, CLKENA));
>
>  	return 0;
>  }
>


-- 
Best Regards
Shawn Lin

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCHv2 06/10] mmc: core: move the cookie's enum values from sdhci.h to mmc.h
From: Adrian Hunter @ 2016-11-16  9:04 UTC (permalink / raw)
  To: Jaehoon Chung, linux-mmc
  Cc: devicetree, Ulf Hansson, heiko, shawn.lin, robh+dt
In-Reply-To: <4168313a-07bc-00a7-ecc8-1ca4978c4d8c@samsung.com>

On 16/11/16 10:58, Jaehoon Chung wrote:
> On 11/16/2016 05:28 PM, Adrian Hunter wrote:
>> On 16/11/16 10:25, Jaehoon Chung wrote:
>>> On 11/16/2016 05:09 PM, Adrian Hunter wrote:
>>>> On 16/11/16 09:53, Jaehoon Chung wrote:
>>>>> Added Adrian for sdhci.h
>>>>>
>>>>> On 11/15/2016 07:12 PM, Jaehoon Chung wrote:
>>>>>> It's not for only sdhci controller.
>>>>>> So it can be moved from sdhci.h to mmc.h. And renamed from sdhci_cookie
>>>>>> to mmc_cookie.
>>>>
>>>> The cookie is currently host private data, so I don't understand the
>>>> motivation behind this.
>>>
>>> dwmmc controller can also use the data->host_cookie. because it's working with post/pre_req().
>>>
>>> So i think it can be used about both sdhci and dwmmc.
>>> Is there no reason that add the private dwmmc data?
>>>
>>> With these cookie value, update the dwmmc controller for post/pre_req().
>>>
>>> https://patchwork.kernel.org/patch/9429287/
>>
>> So why not define dwmmc cookies in dw_mmc.c ?
> 
> Because I understood that it's not sdhci specific cookies. It can be used generally, doesn't?
> 
> Role of post/pre_req() in host controller is the doing dma_map/unmap().
> And data's cookies only needs to notice whether dma is mapped or unmapped, etc.
> 
> Well, If it's really private value and should be added other cookies values in future, i will put cookies in dw_mmc.h.
> (it should be duplicated in sdhci and dwmmc.)

Probably all host controllers should do cookies the same way, but they don't
at the moment, so there is no reason to share definitions.


^ permalink raw reply

* Re: [PATCHv2 02/10] mmc: dw_mmc: fix the debug message for checking card's present
From: Shawn Lin @ 2016-11-16  9:01 UTC (permalink / raw)
  To: Jaehoon Chung
  Cc: linux-mmc-u79uwXL29TY76Z2rM5mHXA,
	shawn.lin-TNX95d0MmH7DzftRWevZcw,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	ulf.hansson-QSEj5FYQhm4dnm+yROfE0A, heiko-4mtYJXux2i+zQB+pC5nmwQ,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A
In-Reply-To: <20161115101232.3854-3-jh80.chung-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>

On 2016/11/15 18:12, Jaehoon Chung wrote:
> If display the debug message, this message should be spamming.
> If flags is maintained the previous value, didn't display the debug
> message.
>
> Signed-off-by: Jaehoon Chung <jh80.chung-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
> Tested-by: Heiko Stuebner <heiko-4mtYJXux2i+zQB+pC5nmwQ@public.gmane.org>

Looks correct to me,

Reviewed-by: Shawn Lin <shawn.lin-TNX95d0MmH7DzftRWevZcw@public.gmane.org>

> ---
>  drivers/mmc/host/dw_mmc.c | 7 ++-----
>  1 file changed, 2 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
> index e53899e..6c0c4c5 100644
> --- a/drivers/mmc/host/dw_mmc.c
> +++ b/drivers/mmc/host/dw_mmc.c
> @@ -1537,13 +1537,10 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
>  			== 0 ? 1 : 0;
>
>  	spin_lock_bh(&host->lock);
> -	if (present) {
> -		set_bit(DW_MMC_CARD_PRESENT, &slot->flags);
> +	if (present && !test_and_set_bit(DW_MMC_CARD_PRESENT, &slot->flags))
>  		dev_dbg(&mmc->class_dev, "card is present\n");
> -	} else {
> -		clear_bit(DW_MMC_CARD_PRESENT, &slot->flags);
> +	else if (!test_and_clear_bit(DW_MMC_CARD_PRESENT, &slot->flags))
>  		dev_dbg(&mmc->class_dev, "card is not present\n");
> -	}
>  	spin_unlock_bh(&host->lock);
>
>  	return present;
>


-- 
Best Regards
Shawn Lin

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCHv2 06/10] mmc: core: move the cookie's enum values from sdhci.h to mmc.h
From: Jaehoon Chung @ 2016-11-16  8:58 UTC (permalink / raw)
  To: Adrian Hunter, linux-mmc-u79uwXL29TY76Z2rM5mHXA
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA, Ulf Hansson,
	heiko-4mtYJXux2i+zQB+pC5nmwQ, shawn.lin-TNX95d0MmH7DzftRWevZcw,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A
In-Reply-To: <d5321daf-b449-e556-ccf1-cd82d497ea85-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>

On 11/16/2016 05:28 PM, Adrian Hunter wrote:
> On 16/11/16 10:25, Jaehoon Chung wrote:
>> On 11/16/2016 05:09 PM, Adrian Hunter wrote:
>>> On 16/11/16 09:53, Jaehoon Chung wrote:
>>>> Added Adrian for sdhci.h
>>>>
>>>> On 11/15/2016 07:12 PM, Jaehoon Chung wrote:
>>>>> It's not for only sdhci controller.
>>>>> So it can be moved from sdhci.h to mmc.h. And renamed from sdhci_cookie
>>>>> to mmc_cookie.
>>>
>>> The cookie is currently host private data, so I don't understand the
>>> motivation behind this.
>>
>> dwmmc controller can also use the data->host_cookie. because it's working with post/pre_req().
>>
>> So i think it can be used about both sdhci and dwmmc.
>> Is there no reason that add the private dwmmc data?
>>
>> With these cookie value, update the dwmmc controller for post/pre_req().
>>
>> https://patchwork.kernel.org/patch/9429287/
> 
> So why not define dwmmc cookies in dw_mmc.c ?

Because I understood that it's not sdhci specific cookies. It can be used generally, doesn't?

Role of post/pre_req() in host controller is the doing dma_map/unmap().
And data's cookies only needs to notice whether dma is mapped or unmapped, etc.

Well, If it's really private value and should be added other cookies values in future, i will put cookies in dw_mmc.h.
(it should be duplicated in sdhci and dwmmc.)

Best Regards,
Jaehoon Chung

> 
> 
> 
> 

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH 1/3] arm: hisi: add ARCH_MULTI_V5 support
From: wenpan @ 2016-11-16  8:56 UTC (permalink / raw)
  To: Arnd Bergmann, Marty Plummer
  Cc: mturquette-rdvid1DuHRBWk0Htik3J/w, sboyd-sgV2jX0FEOL9JmXXK+q4OQ,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
	linux-I+IVW8TIWO2tmTQ+vhA3Yw, xuwei5-C8/M+/jPZTeaMJb+Lgu22Q,
	linux-clk-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	howell.yang-C8/M+/jPZTeaMJb+Lgu22Q,
	xuejiancheng-C8/M+/jPZTeaMJb+Lgu22Q,
	jalen.hsu-C8/M+/jPZTeaMJb+Lgu22Q,
	lvkuanliang-C8/M+/jPZTeaMJb+Lgu22Q,
	suwenping-C8/M+/jPZTeaMJb+Lgu22Q, raojun-C8/M+/jPZTeaMJb+Lgu22Q,
	kevin.lixu-C8/M+/jPZTeaMJb+Lgu22Q,
	qinxiaojun-hv44wF8Li93QT0dZR+AlfA
In-Reply-To: <5893354.6MrIxqzRoI@wuerfel>

Hi Martyo<\f
Does this confict with your patcho<\x1f If noto<\fI hope this could be merged first.  Besides could you tell me the link to your related patch?

Thanks,
Pan

On 2016/10/17 21:48, Arnd Bergmann wrote:
> On Monday, October 17, 2016 8:07:03 PM CEST Pan Wen wrote:
>> Add support for some HiSilicon SoCs which depend on ARCH_MULTI_V5.
>>
>> Signed-off-by: Pan Wen <wenpan-C8/M+/jPZTeaMJb+Lgu22Q@public.gmane.org>
>>
> 
> Looks ok. I've added Marty Plummer to Cc, he was recently proposing
> patches for Hi3520, which I think is closely related to this one.
> Please try to work together so the patches don't conflict. It should
> be fairly straightforward since you are basically doing the same
> change here.
> 
> 	Arnd
> 
> .
> 

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v7 08/14] mmc: sdhci-msm: Implement set_clock callback for sdhci-msm
From: Ritesh Harjani @ 2016-11-16  8:53 UTC (permalink / raw)
  To: Adrian Hunter, Stephen Boyd, ulf.hansson
  Cc: linux-mmc, shawn.lin, andy.gross, devicetree, linux-clk,
	david.brown, linux-arm-msm, georgi.djakov, alex.lemberg,
	mateusz.nowak, Yuliy.Izrailov, asutoshd, kdorfman, david.griego,
	stummala, venkatg, rnayak, pramod.gurav
In-Reply-To: <875c9051-bd8b-60cf-82e4-3e26612a8623@intel.com>



On 11/16/2016 1:12 PM, Adrian Hunter wrote:
> On 16/11/16 06:42, Ritesh Harjani wrote:
>> Hi,
>>
>> On 11/15/2016 10:40 AM, Ritesh Harjani wrote:
>>> Hi Stephen/Adrian,
>>>
>>> On 11/15/2016 1:07 AM, Stephen Boyd wrote:
>>>> On 11/14, Ritesh Harjani wrote:
>>>>> @@ -577,6 +578,90 @@ static unsigned int
>>>>> sdhci_msm_get_min_clock(struct sdhci_host *host)
>>>>>      return SDHCI_MSM_MIN_CLOCK;
>>>>>  }
>>>>>
>>>>> +/**
>>>>> + * __sdhci_msm_set_clock - sdhci_msm clock control.
>>>>> + *
>>>>> + * Description:
>>>>> + * Implement MSM version of sdhci_set_clock.
>>>>> + * This is required since MSM controller does not
>>>>> + * use internal divider and instead directly control
>>>>> + * the GCC clock as per HW recommendation.
>>>>> + **/
>>>>> +void __sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
>>>>> +{
>>>>> +    u16 clk;
>>>>> +    unsigned long timeout;
>>>>> +
>>>>> +    /*
>>>>> +     * Keep actual_clock as zero -
>>>>> +     * - since there is no divider used so no need of having
>>>>> actual_clock.
>>>>> +     * - MSM controller uses SDCLK for data timeout calculation. If
>>>>> +     *   actual_clock is zero, host->clock is taken for calculation.
>>>>> +     */
>>>>> +    host->mmc->actual_clock = 0;
>>>>> +
>>>>> +    sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
>>>>> +
>>>>> +    if (clock == 0)
>>>>> +        return;
>>>>> +
>>>>> +    /*
>>>>> +     * MSM controller do not use clock divider.
>>>>> +     * Thus read SDHCI_CLOCK_CONTROL and only enable
>>>>> +     * clock with no divider value programmed.
>>>>> +     */
>>>>> +    clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
>>>>> +
>>>>> +    clk |= SDHCI_CLOCK_INT_EN;
>>>>> +    sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
>>>>> +
>>>>> +    /* Wait max 20 ms */
>>>>> +    timeout = 20;
>>>>> +    while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
>>>>> +        & SDHCI_CLOCK_INT_STABLE)) {
>>>>> +        if (timeout == 0) {
>>>>> +            pr_err("%s: Internal clock never stabilised\n",
>>>>> +                   mmc_hostname(host->mmc));
>>>>> +            return;
>>>>> +        }
>>>>> +        timeout--;
>>>>> +        mdelay(1);
>>>>> +    }
>>>>> +
>>>>> +    clk |= SDHCI_CLOCK_CARD_EN;
>>>>> +    sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
>>>>
>>>> This is almost a copy/paste of sdhci_set_clock(). Can we make
>>>> sdhci_set_clock() call a __sdhci_set_clock() function that takes
>>>> unsigned int clock, and also a flag indicating if we want to set
>>>> the internal clock divider or not? Then we can call
>>>> __sdhci_set_clock() from sdhci_set_clock() with (clock, true) as
>>>> arguments and (clock, false).
>> Actually what you may be referring here is some sort of quirks which is not
>> entertained any more for sdhci driver.
>> sdhci is tending towards becoming a library and hence such changes are
>> restricted.
>>
>> But I think we may do below changes to avoid duplication of code which
>> enables the sdhci internal clock and waits for internal clock to be stable.
>>
>> Adrian, could you please tell if this should be ok?
>
> That seems fine, but the name seems too long - how about changing
> sdhci_set_clock_enable to sdhci_enable_clk.
Sure. Will make the changes then.

>
>> Then we may be able to call for sdhci_set_clock_enable function from
>> sdhci_msm_set_clock.
>>
>>
>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>> index 42ef3eb..28e605c 100644
>> --- a/drivers/mmc/host/sdhci.c
>> +++ b/drivers/mmc/host/sdhci.c
>> @@ -1343,19 +1343,8 @@ u16 sdhci_calc_clk(struct sdhci_host *host, unsigned
>> int clock,
>>  }
>>  EXPORT_SYMBOL_GPL(sdhci_calc_clk);
>>
>> -void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
>> +void sdhci_set_clock_enable(struct sdhci_host *host, unsigned short clk)
>>  {
>> -       u16 clk;
>> -       unsigned long timeout;
>> -
>> -       host->mmc->actual_clock = 0;
>> -
>> -       sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
>> -
>> -       if (clock == 0)
>> -               return;
>> -
>> -       clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock);
>>
>>         clk |= SDHCI_CLOCK_INT_EN;
>>         sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
>> @@ -1377,6 +1366,24 @@ void sdhci_set_clock(struct sdhci_host *host,
>> unsigned int clock)
>>         clk |= SDHCI_CLOCK_CARD_EN;
>>         sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
>>  }
>> +EXPORT_SYMBOL_GPL(sdhci_set_clock_enable);
>> +
>> +void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
>> +{
>> +       u16 clk;
>> +       unsigned long timeout;
>> +
>> +       host->mmc->actual_clock = 0;
>> +
>> +       sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
>> +
>> +       if (clock == 0)
>> +               return;
>> +
>> +       clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock);
>> +
>> +       sdhci_set_clock_enable(host, clk);
>> +}
>>  EXPORT_SYMBOL_GPL(sdhci_set_clock);
>>
>>  static void sdhci_set_power_reg(struct sdhci_host *host, unsigned char mode,
>> diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
>> index 766df17..43382e1 100644
>> --- a/drivers/mmc/host/sdhci.h
>> +++ b/drivers/mmc/host/sdhci.h
>> @@ -681,6 +681,7 @@ static inline bool sdhci_sdio_irq_enabled(struct
>> sdhci_host *host)
>>  u16 sdhci_calc_clk(struct sdhci_host *host, unsigned int clock,
>>                    unsigned int *actual_clock);
>>  void sdhci_set_clock(struct sdhci_host *host, unsigned int clock);
>> +void sdhci_set_clock_enable(struct sdhci_host *host, unsigned short clk);
>>  void sdhci_set_power(struct sdhci_host *host, unsigned char mode,
>>                      unsigned short vdd);
>>  void sdhci_set_power_noreg(struct sdhci_host *host, unsigned char mode,
>>
>>
>>
>>> Adrian,
>>> Could you please comment here ?
>>>
>>>>
>>>>> +}
>>>>> +
>>>>> +/* sdhci_msm_set_clock - Called with (host->lock) spinlock held. */
>>>>> +static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned
>>>>> int clock)
>>>>> +{
>>>>> +    struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
>>>>> +    struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
>>>>> +    int rc;
>>>>> +
>>>>> +    if (!clock) {
>>>>> +        msm_host->clk_rate = clock;
>>>>> +        goto out;
>>>>> +    }
>>>>> +
>>>>> +    spin_unlock_irq(&host->lock);
>>>>> +    if (clock != msm_host->clk_rate) {
>>>>
>>>> Why do we need to check here? Can't we call clk_set_rate()
>>>> Unconditionally?
>>> Since it may so happen that above layers may call for ->set_clock
>>> function with same requested clock more than once, hence we cache the
>>> host->clock here.
>>> Also, since requested clock (host->clock) can be say 400Mhz but the
>>> actual pltfm supported clock would be say 384MHz.
>>>
>>>
>>>>
>>>>> +        rc = clk_set_rate(msm_host->clk, clock);
>>>>> +        if (rc) {
>>>>> +            pr_err("%s: Failed to set clock at rate %u\n",
>>>>> +                   mmc_hostname(host->mmc), clock);
>>>>> +            spin_lock_irq(&host->lock);
>>>>> +            goto out;
>>>>
>>>> Or replace the above two lines with goto err;
>>> Ok, I will have another label out_lock instead of err.
>>>>
>>>>> +        }
>>>>> +        msm_host->clk_rate = clock;
>>>>> +        pr_debug("%s: Setting clock at rate %lu\n",
>>>>> +             mmc_hostname(host->mmc), clk_get_rate(msm_host->clk));
>>>>> +    }
>>>>
>>>> And put an err label here.
>>> will put the label here as out_lock;
>>>>
>>>>> +    spin_lock_irq(&host->lock);
>>>>> +out:
>>>>> +    __sdhci_msm_set_clock(host, clock);
>>>>> +}
>>>>> +
>>>>>  static const struct of_device_id sdhci_msm_dt_match[] = {
>>>>>      { .compatible = "qcom,sdhci-msm-v4" },
>>>>>      {},
>>>>
>>>
>>
>

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply

* [PATCH v3 3/3] clk: rockchip: add clock controller for rk1108
From: Shawn Lin @ 2016-11-16  8:49 UTC (permalink / raw)
  To: Heiko Stuebner
  Cc: Stephen Boyd, Rob Herring, devicetree, Andy Yan,
	Michael Turquette, linux-clk, linux-rockchip, Shawn Lin
In-Reply-To: <1479286163-34789-1-git-send-email-shawn.lin@rock-chips.com>

Add the clock tree definition and driver for rk1108 SoC.

Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>

Tested-by: Jacob Chen <jacob2.chen@rock-chips.com>
---

Changes in v3:
- remove some unused clk parent and add some new parent
  to complete all the input clocks.

Changes in v2:
- fix some CodingStyle issues

 drivers/clk/rockchip/Makefile     |   1 +
 drivers/clk/rockchip/clk-rk1108.c | 531 ++++++++++++++++++++++++++++++++++++++
 drivers/clk/rockchip/clk.h        |  15 ++
 3 files changed, 547 insertions(+)
 create mode 100644 drivers/clk/rockchip/clk-rk1108.c

diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile
index b5f2c8e..16e098c 100644
--- a/drivers/clk/rockchip/Makefile
+++ b/drivers/clk/rockchip/Makefile
@@ -11,6 +11,7 @@ obj-y	+= clk-mmc-phase.o
 obj-y	+= clk-ddr.o
 obj-$(CONFIG_RESET_CONTROLLER)	+= softrst.o
 
+obj-y	+= clk-rk1108.o
 obj-y	+= clk-rk3036.o
 obj-y	+= clk-rk3188.o
 obj-y	+= clk-rk3228.o
diff --git a/drivers/clk/rockchip/clk-rk1108.c b/drivers/clk/rockchip/clk-rk1108.c
new file mode 100644
index 0000000..92750d7
--- /dev/null
+++ b/drivers/clk/rockchip/clk-rk1108.c
@@ -0,0 +1,531 @@
+/*
+ * Copyright (c) 2016 Rockchip Electronics Co. Ltd.
+ * Author: Shawn Lin <shawn.lin@rock-chips.com>
+ *         Andy Yan <andy.yan@rock-chips.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/syscore_ops.h>
+#include <dt-bindings/clock/rk1108-cru.h>
+#include "clk.h"
+
+#define RK1108_GRF_SOC_STATUS0	0x480
+
+enum rk1108_plls {
+	apll, dpll, gpll,
+};
+
+static struct rockchip_pll_rate_table rk1108_pll_rates[] = {
+	/* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
+	RK3036_PLL_RATE(1608000000, 1, 67, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1584000000, 1, 66, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1560000000, 1, 65, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1536000000, 1, 64, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1512000000, 1, 63, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1488000000, 1, 62, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1464000000, 1, 61, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1440000000, 1, 60, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1416000000, 1, 59, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1392000000, 1, 58, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1368000000, 1, 57, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1344000000, 1, 56, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1320000000, 1, 55, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1296000000, 1, 54, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1272000000, 1, 53, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1248000000, 1, 52, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1188000000, 2, 99, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1104000000, 1, 46, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1100000000, 12, 550, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0),
+	RK3036_PLL_RATE(1000000000, 6, 500, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 984000000, 1, 82, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 960000000, 1, 80, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 936000000, 1, 78, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 912000000, 1, 76, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 900000000, 4, 300, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 888000000, 1, 74, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 864000000, 1, 72, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 840000000, 1, 70, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 816000000, 1, 68, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 800000000, 6, 400, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 700000000, 6, 350, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 696000000, 1, 58, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 600000000, 1, 75, 3, 1, 1, 0),
+	RK3036_PLL_RATE( 594000000, 2, 99, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 504000000, 1, 63, 3, 1, 1, 0),
+	RK3036_PLL_RATE( 500000000, 6, 250, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 408000000, 1, 68, 2, 2, 1, 0),
+	RK3036_PLL_RATE( 312000000, 1, 52, 2, 2, 1, 0),
+	RK3036_PLL_RATE( 216000000, 1, 72, 4, 2, 1, 0),
+	RK3036_PLL_RATE(  96000000, 1, 64, 4, 4, 1, 0),
+	{ /* sentinel */ },
+};
+
+#define RK1108_DIV_CORE_MASK		0xf
+#define RK1108_DIV_CORE_SHIFT		4
+
+#define RK1108_CLKSEL0(_core_peri_div)	\
+	{				\
+		.reg = RK1108_CLKSEL_CON(1),	\
+		.val = HIWORD_UPDATE(_core_peri_div, RK1108_DIV_CORE_MASK,\
+				RK1108_DIV_CORE_SHIFT)	\
+	}
+
+#define RK1108_CPUCLK_RATE(_prate, _core_peri_div)			\
+	{								\
+		.prate = _prate,					\
+		.divs = {						\
+			RK1108_CLKSEL0(_core_peri_div),		\
+		},							\
+	}
+
+static struct rockchip_cpuclk_rate_table rk1108_cpuclk_rates[] __initdata = {
+	RK1108_CPUCLK_RATE(816000000, 4),
+	RK1108_CPUCLK_RATE(600000000, 4),
+	RK1108_CPUCLK_RATE(312000000, 4),
+};
+
+static const struct rockchip_cpuclk_reg_data rk1108_cpuclk_data = {
+	.core_reg = RK1108_CLKSEL_CON(0),
+	.div_core_shift = 0,
+	.div_core_mask = 0x1f,
+	.mux_core_alt = 1,
+	.mux_core_main = 0,
+	.mux_core_shift = 8,
+	.mux_core_mask = 0x1,
+};
+
+PNAME(mux_pll_p)		= { "xin24m", "xin24m"};
+PNAME(mux_ddrphy_p)		= { "dpll_ddr", "gpll_ddr", "apll_ddr" };
+PNAME(mux_armclk_p)		= { "apll_core", "gpll_core", "dpll_core" };
+PNAME(mux_usb480m_pre_p)	= { "usbphy", "xin24m" };
+PNAME(mux_hdmiphy_phy_p)	= { "hdmiphy", "xin24m" };
+PNAME(mux_dclk_hdmiphy_pre_p)	= { "dclk_hdmiphy_src_gpll", "dclk_hdmiphy_src_dpll" };
+PNAME(mux_pll_src_4plls_p)	= { "dpll", "hdmiphy", "gpll", "usb480m" };
+PNAME(mux_pll_src_3plls_p)	= { "apll", "gpll", "dpll" };
+PNAME(mux_pll_src_2plls_p)	= { "dpll", "gpll" };
+PNAME(mux_pll_src_apll_gpll_p)	= { "apll", "gpll" };
+PNAME(mux_aclk_peri_src_p)	= { "aclk_peri_src_dpll", "aclk_peri_src_gpll" };
+PNAME(mux_aclk_bus_src_p)	= { "aclk_bus_src_gpll", "aclk_bus_src_apll", "aclk_bus_src_dpll" };
+PNAME(mux_mmc_src_p)		= { "dpll", "gpll", "xin24m", "usb480m" };
+PNAME(mux_pll_src_dpll_gpll_usb480m_p)	= { "dpll", "gpll", "usb480m" };
+PNAME(mux_uart0_p)		= { "uart0_src", "uart0_frac", "xin24m" };
+PNAME(mux_uart1_p)		= { "uart1_src", "uart1_frac", "xin24m" };
+PNAME(mux_uart2_p)		= { "uart2_src", "uart2_frac", "xin24m" };
+PNAME(mux_sclk_macphy_p)	= { "sclk_macphy_pre", "ext_gmac" };
+PNAME(mux_i2s0_pre_p)		= { "i2s0_src", "i2s0_frac", "ext_i2s", "xin12m" };
+PNAME(mux_i2s_out_p)		= { "i2s0_pre", "xin12m" };
+PNAME(mux_i2s1_p)		= { "i2s1_src", "i2s1_frac", "xin12m" };
+PNAME(mux_i2s2_p)		= { "i2s2_src", "i2s2_frac", "xin12m" };
+
+static struct rockchip_pll_clock rk1108_pll_clks[] __initdata = {
+	[apll] = PLL(pll_rk3399, PLL_APLL, "apll", mux_pll_p, 0, RK1108_PLL_CON(0),
+		     RK1108_PLL_CON(3), 8, 31, 0, rk1108_pll_rates),
+	[dpll] = PLL(pll_rk3399, PLL_DPLL, "dpll", mux_pll_p, 0, RK1108_PLL_CON(8),
+		     RK1108_PLL_CON(11), 8, 31, 0, NULL),
+	[gpll] = PLL(pll_rk3399, PLL_GPLL, "gpll", mux_pll_p, 0, RK1108_PLL_CON(16),
+		     RK1108_PLL_CON(19), 8, 31, ROCKCHIP_PLL_SYNC_RATE, rk1108_pll_rates),
+};
+
+#define MFLAGS CLK_MUX_HIWORD_MASK
+#define DFLAGS CLK_DIVIDER_HIWORD_MASK
+#define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE)
+#define IFLAGS ROCKCHIP_INVERTER_HIWORD_MASK
+
+static struct rockchip_clk_branch rk1108_uart0_fracmux __initdata =
+	MUX(SCLK_UART0, "sclk_uart0", mux_uart0_p, CLK_SET_RATE_PARENT,
+			RK1108_CLKSEL_CON(13), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk1108_uart1_fracmux __initdata =
+	MUX(SCLK_UART1, "sclk_uart1", mux_uart1_p, CLK_SET_RATE_PARENT,
+			RK1108_CLKSEL_CON(14), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk1108_uart2_fracmux __initdata =
+	MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT,
+			RK1108_CLKSEL_CON(15), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk1108_i2s0_fracmux __initdata =
+	MUX(0, "i2s0_pre", mux_i2s0_pre_p, CLK_SET_RATE_PARENT,
+			RK1108_CLKSEL_CON(5), 12, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk1108_i2s1_fracmux __initdata =
+	MUX(0, "i2s1_pre", mux_i2s1_p, CLK_SET_RATE_PARENT,
+			RK1108_CLKSEL_CON(6), 12, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk1108_i2s2_fracmux __initdata =
+	MUX(0, "i2s2_pre", mux_i2s2_p, CLK_SET_RATE_PARENT,
+			RK1108_CLKSEL_CON(7), 12, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk1108_clk_branches[] __initdata = {
+	MUX(0, "hdmi_phy", mux_hdmiphy_phy_p, CLK_SET_RATE_PARENT,
+			RK1108_MISC_CON, 13, 2, MFLAGS),
+	MUX(0, "usb480m", mux_usb480m_pre_p, CLK_SET_RATE_PARENT,
+			RK1108_MISC_CON, 15, 2, MFLAGS),
+	/*
+	 * Clock-Architecture Diagram 2
+	 */
+
+	/* PD_CORE */
+	GATE(0, "dpll_core", "dpll", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(0), 1, GFLAGS),
+	GATE(0, "apll_core", "apll", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(0), 0, GFLAGS),
+	GATE(0, "gpll_core", "gpll", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(0), 2, GFLAGS),
+	COMPOSITE_NOMUX(0, "pclken_dbg", "armclk", CLK_IGNORE_UNUSED,
+			RK1108_CLKSEL_CON(1), 4, 4, DFLAGS | CLK_DIVIDER_READ_ONLY,
+			RK1108_CLKGATE_CON(0), 5, GFLAGS),
+	COMPOSITE_NOMUX(ACLK_ENMCORE, "aclkenm_core", "armclk", CLK_IGNORE_UNUSED,
+			RK1108_CLKSEL_CON(1), 0, 3, DFLAGS | CLK_DIVIDER_READ_ONLY,
+			RK1108_CLKGATE_CON(0), 4, GFLAGS),
+	GATE(ACLK_CORE, "aclk_core", "aclkenm_core", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(11), 0, GFLAGS),
+	GATE(0, "pclk_dbg", "pclken_dbg", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(11), 1, GFLAGS),
+
+	/* PD_RKVENC */
+
+	/* PD_RKVDEC */
+
+	/* PD_PMU_wrapper */
+	COMPOSITE_NOMUX(0, "pmu_24m_ena", "gpll", CLK_IGNORE_UNUSED,
+			RK1108_CLKSEL_CON(38), 0, 5, DFLAGS,
+			RK1108_CLKGATE_CON(8), 12, GFLAGS),
+	GATE(0, "pmu", "pmu_24m_ena", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(10), 0, GFLAGS),
+	GATE(0, "intmem1", "pmu_24m_ena", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(10), 1, GFLAGS),
+	GATE(0, "gpio0_pmu", "pmu_24m_ena", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(10), 2, GFLAGS),
+	GATE(0, "pmugrf", "pmu_24m_ena", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(10), 3, GFLAGS),
+	GATE(0, "pmu_noc", "pmu_24m_ena", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(10), 4, GFLAGS),
+	GATE(0, "i2c0_pmu_pclk", "pmu_24m_ena", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(10), 5, GFLAGS),
+	GATE(0, "pwm0_pmu_pclk", "pmu_24m_ena", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(10), 6, GFLAGS),
+	COMPOSITE(0, "pwm0_pmu_clk", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
+			RK1108_CLKSEL_CON(12), 7, 1, MFLAGS, 0, 7, DFLAGS,
+			RK1108_CLKGATE_CON(8), 15, GFLAGS),
+	COMPOSITE(0, "i2c0_pmu_clk", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
+			RK1108_CLKSEL_CON(19), 7, 1, MFLAGS, 0, 7, DFLAGS,
+			RK1108_CLKGATE_CON(8), 14, GFLAGS),
+	GATE(0, "pvtm_pmu", "xin24m", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(8), 13, GFLAGS),
+
+	/*
+	 * Clock-Architecture Diagram 4
+	 */
+	COMPOSITE(0, "aclk_vio0_2wrap_occ", mux_pll_src_4plls_p, CLK_IGNORE_UNUSED,
+			RK1108_CLKSEL_CON(28), 6, 2, MFLAGS, 0, 5, DFLAGS,
+			RK1108_CLKGATE_CON(6), 0, GFLAGS),
+	GATE(0, "aclk_vio0_pre", "aclk_vio0_2wrap_occ", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(17), 0, GFLAGS),
+	COMPOSITE_NOMUX(0, "hclk_vio_pre", "aclk_vio0_pre", 0,
+			RK1108_CLKSEL_CON(29), 0, 5, DFLAGS,
+			RK1108_CLKGATE_CON(7), 2, GFLAGS),
+	COMPOSITE_NOMUX(0, "pclk_vio_pre", "aclk_vio0_pre", 0,
+			RK1108_CLKSEL_CON(29), 8, 5, DFLAGS,
+			RK1108_CLKGATE_CON(7), 3, GFLAGS),
+
+	INVERTER(0, "pclk_vip", "ext_vip",
+			RK1108_CLKSEL_CON(31), 8, IFLAGS),
+	GATE(0, "pclk_isp_pre", "pclk_vip", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(7), 6, GFLAGS),
+	GATE(0, "pclk_isp", "pclk_isp_pre", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(18), 10, GFLAGS),
+	GATE(0, "dclk_hdmiphy_src_gpll", "gpll", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(6), 5, GFLAGS),
+	GATE(0, "dclk_hdmiphy_src_dpll", "dpll", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(6), 4, GFLAGS),
+	COMPOSITE_NOGATE(0, "dclk_hdmiphy", mux_dclk_hdmiphy_pre_p, 0,
+			RK1108_CLKSEL_CON(32), 6, 2, MFLAGS, 8, 6, DFLAGS),
+
+	/*
+	 * Clock-Architecture Diagram 5
+	 */
+
+	FACTOR(0, "xin12m", "xin24m", 0, 1, 2),
+
+	COMPOSITE(0, "i2s0_src", mux_pll_src_2plls_p, 0,
+			RK1108_CLKSEL_CON(5), 8, 1, MFLAGS, 0, 7, DFLAGS,
+			RK1108_CLKGATE_CON(2), 0, GFLAGS),
+	COMPOSITE_FRACMUX(0, "i2s1_frac", "i2s1_src", CLK_SET_RATE_PARENT,
+			RK1108_CLKSEL_CON(8), 0,
+			RK1108_CLKGATE_CON(2), 1, GFLAGS,
+			&rk1108_i2s0_fracmux),
+	GATE(SCLK_I2S0, "sclk_i2s0", "i2s0_pre", CLK_SET_RATE_PARENT,
+			RK1108_CLKGATE_CON(2), 2, GFLAGS),
+	COMPOSITE_NODIV(0, "i2s_out", mux_i2s_out_p, 0,
+			RK1108_CLKSEL_CON(5), 15, 1, MFLAGS,
+			RK1108_CLKGATE_CON(2), 3, GFLAGS),
+
+	COMPOSITE(0, "i2s1_src", mux_pll_src_2plls_p, 0,
+			RK1108_CLKSEL_CON(6), 8, 1, MFLAGS, 0, 7, DFLAGS,
+			RK1108_CLKGATE_CON(2), 4, GFLAGS),
+	COMPOSITE_FRACMUX(0, "i2s1_frac", "i2s1_src", CLK_SET_RATE_PARENT,
+			RK2928_CLKSEL_CON(9), 0,
+			RK2928_CLKGATE_CON(2), 5, GFLAGS,
+			&rk1108_i2s1_fracmux),
+	GATE(SCLK_I2S1, "sclk_i2s1", "i2s1_pre", CLK_SET_RATE_PARENT,
+			RK1108_CLKGATE_CON(2), 6, GFLAGS),
+
+	COMPOSITE(0, "i2s2_src", mux_pll_src_2plls_p, 0,
+			RK1108_CLKSEL_CON(7), 8, 1, MFLAGS, 0, 7, DFLAGS,
+			RK1108_CLKGATE_CON(3), 8, GFLAGS),
+	COMPOSITE_FRACMUX(0, "i2s2_frac", "i2s2_src", CLK_SET_RATE_PARENT,
+			RK1108_CLKSEL_CON(10), 0,
+			RK1108_CLKGATE_CON(2), 9, GFLAGS,
+			&rk1108_i2s2_fracmux),
+	GATE(SCLK_I2S2, "sclk_i2s2", "i2s2_pre", CLK_SET_RATE_PARENT,
+			RK1108_CLKGATE_CON(2), 10, GFLAGS),
+
+	/* PD_BUS */
+	GATE(0, "aclk_bus_src_gpll", "gpll", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(1), 0, GFLAGS),
+	GATE(0, "aclk_bus_src_apll", "apll", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(1), 1, GFLAGS),
+	GATE(0, "aclk_bus_src_dpll", "dpll", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(1), 2, GFLAGS),
+	COMPOSITE_NOGATE(ACLK_PRE, "aclk_bus_pre", mux_aclk_bus_src_p, 0,
+			RK1108_CLKSEL_CON(2), 8, 2, MFLAGS, 0, 5, DFLAGS),
+	COMPOSITE_NOMUX(0, "hclk_bus_pre", "aclk_bus_2wrap_occ", 0,
+			RK1108_CLKSEL_CON(3), 0, 5, DFLAGS,
+			RK1108_CLKGATE_CON(1), 4, GFLAGS),
+	COMPOSITE_NOMUX(0, "pclken_bus", "aclk_bus_2wrap_occ", 0,
+			RK1108_CLKSEL_CON(3), 8, 5, DFLAGS,
+			RK1108_CLKGATE_CON(1), 5, GFLAGS),
+	GATE(0, "pclk_bus_pre", "pclken_bus", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(1), 6, GFLAGS),
+	GATE(0, "pclk_top_pre", "pclken_bus", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(1), 7, GFLAGS),
+	GATE(0, "pclk_ddr_pre", "pclken_bus", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(1), 8, GFLAGS),
+	GATE(0, "clk_timer0", "mux_pll_p", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(1), 9, GFLAGS),
+	GATE(0, "clk_timer1", "mux_pll_p", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(1), 10, GFLAGS),
+	GATE(0, "pclk_timer", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(13), 4, GFLAGS),
+
+	COMPOSITE(0, "uart0_src", mux_pll_src_dpll_gpll_usb480m_p, CLK_IGNORE_UNUSED,
+			RK1108_CLKSEL_CON(13), 12, 2, MFLAGS, 0, 7, DFLAGS,
+			RK1108_CLKGATE_CON(3), 1, GFLAGS),
+	COMPOSITE(0, "uart1_src", mux_pll_src_dpll_gpll_usb480m_p, CLK_IGNORE_UNUSED,
+			RK1108_CLKSEL_CON(14), 12, 2, MFLAGS, 0, 7, DFLAGS,
+			RK1108_CLKGATE_CON(3), 3, GFLAGS),
+	COMPOSITE(0, "uart21_src", mux_pll_src_dpll_gpll_usb480m_p, CLK_IGNORE_UNUSED,
+			RK1108_CLKSEL_CON(15), 12, 2, MFLAGS, 0, 7, DFLAGS,
+			RK1108_CLKGATE_CON(3), 5, GFLAGS),
+
+	COMPOSITE_FRACMUX(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT,
+			RK1108_CLKSEL_CON(16), 0,
+			RK1108_CLKGATE_CON(3), 2, GFLAGS,
+			&rk1108_uart0_fracmux),
+	COMPOSITE_FRACMUX(0, "uart1_frac", "uart1_src", CLK_SET_RATE_PARENT,
+			RK1108_CLKSEL_CON(17), 0,
+			RK1108_CLKGATE_CON(3), 4, GFLAGS,
+			&rk1108_uart1_fracmux),
+	COMPOSITE_FRACMUX(0, "uart2_frac", "uart2_src", CLK_SET_RATE_PARENT,
+			RK1108_CLKSEL_CON(18), 0,
+			RK1108_CLKGATE_CON(3), 6, GFLAGS,
+			&rk1108_uart2_fracmux),
+	GATE(PCLK_UART0, "pclk_uart0", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(13), 10, GFLAGS),
+	GATE(PCLK_UART1, "pclk_uart1", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(13), 11, GFLAGS),
+	GATE(PCLK_UART2, "pclk_uart2", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(13), 12, GFLAGS),
+
+	COMPOSITE(0, "clk_i2c1", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
+			RK1108_CLKSEL_CON(19), 15, 2, MFLAGS, 8, 7, DFLAGS,
+			RK1108_CLKGATE_CON(3), 7, GFLAGS),
+	COMPOSITE(0, "clk_i2c2", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
+			RK1108_CLKSEL_CON(20), 7, 2, MFLAGS, 0, 7, DFLAGS,
+			RK1108_CLKGATE_CON(3), 8, GFLAGS),
+	COMPOSITE(0, "clk_i2c3", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
+			RK1108_CLKSEL_CON(20), 15, 2, MFLAGS, 8, 7, DFLAGS,
+			RK1108_CLKGATE_CON(3), 9, GFLAGS),
+	GATE(0, "pclk_i2c1", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(13), 0, GFLAGS),
+	GATE(0, "pclk_i2c2", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(13), 1, GFLAGS),
+	GATE(0, "pclk_i2c3", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(13), 2, GFLAGS),
+	COMPOSITE(0, "clk_pwm1", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
+			RK1108_CLKSEL_CON(12), 15, 2, MFLAGS, 8, 7, DFLAGS,
+			RK1108_CLKGATE_CON(3), 10, GFLAGS),
+	GATE(0, "pclk_pwm1", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(13), 6, GFLAGS),
+	GATE(0, "pclk_wdt", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(13), 3, GFLAGS),
+	GATE(0, "pclk_gpio1", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(13), 7, GFLAGS),
+	GATE(0, "pclk_gpio2", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(13), 8, GFLAGS),
+	GATE(0, "pclk_gpio3", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(13), 9, GFLAGS),
+
+	GATE(0, "pclk_grf", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(14), 0, GFLAGS),
+
+	GATE(ACLK_DMAC, "aclk_dmac", "aclk_bus_pre", 0,
+	     RK1108_CLKGATE_CON(12), 2, GFLAGS),
+	GATE(0, "hclk_rom", "hclk_bus_pre", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(12), 3, GFLAGS),
+	GATE(0, "aclk_intmem", "aclk_bus_pre", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(12), 1, GFLAGS),
+
+	/* PD_DDR */
+	GATE(0, "apll_ddr", "apll", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(0), 8, GFLAGS),
+	GATE(0, "dpll_ddr", "dpll", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(0), 9, GFLAGS),
+	GATE(0, "gpll_ddr", "gpll", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(0), 10, GFLAGS),
+	COMPOSITE(0, "ddrphy4x", mux_ddrphy_p, CLK_IGNORE_UNUSED,
+			RK1108_CLKSEL_CON(4), 8, 2, MFLAGS, 0, 3,
+			DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
+			RK1108_CLKGATE_CON(10), 9, GFLAGS),
+	GATE(0, "ddrupctl", "ddrphy_pre", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(12), 4, GFLAGS),
+	GATE(0, "ddrc", "ddrphy", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(12), 5, GFLAGS),
+	GATE(0, "ddrmon", "ddrphy_pre", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(12), 6, GFLAGS),
+	GATE(0, "timer_clk", "xin24m", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(0), 11, GFLAGS),
+
+	/*
+	 * Clock-Architecture Diagram 6
+	 */
+
+	/* PD_PERI */
+	COMPOSITE_NOMUX(0, "pclk_periph_pre", "gpll", 0,
+			RK1108_CLKSEL_CON(23), 10, 5, DFLAGS,
+			RK1108_CLKGATE_CON(4), 5, GFLAGS),
+	GATE(0, "pclk_periph", "pclk_periph_pre", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(15), 13, GFLAGS),
+	COMPOSITE_NOMUX(0, "hclk_periph_pre", "gpll", 0,
+			RK1108_CLKSEL_CON(23), 5, 5, DFLAGS,
+			RK1108_CLKGATE_CON(4), 4, GFLAGS),
+	GATE(0, "hclk_periph", "hclk_periph_pre", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(15), 12, GFLAGS),
+
+	GATE(0, "aclk_peri_src_dpll", "dpll", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(4), 1, GFLAGS),
+	GATE(0, "aclk_peri_src_gpll", "gpll", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(4), 2, GFLAGS),
+	COMPOSITE(0, "aclk_periph", mux_aclk_peri_src_p, CLK_IGNORE_UNUSED,
+			RK1108_CLKSEL_CON(23), 15, 2, MFLAGS, 0, 5, DFLAGS,
+			RK1108_CLKGATE_CON(15), 11, GFLAGS),
+
+	COMPOSITE(SCLK_SDMMC, "sclk_sdmmc0", mux_mmc_src_p, 0,
+			RK1108_CLKSEL_CON(25), 8, 2, MFLAGS, 0, 8, DFLAGS,
+			RK1108_CLKGATE_CON(5), 0, GFLAGS),
+
+	COMPOSITE_NODIV(0, "sclk_sdio_src", mux_mmc_src_p, 0,
+			RK1108_CLKSEL_CON(25), 10, 2, MFLAGS,
+			RK1108_CLKGATE_CON(5), 2, GFLAGS),
+	DIV(SCLK_SDIO, "sclk_sdio", "sclk_sdio_src", 0,
+			RK1108_CLKSEL_CON(26), 0, 8, DFLAGS),
+
+	COMPOSITE_NODIV(0, "sclk_emmc_src", mux_mmc_src_p, 0,
+			RK1108_CLKSEL_CON(25), 12, 2, MFLAGS,
+			RK1108_CLKGATE_CON(5), 1, GFLAGS),
+	DIV(SCLK_EMMC, "sclk_emmc", "sclk_emmc_src", 0,
+			RK2928_CLKSEL_CON(26), 8, 8, DFLAGS),
+	GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 0, GFLAGS),
+	GATE(HCLK_SDIO, "hclk_sdio", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 1, GFLAGS),
+	GATE(HCLK_EMMC, "hclk_emmc", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 2, GFLAGS),
+
+	COMPOSITE(SCLK_NANDC, "sclk_nandc", mux_pll_src_2plls_p, 0,
+			RK1108_CLKSEL_CON(27), 14, 2, MFLAGS, 8, 5, DFLAGS,
+			RK1108_CLKGATE_CON(5), 3, GFLAGS),
+	GATE(HCLK_NANDC, "hclk_nandc", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 3, GFLAGS),
+
+	COMPOSITE(SCLK_SFC, "sclk_sfc", mux_pll_src_2plls_p, 0,
+			RK1108_CLKSEL_CON(27), 7, 2, MFLAGS, 0, 7, DFLAGS,
+			RK1108_CLKGATE_CON(5), 4, GFLAGS),
+	GATE(HCLK_SFC, "hclk_sfc", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 10, GFLAGS),
+
+	COMPOSITE(0, "sclk_macphy_pre", mux_pll_src_apll_gpll_p, 0,
+			RK1108_CLKSEL_CON(24), 12, 2, MFLAGS, 0, 5, DFLAGS,
+			RK1108_CLKGATE_CON(4), 10, GFLAGS),
+	MUX(0, "sclk_macphy", mux_sclk_macphy_p, CLK_SET_RATE_PARENT,
+			RK1108_CLKSEL_CON(24), 8, 2, MFLAGS),
+	GATE(0, "sclk_macphy_rx", "sclk_macphy", 0, RK1108_CLKGATE_CON(4), 8, GFLAGS),
+	GATE(0, "sclk_mac_ref", "sclk_macphy", 0, RK1108_CLKGATE_CON(4), 6, GFLAGS),
+	GATE(0, "sclk_mac_refout", "sclk_macphy", 0, RK1108_CLKGATE_CON(4), 7, GFLAGS),
+
+	MMC(SCLK_SDMMC_DRV,    "sdmmc_drv",    "sclk_sdmmc", RK1108_SDMMC_CON0, 1),
+	MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "sclk_sdmmc", RK1108_SDMMC_CON1, 1),
+
+	MMC(SCLK_SDIO_DRV,     "sdio_drv",     "sclk_sdio",  RK1108_SDIO_CON0,  1),
+	MMC(SCLK_SDIO_SAMPLE,  "sdio_sample",  "sclk_sdio",  RK1108_SDIO_CON1,  1),
+
+	MMC(SCLK_EMMC_DRV,     "emmc_drv",     "sclk_emmc",  RK1108_EMMC_CON0,  1),
+	MMC(SCLK_EMMC_SAMPLE,  "emmc_sample",  "sclk_emmc",  RK1108_EMMC_CON1,  1),
+};
+
+static const char *const rk1108_critical_clocks[] __initconst = {
+	"aclk_core",
+	"aclk_bus_src_gpll",
+	"aclk_periph",
+	"hclk_periph",
+	"pclk_periph",
+};
+
+static void __init rk1108_clk_init(struct device_node *np)
+{
+	struct rockchip_clk_provider *ctx;
+	void __iomem *reg_base;
+
+	reg_base = of_iomap(np, 0);
+	if (!reg_base) {
+		pr_err("%s: could not map cru region\n", __func__);
+		return;
+	}
+
+	ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS);
+	if (IS_ERR(ctx)) {
+		pr_err("%s: rockchip clk init failed\n", __func__);
+		iounmap(reg_base);
+		return;
+	}
+
+	rockchip_clk_register_plls(ctx, rk1108_pll_clks,
+				   ARRAY_SIZE(rk1108_pll_clks),
+				   RK1108_GRF_SOC_STATUS0);
+	rockchip_clk_register_branches(ctx, rk1108_clk_branches,
+				  ARRAY_SIZE(rk1108_clk_branches));
+	rockchip_clk_protect_critical(rk1108_critical_clocks,
+				      ARRAY_SIZE(rk1108_critical_clocks));
+
+	rockchip_clk_register_armclk(ctx, ARMCLK, "armclk",
+			mux_armclk_p, ARRAY_SIZE(mux_armclk_p),
+			&rk1108_cpuclk_data, rk1108_cpuclk_rates,
+			ARRAY_SIZE(rk1108_cpuclk_rates));
+
+	rockchip_register_softrst(np, 13, reg_base + RK1108_SOFTRST_CON(0),
+				  ROCKCHIP_SOFTRST_HIWORD_MASK);
+
+	rockchip_register_restart_notifier(ctx, RK1108_GLB_SRST_FST, NULL);
+
+	rockchip_clk_of_add_provider(np, ctx);
+}
+CLK_OF_DECLARE(rk1108_cru, "rockchip,rk1108-cru", rk1108_clk_init);
diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h
index 1653edd..d67eecc 100644
--- a/drivers/clk/rockchip/clk.h
+++ b/drivers/clk/rockchip/clk.h
@@ -34,6 +34,21 @@
 #define HIWORD_UPDATE(val, mask, shift) \
 		((val) << (shift) | (mask) << ((shift) + 16))
 
+/* register positions shared by RK1108, RK2928, RK3036, RK3066, RK3188 and RK3228 */
+#define RK1108_PLL_CON(x)		((x) * 0x4)
+#define RK1108_CLKSEL_CON(x)		((x) * 0x4 + 0x60)
+#define RK1108_CLKGATE_CON(x)		((x) * 0x4 + 0x120)
+#define RK1108_SOFTRST_CON(x)		((x) * 0x4 + 0x180)
+#define RK1108_GLB_SRST_FST		0x1c0
+#define RK1108_GLB_SRST_SND		0x1c4
+#define RK1108_MISC_CON			0x1cc
+#define RK1108_SDMMC_CON0		0x1d8
+#define RK1108_SDMMC_CON1		0x1dc
+#define RK1108_SDIO_CON0		0x1e0
+#define RK1108_SDIO_CON1		0x1e4
+#define RK1108_EMMC_CON0		0x1e8
+#define RK1108_EMMC_CON1		0x1ec
+
 #define RK2928_PLL_CON(x)		((x) * 0x4)
 #define RK2928_MODE_CON		0x40
 #define RK2928_CLKSEL_CON(x)	((x) * 0x4 + 0x44)
-- 
1.9.1



^ permalink raw reply related

* [PATCH v3 2/3] clk: rockchip: add dt-binding header for rk1108
From: Shawn Lin @ 2016-11-16  8:49 UTC (permalink / raw)
  To: Heiko Stuebner
  Cc: Stephen Boyd, Rob Herring, devicetree-u79uwXL29TY76Z2rM5mHXA,
	Andy Yan, Michael Turquette, linux-clk-u79uwXL29TY76Z2rM5mHXA,
	linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Shawn Lin
In-Reply-To: <1479286163-34789-1-git-send-email-shawn.lin-TNX95d0MmH7DzftRWevZcw@public.gmane.org>

Add the dt-bindings header for the rk1108, that gets shared
between the clock controller and the clock references in the dts.

Signed-off-by: Shawn Lin <shawn.lin-TNX95d0MmH7DzftRWevZcw@public.gmane.org>

---

Changes in v3:
- rename PLL name and advance the clk id to save some space

Changes in v2:
- split dt-binding header from clk driver

 include/dt-bindings/clock/rk1108-cru.h | 269 +++++++++++++++++++++++++++++++++
 1 file changed, 269 insertions(+)
 create mode 100644 include/dt-bindings/clock/rk1108-cru.h

diff --git a/include/dt-bindings/clock/rk1108-cru.h b/include/dt-bindings/clock/rk1108-cru.h
new file mode 100644
index 0000000..b28abb0
--- /dev/null
+++ b/include/dt-bindings/clock/rk1108-cru.h
@@ -0,0 +1,269 @@
+/*
+ * Copyright (c) 2016 Rockchip Electronics Co. Ltd.
+ * Author: Shawn Lin <shawn.lin-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _DT_BINDINGS_CLK_ROCKCHIP_RK1108_H
+#define _DT_BINDINGS_CLK_ROCKCHIP_RK1108_H
+
+/* pll id */
+#define PLL_APLL			0
+#define PLL_DPLL			1
+#define PLL_GPLL			2
+#define ARMCLK				3
+
+/* sclk gates (special clocks) */
+#define SCLK_SPI0			65
+#define SCLK_NANDC			67
+#define SCLK_SDMMC			68
+#define SCLK_SDIO			69
+#define SCLK_EMMC			71
+#define SCLK_UART0			72
+#define SCLK_UART1			73
+#define SCLK_UART2			74
+#define SCLK_I2S0			75
+#define SCLK_I2S1			76
+#define SCLK_I2S2			77
+#define SCLK_TIMER0			78
+#define SCLK_TIMER1			79
+#define SCLK_SFC			80
+#define SCLK_SDMMC_DRV			81
+#define SCLK_SDIO_DRV			82
+#define SCLK_EMMC_DRV			83
+#define SCLK_SDMMC_SAMPLE		84
+#define SCLK_SDIO_SAMPLE		85
+#define SCLK_EMMC_SAMPLE		86
+
+/* aclk gates */
+#define ACLK_DMAC			192
+#define ACLK_PRE			193
+#define ACLK_CORE			194
+#define ACLK_ENMCORE			195
+
+/* pclk gates */
+#define PCLK_GPIO1			256
+#define PCLK_GPIO2			257
+#define PCLK_GPIO3			258
+#define PCLK_GRF			259
+#define PCLK_I2C1			260
+#define PCLK_I2C2			261
+#define PCLK_I2C3			262
+#define PCLK_SPI			263
+#define PCLK_SFC			264
+#define PCLK_UART0			265
+#define PCLK_UART1			266
+#define PCLK_UART2			267
+#define PCLK_TSADC			268
+#define PCLK_PWM			269
+#define PCLK_TIMER			270
+#define PCLK_PERI			271
+
+/* hclk gates */
+#define HCLK_I2S0_8CH			320
+#define HCLK_I2S1_8CH			321
+#define HCLK_I2S2_2CH			322
+#define HCLK_NANDC			323
+#define HCLK_SDMMC			324
+#define HCLK_SDIO			325
+#define HCLK_EMMC			326
+#define HCLK_PERI			327
+#define HCLK_SFC			328
+
+#define CLK_NR_CLKS			(HCLK_SFC + 1)
+
+/* reset id */
+#define SRST_CORE_PO_AD		0
+#define SRST_CORE_AD			1
+#define SRST_L2_AD			2
+#define SRST_CPU_NIU_AD		3
+#define SRST_CORE_PO			4
+#define SRST_CORE			5
+#define SRST_L2			6
+#define SRST_CORE_DBG			8
+#define PRST_DBG			9
+#define RST_DAP			10
+#define PRST_DBG_NIU			11
+#define ARST_STRC_SYS_AD		15
+
+#define SRST_DDRPHY_CLKDIV		16
+#define SRST_DDRPHY			17
+#define PRST_DDRPHY			18
+#define PRST_HDMIPHY			19
+#define PRST_VDACPHY			20
+#define PRST_VADCPHY			21
+#define PRST_MIPI_CSI_PHY		22
+#define PRST_MIPI_DSI_PHY		23
+#define PRST_ACODEC			24
+#define ARST_BUS_NIU			25
+#define PRST_TOP_NIU			26
+#define ARST_INTMEM			27
+#define HRST_ROM			28
+#define ARST_DMAC			29
+#define SRST_MSCH_NIU			30
+#define PRST_MSCH_NIU			31
+
+#define PRST_DDRUPCTL			32
+#define NRST_DDRUPCTL			33
+#define PRST_DDRMON			34
+#define HRST_I2S0_8CH			35
+#define MRST_I2S0_8CH			36
+#define HRST_I2S1_2CH			37
+#define MRST_IS21_2CH			38
+#define HRST_I2S2_2CH			39
+#define MRST_I2S2_2CH			40
+#define HRST_CRYPTO			41
+#define SRST_CRYPTO			42
+#define PRST_SPI			43
+#define SRST_SPI			44
+#define PRST_UART0			45
+#define PRST_UART1			46
+#define PRST_UART2			47
+
+#define SRST_UART0			48
+#define SRST_UART1			49
+#define SRST_UART2			50
+#define PRST_I2C1			51
+#define PRST_I2C2			52
+#define PRST_I2C3			53
+#define SRST_I2C1			54
+#define SRST_I2C2			55
+#define SRST_I2C3			56
+#define PRST_PWM1			58
+#define SRST_PWM1			60
+#define PRST_WDT			61
+#define PRST_GPIO1			62
+#define PRST_GPIO2			63
+
+#define PRST_GPIO3			64
+#define PRST_GRF			65
+#define PRST_EFUSE			66
+#define PRST_EFUSE512			67
+#define PRST_TIMER0			68
+#define SRST_TIMER0			69
+#define SRST_TIMER1			70
+#define PRST_TSADC			71
+#define SRST_TSADC			72
+#define PRST_SARADC			73
+#define SRST_SARADC			74
+#define HRST_SYSBUS			75
+#define PRST_USBGRF			76
+
+#define ARST_PERIPH_NIU		80
+#define HRST_PERIPH_NIU		81
+#define PRST_PERIPH_NIU		82
+#define HRST_PERIPH			83
+#define HRST_SDMMC			84
+#define HRST_SDIO			85
+#define HRST_EMMC			86
+#define HRST_NANDC			87
+#define NRST_NANDC			88
+#define HRST_SFC			89
+#define SRST_SFC			90
+#define ARST_GMAC			91
+#define HRST_OTG			92
+#define SRST_OTG			93
+#define SRST_OTG_ADP			94
+#define HRST_HOST0			95
+
+#define HRST_HOST0_AUX			96
+#define HRST_HOST0_ARB			97
+#define SRST_HOST0_EHCIPHY		98
+#define SRST_HOST0_UTMI		99
+#define SRST_USBPOR			100
+#define SRST_UTMI0			101
+#define SRST_UTMI1			102
+
+#define ARST_VIO0_NIU			102
+#define ARST_VIO1_NIU			103
+#define HRST_VIO_NIU			104
+#define PRST_VIO_NIU			105
+#define ARST_VOP			106
+#define HRST_VOP			107
+#define DRST_VOP			108
+#define ARST_IEP			109
+#define HRST_IEP			110
+#define ARST_RGA			111
+#define HRST_RGA			112
+#define SRST_RGA			113
+#define PRST_CVBS			114
+#define PRST_HDMI			115
+#define SRST_HDMI			116
+#define PRST_MIPI_DSI			117
+
+#define ARST_ISP_NIU			118
+#define HRST_ISP_NIU			119
+#define HRST_ISP			120
+#define SRST_ISP			121
+#define ARST_VIP0			122
+#define HRST_VIP0			123
+#define PRST_VIP0			124
+#define ARST_VIP1			125
+#define HRST_VIP1			126
+#define PRST_VIP1			127
+#define ARST_VIP2			128
+#define HRST_VIP2			129
+#define PRST_VIP2			120
+#define ARST_VIP3			121
+#define HRST_VIP3			122
+#define PRST_VIP4			123
+
+#define PRST_CIF1TO4			124
+#define SRST_CVBS_CLK			125
+#define HRST_CVBS			126
+
+#define ARST_VPU_NIU			140
+#define HRST_VPU_NIU			141
+#define ARST_VPU			142
+#define HRST_VPU			143
+#define ARST_RKVDEC_NIU		144
+#define HRST_RKVDEC_NIU		145
+#define ARST_RKVDEC			146
+#define HRST_RKVDEC			147
+#define SRST_RKVDEC_CABAC		148
+#define SRST_RKVDEC_CORE		149
+#define ARST_RKVENC_NIU		150
+#define HRST_RKVENC_NIU		151
+#define ARST_RKVENC			152
+#define HRST_RKVENC			153
+#define SRST_RKVENC_CORE		154
+
+#define SRST_DSP_CORE			156
+#define SRST_DSP_SYS			157
+#define SRST_DSP_GLOBAL		158
+#define SRST_DSP_OECM			159
+#define PRST_DSP_IOP_NIU		160
+#define ARST_DSP_EPP_NIU		161
+#define ARST_DSP_EDP_NIU		162
+#define PRST_DSP_DBG_NIU		163
+#define PRST_DSP_CFG_NIU		164
+#define PRST_DSP_GRF			165
+#define PRST_DSP_MAILBOX		166
+#define PRST_DSP_INTC			167
+#define PRST_DSP_PFM_MON		169
+#define SRST_DSP_PFM_MON		170
+#define ARST_DSP_EDAP_NIU		171
+
+#define SRST_PMU			172
+#define SRST_PMU_I2C0			173
+#define PRST_PMU_I2C0			174
+#define PRST_PMU_GPIO0			175
+#define PRST_PMU_INTMEM		176
+#define PRST_PMU_PWM0			177
+#define SRST_PMU_PWM0			178
+#define PRST_PMU_GRF			179
+#define SRST_PMU_NIU			180
+#define SRST_PMU_PVTM			181
+#define ARST_DSP_EDP_PERF		184
+#define ARST_DSP_EPP_PERF		185
+
+#endif /* _DT_BINDINGS_CLK_ROCKCHIP_RK1108_H */
-- 
1.9.1


--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* [PATCH v3 1/3] dt-bindings: add documentation for rk1108 cru
From: Shawn Lin @ 2016-11-16  8:49 UTC (permalink / raw)
  To: Heiko Stuebner
  Cc: Stephen Boyd, Rob Herring, devicetree-u79uwXL29TY76Z2rM5mHXA,
	Andy Yan, Michael Turquette, linux-clk-u79uwXL29TY76Z2rM5mHXA,
	linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Shawn Lin

This adds the dt-binding documentation for the clock and reset unit
found on Rockchip rk1108 SoCs.

Signed-off-by: Shawn Lin <shawn.lin-TNX95d0MmH7DzftRWevZcw@public.gmane.org>

---

Changes in v3:
- fix mismatch of external clk input name
- add hdmiphy and usbphy clk input

Changes in v2: None

 .../bindings/clock/rockchip,rk1108-cru.txt         | 59 ++++++++++++++++++++++
 1 file changed, 59 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/rockchip,rk1108-cru.txt

diff --git a/Documentation/devicetree/bindings/clock/rockchip,rk1108-cru.txt b/Documentation/devicetree/bindings/clock/rockchip,rk1108-cru.txt
new file mode 100644
index 0000000..4da1261
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/rockchip,rk1108-cru.txt
@@ -0,0 +1,59 @@
+* Rockchip RK1108 Clock and Reset Unit
+
+The RK1108 clock controller generates and supplies clock to various
+controllers within the SoC and also implements a reset controller for SoC
+peripherals.
+
+Required Properties:
+
+- compatible: should be "rockchip,rk1108-cru"
+- reg: physical base address of the controller and length of memory mapped
+  region.
+- #clock-cells: should be 1.
+- #reset-cells: should be 1.
+
+Optional Properties:
+
+- rockchip,grf: phandle to the syscon managing the "general register files"
+  If missing pll rates are not changeable, due to the missing pll lock status.
+
+Each clock is assigned an identifier and client nodes can use this identifier
+to specify the clock which they consume. All available clocks are defined as
+preprocessor macros in the dt-bindings/clock/rk1108-cru.h headers and can be
+used in device tree sources. Similar macros exist for the reset sources in
+these files.
+
+External clocks:
+
+There are several clocks that are generated outside the SoC. It is expected
+that they are defined using standard clock bindings with following
+clock-output-names:
+ - "xin24m" - crystal input - required,
+ - "ext_vip" - external VIP clock - optional
+ - "ext_i2s" - external I2S clock - optional
+ - "ext_gmac" - external GMAC clock - optional
+ - "hdmiphy" - external clock input derived from HDMI PHY - optional
+ - "usbphy" - external clock input derived from USB PHY - optional
+
+Example: Clock controller node:
+
+	cru: cru@20200000 {
+		compatible = "rockchip,rk1108-cru";
+		reg = <0x20200000 0x1000>;
+		rockchip,grf = <&grf>;
+
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+	};
+
+Example: UART controller node that consumes the clock generated by the clock
+  controller:
+
+	uart0: serial@10230000 {
+		compatible = "rockchip,rk1108-uart", "snps,dw-apb-uart";
+		reg = <0x10230000 0x100>;
+		interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		clocks = <&cru SCLK_UART0>;
+	};
-- 
1.9.1


--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* [PATCH] ARM: zynq: Fix pmu register description coding style
From: Michal Simek @ 2016-11-16  8:32 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: julia, Sören Brinkmann, devicetree, monstr, Steffen Trumtrar,
	linux-kernel, Peter Crosthwaite, Rob Herring, Rob Herring,
	Mark Rutland, Josh Cartwright, Russell King

Drop the space before/after '<' and '>'; and
separate the entries to be a bit more readable.

Reported-by: Julia Cartwright <julia@ni.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
---

 arch/arm/boot/dts/zynq-7000.dtsi | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/zynq-7000.dtsi b/arch/arm/boot/dts/zynq-7000.dtsi
index 402b5bbe3b5b..f3ac9bfe580e 100644
--- a/arch/arm/boot/dts/zynq-7000.dtsi
+++ b/arch/arm/boot/dts/zynq-7000.dtsi
@@ -46,7 +46,8 @@
 		compatible = "arm,cortex-a9-pmu";
 		interrupts = <0 5 4>, <0 6 4>;
 		interrupt-parent = <&intc>;
-		reg = < 0xf8891000 0x1000 0xf8893000 0x1000 >;
+		reg = <0xf8891000 0x1000>,
+		      <0xf8893000 0x1000>;
 	};
 
 	regulator_vccpint: fixedregulator {
-- 
1.9.1

^ permalink raw reply related

* Re: [PATCHv2 06/10] mmc: core: move the cookie's enum values from sdhci.h to mmc.h
From: Adrian Hunter @ 2016-11-16  8:28 UTC (permalink / raw)
  To: Jaehoon Chung, linux-mmc-u79uwXL29TY76Z2rM5mHXA
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA, Ulf Hansson,
	heiko-4mtYJXux2i+zQB+pC5nmwQ, shawn.lin-TNX95d0MmH7DzftRWevZcw,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A
In-Reply-To: <89535076-4a77-64a5-68d9-ce15e03b8fb3-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>

On 16/11/16 10:25, Jaehoon Chung wrote:
> On 11/16/2016 05:09 PM, Adrian Hunter wrote:
>> On 16/11/16 09:53, Jaehoon Chung wrote:
>>> Added Adrian for sdhci.h
>>>
>>> On 11/15/2016 07:12 PM, Jaehoon Chung wrote:
>>>> It's not for only sdhci controller.
>>>> So it can be moved from sdhci.h to mmc.h. And renamed from sdhci_cookie
>>>> to mmc_cookie.
>>
>> The cookie is currently host private data, so I don't understand the
>> motivation behind this.
> 
> dwmmc controller can also use the data->host_cookie. because it's working with post/pre_req().
> 
> So i think it can be used about both sdhci and dwmmc.
> Is there no reason that add the private dwmmc data?
> 
> With these cookie value, update the dwmmc controller for post/pre_req().
> 
> https://patchwork.kernel.org/patch/9429287/

So why not define dwmmc cookies in dw_mmc.c ?

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCHv2 06/10] mmc: core: move the cookie's enum values from sdhci.h to mmc.h
From: Jaehoon Chung @ 2016-11-16  8:25 UTC (permalink / raw)
  To: Adrian Hunter, linux-mmc
  Cc: devicetree, Ulf Hansson, heiko, shawn.lin, robh+dt
In-Reply-To: <ecb4b5d0-4cbf-bf44-3287-f1580b2e990a@intel.com>

On 11/16/2016 05:09 PM, Adrian Hunter wrote:
> On 16/11/16 09:53, Jaehoon Chung wrote:
>> Added Adrian for sdhci.h
>>
>> On 11/15/2016 07:12 PM, Jaehoon Chung wrote:
>>> It's not for only sdhci controller.
>>> So it can be moved from sdhci.h to mmc.h. And renamed from sdhci_cookie
>>> to mmc_cookie.
> 
> The cookie is currently host private data, so I don't understand the
> motivation behind this.

dwmmc controller can also use the data->host_cookie. because it's working with post/pre_req().

So i think it can be used about both sdhci and dwmmc.
Is there no reason that add the private dwmmc data?

With these cookie value, update the dwmmc controller for post/pre_req().

https://patchwork.kernel.org/patch/9429287/

Best Regards,
Jaehoon Chung

> 
>>>
>>> Signed-off-by: Jaehoon Chung <jh80.chung@samsung.com>
>>> Tested-by: Heiko Stuebner <heiko@sntech.de>
>>> ---
>>>  drivers/mmc/host/sdhci.h | 6 ------
>>>  include/linux/mmc/core.h | 6 ++++++
>>>  2 files changed, 6 insertions(+), 6 deletions(-)
>>>
>>> diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
>>> index 766df17..325663b 100644
>>> --- a/drivers/mmc/host/sdhci.h
>>> +++ b/drivers/mmc/host/sdhci.h
>>> @@ -321,12 +321,6 @@ struct sdhci_adma2_64_desc {
>>>  /* Allow for a a command request and a data request at the same time */
>>>  #define SDHCI_MAX_MRQS		2
>>>  
>>> -enum sdhci_cookie {
>>> -	COOKIE_UNMAPPED,
>>> -	COOKIE_PRE_MAPPED,	/* mapped by sdhci_pre_req() */
>>> -	COOKIE_MAPPED,		/* mapped by sdhci_prepare_data() */
>>> -};
>>> -
>>>  struct sdhci_host {
>>>  	/* Data set by hardware interface driver */
>>>  	const char *hw_name;	/* Hardware bus name */
>>> diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
>>> index 0ce928b..82d707f 100644
>>> --- a/include/linux/mmc/core.h
>>> +++ b/include/linux/mmc/core.h
>>> @@ -118,6 +118,12 @@ struct mmc_command {
>>>  	struct mmc_request	*mrq;		/* associated request */
>>>  };
>>>  
>>> +enum mmc_cookie {
>>> +	COOKIE_UNMAPPED,
>>> +	COOKIE_PRE_MAPPED,	/* mapped by pre_req() of controller */
>>> +	COOKIE_MAPPED,		/* mapped by prepare_data() of controller */
>>> +};
>>> +
>>>  struct mmc_data {
>>>  	unsigned int		timeout_ns;	/* data timeout (in ns, max 80ms) */
>>>  	unsigned int		timeout_clks;	/* data timeout (in clocks) */
>>>
>>
>>
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> 
> 


^ permalink raw reply

* Re: [linux-sunxi] Re: [PATCH v3 1/2] drm/bridge: dumb-vga-dac: Support a VDD regulator supply
From: Archit Taneja @ 2016-11-16  8:17 UTC (permalink / raw)
  To: Chen-Yu Tsai
  Cc: David Airlie, Rob Herring, Maxime Ripard, Mark Rutland, dri-devel,
	linux-arm-kernel, linux-kernel, devicetree, linux-sunxi
In-Reply-To: <CAGb2v67LR4KEb0tfGkT8+TqTauNyCMq1n6mRdXsa6TUJV0xncA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>

Hi,

On 11/15/2016 08:29 AM, Chen-Yu Tsai wrote:
> Hi,
>
> On Wed, Nov 2, 2016 at 9:33 AM, Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org> wrote:
>> On Mon, Oct 31, 2016 at 2:28 PM, Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org> wrote:
>>> On Sat, Oct 29, 2016 at 07:06:10PM +0800, Chen-Yu Tsai wrote:
>>>> Some dumb VGA DACs are active components which require external power.
>>>> Add support for specifying a regulator as its power supply.
>>>>
>>>> Signed-off-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
>>>> ---
>>>>  .../bindings/display/bridge/dumb-vga-dac.txt       |  2 ++
>>>
>>> For the binding,
>>>
>>> Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
>
> Any comments on this patch from the DRM people?

A comment below.

>
> ChenYu
>
>>>
>>> One code comment below...
>>>
>>>>  drivers/gpu/drm/bridge/dumb-vga-dac.c              | 35 ++++++++++++++++++++++
>>>>  2 files changed, 37 insertions(+)
>>>>
>>>> diff --git a/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt b/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt
>>>> index 003bc246a270..164cbb15f04c 100644
>>>> --- a/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt
>>>> +++ b/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt
>>>> @@ -16,6 +16,8 @@ graph bindings specified in Documentation/devicetree/bindings/graph.txt.
>>>>  - Video port 0 for RGB input
>>>>  - Video port 1 for VGA output
>>>>
>>>> +Optional properties:
>>>> +- vdd-supply: Power supply for DAC
>>>>
>>>>  Example
>>>>  -------
>>>> diff --git a/drivers/gpu/drm/bridge/dumb-vga-dac.c b/drivers/gpu/drm/bridge/dumb-vga-dac.c
>>>> index afec232185a7..59781e031220 100644
>>>> --- a/drivers/gpu/drm/bridge/dumb-vga-dac.c
>>>> +++ b/drivers/gpu/drm/bridge/dumb-vga-dac.c
>>>> @@ -12,6 +12,7 @@
>>>>
>>>>  #include <linux/module.h>
>>>>  #include <linux/of_graph.h>
>>>> +#include <linux/regulator/consumer.h>
>>>>
>>>>  #include <drm/drmP.h>
>>>>  #include <drm/drm_atomic_helper.h>
>>>> @@ -23,6 +24,7 @@ struct dumb_vga {
>>>>       struct drm_connector    connector;
>>>>
>>>>       struct i2c_adapter      *ddc;
>>>> +     struct regulator        *vdd;
>>>>  };
>>>>
>>>>  static inline struct dumb_vga *
>>>> @@ -124,8 +126,33 @@ static int dumb_vga_attach(struct drm_bridge *bridge)
>>>>       return 0;
>>>>  }
>>>>
>>>> +static void dumb_vga_enable(struct drm_bridge *bridge)
>>>> +{
>>>> +     struct dumb_vga *vga = drm_bridge_to_dumb_vga(bridge);
>>>> +     int ret;
>>>> +
>>>> +     if (!IS_ERR(vga->vdd)) {
>>>
>>> if (IS_ERR())
>>>         return;
>>>
>>> ...will save some intentation.
>>
>> I thought about that, though if someone were to add more stuff to
>> this, such as an enable GPIO, they might have to rework it. A standalone
>> block of code would be easier to work with. I'm OK either way though.
>>
>> ChenYu
>>
>>>
>>>> +             ret = regulator_enable(vga->vdd);
>>>> +
>>>> +             if (ret) {
>>>> +                     DRM_ERROR("Failed to enable vdd regulator: %d\n", ret);
>>>> +                     return;
>>>> +             }
>>>> +     }
>>>> +}
>>>> +
>>>> +static void dumb_vga_disable(struct drm_bridge *bridge)
>>>> +{
>>>> +     struct dumb_vga *vga = drm_bridge_to_dumb_vga(bridge);
>>>> +
>>>> +     if (!IS_ERR(vga->vdd))
>>>> +             regulator_disable(vga->vdd);
>>>> +}
>>>> +
>>>>  static const struct drm_bridge_funcs dumb_vga_bridge_funcs = {
>>>>       .attach         = dumb_vga_attach,
>>>> +     .enable         = dumb_vga_enable,
>>>> +     .disable        = dumb_vga_disable,
>>>>  };
>>>>
>>>>  static struct i2c_adapter *dumb_vga_retrieve_ddc(struct device *dev)
>>>> @@ -169,6 +196,14 @@ static int dumb_vga_probe(struct platform_device *pdev)
>>>>               return -ENOMEM;
>>>>       platform_set_drvdata(pdev, vga);
>>>>
>>>> +     vga->vdd = devm_regulator_get_optional(&pdev->dev, "vdd");
>>>> +     if (IS_ERR(vga->vdd)) {
>>>> +             ret = PTR_ERR(vga->vdd);
>>>> +             if (ret == -EPROBE_DEFER)
>>>> +                     return -EPROBE_DEFER;
>>>> +             dev_dbg(&pdev->dev, "No vdd regulator found: %d\n", ret);

A cleaner way would be to set vga->vdd to NULL here, and do:

	int ret = 0;

	if (vga->vdd)
		ret = regulator_enable(vga->vdd);

	if (ret) {
		...
		return;
	}

	/* if a gpio is added later */
	if (vga->gpio)
		ret = gpiod_set_value_cansleep(vga->gpio, 1);

	if (ret) {
		...
		return;
	}
	...

We don't really care what error code is contained in vga->vdd once we have
identified whether we got a regulator or not.

The same thing can be done for ddc too, but that can done left for later.

If you're okay with the suggestion, can you re-spin a patch?

Thanks,
Archit

>>>> +     }
>>>> +
>>>>       vga->ddc = dumb_vga_retrieve_ddc(&pdev->dev);
>>>>       if (IS_ERR(vga->ddc)) {
>>>>               if (PTR_ERR(vga->ddc) == -ENODEV) {
>>>> --
>>>> 2.9.3
>>>>
>>>
>>> --
>>> You received this message because you are subscribed to the Google Groups "linux-sunxi" group.
>>> To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
>>> For more options, visit https://groups.google.com/d/optout.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCHv2 06/10] mmc: core: move the cookie's enum values from sdhci.h to mmc.h
From: Adrian Hunter @ 2016-11-16  8:09 UTC (permalink / raw)
  To: Jaehoon Chung, linux-mmc-u79uwXL29TY76Z2rM5mHXA
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA, Ulf Hansson,
	heiko-4mtYJXux2i+zQB+pC5nmwQ, shawn.lin-TNX95d0MmH7DzftRWevZcw,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A
In-Reply-To: <12405f58-695d-03d8-407f-d7471e93a6de-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>

On 16/11/16 09:53, Jaehoon Chung wrote:
> Added Adrian for sdhci.h
> 
> On 11/15/2016 07:12 PM, Jaehoon Chung wrote:
>> It's not for only sdhci controller.
>> So it can be moved from sdhci.h to mmc.h. And renamed from sdhci_cookie
>> to mmc_cookie.

The cookie is currently host private data, so I don't understand the
motivation behind this.

>>
>> Signed-off-by: Jaehoon Chung <jh80.chung-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
>> Tested-by: Heiko Stuebner <heiko-4mtYJXux2i+zQB+pC5nmwQ@public.gmane.org>
>> ---
>>  drivers/mmc/host/sdhci.h | 6 ------
>>  include/linux/mmc/core.h | 6 ++++++
>>  2 files changed, 6 insertions(+), 6 deletions(-)
>>
>> diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
>> index 766df17..325663b 100644
>> --- a/drivers/mmc/host/sdhci.h
>> +++ b/drivers/mmc/host/sdhci.h
>> @@ -321,12 +321,6 @@ struct sdhci_adma2_64_desc {
>>  /* Allow for a a command request and a data request at the same time */
>>  #define SDHCI_MAX_MRQS		2
>>  
>> -enum sdhci_cookie {
>> -	COOKIE_UNMAPPED,
>> -	COOKIE_PRE_MAPPED,	/* mapped by sdhci_pre_req() */
>> -	COOKIE_MAPPED,		/* mapped by sdhci_prepare_data() */
>> -};
>> -
>>  struct sdhci_host {
>>  	/* Data set by hardware interface driver */
>>  	const char *hw_name;	/* Hardware bus name */
>> diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
>> index 0ce928b..82d707f 100644
>> --- a/include/linux/mmc/core.h
>> +++ b/include/linux/mmc/core.h
>> @@ -118,6 +118,12 @@ struct mmc_command {
>>  	struct mmc_request	*mrq;		/* associated request */
>>  };
>>  
>> +enum mmc_cookie {
>> +	COOKIE_UNMAPPED,
>> +	COOKIE_PRE_MAPPED,	/* mapped by pre_req() of controller */
>> +	COOKIE_MAPPED,		/* mapped by prepare_data() of controller */
>> +};
>> +
>>  struct mmc_data {
>>  	unsigned int		timeout_ns;	/* data timeout (in ns, max 80ms) */
>>  	unsigned int		timeout_clks;	/* data timeout (in clocks) */
>>
> 
> 

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH resend v4] i2c: hibvt: add Hisilicon BVT I2C controller driver
From: Jiancheng Xue @ 2016-11-16  8:00 UTC (permalink / raw)
  To: wsa
  Cc: Pan Wen, robh+dt, mark.rutland, linux-i2c, devicetree,
	linux-kernel, howell.yang, jalen.hsu, lvkuanliang, suwenping,
	raojun, kevin.lixu
In-Reply-To: <20161021081709.7307-1-wenpan@hisilicon.com>

Hi Wolfram,

On 2016/10/21 16:17, Pan Wen wrote:
> add Hisilicon BVT I2C controller driver support.
> 
> Signed-off-by: Pan Wen <wenpan@hisilicon.com>
> Acked-by: Rob Herring <robh@kernel.org>
> ---
> change log
> v4:
> Modify the default frequency to 100KHz.
> v3:
> Add a SoC specific compatible string.
> v2:
> 1)Fixed a compile error.
> 2)Dropped the clock-names property.
>  .../devicetree/bindings/i2c/i2c-hibvt.txt          |  24 +
>  drivers/i2c/busses/Kconfig                         |  10 +
>  drivers/i2c/busses/Makefile                        |   1 +
>  drivers/i2c/busses/i2c-hibvt.c                     | 737 +++++++++++++++++++++
>  4 files changed, 772 insertions(+)

Could you give us some comments on this patch?
If there are some issues about it, please let us know.
Thank you very much!

Best Regards,
Jiancheng

>  create mode 100644 Documentation/devicetree/bindings/i2c/i2c-hibvt.txt
>  create mode 100644 drivers/i2c/busses/i2c-hibvt.c
> 
> diff --git a/Documentation/devicetree/bindings/i2c/i2c-hibvt.txt b/Documentation/devicetree/bindings/i2c/i2c-hibvt.txt
> new file mode 100644
> index 0000000..db3d2e2
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/i2c/i2c-hibvt.txt
> @@ -0,0 +1,24 @@
> +Hisilicon BVT I2C master controller
> +
> +Required properties:
> +- compatible: should be "hisilicon,hibvt-i2c" and one of the following:
> +	"hisilicon,hi3516cv300-i2c"
> +- reg: physical base address of the controller and length of memory mapped.
> +     region.
> +- interrupts: interrupt number to the cpu.
> +- clocks: phandles to input clocks.
> +
> +Optional properties:
> +- clock-frequency: Desired I2C bus frequency in Hz, otherwise defaults to 100000.
> +
> +Other properties:
> +see Documentation/devicetree/bindings/i2c/i2c.txt.
> +
> +Examples:
> +i2c_bus0: i2c@12110000 {
> +	compatible = "hisilicon,hi3516cv300-i2c", "hisilicon,hibvt-i2c";
> +	reg = <0x12110000 0x100>;
> +	interrupts = <20>;
> +	clocks = <&crg_ctrl HI3516CV300_APB_CLK>;
> +	clock-frequency = <100000>;
> +};
> diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
> index 5c3993b..fc1b679 100644
> --- a/drivers/i2c/busses/Kconfig
> +++ b/drivers/i2c/busses/Kconfig
> @@ -555,6 +555,16 @@ config I2C_GPIO
>  	  This is a very simple bitbanging I2C driver utilizing the
>  	  arch-neutral GPIO API to control the SCL and SDA lines.
>  
> +config I2C_HIBVT
> +	tristate "Hisilicon BVT I2C Controller"
> +	depends on ARCH_HISI
> +	help
> +	  Say Y here to include support for Hisilicon BVT I2C controller in the
> +	  Hisilicon BVT SoCs.
> +
> +	  This driver can also be built as a module.  If so, the module
> +	  will be called i2c-hibvt.
> +
>  config I2C_HIGHLANDER
>  	tristate "Highlander FPGA SMBus interface"
>  	depends on SH_HIGHLANDER
> diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
> index 37f2819..42ef2e0 100644
> --- a/drivers/i2c/busses/Makefile
> +++ b/drivers/i2c/busses/Makefile
> @@ -51,6 +51,7 @@ obj-$(CONFIG_I2C_EG20T)		+= i2c-eg20t.o
>  obj-$(CONFIG_I2C_EMEV2)		+= i2c-emev2.o
>  obj-$(CONFIG_I2C_EXYNOS5)	+= i2c-exynos5.o
>  obj-$(CONFIG_I2C_GPIO)		+= i2c-gpio.o
> +obj-$(CONFIG_I2C_HIBVT)		+= i2c-hibvt.o
>  obj-$(CONFIG_I2C_HIGHLANDER)	+= i2c-highlander.o
>  obj-$(CONFIG_I2C_HIX5HD2)	+= i2c-hix5hd2.o
>  obj-$(CONFIG_I2C_IBM_IIC)	+= i2c-ibm_iic.o
> diff --git a/drivers/i2c/busses/i2c-hibvt.c b/drivers/i2c/busses/i2c-hibvt.c
> new file mode 100644
> index 0000000..e8af63e
> --- /dev/null
> +++ b/drivers/i2c/busses/i2c-hibvt.c
> @@ -0,0 +1,737 @@
> +/*
> + * Hisilicon BVT I2C Controller Driver
> + *
> + * Copyright (c) 2016 HiSilicon Technologies Co., Ltd.
> + *
> + * Authors: wenpan@hisilicon.com
> + *
> + * This program is free software; you can redistribute  it and/or modify it
> + * under  the terms of  the GNU General Public License as published by the
> + * Free Software Foundation;  either version 2 of the  License, or (at your
> + * option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + *
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/delay.h>
> +#include <linux/i2c.h>
> +#include <linux/interrupt.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +
> +/*
> + * I2C Registers offsets
> + */
> +#define HIBVT_I2C_GLB		0x0
> +#define HIBVT_I2C_SCL_H		0x4
> +#define HIBVT_I2C_SCL_L		0x8
> +#define HIBVT_I2C_DATA1		0x10
> +#define HIBVT_I2C_TXF		0x20
> +#define HIBVT_I2C_RXF		0x24
> +#define HIBVT_I2C_CMD_BASE	0x30
> +#define HIBVT_I2C_LOOP1		0xb0
> +#define HIBVT_I2C_DST1		0xb4
> +#define HIBVT_I2C_TX_WATER	0xc8
> +#define HIBVT_I2C_RX_WATER	0xcc
> +#define HIBVT_I2C_CTRL1		0xd0
> +#define HIBVT_I2C_STAT		0xd8
> +#define HIBVT_I2C_INTR_RAW	0xe0
> +#define HIBVT_I2C_INTR_EN	0xe4
> +#define HIBVT_I2C_INTR_STAT	0xe8
> +
> +/*
> + * I2C Global Config Register -- HIBVT_I2C_GLB
> + */
> +#define GLB_EN_MASK		BIT(0)
> +#define GLB_SDA_HOLD_MASK	GENMASK(23, 8)
> +#define GLB_SDA_HOLD_SHIFT	(8)
> +
> +/*
> + * I2C Timing CMD Register -- HIBVT_I2C_CMD_BASE + n * 4 (n = 0, 1, 2, ... 31)
> + */
> +#define CMD_EXIT	0x0
> +#define CMD_TX_S	0x1
> +#define CMD_TX_D1_2	0x4
> +#define CMD_TX_D1_1	0x5
> +#define CMD_TX_FIFO	0x9
> +#define CMD_RX_FIFO	0x12
> +#define CMD_RX_ACK	0x13
> +#define CMD_IGN_ACK	0x15
> +#define CMD_TX_ACK	0x16
> +#define CMD_TX_NACK	0x17
> +#define CMD_JMP1	0x18
> +#define CMD_UP_TXF	0x1d
> +#define CMD_TX_RS	0x1e
> +#define CMD_TX_P	0x1f
> +
> +/*
> + * I2C Control Register 1 -- HIBVT_I2C_CTRL1
> + */
> +#define CTRL1_CMD_START_MASK	BIT(0)
> +
> +/*
> + * I2C Status Register -- HIBVT_I2C_STAT
> + */
> +#define STAT_RXF_NOE_MASK	BIT(16) /* RX FIFO not empty flag */
> +#define STAT_TXF_NOF_MASK	BIT(19) /* TX FIFO not full flag */
> +
> +
> +/*
> + * I2C Interrupt status and mask Register --
> + * HIBVT_I2C_INTR_RAW, HIBVT_I2C_STAT, HIBVT_I2C_INTR_STAT
> + */
> +#define INTR_ABORT_MASK		(BIT(0) | BIT(11))
> +#define INTR_RX_MASK		BIT(2)
> +#define INTR_TX_MASK		BIT(4)
> +#define INTR_CMD_DONE_MASK	BIT(12)
> +#define INTR_USE_MASK		(INTR_ABORT_MASK \
> +				|INTR_RX_MASK \
> +				| INTR_TX_MASK \
> +				| INTR_CMD_DONE_MASK)
> +#define INTR_ALL_MASK		GENMASK(31, 0)
> +
> +#define I2C_DEFAULT_FREQUENCY	100000
> +#define I2C_TXF_DEPTH		64
> +#define I2C_RXF_DEPTH		64
> +#define I2C_TXF_WATER		32
> +#define I2C_RXF_WATER		32
> +#define I2C_WAIT_TIMEOUT	0x10000
> +#define I2C_IRQ_TIMEOUT		(msecs_to_jiffies(1000))
> +
> +
> +struct hibvt_i2c_dev {
> +	struct device		*dev;
> +	struct i2c_adapter	adap;
> +	void __iomem		*base;
> +	struct clk		*clk;
> +	int			irq;
> +
> +	unsigned int		freq;
> +	struct i2c_msg		*msg;
> +	unsigned int		msg_num;
> +	unsigned int		msg_idx;
> +	unsigned int		msg_buf_ptr;
> +	struct completion	msg_complete;
> +
> +	spinlock_t		lock;
> +	int			status;
> +};
> +
> +static inline void hibvt_i2c_disable(struct hibvt_i2c_dev *i2c)
> +{
> +	unsigned int val;
> +
> +	val = readl(i2c->base + HIBVT_I2C_GLB);
> +	val &= ~GLB_EN_MASK;
> +	writel(val, i2c->base + HIBVT_I2C_GLB);
> +}
> +
> +static inline void hibvt_i2c_enable(struct hibvt_i2c_dev *i2c)
> +{
> +	unsigned int val;
> +
> +	val = readl(i2c->base + HIBVT_I2C_GLB);
> +	val |= GLB_EN_MASK;
> +	writel(val, i2c->base + HIBVT_I2C_GLB);
> +}
> +
> +static inline void hibvt_i2c_cfg_irq(struct hibvt_i2c_dev *i2c,
> +		unsigned int flag)
> +{
> +	writel(flag, i2c->base + HIBVT_I2C_INTR_EN);
> +}
> +
> +static inline void hibvt_i2c_disable_irq(struct hibvt_i2c_dev *i2c,
> +		unsigned int flag)
> +{
> +	unsigned int val;
> +
> +	val = readl(i2c->base + HIBVT_I2C_INTR_EN);
> +	val &= ~flag;
> +	writel(val, i2c->base + HIBVT_I2C_INTR_EN);
> +}
> +
> +static inline unsigned int hibvt_i2c_clr_irq(struct hibvt_i2c_dev *i2c)
> +{
> +	unsigned int val;
> +
> +	val = readl(i2c->base + HIBVT_I2C_INTR_STAT);
> +	writel(INTR_ALL_MASK, i2c->base + HIBVT_I2C_INTR_RAW);
> +
> +	return val;
> +}
> +
> +static inline void hibvt_i2c_cmdreg_set(struct hibvt_i2c_dev *i2c,
> +		unsigned int cmd, unsigned int *offset)
> +{
> +	dev_dbg(i2c->dev, "hii2c reg: offset=0x%x, cmd=0x%x...\n",
> +			*offset * 4, cmd);
> +	writel(cmd, i2c->base + HIBVT_I2C_CMD_BASE + *offset * 4);
> +	(*offset)++;
> +}
> +
> +/*
> + * config i2c slave addr
> + */
> +static inline void hibvt_i2c_set_addr(struct hibvt_i2c_dev *i2c)
> +{
> +	struct i2c_msg *msg = i2c->msg;
> +	u16 addr;
> +
> +	if (msg->flags & I2C_M_TEN) {
> +		/* First byte is 11110XX0 where XX is upper 2 bits */
> +		addr = ((msg->addr & 0x300) << 1) | 0xf000;
> +		if (msg->flags & I2C_M_RD)
> +			addr |= 1 << 8;
> +
> +		/* Second byte is the remaining 8 bits */
> +		addr |= msg->addr & 0xff;
> +	} else {
> +		addr = (msg->addr & 0x7f) << 1;
> +		if (msg->flags & I2C_M_RD)
> +			addr |= 1;
> +	}
> +
> +	writel(addr, i2c->base + HIBVT_I2C_DATA1);
> +}
> +
> +/*
> + * Start command sequence
> + */
> +static inline void hibvt_i2c_start_cmd(struct hibvt_i2c_dev *i2c)
> +{
> +	unsigned int val;
> +
> +	val = readl(i2c->base + HIBVT_I2C_CTRL1);
> +	val |= CTRL1_CMD_START_MASK;
> +	writel(val, i2c->base + HIBVT_I2C_CTRL1);
> +}
> +
> +static int hibvt_i2c_wait_rx_noempty(struct hibvt_i2c_dev *i2c)
> +{
> +	unsigned int time_cnt = 0;
> +	unsigned int val;
> +
> +	do {
> +		val = readl(i2c->base + HIBVT_I2C_STAT);
> +		if (val & STAT_RXF_NOE_MASK)
> +			return 0;
> +
> +		udelay(50);
> +	} while (time_cnt++ < I2C_WAIT_TIMEOUT);
> +
> +	dev_err(i2c->dev, "wait rx no empty timeout, RIS: 0x%x, SR: 0x%x\n",
> +			readl(i2c->base + HIBVT_I2C_INTR_RAW), val);
> +	return -EIO;
> +}
> +
> +static int hibvt_i2c_wait_tx_nofull(struct hibvt_i2c_dev *i2c)
> +{
> +	unsigned int time_cnt = 0;
> +	unsigned int val;
> +
> +	do {
> +		val = readl(i2c->base + HIBVT_I2C_STAT);
> +		if (val & STAT_TXF_NOF_MASK)
> +			return 0;
> +
> +		udelay(50);
> +	} while (time_cnt++ < I2C_WAIT_TIMEOUT);
> +
> +	dev_err(i2c->dev, "wait rx no empty timeout, RIS: 0x%x, SR: 0x%x\n",
> +			readl(i2c->base + HIBVT_I2C_INTR_RAW), val);
> +	return -EIO;
> +}
> +
> +static int hibvt_i2c_wait_idle(struct hibvt_i2c_dev *i2c)
> +{
> +	unsigned int time_cnt = 0;
> +	unsigned int val;
> +
> +	do {
> +		val = readl(i2c->base + HIBVT_I2C_INTR_RAW);
> +		if (val & (INTR_ABORT_MASK)) {
> +			dev_err(i2c->dev, "wait idle abort!, RIS: 0x%x\n",
> +					val);
> +			return -EIO;
> +		}
> +
> +		if (val & INTR_CMD_DONE_MASK)
> +			return 0;
> +
> +		udelay(50);
> +	} while (time_cnt++ < I2C_WAIT_TIMEOUT);
> +
> +	dev_err(i2c->dev, "wait idle timeout, RIS: 0x%x, SR: 0x%x\n",
> +			val, readl(i2c->base + HIBVT_I2C_STAT));
> +
> +	return -EIO;
> +}
> +
> +static void hibvt_i2c_set_freq(struct hibvt_i2c_dev *i2c)
> +{
> +	unsigned int max_freq, freq;
> +	unsigned int clk_rate;
> +	unsigned int val, sda_hold;
> +
> +	freq = i2c->freq;
> +	clk_rate = clk_get_rate(i2c->clk);
> +	max_freq = clk_rate >> 1;
> +
> +	if (freq > max_freq) {
> +		i2c->freq = max_freq;
> +		freq = i2c->freq;
> +	}
> +
> +	if (freq <= 100000) {
> +		val = clk_rate / (freq * 2) - 1;
> +		writel(val, i2c->base + HIBVT_I2C_SCL_H);
> +		writel(val, i2c->base + HIBVT_I2C_SCL_L);
> +	} else {
> +		val = (clk_rate * 36) / (freq * 100);
> +		writel(val, i2c->base + HIBVT_I2C_SCL_H);
> +		val = (clk_rate * 64) / (freq * 100);
> +		writel(val, i2c->base + HIBVT_I2C_SCL_L);
> +	}
> +
> +	sda_hold = val * 3 / 10;
> +	sda_hold = (sda_hold << GLB_SDA_HOLD_SHIFT) & GLB_SDA_HOLD_MASK;
> +	val = readl(i2c->base + HIBVT_I2C_GLB);
> +	val &= ~GLB_SDA_HOLD_MASK;
> +	val |= sda_hold;
> +	writel(val, i2c->base + HIBVT_I2C_GLB);
> +}
> +
> +/*
> + * set i2c controller TX and RX FIFO water
> + */
> +static inline void hibvt_i2c_set_water(struct hibvt_i2c_dev *i2c)
> +{
> +	writel(I2C_TXF_WATER, i2c->base + HIBVT_I2C_TX_WATER);
> +	writel(I2C_RXF_WATER, i2c->base + HIBVT_I2C_RX_WATER);
> +}
> +
> +/*
> + * initialise the controller, set i2c bus interface freq
> + */
> +static void hibvt_i2c_hw_init(struct hibvt_i2c_dev *i2c)
> +{
> +	hibvt_i2c_disable(i2c);
> +	hibvt_i2c_disable_irq(i2c, INTR_ALL_MASK);
> +	hibvt_i2c_set_freq(i2c);
> +	hibvt_i2c_set_water(i2c);
> +}
> +
> +/*
> + * hibvt_i2c_cfg_cmd - config i2c controller command sequence
> + *
> + * After all the timing command is configured,
> + * and then start the command, you can i2c communication,
> + * and then only need to read and write i2c fifo.
> + */
> +static void hibvt_i2c_cfg_cmd(struct hibvt_i2c_dev *i2c)
> +{
> +	struct i2c_msg *msg = i2c->msg;
> +	int offset = 0;
> +
> +	if (i2c->msg_idx == 0)
> +		hibvt_i2c_cmdreg_set(i2c, CMD_TX_S, &offset);
> +	else
> +		hibvt_i2c_cmdreg_set(i2c, CMD_TX_RS, &offset);
> +
> +	if (msg->flags & I2C_M_TEN) {
> +		if (i2c->msg_idx == 0) {
> +			hibvt_i2c_cmdreg_set(i2c, CMD_TX_D1_2, &offset);
> +			hibvt_i2c_cmdreg_set(i2c, CMD_TX_D1_1, &offset);
> +		} else {
> +			hibvt_i2c_cmdreg_set(i2c, CMD_TX_D1_2, &offset);
> +		}
> +	} else {
> +		hibvt_i2c_cmdreg_set(i2c, CMD_TX_D1_1, &offset);
> +	}
> +
> +	if (msg->flags & I2C_M_IGNORE_NAK)
> +		hibvt_i2c_cmdreg_set(i2c, CMD_IGN_ACK, &offset);
> +	else
> +		hibvt_i2c_cmdreg_set(i2c, CMD_RX_ACK, &offset);
> +
> +	if (msg->flags & I2C_M_RD) {
> +		if (msg->len >= 2) {
> +			writel(offset, i2c->base + HIBVT_I2C_DST1);
> +			writel(msg->len - 2, i2c->base + HIBVT_I2C_LOOP1);
> +			hibvt_i2c_cmdreg_set(i2c, CMD_RX_FIFO, &offset);
> +			hibvt_i2c_cmdreg_set(i2c, CMD_TX_ACK, &offset);
> +			hibvt_i2c_cmdreg_set(i2c, CMD_JMP1, &offset);
> +		}
> +		hibvt_i2c_cmdreg_set(i2c, CMD_RX_FIFO, &offset);
> +		hibvt_i2c_cmdreg_set(i2c, CMD_TX_NACK, &offset);
> +	} else {
> +		writel(offset, i2c->base + HIBVT_I2C_DST1);
> +		writel(msg->len - 1, i2c->base + HIBVT_I2C_LOOP1);
> +		hibvt_i2c_cmdreg_set(i2c, CMD_UP_TXF, &offset);
> +		hibvt_i2c_cmdreg_set(i2c, CMD_TX_FIFO, &offset);
> +
> +		if (msg->flags & I2C_M_IGNORE_NAK)
> +			hibvt_i2c_cmdreg_set(i2c, CMD_IGN_ACK, &offset);
> +		else
> +			hibvt_i2c_cmdreg_set(i2c, CMD_RX_ACK, &offset);
> +
> +		hibvt_i2c_cmdreg_set(i2c, CMD_JMP1, &offset);
> +	}
> +
> +	if ((i2c->msg_idx == (i2c->msg_num - 1)) || (msg->flags & I2C_M_STOP)) {
> +		dev_dbg(i2c->dev, "run to %s %d...TX STOP\n",
> +				__func__, __LINE__);
> +		hibvt_i2c_cmdreg_set(i2c, CMD_TX_P, &offset);
> +	}
> +
> +	hibvt_i2c_cmdreg_set(i2c, CMD_EXIT, &offset);
> +}
> +
> +static int hibvt_i2c_polling_xfer_one_msg(struct hibvt_i2c_dev *i2c)
> +{
> +	int status;
> +	unsigned int val;
> +	struct i2c_msg *msg = i2c->msg;
> +
> +	dev_dbg(i2c->dev, "[%s,%d]msg->flags=0x%x, len=0x%x\n",
> +			__func__, __LINE__, msg->flags, msg->len);
> +
> +	hibvt_i2c_enable(i2c);
> +	hibvt_i2c_clr_irq(i2c);
> +	hibvt_i2c_set_addr(i2c);
> +	hibvt_i2c_cfg_cmd(i2c);
> +	hibvt_i2c_start_cmd(i2c);
> +
> +	i2c->msg_buf_ptr = 0;
> +
> +	if (msg->flags & I2C_M_RD) {
> +		while (i2c->msg_buf_ptr < msg->len) {
> +			status = hibvt_i2c_wait_rx_noempty(i2c);
> +			if (status)
> +				goto end;
> +
> +			val = readl(i2c->base + HIBVT_I2C_RXF);
> +			msg->buf[i2c->msg_buf_ptr] = val;
> +			i2c->msg_buf_ptr++;
> +
> +		}
> +	} else {
> +		while (i2c->msg_buf_ptr < msg->len) {
> +			status = hibvt_i2c_wait_tx_nofull(i2c);
> +			if (status)
> +				goto end;
> +
> +			val = msg->buf[i2c->msg_buf_ptr];
> +			writel(val, i2c->base + HIBVT_I2C_TXF);
> +			i2c->msg_buf_ptr++;
> +		}
> +	}
> +
> +	status = hibvt_i2c_wait_idle(i2c);
> +end:
> +	hibvt_i2c_disable(i2c);
> +
> +	return status;
> +}
> +
> +static irqreturn_t hibvt_i2c_isr(int irq, void *dev_id)
> +{
> +	struct hibvt_i2c_dev *i2c = dev_id;
> +	unsigned int irq_status;
> +	struct i2c_msg *msg = i2c->msg;
> +
> +	spin_lock(&i2c->lock);
> +
> +	irq_status = hibvt_i2c_clr_irq(i2c);
> +	dev_dbg(i2c->dev, "%s RIS:  0x%x\n", __func__, irq_status);
> +
> +	if (!irq_status) {
> +		dev_dbg(i2c->dev, "no irq\n");
> +		goto end;
> +	}
> +
> +	if (irq_status & INTR_ABORT_MASK) {
> +		dev_err(i2c->dev, "irq handle abort, RIS: 0x%x\n",
> +				irq_status);
> +		i2c->status = -EIO;
> +		hibvt_i2c_disable_irq(i2c, INTR_ALL_MASK);
> +
> +		complete(&i2c->msg_complete);
> +		goto end;
> +	}
> +
> +	if (msg->flags & I2C_M_RD) {
> +		while ((readl(i2c->base + HIBVT_I2C_STAT) & STAT_RXF_NOE_MASK)
> +				&& (i2c->msg_buf_ptr < msg->len)) {
> +			msg->buf[i2c->msg_buf_ptr] =
> +				readl(i2c->base + HIBVT_I2C_RXF);
> +			i2c->msg_buf_ptr++;
> +		}
> +	} else {
> +		while ((readl(i2c->base + HIBVT_I2C_STAT) & STAT_TXF_NOF_MASK)
> +				&& (i2c->msg_buf_ptr < msg->len)) {
> +			writel(msg->buf[i2c->msg_buf_ptr],
> +					i2c->base + HIBVT_I2C_TXF);
> +			i2c->msg_buf_ptr++;
> +		}
> +	}
> +
> +	if (i2c->msg_buf_ptr >= msg->len)
> +		hibvt_i2c_disable_irq(i2c, INTR_TX_MASK | INTR_RX_MASK);
> +
> +	if (irq_status & INTR_CMD_DONE_MASK) {
> +		dev_dbg(i2c->dev, "cmd done\n");
> +		i2c->status =  0;
> +		hibvt_i2c_disable_irq(i2c, INTR_ALL_MASK);
> +
> +		complete(&i2c->msg_complete);
> +	}
> +
> +end:
> +	spin_unlock(&i2c->lock);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static int hibvt_i2c_interrupt_xfer_one_msg(struct hibvt_i2c_dev *i2c)
> +{
> +	int status;
> +	struct i2c_msg *msg = i2c->msg;
> +	unsigned long timeout;
> +	unsigned long flags;
> +
> +	dev_dbg(i2c->dev, "[%s,%d]msg->flags=0x%x, len=0x%x\n",
> +			__func__, __LINE__, msg->flags, msg->len);
> +
> +	reinit_completion(&i2c->msg_complete);
> +	i2c->msg_buf_ptr = 0;
> +	i2c->status = -EIO;
> +
> +	spin_lock_irqsave(&i2c->lock, flags);
> +	hibvt_i2c_enable(i2c);
> +	hibvt_i2c_clr_irq(i2c);
> +	if (msg->flags & I2C_M_RD)
> +		hibvt_i2c_cfg_irq(i2c, INTR_USE_MASK & ~INTR_TX_MASK);
> +	else
> +		hibvt_i2c_cfg_irq(i2c, INTR_USE_MASK & ~INTR_RX_MASK);
> +
> +	hibvt_i2c_set_addr(i2c);
> +	hibvt_i2c_cfg_cmd(i2c);
> +	hibvt_i2c_start_cmd(i2c);
> +	spin_unlock_irqrestore(&i2c->lock, flags);
> +
> +	timeout = wait_for_completion_timeout(&i2c->msg_complete,
> +			I2C_IRQ_TIMEOUT);
> +
> +	if (timeout == 0) {
> +		hibvt_i2c_disable_irq(i2c, INTR_ALL_MASK);
> +		status = -EIO;
> +		dev_err(i2c->dev, "%s timeout\n",
> +			 msg->flags & I2C_M_RD ? "rx" : "tx");
> +	} else {
> +		status = i2c->status;
> +	}
> +
> +	hibvt_i2c_disable(i2c);
> +
> +	return status;
> +}
> +
> +/*
> + * Master transfer function
> + */
> +static int hibvt_i2c_xfer(struct i2c_adapter *adap,
> +			struct i2c_msg *msgs, int num)
> +{
> +	struct hibvt_i2c_dev *i2c = i2c_get_adapdata(adap);
> +	int status;
> +
> +	if (!msgs) {
> +		dev_err(i2c->dev, "msgs == NULL\n");
> +		return -EIO;
> +	}
> +
> +	i2c->msg = msgs;
> +	i2c->msg_num = num;
> +	i2c->msg_idx = 0;
> +
> +	if (i2c->irq >= 0) {
> +		while (i2c->msg_idx < i2c->msg_num) {
> +			status = hibvt_i2c_interrupt_xfer_one_msg(i2c);
> +			if (status)
> +				break;
> +
> +			i2c->msg++;
> +			i2c->msg_idx++;
> +		}
> +	} else {
> +		while (i2c->msg_idx < i2c->msg_num) {
> +			status = hibvt_i2c_polling_xfer_one_msg(i2c);
> +			if (status)
> +				break;
> +
> +			i2c->msg++;
> +			i2c->msg_idx++;
> +		}
> +	}
> +
> +	if (!status || i2c->msg_idx > 0)
> +		status = i2c->msg_idx;
> +
> +	return status;
> +}
> +
> +static u32 hibvt_i2c_func(struct i2c_adapter *adap)
> +{
> +	return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR
> +		| I2C_FUNC_PROTOCOL_MANGLING;
> +}
> +
> +static const struct i2c_algorithm hibvt_i2c_algo = {
> +	.master_xfer		= hibvt_i2c_xfer,
> +	.functionality		= hibvt_i2c_func,
> +};
> +
> +static int hibvt_i2c_probe(struct platform_device *pdev)
> +{
> +	int status;
> +	struct hibvt_i2c_dev *i2c;
> +	struct i2c_adapter *adap;
> +	struct resource *res;
> +
> +	i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL);
> +	if (!i2c)
> +		return -ENOMEM;
> +
> +	platform_set_drvdata(pdev, i2c);
> +	i2c->dev = &pdev->dev;
> +	spin_lock_init(&i2c->lock);
> +	init_completion(&i2c->msg_complete);
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	i2c->base = devm_ioremap_resource(&pdev->dev, res);
> +	if (IS_ERR(i2c->base)) {
> +		dev_err(i2c->dev, "cannot ioremap resource\n");
> +		return -ENOMEM;
> +	}
> +
> +	i2c->clk = devm_clk_get(&pdev->dev, NULL);
> +	if (IS_ERR(i2c->clk)) {
> +		dev_err(i2c->dev, "cannot get clock\n");
> +		return -ENOENT;
> +	}
> +	clk_prepare_enable(i2c->clk);
> +
> +	if (of_property_read_u32(pdev->dev.of_node, "clock-frequency",
> +				&i2c->freq)) {
> +		dev_warn(i2c->dev, "setting default clock-frequency@%dHz\n",
> +				I2C_DEFAULT_FREQUENCY);
> +		i2c->freq = I2C_DEFAULT_FREQUENCY;
> +	}
> +
> +	/* i2c controller initialization, disable interrupt */
> +	hibvt_i2c_hw_init(i2c);
> +
> +	i2c->irq = platform_get_irq(pdev, 0);
> +	status = devm_request_irq(&pdev->dev, i2c->irq, hibvt_i2c_isr,
> +			IRQF_SHARED, dev_name(&pdev->dev), i2c);
> +	if (status) {
> +		dev_dbg(i2c->dev, "falling back to polling mode");
> +		i2c->irq = -1;
> +	}
> +
> +	adap = &i2c->adap;
> +	i2c_set_adapdata(adap, i2c);
> +	adap->owner = THIS_MODULE;
> +	strlcpy(adap->name, "hibvt-i2c", sizeof(adap->name));
> +	adap->dev.parent = &pdev->dev;
> +	adap->dev.of_node = pdev->dev.of_node;
> +	adap->algo = &hibvt_i2c_algo;
> +
> +	/* Add the i2c adapter */
> +	status = i2c_add_adapter(adap);
> +	if (status) {
> +		dev_err(i2c->dev, "failed to add bus to i2c core\n");
> +		goto err_add_adapter;
> +	}
> +
> +	dev_info(i2c->dev, "%s%d@%dhz registered\n",
> +			adap->name, adap->nr, i2c->freq);
> +
> +	return 0;
> +
> +err_add_adapter:
> +	clk_disable_unprepare(i2c->clk);
> +	return status;
> +}
> +
> +static int hibvt_i2c_remove(struct platform_device *pdev)
> +{
> +	struct hibvt_i2c_dev *i2c = platform_get_drvdata(pdev);
> +
> +	clk_disable_unprepare(i2c->clk);
> +	i2c_del_adapter(&i2c->adap);
> +
> +	return 0;
> +}
> +
> +#ifdef CONFIG_PM_SLEEP
> +static int hibvt_i2c_suspend(struct device *dev)
> +{
> +	struct hibvt_i2c_dev *i2c = dev_get_drvdata(dev);
> +
> +	i2c_lock_adapter(&i2c->adap);
> +	clk_disable_unprepare(i2c->clk);
> +	i2c_unlock_adapter(&i2c->adap);
> +
> +	return 0;
> +}
> +
> +static int hibvt_i2c_resume(struct device *dev)
> +{
> +	struct hibvt_i2c_dev *i2c = dev_get_drvdata(dev);
> +
> +	i2c_lock_adapter(&i2c->adap);
> +	clk_prepare_enable(i2c->clk);
> +	hibvt_i2c_hw_init(i2c);
> +	i2c_unlock_adapter(&i2c->adap);
> +
> +	return 0;
> +}
> +#endif
> +
> +static SIMPLE_DEV_PM_OPS(hibvt_i2c_dev_pm, hibvt_i2c_suspend,
> +		hibvt_i2c_resume);
> +
> +static const struct of_device_id hibvt_i2c_match[] = {
> +	{ .compatible = "hisilicon,hibvt-i2c"},
> +	{ .compatible = "hisilicon,hi3516cv300-i2c"},
> +	{},
> +};
> +MODULE_DEVICE_TABLE(of, hibvt_i2c_match);
> +
> +static struct platform_driver hibvt_i2c_driver = {
> +	.driver		= {
> +		.name	= "hibvt-i2c",
> +		.of_match_table = hibvt_i2c_match,
> +		.pm	= &hibvt_i2c_dev_pm,
> +	},
> +	.probe		= hibvt_i2c_probe,
> +	.remove		= hibvt_i2c_remove,
> +};
> +
> +module_platform_driver(hibvt_i2c_driver);
> +
> +MODULE_AUTHOR("Pan Wen, <wenpan@hisilicon.com>");
> +MODULE_DESCRIPTION("HISILICON BVT I2C Bus driver");
> +MODULE_LICENSE("GPL v2");
> 

^ permalink raw reply

* Re: [PATCHv2 06/10] mmc: core: move the cookie's enum values from sdhci.h to mmc.h
From: Jaehoon Chung @ 2016-11-16  7:53 UTC (permalink / raw)
  To: linux-mmc-u79uwXL29TY76Z2rM5mHXA
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA, Ulf Hansson,
	heiko-4mtYJXux2i+zQB+pC5nmwQ, shawn.lin-TNX95d0MmH7DzftRWevZcw,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, Adrian Hunter
In-Reply-To: <20161115101232.3854-7-jh80.chung-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>

Added Adrian for sdhci.h

On 11/15/2016 07:12 PM, Jaehoon Chung wrote:
> It's not for only sdhci controller.
> So it can be moved from sdhci.h to mmc.h. And renamed from sdhci_cookie
> to mmc_cookie.
> 
> Signed-off-by: Jaehoon Chung <jh80.chung-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
> Tested-by: Heiko Stuebner <heiko-4mtYJXux2i+zQB+pC5nmwQ@public.gmane.org>
> ---
>  drivers/mmc/host/sdhci.h | 6 ------
>  include/linux/mmc/core.h | 6 ++++++
>  2 files changed, 6 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
> index 766df17..325663b 100644
> --- a/drivers/mmc/host/sdhci.h
> +++ b/drivers/mmc/host/sdhci.h
> @@ -321,12 +321,6 @@ struct sdhci_adma2_64_desc {
>  /* Allow for a a command request and a data request at the same time */
>  #define SDHCI_MAX_MRQS		2
>  
> -enum sdhci_cookie {
> -	COOKIE_UNMAPPED,
> -	COOKIE_PRE_MAPPED,	/* mapped by sdhci_pre_req() */
> -	COOKIE_MAPPED,		/* mapped by sdhci_prepare_data() */
> -};
> -
>  struct sdhci_host {
>  	/* Data set by hardware interface driver */
>  	const char *hw_name;	/* Hardware bus name */
> diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
> index 0ce928b..82d707f 100644
> --- a/include/linux/mmc/core.h
> +++ b/include/linux/mmc/core.h
> @@ -118,6 +118,12 @@ struct mmc_command {
>  	struct mmc_request	*mrq;		/* associated request */
>  };
>  
> +enum mmc_cookie {
> +	COOKIE_UNMAPPED,
> +	COOKIE_PRE_MAPPED,	/* mapped by pre_req() of controller */
> +	COOKIE_MAPPED,		/* mapped by prepare_data() of controller */
> +};
> +
>  struct mmc_data {
>  	unsigned int		timeout_ns;	/* data timeout (in ns, max 80ms) */
>  	unsigned int		timeout_clks;	/* data timeout (in clocks) */
> 

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v7 08/14] mmc: sdhci-msm: Implement set_clock callback for sdhci-msm
From: Adrian Hunter @ 2016-11-16  7:42 UTC (permalink / raw)
  To: Ritesh Harjani, Stephen Boyd, ulf.hansson
  Cc: linux-mmc, shawn.lin, andy.gross, devicetree, linux-clk,
	david.brown, linux-arm-msm, georgi.djakov, alex.lemberg,
	mateusz.nowak, Yuliy.Izrailov, asutoshd, kdorfman, david.griego,
	stummala, venkatg, rnayak, pramod.gurav
In-Reply-To: <d723b9fb-0cfc-e72b-ad78-36c8b996b012@codeaurora.org>

On 16/11/16 06:42, Ritesh Harjani wrote:
> Hi,
> 
> On 11/15/2016 10:40 AM, Ritesh Harjani wrote:
>> Hi Stephen/Adrian,
>>
>> On 11/15/2016 1:07 AM, Stephen Boyd wrote:
>>> On 11/14, Ritesh Harjani wrote:
>>>> @@ -577,6 +578,90 @@ static unsigned int
>>>> sdhci_msm_get_min_clock(struct sdhci_host *host)
>>>>      return SDHCI_MSM_MIN_CLOCK;
>>>>  }
>>>>
>>>> +/**
>>>> + * __sdhci_msm_set_clock - sdhci_msm clock control.
>>>> + *
>>>> + * Description:
>>>> + * Implement MSM version of sdhci_set_clock.
>>>> + * This is required since MSM controller does not
>>>> + * use internal divider and instead directly control
>>>> + * the GCC clock as per HW recommendation.
>>>> + **/
>>>> +void __sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
>>>> +{
>>>> +    u16 clk;
>>>> +    unsigned long timeout;
>>>> +
>>>> +    /*
>>>> +     * Keep actual_clock as zero -
>>>> +     * - since there is no divider used so no need of having
>>>> actual_clock.
>>>> +     * - MSM controller uses SDCLK for data timeout calculation. If
>>>> +     *   actual_clock is zero, host->clock is taken for calculation.
>>>> +     */
>>>> +    host->mmc->actual_clock = 0;
>>>> +
>>>> +    sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
>>>> +
>>>> +    if (clock == 0)
>>>> +        return;
>>>> +
>>>> +    /*
>>>> +     * MSM controller do not use clock divider.
>>>> +     * Thus read SDHCI_CLOCK_CONTROL and only enable
>>>> +     * clock with no divider value programmed.
>>>> +     */
>>>> +    clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
>>>> +
>>>> +    clk |= SDHCI_CLOCK_INT_EN;
>>>> +    sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
>>>> +
>>>> +    /* Wait max 20 ms */
>>>> +    timeout = 20;
>>>> +    while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
>>>> +        & SDHCI_CLOCK_INT_STABLE)) {
>>>> +        if (timeout == 0) {
>>>> +            pr_err("%s: Internal clock never stabilised\n",
>>>> +                   mmc_hostname(host->mmc));
>>>> +            return;
>>>> +        }
>>>> +        timeout--;
>>>> +        mdelay(1);
>>>> +    }
>>>> +
>>>> +    clk |= SDHCI_CLOCK_CARD_EN;
>>>> +    sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
>>>
>>> This is almost a copy/paste of sdhci_set_clock(). Can we make
>>> sdhci_set_clock() call a __sdhci_set_clock() function that takes
>>> unsigned int clock, and also a flag indicating if we want to set
>>> the internal clock divider or not? Then we can call
>>> __sdhci_set_clock() from sdhci_set_clock() with (clock, true) as
>>> arguments and (clock, false).
> Actually what you may be referring here is some sort of quirks which is not
> entertained any more for sdhci driver.
> sdhci is tending towards becoming a library and hence such changes are
> restricted.
> 
> But I think we may do below changes to avoid duplication of code which
> enables the sdhci internal clock and waits for internal clock to be stable.
> 
> Adrian, could you please tell if this should be ok?

That seems fine, but the name seems too long - how about changing
sdhci_set_clock_enable to sdhci_enable_clk.

> Then we may be able to call for sdhci_set_clock_enable function from
> sdhci_msm_set_clock.
> 
> 
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index 42ef3eb..28e605c 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -1343,19 +1343,8 @@ u16 sdhci_calc_clk(struct sdhci_host *host, unsigned
> int clock,
>  }
>  EXPORT_SYMBOL_GPL(sdhci_calc_clk);
> 
> -void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
> +void sdhci_set_clock_enable(struct sdhci_host *host, unsigned short clk)
>  {
> -       u16 clk;
> -       unsigned long timeout;
> -
> -       host->mmc->actual_clock = 0;
> -
> -       sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
> -
> -       if (clock == 0)
> -               return;
> -
> -       clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock);
> 
>         clk |= SDHCI_CLOCK_INT_EN;
>         sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
> @@ -1377,6 +1366,24 @@ void sdhci_set_clock(struct sdhci_host *host,
> unsigned int clock)
>         clk |= SDHCI_CLOCK_CARD_EN;
>         sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
>  }
> +EXPORT_SYMBOL_GPL(sdhci_set_clock_enable);
> +
> +void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
> +{
> +       u16 clk;
> +       unsigned long timeout;
> +
> +       host->mmc->actual_clock = 0;
> +
> +       sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
> +
> +       if (clock == 0)
> +               return;
> +
> +       clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock);
> +
> +       sdhci_set_clock_enable(host, clk);
> +}
>  EXPORT_SYMBOL_GPL(sdhci_set_clock);
> 
>  static void sdhci_set_power_reg(struct sdhci_host *host, unsigned char mode,
> diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
> index 766df17..43382e1 100644
> --- a/drivers/mmc/host/sdhci.h
> +++ b/drivers/mmc/host/sdhci.h
> @@ -681,6 +681,7 @@ static inline bool sdhci_sdio_irq_enabled(struct
> sdhci_host *host)
>  u16 sdhci_calc_clk(struct sdhci_host *host, unsigned int clock,
>                    unsigned int *actual_clock);
>  void sdhci_set_clock(struct sdhci_host *host, unsigned int clock);
> +void sdhci_set_clock_enable(struct sdhci_host *host, unsigned short clk);
>  void sdhci_set_power(struct sdhci_host *host, unsigned char mode,
>                      unsigned short vdd);
>  void sdhci_set_power_noreg(struct sdhci_host *host, unsigned char mode,
> 
> 
> 
>> Adrian,
>> Could you please comment here ?
>>
>>>
>>>> +}
>>>> +
>>>> +/* sdhci_msm_set_clock - Called with (host->lock) spinlock held. */
>>>> +static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned
>>>> int clock)
>>>> +{
>>>> +    struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
>>>> +    struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
>>>> +    int rc;
>>>> +
>>>> +    if (!clock) {
>>>> +        msm_host->clk_rate = clock;
>>>> +        goto out;
>>>> +    }
>>>> +
>>>> +    spin_unlock_irq(&host->lock);
>>>> +    if (clock != msm_host->clk_rate) {
>>>
>>> Why do we need to check here? Can't we call clk_set_rate()
>>> Unconditionally?
>> Since it may so happen that above layers may call for ->set_clock
>> function with same requested clock more than once, hence we cache the
>> host->clock here.
>> Also, since requested clock (host->clock) can be say 400Mhz but the
>> actual pltfm supported clock would be say 384MHz.
>>
>>
>>>
>>>> +        rc = clk_set_rate(msm_host->clk, clock);
>>>> +        if (rc) {
>>>> +            pr_err("%s: Failed to set clock at rate %u\n",
>>>> +                   mmc_hostname(host->mmc), clock);
>>>> +            spin_lock_irq(&host->lock);
>>>> +            goto out;
>>>
>>> Or replace the above two lines with goto err;
>> Ok, I will have another label out_lock instead of err.
>>>
>>>> +        }
>>>> +        msm_host->clk_rate = clock;
>>>> +        pr_debug("%s: Setting clock at rate %lu\n",
>>>> +             mmc_hostname(host->mmc), clk_get_rate(msm_host->clk));
>>>> +    }
>>>
>>> And put an err label here.
>> will put the label here as out_lock;
>>>
>>>> +    spin_lock_irq(&host->lock);
>>>> +out:
>>>> +    __sdhci_msm_set_clock(host, clock);
>>>> +}
>>>> +
>>>>  static const struct of_device_id sdhci_msm_dt_match[] = {
>>>>      { .compatible = "qcom,sdhci-msm-v4" },
>>>>      {},
>>>
>>
> 

^ permalink raw reply

* Re: [upstream-release] [PATCH 1/2] drivers: usb: phy: Add qoriq usb 3.0 phy driver support
From: Scott Wood @ 2016-11-16  7:22 UTC (permalink / raw)
  To: Sriram Dash, linux-kernel@vger.kernel.org,
	linux-usb@vger.kernel.org, devicetree@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org
  Cc: mark.rutland@arm.com, felipe.balbi@linux.intel.com,
	mathias.nyman@intel.com, catalin.marinas@arm.com,
	will.deacon@arm.com, kishon@ti.com, robh+dt@kernel.org,
	stern@rowland.harvard.edu, Suresh Gupta,
	gregkh@linuxfoundation.org, pku.leo@gmail.com
In-Reply-To: <DB5PR0401MB1925FB1FE45C15B0671E46D1F5BF0@DB5PR0401MB1925.eurprd04.prod.outlook.com>

On 11/15/2016 06:39 AM, Sriram Dash wrote:
>> From: Scott Wood
>> On 11/13/2016 11:27 PM, Sriram Dash wrote:
>>> diff --git a/Documentation/devicetree/bindings/phy/phy-qoriq-usb3.txt
>>> b/Documentation/devicetree/bindings/phy/phy-qoriq-usb3.txt
>>> new file mode 100644
>>> index 0000000..d934c80
>>> --- /dev/null
>>> +++ b/Documentation/devicetree/bindings/phy/phy-qoriq-usb3.txt
>>> @@ -0,0 +1,36 @@
>>> +Driver for Freescale USB 3.0 PHY
>>> +
>>> +Required properties:
>>> +
>>> +- compatible :	fsl,qoriq-usb3-phy
>>
> 
> Hi Scott,
> 
>> This is a very vague compatible.  Are there versioning registers within this register
>> block?
>>
> 
> There are versioning registers for the phy (1.0 and 1.1). But the current erratum
> A008751 does not require the mentioning of the version numbers. Was planning
> to take care of the versioning when there is code diversity on the basis of the
> version number.

That is not how device tree bindings work.  The describe the hardware,
not the driver.

That said, is the block version sufficient to tell whether a given chip
has this erratum?  If so, you don't need a special property for the
erratum.  If not, what is different about the PHY that is not described
by the versioning?

In any case, it would be nice to mention the version register and its
offset in the binding, just so that it becomes part of the definition of
this compatible string, and if we come out with some QorIQ chip with a
USB3 PHY that is totally different and doesn't have that version
register, it'll be clear that it needs a different compatible.

>>> +static inline u32 qoriq_usb3_phy_readl(void __iomem *addr, u32
>>> +offset) {
>>> +	return __raw_readl(addr + offset);
>>> +}
>>> +
>>> +static inline void qoriq_usb3_phy_writel(void __iomem *addr, u32 offset,
>>> +	u32 data)
>>> +{
>>> +	__raw_writel(data, addr + offset);
>>> +}
>>
>> Why raw?  Besides missing barriers, this will cause the accesses to be native-endian
>> which is not correct.
>>
> 
> The only reason for __raw_writel is to make the code faster.

Does that really matter here?

> However, shall I use writel(with both barriers and byte swap) instead 

Yes, if the registers are little-endian on all chips.

> and then make appropriate changes in the value 32'h27672B2A?

Not sure what you mean here.

> In my knowledge, there are more than 5 errata in pipeline,

Then please get all of these errata described in the device tree ASAP
(unless their presence can be reliably inferred from the block version,
as discussed above).

> However, in future, if any other erratum comes up, and it has to be applied
> at any point other than during init, then the variable has to be added in
> qoriq_usb3_phy struct and the property has to be read separately.

Or if the erratum is detected by some means other than a device tree
property...

-Scott

^ permalink raw reply

* Re: [PATCH v4 4/4] ARM: dts: da850: Add the usb otg device nodeg
From: Sekhar Nori @ 2016-11-16  6:36 UTC (permalink / raw)
  To: Bin Liu, Alexandre Bailon, khilman, robh+dt, linux-kernel,
	linux-usb, devicetree, linux-arm-kernel
In-Reply-To: <20161115211951.GH11011@uda0271908>

On Wednesday 16 November 2016 02:49 AM, Bin Liu wrote:
> On Tue, Nov 15, 2016 at 04:16:02PM +0530, Sekhar Nori wrote:
>> On Thursday 03 November 2016 09:29 PM, Alexandre Bailon wrote:
>>> This adds the device tree node for the usb otg
>>> controller present in the da850 family of SoC's.
>>> This also enables the otg usb controller for the lcdk board.
>>>
>>> Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
>>> ---
>>>  arch/arm/boot/dts/da850-lcdk.dts |  8 ++++++++
>>>  arch/arm/boot/dts/da850.dtsi     | 15 +++++++++++++++
>>>  2 files changed, 23 insertions(+)
>>>
>>> diff --git a/arch/arm/boot/dts/da850-lcdk.dts b/arch/arm/boot/dts/da850-lcdk.dts
>>> index 7b8ab21..9f5040c 100644
>>> --- a/arch/arm/boot/dts/da850-lcdk.dts
>>> +++ b/arch/arm/boot/dts/da850-lcdk.dts
>>> @@ -158,6 +158,14 @@
>>>  	rx-num-evt = <32>;
>>>  };
>>>  
>>> +&usb_phy {
>>> +	status = "okay";
>>> +	};
>>
>> As mentioned by David already, this node needs to be removed. Please
>> rebase this on top of latest linux-davinci/master when ready for merging
>> (driver changes accepted).
> 
> Dropped this patch due to this comment.

Bin, Please do not apply dts or arch/arm/mach-davinci patches. I have a
bunch queued through my tree and more in pipeline and it will cause
unnecessary merge conflicts in linux-next or at Linus.

For future, I have asked Alexandre to send driver and dts patches as
separate series so there is no confusion on who should apply.

Thanks,
Sekhar

^ permalink raw reply

* [RESEND PATCH v7 3/3] clocksource: Add clockevent support to NPS400 driver
From: Noam Camus @ 2016-11-16  6:31 UTC (permalink / raw)
  To: robh+dt, mark.rutland, daniel.lezcano
  Cc: devicetree, Noam Camus, Vineet.Gupta1, Alexey.Brodkin,
	linux-kernel, tglx, linux-snps-arc
In-Reply-To: <1479277873-18994-1-git-send-email-noamca@mellanox.com>

From: Noam Camus <noamca@mellanox.com>

Till now we used clockevent from generic ARC driver.
This was enough as long as we worked with simple multicore SoC.
When we are working with multithread SoC each HW thread can be
scheduled to receive timer interrupt using timer mask register.
This patch will provide a way to control clock events per HW thread.

The design idea is that for each core there is dedicated register
(TSI) serving all 16 HW threads.
The register is a bitmask with one bit for each HW thread.
When HW thread wants that next expiration of timer interrupt will
hit it then the proper bit should be set in this dedicated register.
When timer expires all HW threads within this core which their bit
is set at the TSI register will be interrupted.

Driver can be used from device tree by:
compatible = "ezchip,nps400-timer0" <-- for clocksource
compatible = "ezchip,nps400-timer1" <-- for clockevent

Note that name convention for timer0/timer1 was taken from legacy
ARC design. This design is our base before adding HW threads.
For backward compatibility we keep "ezchip,nps400-timer" for clocksource

Signed-off-by: Noam Camus <noamca@mellanox.com>
Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
 .../bindings/timer/ezchip,nps400-timer.txt         |   15 --
 .../bindings/timer/ezchip,nps400-timer0.txt        |   17 ++
 .../bindings/timer/ezchip,nps400-timer1.txt        |   15 ++
 drivers/clocksource/timer-nps.c                    |  170 ++++++++++++++++++++
 4 files changed, 202 insertions(+), 15 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt
 create mode 100644 Documentation/devicetree/bindings/timer/ezchip,nps400-timer0.txt
 create mode 100644 Documentation/devicetree/bindings/timer/ezchip,nps400-timer1.txt

diff --git a/Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt b/Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt
deleted file mode 100644
index c8c03d7..0000000
--- a/Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-NPS Network Processor
-
-Required properties:
-
-- compatible :	should be "ezchip,nps400-timer"
-
-Clocks required for compatible = "ezchip,nps400-timer":
-- clocks : Must contain a single entry describing the clock input
-
-Example:
-
-timer {
-	compatible = "ezchip,nps400-timer";
-	clocks = <&sysclk>;
-};
diff --git a/Documentation/devicetree/bindings/timer/ezchip,nps400-timer0.txt b/Documentation/devicetree/bindings/timer/ezchip,nps400-timer0.txt
new file mode 100644
index 0000000..e3cfce8
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/ezchip,nps400-timer0.txt
@@ -0,0 +1,17 @@
+NPS Network Processor
+
+Required properties:
+
+- compatible :	should be "ezchip,nps400-timer0"
+
+Clocks required for compatible = "ezchip,nps400-timer0":
+- interrupts : The interrupt of the first timer
+- clocks : Must contain a single entry describing the clock input
+
+Example:
+
+timer {
+	compatible = "ezchip,nps400-timer0";
+	interrupts = <3>;
+	clocks = <&sysclk>;
+};
diff --git a/Documentation/devicetree/bindings/timer/ezchip,nps400-timer1.txt b/Documentation/devicetree/bindings/timer/ezchip,nps400-timer1.txt
new file mode 100644
index 0000000..c0ab419
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/ezchip,nps400-timer1.txt
@@ -0,0 +1,15 @@
+NPS Network Processor
+
+Required properties:
+
+- compatible :	should be "ezchip,nps400-timer1"
+
+Clocks required for compatible = "ezchip,nps400-timer1":
+- clocks : Must contain a single entry describing the clock input
+
+Example:
+
+timer {
+	compatible = "ezchip,nps400-timer1";
+	clocks = <&sysclk>;
+};
diff --git a/drivers/clocksource/timer-nps.c b/drivers/clocksource/timer-nps.c
index 0c8e21f..b4c8a02 100644
--- a/drivers/clocksource/timer-nps.c
+++ b/drivers/clocksource/timer-nps.c
@@ -111,3 +111,173 @@ static int __init nps_setup_clocksource(struct device_node *node)
 
 CLOCKSOURCE_OF_DECLARE(ezchip_nps400_clksrc, "ezchip,nps400-timer",
 		       nps_setup_clocksource);
+CLOCKSOURCE_OF_DECLARE(ezchip_nps400_clk_src, "ezchip,nps400-timer1",
+		       nps_setup_clocksource);
+
+#ifdef CONFIG_EZNPS_MTM_EXT
+#include <soc/nps/mtm.h>
+
+/* Timer related Aux registers */
+#define NPS_REG_TIMER0_TSI	0xFFFFF850
+#define NPS_REG_TIMER0_LIMIT	0x23
+#define NPS_REG_TIMER0_CTRL	0x22
+#define NPS_REG_TIMER0_CNT	0x21
+
+/*
+ * Interrupt Enabled (IE) - re-arm the timer
+ * Not Halted (NH) - is cleared when working with JTAG (for debug)
+ */
+#define TIMER0_CTRL_IE		BIT(0)
+#define TIMER0_CTRL_NH		BIT(1)
+
+static unsigned long nps_timer0_freq;
+static unsigned long nps_timer0_irq;
+
+static void nps_clkevent_rm_thread(void)
+{
+	int thread;
+	unsigned int cflags, enabled_threads;
+
+	hw_schd_save(&cflags);
+
+	enabled_threads = read_aux_reg(NPS_REG_TIMER0_TSI);
+
+	/* remove thread from TSI1 */
+	thread = read_aux_reg(CTOP_AUX_THREAD_ID);
+	enabled_threads &= ~(1 << thread);
+	write_aux_reg(NPS_REG_TIMER0_TSI, enabled_threads);
+
+	/* Acknowledge and if needed re-arm the timer */
+	if (!enabled_threads)
+		write_aux_reg(NPS_REG_TIMER0_CTRL, TIMER0_CTRL_NH);
+	else
+		write_aux_reg(NPS_REG_TIMER0_CTRL,
+			      TIMER0_CTRL_IE | TIMER0_CTRL_NH);
+
+	hw_schd_restore(cflags);
+}
+
+static void nps_clkevent_add_thread(unsigned long delta)
+{
+	int thread;
+	unsigned int cflags, enabled_threads;
+
+	hw_schd_save(&cflags);
+
+	/* add thread to TSI1 */
+	thread = read_aux_reg(CTOP_AUX_THREAD_ID);
+	enabled_threads = read_aux_reg(NPS_REG_TIMER0_TSI);
+	enabled_threads |= (1 << thread);
+	write_aux_reg(NPS_REG_TIMER0_TSI, enabled_threads);
+
+	/* set next timer event */
+	write_aux_reg(NPS_REG_TIMER0_LIMIT, delta);
+	write_aux_reg(NPS_REG_TIMER0_CNT, 0);
+	write_aux_reg(NPS_REG_TIMER0_CTRL,
+		      TIMER0_CTRL_IE | TIMER0_CTRL_NH);
+
+	hw_schd_restore(cflags);
+}
+
+/*
+ * Whenever anyone tries to change modes, we just mask interrupts
+ * and wait for the next event to get set.
+ */
+static int nps_clkevent_set_state(struct clock_event_device *dev)
+{
+	nps_clkevent_rm_thread();
+	disable_percpu_irq(nps_timer0_irq);
+
+	return 0;
+}
+
+static int nps_clkevent_set_next_event(unsigned long delta,
+				       struct clock_event_device *dev)
+{
+	nps_clkevent_add_thread(delta);
+	enable_percpu_irq(nps_timer0_irq, IRQ_TYPE_NONE);
+
+	return 0;
+}
+
+static DEFINE_PER_CPU(struct clock_event_device, nps_clockevent_device) = {
+	.name				=	"NPS Timer0",
+	.features			=	CLOCK_EVT_FEAT_ONESHOT,
+	.rating				=	300,
+	.set_next_event			=	nps_clkevent_set_next_event,
+	.set_state_oneshot		=	nps_clkevent_set_state,
+	.set_state_oneshot_stopped	=	nps_clkevent_set_state,
+	.set_state_shutdown		=	nps_clkevent_set_state,
+	.tick_resume			=	nps_clkevent_set_state,
+};
+
+static irqreturn_t timer_irq_handler(int irq, void *dev_id)
+{
+	struct clock_event_device *evt = dev_id;
+
+	nps_clkevent_rm_thread();
+	evt->event_handler(evt);
+
+	return IRQ_HANDLED;
+}
+
+static int nps_timer_starting_cpu(unsigned int cpu)
+{
+	struct clock_event_device *evt = this_cpu_ptr(&nps_clockevent_device);
+
+	evt->cpumask = cpumask_of(smp_processor_id());
+
+	clockevents_config_and_register(evt, nps_timer0_freq, 0, ULONG_MAX);
+	enable_percpu_irq(nps_timer0_irq, IRQ_TYPE_NONE);
+
+	return 0;
+}
+
+static int nps_timer_dying_cpu(unsigned int cpu)
+{
+	disable_percpu_irq(nps_timer0_irq);
+	return 0;
+}
+
+static int __init nps_setup_clockevent(struct device_node *node)
+{
+	struct clk *clk;
+	int ret;
+
+	nps_timer0_irq = irq_of_parse_and_map(node, 0);
+	if (nps_timer0_irq <= 0) {
+		pr_err("clockevent: missing irq");
+		return -EINVAL;
+	}
+
+	ret = nps_get_timer_clk(node, &nps_timer0_freq, &clk);
+	if (ret)
+		return ret;
+
+	/* Needs apriori irq_set_percpu_devid() done in intc map function */
+	ret = request_percpu_irq(nps_timer0_irq, timer_irq_handler,
+				 "Timer0 (per-cpu-tick)",
+				 &nps_clockevent_device);
+	if (ret) {
+		pr_err("Couldn't request irq\n");
+		clk_disable_unprepare(clk);
+		return ret;
+	}
+
+	ret = cpuhp_setup_state(CPUHP_AP_ARC_TIMER_STARTING,
+				"clockevents/nps:starting",
+				nps_timer_starting_cpu,
+				nps_timer_dying_cpu);
+	if (ret) {
+		pr_err("Failed to setup hotplug state");
+		clk_disable_unprepare(clk);
+		free_percpu_irq(nps_timer0_irq, &nps_clockevent_device);
+		return ret;
+	}
+
+	return 0;
+}
+
+CLOCKSOURCE_OF_DECLARE(ezchip_nps400_clk_evt, "ezchip,nps400-timer0",
+		       nps_setup_clockevent);
+#endif /* CONFIG_EZNPS_MTM_EXT */
-- 
1.7.1

^ permalink raw reply related

* [RESEND PATCH v7 2/3] clocksource: update "fn" at CLOCKSOURCE_OF_DECLARE() of nps400 timer
From: Noam Camus @ 2016-11-16  6:31 UTC (permalink / raw)
  To: robh+dt, mark.rutland, daniel.lezcano
  Cc: tglx, devicetree, linux-kernel, linux-snps-arc, Vineet.Gupta1,
	Alexey.Brodkin, Noam Camus
In-Reply-To: <1479277873-18994-1-git-send-email-noamca@mellanox.com>

From: Noam Camus <noamca@mellanox.com>

nps_setup_clocksource() should take node as only argument as defined by
typedef int (*of_init_fn_1_ret)(struct device_node *)

Therefore need to replace:
int __init nps_setup_clocksource(struct device_node *node, struct clk *clk)
with
int __init nps_setup_clocksource(struct device_node *node)

This patch also serve as preparation for next patch which add support
for clockevents to nps400.
Specifically we add new function nps_get_timer_clk() to serve clocksource
and later clockevent registration.

Signed-off-by: Noam Camus <noamca@mellanox.com>
Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
 drivers/clocksource/timer-nps.c |   65 +++++++++++++++++++++++---------------
 1 files changed, 39 insertions(+), 26 deletions(-)

diff --git a/drivers/clocksource/timer-nps.c b/drivers/clocksource/timer-nps.c
index 70c149a..0c8e21f 100644
--- a/drivers/clocksource/timer-nps.c
+++ b/drivers/clocksource/timer-nps.c
@@ -46,7 +46,35 @@
 /* This array is per cluster of CPUs (Each NPS400 cluster got 256 CPUs) */
 static void *nps_msu_reg_low_addr[NPS_CLUSTER_NUM] __read_mostly;
 
-static unsigned long nps_timer_rate;
+static int __init nps_get_timer_clk(struct device_node *node,
+			     unsigned long *timer_freq,
+			     struct clk **clk)
+{
+	int ret;
+
+	*clk = of_clk_get(node, 0);
+	if (IS_ERR(*clk)) {
+		pr_err("timer missing clk");
+		return PTR_ERR(*clk);
+	}
+
+	ret = clk_prepare_enable(*clk);
+	if (ret) {
+		pr_err("Couldn't enable parent clk\n");
+		clk_put(*clk);
+		return ret;
+	}
+
+	*timer_freq = clk_get_rate(*clk);
+	if (!(*timer_freq)) {
+		pr_err("Couldn't get clk rate\n");
+		clk_disable_unprepare(*clk);
+		clk_put(*clk);
+		return -EINVAL;
+	}
+
+	return 0;
+}
 
 static cycle_t nps_clksrc_read(struct clocksource *clksrc)
 {
@@ -55,26 +83,24 @@ static cycle_t nps_clksrc_read(struct clocksource *clksrc)
 	return (cycle_t)ioread32be(nps_msu_reg_low_addr[cluster]);
 }
 
-static int __init nps_setup_clocksource(struct device_node *node,
-					struct clk *clk)
+static int __init nps_setup_clocksource(struct device_node *node)
 {
 	int ret, cluster;
+	struct clk *clk;
+	unsigned long nps_timer1_freq;
+
 
 	for (cluster = 0; cluster < NPS_CLUSTER_NUM; cluster++)
 		nps_msu_reg_low_addr[cluster] =
 			nps_host_reg((cluster << NPS_CLUSTER_OFFSET),
-				 NPS_MSU_BLKID, NPS_MSU_TICK_LOW);
+				     NPS_MSU_BLKID, NPS_MSU_TICK_LOW);
 
-	ret = clk_prepare_enable(clk);
-	if (ret) {
-		pr_err("Couldn't enable parent clock\n");
+	ret = nps_get_timer_clk(node, &nps_timer1_freq, &clk);
+	if (ret)
 		return ret;
-	}
 
-	nps_timer_rate = clk_get_rate(clk);
-
-	ret = clocksource_mmio_init(nps_msu_reg_low_addr, "EZnps-tick",
-				    nps_timer_rate, 301, 32, nps_clksrc_read);
+	ret = clocksource_mmio_init(nps_msu_reg_low_addr, "nps-tick",
+				    nps_timer1_freq, 300, 32, nps_clksrc_read);
 	if (ret) {
 		pr_err("Couldn't register clock source.\n");
 		clk_disable_unprepare(clk);
@@ -83,18 +109,5 @@ static int __init nps_setup_clocksource(struct device_node *node,
 	return ret;
 }
 
-static int __init nps_timer_init(struct device_node *node)
-{
-	struct clk *clk;
-
-	clk = of_clk_get(node, 0);
-	if (IS_ERR(clk)) {
-		pr_err("Can't get timer clock.\n");
-		return PTR_ERR(clk);
-	}
-
-	return nps_setup_clocksource(node, clk);
-}
-
 CLOCKSOURCE_OF_DECLARE(ezchip_nps400_clksrc, "ezchip,nps400-timer",
-		       nps_timer_init);
+		       nps_setup_clocksource);
-- 
1.7.1

^ permalink raw reply related

* [RESEND PATCH v7 1/3] soc: Support for NPS HW scheduling
From: Noam Camus @ 2016-11-16  6:31 UTC (permalink / raw)
  To: robh+dt, mark.rutland, daniel.lezcano
  Cc: devicetree, Noam Camus, Vineet.Gupta1, Alexey.Brodkin,
	linux-kernel, tglx, linux-snps-arc
In-Reply-To: <1479277873-18994-1-git-send-email-noamca@mellanox.com>

From: Noam Camus <noamca@mellanox.com>

This new header file is for NPS400 SoC (part of ARC architecture).
The header file includes macros for save/restore of HW scheduling.
The control of HW scheduling is achieved by writing core registers.
This code was moved from arc/plat-eznps so it can be used
from drivers/clocksource/, available only for CONFIG_EZNPS_MTM_EXT.

Signed-off-by: Noam Camus <noamca@mellanox.com>
Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
 arch/arc/plat-eznps/include/plat/ctop.h |    2 -
 include/soc/nps/mtm.h                   |   59 +++++++++++++++++++++++++++++++
 2 files changed, 59 insertions(+), 2 deletions(-)
 create mode 100644 include/soc/nps/mtm.h

diff --git a/arch/arc/plat-eznps/include/plat/ctop.h b/arch/arc/plat-eznps/include/plat/ctop.h
index 9d6718c..ee2e32d 100644
--- a/arch/arc/plat-eznps/include/plat/ctop.h
+++ b/arch/arc/plat-eznps/include/plat/ctop.h
@@ -46,9 +46,7 @@
 #define CTOP_AUX_UDMC				(CTOP_AUX_BASE + 0x300)
 
 /* EZchip core instructions */
-#define CTOP_INST_HWSCHD_OFF_R3			0x3B6F00BF
 #define CTOP_INST_HWSCHD_OFF_R4			0x3C6F00BF
-#define CTOP_INST_HWSCHD_RESTORE_R3		0x3E6F70C3
 #define CTOP_INST_HWSCHD_RESTORE_R4		0x3E6F7103
 #define CTOP_INST_SCHD_RW			0x3E6F7004
 #define CTOP_INST_SCHD_RD			0x3E6F7084
diff --git a/include/soc/nps/mtm.h b/include/soc/nps/mtm.h
new file mode 100644
index 0000000..d2f5e7e
--- /dev/null
+++ b/include/soc/nps/mtm.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2016, Mellanox Technologies. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef SOC_NPS_MTM_H
+#define SOC_NPS_MTM_H
+
+#define CTOP_INST_HWSCHD_OFF_R3                 0x3B6F00BF
+#define CTOP_INST_HWSCHD_RESTORE_R3             0x3E6F70C3
+
+static inline void hw_schd_save(unsigned int *flags)
+{
+	__asm__ __volatile__(
+	"       .word %1\n"
+	"       st r3,[%0]\n"
+	:
+	: "r"(flags), "i"(CTOP_INST_HWSCHD_OFF_R3)
+	: "r3", "memory");
+}
+
+static inline void hw_schd_restore(unsigned int flags)
+{
+	__asm__ __volatile__(
+	"       mov r3, %0\n"
+	"       .word %1\n"
+	:
+	: "r"(flags), "i"(CTOP_INST_HWSCHD_RESTORE_R3)
+	: "r3");
+}
+
+#endif /* SOC_NPS_MTM_H */
-- 
1.7.1

^ permalink raw reply related

* [RESEND PATCH v7 0/3] Add clockevent for timer-nps driver to NPS400 SoC
From: Noam Camus @ 2016-11-16  6:31 UTC (permalink / raw)
  To: robh+dt, mark.rutland, daniel.lezcano
  Cc: tglx, devicetree, linux-kernel, linux-snps-arc, Vineet.Gupta1,
	Alexey.Brodkin, Noam Camus

From: Noam Camus <noamca@mellanox.com>

Change log
---
V6 --> V7
Apply several comments made by Daniel Lezcano:
1) Remove CLOCK_EVT_FEAT_PERIODIC support. This way it is
 pure oneshot driver. This simplifies driver so that:
 nps_clkevent_add_thread()
 nps_clkevent_rm_thread()
 are more clearer without any vague logic if to change
 TSI bit of current HW thread or not.
2) tick_resume is also calls nps_clkevent_rm_thread()
3) Few (hopefully last) typo fixes. 

V5 --> V6
Apply several comments made by Daniel Lezcano:
1) nps_get_timer_clk() - use clk_put() on error scenario
2) nps_get_timer_clk() - return EINVAL and not plain 1
3) Fix typos in log (double checked with spell checker)

V4 --> V5
Apply several comments made by Daniel Lezcano:
1) Add __init attribute to nps_get_timer_clk()
2) Fix return value of nps_get_timer_clk()
 when failing to get clk rate
3) Change clocksource rate from 301 -> 300

V3 --> V4
Main changes are [Thanks for the review]:
Fix many typos at log [Daniel]
Add handling for bad return values [Daniel and Thomas]
Replace use of internal irqchip pointers with existing IRQ API [Thomas]
Provide interrupt handler (percpu) with dev_id equal to evt [Thomas]
Fix passing *clk by reference to nps_get_timer_clk() [Daniel]

V2 --> V3
Apply Rob Herring comment about backword compatibility

V1 --> V2
Apply Daniel Lezcano comments:
	CLOCKSOURCE_OF_DECLARE return value
	update hotplug callbacks usage
	squash of 2 first commits.
In this version I created new commit to serve as preperation for adding clockevents.
This way the last patch is more readable with clockevent content.
---

In first version of this driver we supported clocksource for the NPS400.
The support for clockevent was taken from Synopsys ARC timer driver.
This was good for working with our simulator of NPS400.
However in NPS400 ASIC the timers behave differently than simulation.
The timers in ASIC are shared between all threads whithin a core
and hence need different driver to support this behaviour.

The idea of this design is that we got 16 HW threads per core
each represented at bimask in a shared register in this core.
So when thread wants that next clockevent expiration will produce
timer interrupt to itself the correspondance bit in this register
should be set.
So theoretically if all 16 bits are set then all HW threads will get
timer interrupt on next expiration of timer 0.

Note that we use Synopsys ARC design naming convention for the timers
where:
timer0 is used for clockevents
timer1 is used for clocksource.

Noam Camus (3):
  soc: Support for NPS HW scheduling
  clocksource: update "fn" at CLOCKSOURCE_OF_DECLARE() of nps400 timer
  clocksource: Add clockevent support to NPS400 driver

 .../bindings/timer/ezchip,nps400-timer.txt         |   15 --
 .../bindings/timer/ezchip,nps400-timer0.txt        |   17 ++
 .../bindings/timer/ezchip,nps400-timer1.txt        |   15 ++
 arch/arc/plat-eznps/include/plat/ctop.h            |    2 -
 drivers/clocksource/timer-nps.c                    |  223 ++++++++++++++++++--
 include/soc/nps/mtm.h                              |   59 +++++
 6 files changed, 294 insertions(+), 37 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt
 create mode 100644 Documentation/devicetree/bindings/timer/ezchip,nps400-timer0.txt
 create mode 100644 Documentation/devicetree/bindings/timer/ezchip,nps400-timer1.txt
 create mode 100644 include/soc/nps/mtm.h

^ permalink raw reply

* Re: [RESEND PATCH v1 05/11] dt-bindings: perf: hisi: Add Devicetree bindings for Hisilicon SoC PMU
From: Anurup M @ 2016-11-16  5:54 UTC (permalink / raw)
  To: Mark Rutland
  Cc: devicetree, linux-arm-kernel, linux-doc, will.deacon, corbet,
	catalin.marinas, robh+dt, arnd, f.fainelli, rmk+kernel, krzk,
	anurup.m, zhangshaokun, tanxiaojun, xuwei5, sanil.kumar,
	john.garry, gabriele.paoloni, shiju.jose, wangkefeng.wang,
	guohanjun, shyju.pv, linuxarm
In-Reply-To: <20161115095148.GA29104@leverpostej>



On Tuesday 15 November 2016 03:21 PM, Mark Rutland wrote:
> On Mon, Nov 14, 2016 at 05:36:44AM +0530, Anurup M wrote:
>> On Friday 11 November 2016 12:00 AM, Mark Rutland wrote:
>>> On Thu, Nov 03, 2016 at 01:42:01AM -0400, Anurup M wrote:
>>>> +	- scl-id : The Super Cluster ID. This can be the ID of the CPU die
>>>> +		   or IO die in the chip.
>>> What's this needed for?
>> This is used as suffix to the PMU name. hisi_l3c<scl-id>. (hisi_l3c2
>> - for scl-id = 2).
>> This is to identify the pmu correspond to which CPU die in the socket.
>>>> +	- num-events : No of events supported by this PMU device.
>>>> +
>>>> +	- num-counters : No of hardware counters available for counting.
>>> This isn't probeable or well-known?
>> My idea is to have the common properties of SoC PMU added here.
>> The num-events, num-counters etc. So that handling can be made
>> common in the driver.
>> Is it not recommended? Please share your comments.
> This feels like something that should be well-known for the programming
> model of the device. If the number of events and/or counters shange, I'd
> expect other things to also change such that the device is no longer
> compatible with previous versions.
>
> [...]
>
Agreed, it is possible that the versions can be still incompatible. 
Shall move it to
driver in v2.

>> The below two properties (module-id, cfgen-map) differs between
>> chips hip05/06 and hip07.
> The module-id property sounds like a HW description, but it's not
> entirely clear to me what cfgen-map is; more comments on that below.
>
>> Please suggest.
>>>> +	- module-id : Module ID to input for djtag. This property is an array of
>>>> +		      module_id for each L3 cache banks.
>>>> +
>>>> +	- num-banks : Number of banks or instances of the device.
>>> What's a bank? Surely they have separate instances of the PMU?
>> Yes each bank is a separate instance of PMU.
>> If it is recommended to have each L3 cache bank registered as
>> separate PMU with perf, then this property will be removed.
> Generally, I think that separate instances are preferable.
>
>>> What order are these in?
>> The bank number will start from "1" till "4" for L3 cache as there
>> are four banks in hip05/06/07 chips.
>>>> +	- cfgen-map : Config enable array to select the bank.
>>> Huh?
> As above, it's not clear to me what this property represents. Could you
> please clarify?
This property is used to select the bank. The naming lead to confusion.
I shall change it to bank_select.
If it is recommended to register each L3 cache bank as separate PMU then
this property will be moved to driver.

Thanks
Anurup
>
> Thanks,
> Mark.


^ permalink raw reply

* RE: [PATCH 1/2] drivers: usb: phy: Add qoriq usb 3.0 phy driver support
From: Sriram Dash @ 2016-11-16  5:48 UTC (permalink / raw)
  To: Rob Herring
  Cc: mark.rutland@arm.com, devicetree@vger.kernel.org,
	felipe.balbi@linux.intel.com, mathias.nyman@intel.com,
	catalin.marinas@arm.com, linux-usb@vger.kernel.org,
	will.deacon@arm.com, linux-kernel@vger.kernel.org, kishon@ti.com,
	stern@rowland.harvard.edu, Suresh Gupta,
	gregkh@linuxfoundation.org, pku.leo@gmail.com,
	linux-arm-kernel@lists.infradead.org
In-Reply-To: <20161116000740.iq6ffcjanrrvrdnq@rob-hp-laptop>

>From: Rob Herring [mailto:robh@kernel.org]
>On Mon, Nov 14, 2016 at 10:56:54AM +0530, Sriram Dash wrote:
>> Adds qoriq usb 3.0 phy driver support for LS1043A platform.
>> Describes the qoriq usb 2.0 phy driver binding, currently used for
>> LS1043A platform.
>>
>> Signed-off-by: Sriram Dash <sriram.dash@nxp.com>
>> ---
>>  .../devicetree/bindings/phy/phy-qoriq-usb3.txt     |  36 ++++
>>  drivers/phy/Kconfig                                |   8 +
>>  drivers/phy/Makefile                               |   1 +
>>  drivers/phy/phy-qoriq-usb3.c                       | 202 +++++++++++++++++++++
>>  4 files changed, 247 insertions(+)
>>  create mode 100644
>> Documentation/devicetree/bindings/phy/phy-qoriq-usb3.txt
>>  create mode 100644 drivers/phy/phy-qoriq-usb3.c
>>
>> diff --git a/Documentation/devicetree/bindings/phy/phy-qoriq-usb3.txt
>> b/Documentation/devicetree/bindings/phy/phy-qoriq-usb3.txt
>> new file mode 100644
>> index 0000000..d934c80
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/phy/phy-qoriq-usb3.txt
>> @@ -0,0 +1,36 @@
>> +Driver for Freescale USB 3.0 PHY
>> +
>> +Required properties:
>> +
>> +- compatible :	fsl,qoriq-usb3-phy
>> +- reg :		register mappings for Parameter Configuration Register
>> +		and Phy base offset.
>> +- reg-names :	"param_ctrl" and "phy_base"
>> +- phy_type :	For multi port host USB controllers, should be one of
>> +		"ulpi", or "serial". For dual role USB controllers,
>> +		should be one of "ulpi", "utmi", "utmi_wide", or "serial".

Hi Rob,

>
>Do any of these really apply to a USB3 PHY?
>

The concerned USB3 phy used is UTMI. I agree to your point somewhat that
all the types are not required now. Anyway, shall I make it an optional
property, with the mention of only UTMI and ULPI?

>Rob
>
>> +
>> +Example:
>> +		usbphy0: usb3-phy@084F0000 {
>
>usb-phy@...
>

Ok. Will change in the next rev for Documentation and dts (patch 2/2)

>> +                        compatible = "fsl,qoriq-usb3-phy";
>> +                        reg = <0x0 0x01570070 0x0 0xC>, <0x0 0x084F0000 0x0 0x5000>;
>> +                        reg-names = "param_ctrl", "phy_base";
>> +                        #phy-cells = <0>;
>> +                        phy_type = "utmi";
>> +                };
>> +
>> +                usbphy1: usb3-phy@08500000 {
>> +                        compatible = "fsl,qoriq-usb3-phy";
>> +                        reg = <0x0 0x0157007C 0x0 0xC>, <0x0 0x08500000 0x0 0x5000>;
>> +                        reg-names = "param_ctrl", "phy_base";
>> +                        #phy-cells = <0>;
>> +                        phy_type = "utmi";
>> +                };
>> +
>> +                usbphy2: usb3-phy@08510000 {
>> +                        compatible = "fsl,qoriq-usb3-phy";
>> +                        reg = <0x0 0x01570088 0x0 0xC>, <0x0 0x08510000 0x0 0x5000>;
>> +                        reg-names = "param_ctrl", "phy_base";
>> +                        #phy-cells = <0>;
>> +                        phy_type = "utmi";
>> +                };

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox