Skip to content

Commit

Permalink
Merge branch 'clk-rockchip' into clk-next
Browse files Browse the repository at this point in the history
  • Loading branch information
Mike Turquette committed Jul 24, 2014
2 parents dae7df4 + 1fe6949 commit 0957569
Show file tree
Hide file tree
Showing 16 changed files with 3,338 additions and 15 deletions.
61 changes: 61 additions & 0 deletions Documentation/devicetree/bindings/clock/rockchip,rk3188-cru.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
* Rockchip RK3188/RK3066 Clock and Reset Unit

The RK3188/RK3066 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,rk3188-cru", "rockchip,rk3188a-cru" or
"rockchip,rk3066a-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 changable, 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/rk3188-cru.h and
dt-bindings/clock/rk3066-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,
- "xin32k" - rtc clock - optional,
- "xin27m" - 27mhz crystal input on rk3066 - optional,
- "ext_hsadc" - external HSADC clock - optional,
- "ext_cif0" - external camera clock - optional,
- "ext_rmii" - external RMII clock - optional,
- "ext_jtag" - externalJTAG clock - optional

Example: Clock controller node:

cru: cru@20000000 {
compatible = "rockchip,rk3188-cru";
reg = <0x20000000 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@10124000 {
compatible = "snps,dw-apb-uart";
reg = <0x10124000 0x400>;
interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
reg-shift = <2>;
reg-io-width = <1>;
clocks = <&cru SCLK_UART0>;
};
61 changes: 61 additions & 0 deletions Documentation/devicetree/bindings/clock/rockchip,rk3288-cru.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
* Rockchip RK3288 Clock and Reset Unit

The RK3288 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,rk3288-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 changable, 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/rk3288-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,
- "xin32k" - rtc clock - optional,
- "ext_i2s" - external I2S clock - optional,
- "ext_hsadc" - external HSADC clock - optional,
- "ext_edp_24m" - external display port clock - optional,
- "ext_vip" - external VIP clock - optional,
- "ext_isp" - external ISP clock - optional,
- "ext_jtag" - external JTAG clock - optional

Example: Clock controller node:

cru: cru@20000000 {
compatible = "rockchip,rk3188-cru";
reg = <0x20000000 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@10124000 {
compatible = "snps,dw-apb-uart";
reg = <0x10124000 0x400>;
interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
reg-shift = <2>;
reg-io-width = <1>;
clocks = <&cru SCLK_UART0>;
};
3 changes: 3 additions & 0 deletions Documentation/devicetree/bindings/clock/rockchip.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ This binding uses the common clock binding[1].

== Gate clocks ==

These bindings are deprecated!
Please use the soc specific CRU bindings instead.

The gate registers form a continuos block which makes the dt node
structure a matter of taste, as either all gates can be put into
one gate clock spanning all registers or they can be divided into
Expand Down
1 change: 1 addition & 0 deletions arch/arm/mach-rockchip/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ config ARCH_ROCKCHIP
bool "Rockchip RK2928 and RK3xxx SOCs" if ARCH_MULTI_V7
select PINCTRL
select PINCTRL_ROCKCHIP
select ARCH_HAS_RESET_CONTROLLER
select ARCH_REQUIRE_GPIOLIB
select ARM_GIC
select CACHE_L2X0
Expand Down
79 changes: 64 additions & 15 deletions drivers/clk/clk-composite.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,56 @@ static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate,
const struct clk_ops *mux_ops = composite->mux_ops;
struct clk_hw *rate_hw = composite->rate_hw;
struct clk_hw *mux_hw = composite->mux_hw;
struct clk *parent;
unsigned long parent_rate;
long tmp_rate, best_rate = 0;
unsigned long rate_diff;
unsigned long best_rate_diff = ULONG_MAX;
int i;

if (rate_hw && rate_ops && rate_ops->determine_rate) {
rate_hw->clk = hw->clk;
return rate_ops->determine_rate(rate_hw, rate, best_parent_rate,
best_parent_p);
} else if (rate_hw && rate_ops && rate_ops->round_rate &&
mux_hw && mux_ops && mux_ops->set_parent) {
*best_parent_p = NULL;

if (__clk_get_flags(hw->clk) & CLK_SET_RATE_NO_REPARENT) {
*best_parent_p = clk_get_parent(mux_hw->clk);
*best_parent_rate = __clk_get_rate(*best_parent_p);

return rate_ops->round_rate(rate_hw, rate,
best_parent_rate);
}

for (i = 0; i < __clk_get_num_parents(mux_hw->clk); i++) {
parent = clk_get_parent_by_index(mux_hw->clk, i);
if (!parent)
continue;

parent_rate = __clk_get_rate(parent);

tmp_rate = rate_ops->round_rate(rate_hw, rate,
&parent_rate);
if (tmp_rate < 0)
continue;

rate_diff = abs(rate - tmp_rate);

if (!rate_diff || !*best_parent_p
|| best_rate_diff > rate_diff) {
*best_parent_p = parent;
*best_parent_rate = parent_rate;
best_rate_diff = rate_diff;
best_rate = tmp_rate;
}

if (!rate_diff)
return rate;
}

return best_rate;
} else if (mux_hw && mux_ops && mux_ops->determine_rate) {
mux_hw->clk = hw->clk;
return mux_ops->determine_rate(mux_hw, rate, best_parent_rate,
Expand Down Expand Up @@ -162,15 +207,16 @@ struct clk *clk_register_composite(struct device *dev, const char *name,
clk_composite_ops = &composite->ops;

if (mux_hw && mux_ops) {
if (!mux_ops->get_parent || !mux_ops->set_parent) {
if (!mux_ops->get_parent) {
clk = ERR_PTR(-EINVAL);
goto err;
}

composite->mux_hw = mux_hw;
composite->mux_ops = mux_ops;
clk_composite_ops->get_parent = clk_composite_get_parent;
clk_composite_ops->set_parent = clk_composite_set_parent;
if (mux_ops->set_parent)
clk_composite_ops->set_parent = clk_composite_set_parent;
if (mux_ops->determine_rate)
clk_composite_ops->determine_rate = clk_composite_determine_rate;
}
Expand All @@ -180,24 +226,27 @@ struct clk *clk_register_composite(struct device *dev, const char *name,
clk = ERR_PTR(-EINVAL);
goto err;
}
clk_composite_ops->recalc_rate = clk_composite_recalc_rate;

/* .round_rate is a prerequisite for .set_rate */
if (rate_ops->round_rate) {
clk_composite_ops->round_rate = clk_composite_round_rate;
if (rate_ops->set_rate) {
clk_composite_ops->set_rate = clk_composite_set_rate;
}
} else {
WARN(rate_ops->set_rate,
"%s: missing round_rate op is required\n",
__func__);
if (rate_ops->determine_rate)
clk_composite_ops->determine_rate =
clk_composite_determine_rate;
else if (rate_ops->round_rate)
clk_composite_ops->round_rate =
clk_composite_round_rate;

/* .set_rate requires either .round_rate or .determine_rate */
if (rate_ops->set_rate) {
if (rate_ops->determine_rate || rate_ops->round_rate)
clk_composite_ops->set_rate =
clk_composite_set_rate;
else
WARN(1, "%s: missing round_rate op is required\n",
__func__);
}

composite->rate_hw = rate_hw;
composite->rate_ops = rate_ops;
clk_composite_ops->recalc_rate = clk_composite_recalc_rate;
if (rate_ops->determine_rate)
clk_composite_ops->determine_rate = clk_composite_determine_rate;
}

if (gate_hw && gate_ops) {
Expand Down
6 changes: 6 additions & 0 deletions drivers/clk/rockchip/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,9 @@
#

obj-y += clk-rockchip.o
obj-y += clk.o
obj-y += clk-pll.o
obj-$(CONFIG_RESET_CONTROLLER) += softrst.o

obj-y += clk-rk3188.o
obj-y += clk-rk3288.o
Loading

0 comments on commit 0957569

Please sign in to comment.