Message ID | 1370626110-1731-2-git-send-email-dianders@chromium.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Hi Doug, I have one question for using <clock-frequency>. I found the fixed-rate-clocks feature. If we want to set <clock-frequency>, then can we use the fixed-rate-clocks? i'm not sure how use the fixed-rate-clocks. but it seems to set fixed-rate value for clock frequency. clk_set_rate() didn't ensure to set the <clock-frequency> value. Best Regards, Jaehoon Chung On 06/08/2013 02:28 AM, Doug Anderson wrote: > As of now we rely on code outside of the driver to set the ciu clock > frequency. There's no reason to do that. Add support for setting up > the clock in the driver during probe. > > Signed-off-by: Doug Anderson <dianders@chromium.org> > Acked-by: Jaehoon Chung <jh80.chung@samsung.com> > --- > Changes in v2: > - Added example as per Jaehoon. > > .../devicetree/bindings/mmc/synopsis-dw-mshc.txt | 16 ++++++++++++++++ > drivers/mmc/host/dw_mmc.c | 17 +++++++++++++---- > 2 files changed, 29 insertions(+), 4 deletions(-) > > diff --git a/Documentation/devicetree/bindings/mmc/synopsis-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/synopsis-dw-mshc.txt > index d5cc94e..dd31b00 100644 > --- a/Documentation/devicetree/bindings/mmc/synopsis-dw-mshc.txt > +++ b/Documentation/devicetree/bindings/mmc/synopsis-dw-mshc.txt > @@ -39,6 +39,19 @@ Required Properties: > > Optional properties: > > +* clocks: from common clock binding: handle to biu and ciu clocks for the > + bus interface unit clock and the card interface unit clock. > + > +* clock-names: from common clock binding: Shall be "biu" and "ciu". > + If the biu clock is missing we'll simply skip enabling it. If the > + ciu clock is missing we'll just assume that the clock is running at > + clock-frequency. It is an error to omit both the ciu clock and the > + clock-frequency. > + > +* clock-frequency: should be the frequency (in Hz) of the ciu clock. If this > + is specified and the ciu clock is specified then we'll try to set the ciu > + clock to this at probe time. > + > * num-slots: specifies the number of slots supported by the controller. > The number of physical slots actually used could be equal or less than the > value specified by num-slots. If this property is not specified, the value > @@ -70,6 +83,8 @@ board specific portions as listed below. > > dwmmc0@12200000 { > compatible = "snps,dw-mshc"; > + clocks = <&clock 351>, <&clock 132>; > + clock-names = "biu", "ciu"; > reg = <0x12200000 0x1000>; > interrupts = <0 75 0>; > #address-cells = <1>; > @@ -77,6 +92,7 @@ board specific portions as listed below. > }; > > dwmmc0@12200000 { > + clock-frequency = <400000000>; > num-slots = <1>; > supports-highspeed; > broken-cd; > diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c > index ab5642d..b8a2f16 100644 > --- a/drivers/mmc/host/dw_mmc.c > +++ b/drivers/mmc/host/dw_mmc.c > @@ -2107,6 +2107,7 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) > struct device_node *np = dev->of_node; > const struct dw_mci_drv_data *drv_data = host->drv_data; > int idx, ret; > + u32 clock_frequency; > > pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); > if (!pdata) { > @@ -2133,6 +2134,9 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) > > of_property_read_u32(np, "card-detect-delay", &pdata->detect_delay_ms); > > + if (!of_property_read_u32(np, "clock-frequency", &clock_frequency)) > + pdata->bus_hz = clock_frequency; > + > if (drv_data && drv_data->parse_dt) { > ret = drv_data->parse_dt(host); > if (ret) > @@ -2190,18 +2194,23 @@ int dw_mci_probe(struct dw_mci *host) > host->ciu_clk = devm_clk_get(host->dev, "ciu"); > if (IS_ERR(host->ciu_clk)) { > dev_dbg(host->dev, "ciu clock not available\n"); > + host->bus_hz = host->pdata->bus_hz; > } else { > ret = clk_prepare_enable(host->ciu_clk); > if (ret) { > dev_err(host->dev, "failed to enable ciu clock\n"); > goto err_clk_biu; > } > - } > > - if (IS_ERR(host->ciu_clk)) > - host->bus_hz = host->pdata->bus_hz; > - else > + if (host->pdata->bus_hz) { > + ret = clk_set_rate(host->ciu_clk, host->pdata->bus_hz); > + if (ret) > + dev_warn(host->dev, > + "Unable to set bus rate to %ul\n", > + host->pdata->bus_hz); > + } > host->bus_hz = clk_get_rate(host->ciu_clk); > + } > > if (drv_data && drv_data->setup_clock) { > ret = drv_data->setup_clock(host); > -- 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
Jaehoon, On Mon, Jun 17, 2013 at 9:51 PM, Jaehoon Chung <jh80.chung@samsung.com> wrote: > Hi Doug, > > I have one question for using <clock-frequency>. > I found the fixed-rate-clocks feature. > If we want to set <clock-frequency>, then can we use the fixed-rate-clocks? > i'm not sure how use the fixed-rate-clocks. but it seems to set fixed-rate value for clock frequency. > > clk_set_rate() didn't ensure to set the <clock-frequency> value. I'm not sure I understand the question. I don't think that the fixed-rate-clocks have a close relation to the clock-frequency or the ciu clock. The fixed-rate-clock entries for a board usually specify the root clock source for a board. For instance in exynos5250-snow you can see: fixed-rate-clocks { xxti { compatible = "samsung,clock-xxti"; clock-frequency = <24000000>; }; }; Other clocks in the board are derived from this clock through PLLs, muxes, dividers, gates, etc. On 5250 we have: fin_pll (xxti) -> fout_mpll -> fout_mplldiv2 -> mout_mpll_fout -> sclk_mpll -> sclk_mpll_user -> mout_mmc1 -> div_mmc1 div_mmc_pre1 -> sclk_mmc1 In 5250 the ciu clock for mmc1 is sclk_mmc1, which is a simple gate. When you "enable" this clock it, ungates it. The sclk_mmc1 has the flag CLK_SET_RATE_PARENT on it. That means when you try to set the rate it will involve the parent clock (div_mmc_pre1). The parent clock also has CLK_SET_RATE_PARENT, so it can also involve div_mmc1. I haven't dug through to see how the clock framework splits up divides between div_mmc1 and div_mmc_pre1, but it's supposed to handle that. We don't allow clk_set_rate to percolate any higher (no CLK_SET_RATE_PARENT at mout_mmc1). -Doug -- 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
Hi Doug, I'm researching for fixed-rate-clocks. Maybe i misunderstood for using <fixed-rate-clocks>. :) Best Regards, Jaehoon Chung On 06/19/2013 12:15 AM, Doug Anderson wrote: > Jaehoon, > > On Mon, Jun 17, 2013 at 9:51 PM, Jaehoon Chung <jh80.chung@samsung.com> wrote: >> Hi Doug, >> >> I have one question for using <clock-frequency>. >> I found the fixed-rate-clocks feature. >> If we want to set <clock-frequency>, then can we use the fixed-rate-clocks? >> i'm not sure how use the fixed-rate-clocks. but it seems to set fixed-rate value for clock frequency. >> >> clk_set_rate() didn't ensure to set the <clock-frequency> value. > > I'm not sure I understand the question. I don't think that the > fixed-rate-clocks have a close relation to the clock-frequency or the > ciu clock. The fixed-rate-clock entries for a board usually specify > the root clock source for a board. For instance in exynos5250-snow > you can see: > > fixed-rate-clocks { > xxti { > compatible = "samsung,clock-xxti"; > clock-frequency = <24000000>; > }; > }; > > Other clocks in the board are derived from this clock through PLLs, > muxes, dividers, gates, etc. On 5250 we have: > > fin_pll (xxti) -> fout_mpll -> fout_mplldiv2 -> mout_mpll_fout -> > sclk_mpll -> sclk_mpll_user -> mout_mmc1 -> div_mmc1 > div_mmc_pre1 -> sclk_mmc1 > > In 5250 the ciu clock for mmc1 is sclk_mmc1, which is a simple gate. > When you "enable" this clock it, ungates it. The sclk_mmc1 has the > flag CLK_SET_RATE_PARENT on it. That means when you try to set the > rate it will involve the parent clock (div_mmc_pre1). The parent > clock also has CLK_SET_RATE_PARENT, so it can also involve div_mmc1. > I haven't dug through to see how the clock framework splits up divides > between div_mmc1 and div_mmc_pre1, but it's supposed to handle that. > > We don't allow clk_set_rate to percolate any higher (no > CLK_SET_RATE_PARENT at mout_mmc1). > > -Doug > -- > 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 > -- 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
Hi Doug, On Fri, Jun 07 2013, Doug Anderson wrote: > As of now we rely on code outside of the driver to set the ciu clock > frequency. There's no reason to do that. Add support for setting up > the clock in the driver during probe. > > Signed-off-by: Doug Anderson <dianders@chromium.org> > Acked-by: Jaehoon Chung <jh80.chung@samsung.com> > --- > Changes in v2: > - Added example as per Jaehoon. Thanks, pushed to mmc-next for 3.11. - Chris.
diff --git a/Documentation/devicetree/bindings/mmc/synopsis-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/synopsis-dw-mshc.txt index d5cc94e..dd31b00 100644 --- a/Documentation/devicetree/bindings/mmc/synopsis-dw-mshc.txt +++ b/Documentation/devicetree/bindings/mmc/synopsis-dw-mshc.txt @@ -39,6 +39,19 @@ Required Properties: Optional properties: +* clocks: from common clock binding: handle to biu and ciu clocks for the + bus interface unit clock and the card interface unit clock. + +* clock-names: from common clock binding: Shall be "biu" and "ciu". + If the biu clock is missing we'll simply skip enabling it. If the + ciu clock is missing we'll just assume that the clock is running at + clock-frequency. It is an error to omit both the ciu clock and the + clock-frequency. + +* clock-frequency: should be the frequency (in Hz) of the ciu clock. If this + is specified and the ciu clock is specified then we'll try to set the ciu + clock to this at probe time. + * num-slots: specifies the number of slots supported by the controller. The number of physical slots actually used could be equal or less than the value specified by num-slots. If this property is not specified, the value @@ -70,6 +83,8 @@ board specific portions as listed below. dwmmc0@12200000 { compatible = "snps,dw-mshc"; + clocks = <&clock 351>, <&clock 132>; + clock-names = "biu", "ciu"; reg = <0x12200000 0x1000>; interrupts = <0 75 0>; #address-cells = <1>; @@ -77,6 +92,7 @@ board specific portions as listed below. }; dwmmc0@12200000 { + clock-frequency = <400000000>; num-slots = <1>; supports-highspeed; broken-cd; diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index ab5642d..b8a2f16 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -2107,6 +2107,7 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) struct device_node *np = dev->of_node; const struct dw_mci_drv_data *drv_data = host->drv_data; int idx, ret; + u32 clock_frequency; pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) { @@ -2133,6 +2134,9 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) of_property_read_u32(np, "card-detect-delay", &pdata->detect_delay_ms); + if (!of_property_read_u32(np, "clock-frequency", &clock_frequency)) + pdata->bus_hz = clock_frequency; + if (drv_data && drv_data->parse_dt) { ret = drv_data->parse_dt(host); if (ret) @@ -2190,18 +2194,23 @@ int dw_mci_probe(struct dw_mci *host) host->ciu_clk = devm_clk_get(host->dev, "ciu"); if (IS_ERR(host->ciu_clk)) { dev_dbg(host->dev, "ciu clock not available\n"); + host->bus_hz = host->pdata->bus_hz; } else { ret = clk_prepare_enable(host->ciu_clk); if (ret) { dev_err(host->dev, "failed to enable ciu clock\n"); goto err_clk_biu; } - } - if (IS_ERR(host->ciu_clk)) - host->bus_hz = host->pdata->bus_hz; - else + if (host->pdata->bus_hz) { + ret = clk_set_rate(host->ciu_clk, host->pdata->bus_hz); + if (ret) + dev_warn(host->dev, + "Unable to set bus rate to %ul\n", + host->pdata->bus_hz); + } host->bus_hz = clk_get_rate(host->ciu_clk); + } if (drv_data && drv_data->setup_clock) { ret = drv_data->setup_clock(host);