提交 f36fc04e 编写于 作者: L Linus Torvalds

Merge tag 'clk-for-linus-4.3' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux

Pull clk updates from Michael Turquette:
 "The clk framework changes for 4.3 are mostly updates to existing
  drivers and the addition of new clock drivers.  Stephen Boyd has also
  done a lot of subsystem-wide driver clean-ups (thanks!).  There are
  also fixes to the framework core and changes to better split clock
  provider drivers from clock consumer drivers"

* tag 'clk-for-linus-4.3' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux: (227 commits)
  clk: s5pv210: add missing call to samsung_clk_of_add_provider()
  clk: pistachio: correct critical clock list
  clk: pistachio: Fix PLL rate calculation in integer mode
  clk: pistachio: Fix override of clk-pll settings from boot loader
  clk: pistachio: Fix 32bit integer overflows
  clk: tegra: Fix some static checker problems
  clk: qcom: Fix MSM8916 prng clock enable bit
  clk: Add missing header for 'bool' definition to clk-conf.h
  drivers/clk: appropriate __init annotation for const data
  clk: rockchip: register pll mux before pll itself
  clk: add bindings for the Ux500 clocks
  clk/ARM: move Ux500 PRCC bases to the device tree
  clk: remove duplicated code with __clk_set_parent_after
  clk: Convert __clk_get_name(hw->clk) to clk_hw_get_name(hw)
  clk: Constify clk_hw argument to provider APIs
  clk: Hi6220: add stub clock driver
  dt-bindings: clk: Hi6220: Document stub clock driver
  dt-bindings: arm: Hi6220: add doc for SRAM controller
  clk: atlas7: fix pll missed divide NR in fraction mode
  clk: atlas7: fix bit field and its root clk for coresight_tpiu
  ...
......@@ -71,12 +71,8 @@ the operations defined in clk.h:
long (*round_rate)(struct clk_hw *hw,
unsigned long rate,
unsigned long *parent_rate);
long (*determine_rate)(struct clk_hw *hw,
unsigned long rate,
unsigned long min_rate,
unsigned long max_rate,
unsigned long *best_parent_rate,
struct clk_hw **best_parent_clk);
int (*determine_rate)(struct clk_hw *hw,
struct clk_rate_request *req);
int (*set_parent)(struct clk_hw *hw, u8 index);
u8 (*get_parent)(struct clk_hw *hw);
int (*set_rate)(struct clk_hw *hw,
......
......@@ -127,6 +127,24 @@ Example:
#clock-cells = <1>;
};
Hisilicon Hi6220 SRAM controller
Required properties:
- compatible : "hisilicon,hi6220-sramctrl", "syscon"
- reg : Register address and size
Hisilicon's SoCs use sram for multiple purpose; on Hi6220 there have several
SRAM banks for power management, modem, security, etc. Further, use "syscon"
managing the common sram which can be shared by multiple modules.
Example:
/*for Hi6220*/
sram: sram@fff80000 {
compatible = "hisilicon,hi6220-sramctrl", "syscon";
reg = <0x0 0xfff80000 0x0 0x12000>;
};
-----------------------------------------------------------------------
Hisilicon HiP01 system controller
......
SP810 System Controller
-----------------------
Required properties:
- compatible: standard compatible string for a Primecell peripheral,
see Documentation/devicetree/bindings/arm/primecell.txt
for more details
should be: "arm,sp810", "arm,primecell"
- reg: standard registers property, physical address and size
of the control registers
- clock-names: from the common clock bindings, for more details see
Documentation/devicetree/bindings/clock/clock-bindings.txt;
should be: "refclk", "timclk", "apb_pclk"
- clocks: from the common clock bindings, phandle and clock
specifier pairs for the entries of clock-names property
- #clock-cells: from the common clock bindings;
should be: <1>
- clock-output-names: from the common clock bindings;
should be: "timerclken0", "timerclken1", "timerclken2", "timerclken3"
- assigned-clocks: from the common clock binding;
should be: clock specifier for each output clock of this
provider node
- assigned-clock-parents: from the common clock binding;
should be: phandle of input clock listed in clocks
property with the highest frequency
Example:
v2m_sysctl: sysctl@020000 {
compatible = "arm,sp810", "arm,primecell";
reg = <0x020000 0x1000>;
clocks = <&v2m_refclk32khz>, <&v2m_refclk1mhz>, <&smbclk>;
clock-names = "refclk", "timclk", "apb_pclk";
#clock-cells = <1>;
clock-output-names = "timerclken0", "timerclken1", "timerclken2", "timerclken3";
assigned-clocks = <&v2m_sysctl 0>, <&v2m_sysctl 1>, <&v2m_sysctl 3>, <&v2m_sysctl 3>;
assigned-clock-parents = <&v2m_refclk1mhz>, <&v2m_refclk1mhz>, <&v2m_refclk1mhz>, <&v2m_refclk1mhz>;
};
Binding for simple gpio clock multiplexer.
This binding uses the common clock binding[1].
[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
Required properties:
- compatible : shall be "gpio-mux-clock".
- clocks: list of two references to parent clocks.
- #clock-cells : from common clock binding; shall be set to 0.
- select-gpios : GPIO reference for selecting the parent clock.
Example:
clock {
compatible = "gpio-mux-clock";
clocks = <&parentclk1>, <&parentclk2>;
#clock-cells = <0>;
select-gpios = <&gpio 1 GPIO_ACTIVE_HIGH>;
};
......@@ -15,19 +15,36 @@ Required Properties:
- "hisilicon,hi6220-sysctrl"
- "hisilicon,hi6220-mediactrl"
- "hisilicon,hi6220-pmctrl"
- "hisilicon,hi6220-stub-clk"
- reg: physical base address of the controller and length of memory mapped
region.
- #clock-cells: should be 1.
For example:
Optional Properties:
- hisilicon,hi6220-clk-sram: phandle to the syscon managing the SoC internal sram;
the driver need use the sram to pass parameters for frequency change.
- mboxes: use the label reference for the mailbox as the first parameter, the
second parameter is the channel number.
Example 1:
sys_ctrl: sys_ctrl@f7030000 {
compatible = "hisilicon,hi6220-sysctrl", "syscon";
reg = <0x0 0xf7030000 0x0 0x2000>;
#clock-cells = <1>;
};
Example 2:
stub_clock: stub_clock {
compatible = "hisilicon,hi6220-stub-clk";
hisilicon,hi6220-clk-sram = <&sram>;
#clock-cells = <1>;
mboxes = <&mailbox 1>;
};
Each clock is assigned an identifier and client nodes use this identifier
to specify the clock which they consume.
......
NVIDIA Tegra124 DFLL FCPU clocksource
This binding uses the common clock binding:
Documentation/devicetree/bindings/clock/clock-bindings.txt
The DFLL IP block on Tegra is a root clocksource designed for clocking
the fast CPU cluster. It consists of a free-running voltage controlled
oscillator connected to the CPU voltage rail (VDD_CPU), and a closed loop
control module that will automatically adjust the VDD_CPU voltage by
communicating with an off-chip PMIC either via an I2C bus or via PWM signals.
Currently only the I2C mode is supported by these bindings.
Required properties:
- compatible : should be "nvidia,tegra124-dfll"
- reg : Defines the following set of registers, in the order listed:
- registers for the DFLL control logic.
- registers for the I2C output logic.
- registers for the integrated I2C master controller.
- look-up table RAM for voltage register values.
- interrupts: Should contain the DFLL block interrupt.
- clocks: Must contain an entry for each entry in clock-names.
See clock-bindings.txt for details.
- clock-names: Must include the following entries:
- soc: Clock source for the DFLL control logic.
- ref: The closed loop reference clock
- i2c: Clock source for the integrated I2C master.
- resets: Must contain an entry for each entry in reset-names.
See ../reset/reset.txt for details.
- reset-names: Must include the following entries:
- dvco: Reset control for the DFLL DVCO.
- #clock-cells: Must be 0.
- clock-output-names: Name of the clock output.
- vdd-cpu-supply: Regulator for the CPU voltage rail that the DFLL
hardware will start controlling. The regulator will be queried for
the I2C register, control values and supported voltages.
Required properties for the control loop parameters:
- nvidia,sample-rate: Sample rate of the DFLL control loop.
- nvidia,droop-ctrl: See the register CL_DVFS_DROOP_CTRL in the TRM.
- nvidia,force-mode: See the field DFLL_PARAMS_FORCE_MODE in the TRM.
- nvidia,cf: Numeric value, see the field DFLL_PARAMS_CF_PARAM in the TRM.
- nvidia,ci: Numeric value, see the field DFLL_PARAMS_CI_PARAM in the TRM.
- nvidia,cg: Numeric value, see the field DFLL_PARAMS_CG_PARAM in the TRM.
Optional properties for the control loop parameters:
- nvidia,cg-scale: Boolean value, see the field DFLL_PARAMS_CG_SCALE in the TRM.
Required properties for I2C mode:
- nvidia,i2c-fs-rate: I2C transfer rate, if using full speed mode.
Example:
clock@0,70110000 {
compatible = "nvidia,tegra124-dfll";
reg = <0 0x70110000 0 0x100>, /* DFLL control */
<0 0x70110000 0 0x100>, /* I2C output control */
<0 0x70110100 0 0x100>, /* Integrated I2C controller */
<0 0x70110200 0 0x100>; /* Look-up table RAM */
interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&tegra_car TEGRA124_CLK_DFLL_SOC>,
<&tegra_car TEGRA124_CLK_DFLL_REF>,
<&tegra_car TEGRA124_CLK_I2C5>;
clock-names = "soc", "ref", "i2c";
resets = <&tegra_car TEGRA124_RST_DFLL_DVCO>;
reset-names = "dvco";
#clock-cells = <0>;
clock-output-names = "dfllCPU_out";
vdd-cpu-supply = <&vdd_cpu>;
status = "okay";
nvidia,sample-rate = <12500>;
nvidia,droop-ctrl = <0x00000f00>;
nvidia,force-mode = <1>;
nvidia,cf = <10>;
nvidia,ci = <0>;
nvidia,cg = <2>;
nvidia,i2c-fs-rate = <400000>;
};
* Rockchip RK3368 Clock and Reset Unit
The RK3368 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,rk3368-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/rk3368-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_gmac" - external GMAC clock - optional
- "ext_hsadc" - external HSADC clock - optional,
- "ext_isp" - external ISP clock - optional,
- "ext_jtag" - external JTAG clock - optional
- "ext_vip" - external VIP clock - optional,
- "usbotg_out" - output clock of the pll in the otg phy
Example: Clock controller node:
cru: clock-controller@ff760000 {
compatible = "rockchip,rk3368-cru";
reg = <0x0 0xff760000 0x0 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>;
};
Clock bindings for ST-Ericsson Ux500 clocks
Required properties :
- compatible : shall contain only one of the following:
"stericsson,u8500-clks"
"stericsson,u8540-clks"
"stericsson,u9540-clks"
- reg : shall contain base register location and length for
CLKRST1, 2, 3, 5, and 6 in an array. Note the absence of
CLKRST4, which does not exist.
Required subnodes:
- prcmu-clock: a subnode with one clock cell for PRCMU (power,
reset, control unit) clocks. The cell indicates which PRCMU
clock in the prcmu-clock node the consumer wants to use.
- prcc-periph-clock: a subnode with two clock cells for
PRCC (programmable reset- and clock controller) peripheral clocks.
The first cell indicates which PRCC block the consumer
wants to use, possible values are 1, 2, 3, 5, 6. The second
cell indicates which clock inside the PRCC block it wants,
possible values are 0 thru 31.
- prcc-kernel-clock: a subnode with two clock cells for
PRCC (programmable reset- and clock controller) kernel clocks
The first cell indicates which PRCC block the consumer
wants to use, possible values are 1, 2, 3, 5, 6. The second
cell indicates which clock inside the PRCC block it wants,
possible values are 0 thru 31.
- rtc32k-clock: a subnode with zero clock cells for the 32kHz
RTC clock.
- smp-twd-clock: a subnode for the ARM SMP Timer Watchdog cluster
with zero clock cells.
Example:
clocks {
compatible = "stericsson,u8500-clks";
/*
* Registers for the CLKRST block on peripheral
* groups 1, 2, 3, 5, 6,
*/
reg = <0x8012f000 0x1000>, <0x8011f000 0x1000>,
<0x8000f000 0x1000>, <0xa03ff000 0x1000>,
<0xa03cf000 0x1000>;
prcmu_clk: prcmu-clock {
#clock-cells = <1>;
};
prcc_pclk: prcc-periph-clock {
#clock-cells = <2>;
};
prcc_kclk: prcc-kernel-clock {
#clock-cells = <2>;
};
rtc_clk: rtc32k-clock {
#clock-cells = <0>;
};
smp_twd_clk: smp-twd-clock {
#clock-cells = <0>;
};
};
......@@ -220,6 +220,13 @@
clocks {
compatible = "stericsson,u8500-clks";
/*
* Registers for the CLKRST block on peripheral
* groups 1, 2, 3, 5, 6,
*/
reg = <0x8012f000 0x1000>, <0x8011f000 0x1000>,
<0x8000f000 0x1000>, <0xa03ff000 0x1000>,
<0xa03cf000 0x1000>;
prcmu_clk: prcmu-clock {
#clock-cells = <1>;
......
......@@ -241,6 +241,7 @@
compatible = "allwinner,sun4i-a10-axi-gates-clk";
reg = <0x01c2005c 0x4>;
clocks = <&axi>;
clock-indices = <0>;
clock-output-names = "axi_dram";
};
......@@ -257,17 +258,36 @@
compatible = "allwinner,sun4i-a10-ahb-gates-clk";
reg = <0x01c20060 0x8>;
clocks = <&ahb>;
clock-indices = <0>, <1>,
<2>, <3>,
<4>, <5>, <6>,
<7>, <8>, <9>,
<10>, <11>, <12>,
<13>, <14>, <16>,
<17>, <18>, <20>,
<21>, <22>, <23>,
<24>, <25>, <26>,
<32>, <33>, <34>,
<35>, <36>, <37>,
<40>, <41>, <43>,
<44>, <45>,
<46>, <47>,
<50>, <52>;
clock-output-names = "ahb_usb0", "ahb_ehci0",
"ahb_ohci0", "ahb_ehci1", "ahb_ohci1", "ahb_ss",
"ahb_dma", "ahb_bist", "ahb_mmc0", "ahb_mmc1",
"ahb_mmc2", "ahb_mmc3", "ahb_ms", "ahb_nand",
"ahb_sdram", "ahb_ace", "ahb_emac", "ahb_ts",
"ahb_spi0", "ahb_spi1", "ahb_spi2", "ahb_spi3",
"ahb_pata", "ahb_sata", "ahb_gps", "ahb_ve",
"ahb_tvd", "ahb_tve0", "ahb_tve1", "ahb_lcd0",
"ahb_lcd1", "ahb_csi0", "ahb_csi1", "ahb_hdmi",
"ahb_de_be0", "ahb_de_be1", "ahb_de_fe0",
"ahb_de_fe1", "ahb_mp", "ahb_mali400";
"ahb_ohci0", "ahb_ehci1",
"ahb_ohci1", "ahb_ss", "ahb_dma",
"ahb_bist", "ahb_mmc0", "ahb_mmc1",
"ahb_mmc2", "ahb_mmc3", "ahb_ms",
"ahb_nand", "ahb_sdram", "ahb_ace",
"ahb_emac", "ahb_ts", "ahb_spi0",
"ahb_spi1", "ahb_spi2", "ahb_spi3",
"ahb_pata", "ahb_sata", "ahb_gps",
"ahb_ve", "ahb_tvd", "ahb_tve0",
"ahb_tve1", "ahb_lcd0", "ahb_lcd1",
"ahb_csi0", "ahb_csi1", "ahb_hdmi",
"ahb_de_be0", "ahb_de_be1",
"ahb_de_fe0", "ahb_de_fe1",
"ahb_mp", "ahb_mali400";
};
apb0: apb0@01c20054 {
......@@ -283,9 +303,14 @@
compatible = "allwinner,sun4i-a10-apb0-gates-clk";
reg = <0x01c20068 0x4>;
clocks = <&apb0>;
clock-indices = <0>, <1>,
<2>, <3>,
<5>, <6>,
<7>, <10>;
clock-output-names = "apb0_codec", "apb0_spdif",
"apb0_ac97", "apb0_iis", "apb0_pio", "apb0_ir0",
"apb0_ir1", "apb0_keypad";
"apb0_ac97", "apb0_iis",
"apb0_pio", "apb0_ir0",
"apb0_ir1", "apb0_keypad";
};
apb1: clk@01c20058 {
......@@ -301,12 +326,22 @@
compatible = "allwinner,sun4i-a10-apb1-gates-clk";
reg = <0x01c2006c 0x4>;
clocks = <&apb1>;
clock-indices = <0>, <1>,
<2>, <4>,
<5>, <6>,
<7>, <16>,
<17>, <18>,
<19>, <20>,
<21>, <22>,
<23>;
clock-output-names = "apb1_i2c0", "apb1_i2c1",
"apb1_i2c2", "apb1_can", "apb1_scr",
"apb1_ps20", "apb1_ps21", "apb1_uart0",
"apb1_uart1", "apb1_uart2", "apb1_uart3",
"apb1_uart4", "apb1_uart5", "apb1_uart6",
"apb1_uart7";
"apb1_i2c2", "apb1_can",
"apb1_scr", "apb1_ps20",
"apb1_ps21", "apb1_uart0",
"apb1_uart1", "apb1_uart2",
"apb1_uart3", "apb1_uart4",
"apb1_uart5", "apb1_uart6",
"apb1_uart7";
};
nand_clk: clk@01c20080 {
......
......@@ -85,6 +85,17 @@
compatible = "allwinner,sun5i-a10s-ahb-gates-clk";
reg = <0x01c20060 0x8>;
clocks = <&ahb>;
clock-indices = <0>, <1>,
<2>, <5>, <6>,
<7>, <8>, <9>,
<10>, <13>,
<14>, <17>, <18>,
<20>, <21>, <22>,
<26>, <28>, <32>,
<34>, <36>, <40>,
<43>, <44>,
<46>, <51>,
<52>;
clock-output-names = "ahb_usbotg", "ahb_ehci",
"ahb_ohci", "ahb_ss", "ahb_dma",
"ahb_bist", "ahb_mmc0", "ahb_mmc1",
......@@ -103,6 +114,9 @@
compatible = "allwinner,sun5i-a10s-apb0-gates-clk";
reg = <0x01c20068 0x4>;
clocks = <&apb0>;
clock-indices = <0>, <3>,
<5>, <6>,
<10>;
clock-output-names = "apb0_codec", "apb0_iis",
"apb0_pio", "apb0_ir",
"apb0_keypad";
......@@ -113,9 +127,14 @@
compatible = "allwinner,sun5i-a10s-apb1-gates-clk";
reg = <0x01c2006c 0x4>;
clocks = <&apb1>;
clock-indices = <0>, <1>,
<2>, <16>,
<17>, <18>,
<19>;
clock-output-names = "apb1_i2c0", "apb1_i2c1",
"apb1_i2c2", "apb1_uart0", "apb1_uart1",
"apb1_uart2", "apb1_uart3";
"apb1_i2c2", "apb1_uart0",
"apb1_uart1", "apb1_uart2",
"apb1_uart3";
};
};
......
......@@ -104,6 +104,16 @@
compatible = "allwinner,sun5i-a13-ahb-gates-clk";
reg = <0x01c20060 0x8>;
clocks = <&ahb>;
clock-indices = <0>, <1>,
<2>, <5>, <6>,
<7>, <8>, <9>,
<10>, <13>,
<14>, <20>,
<21>, <22>,
<28>, <32>, <36>,
<40>, <44>,
<46>, <51>,
<52>;
clock-output-names = "ahb_usbotg", "ahb_ehci",
"ahb_ohci", "ahb_ss", "ahb_dma",
"ahb_bist", "ahb_mmc0", "ahb_mmc1",
......@@ -121,6 +131,8 @@
compatible = "allwinner,sun5i-a13-apb0-gates-clk";
reg = <0x01c20068 0x4>;
clocks = <&apb0>;
clock-indices = <0>, <5>,
<6>;
clock-output-names = "apb0_codec", "apb0_pio",
"apb0_ir";
};
......@@ -130,8 +142,12 @@
compatible = "allwinner,sun5i-a13-apb1-gates-clk";
reg = <0x01c2006c 0x4>;
clocks = <&apb1>;
clock-indices = <0>, <1>,
<2>, <17>,
<19>;
clock-output-names = "apb1_i2c0", "apb1_i2c1",
"apb1_i2c2", "apb1_uart1", "apb1_uart3";
"apb1_i2c2", "apb1_uart1",
"apb1_uart3";
};
};
};
......
......@@ -178,6 +178,7 @@
compatible = "allwinner,sun4i-a10-axi-gates-clk";
reg = <0x01c2005c 0x4>;
clocks = <&axi>;
clock-indices = <0>;
clock-output-names = "axi_dram";
};
......
......@@ -252,6 +252,20 @@
compatible = "allwinner,sun6i-a31-ahb1-gates-clk";
reg = <0x01c20060 0x8>;
clocks = <&ahb1>;
clock-indices = <1>, <5>,
<6>, <8>, <9>,
<10>, <11>, <12>,
<13>, <14>,
<17>, <18>, <19>,
<20>, <21>, <22>,
<23>, <24>, <26>,
<27>, <29>,
<30>, <31>, <32>,
<36>, <37>, <40>,
<43>, <44>, <45>,
<46>, <47>, <50>,
<52>, <55>, <56>,
<57>, <58>;
clock-output-names = "ahb1_mipidsi", "ahb1_ss",
"ahb1_dma", "ahb1_mmc0", "ahb1_mmc1",
"ahb1_mmc2", "ahb1_mmc3", "ahb1_nand1",
......@@ -281,6 +295,9 @@
compatible = "allwinner,sun6i-a31-apb1-gates-clk";
reg = <0x01c20068 0x4>;
clocks = <&apb1>;
clock-indices = <0>, <4>,
<5>, <12>,
<13>;
clock-output-names = "apb1_codec", "apb1_digital_mic",
"apb1_pio", "apb1_daudio0",
"apb1_daudio1";
......@@ -299,6 +316,10 @@
compatible = "allwinner,sun6i-a31-apb2-gates-clk";
reg = <0x01c2006c 0x4>;
clocks = <&apb2>;
clock-indices = <0>, <1>,
<2>, <3>, <16>,
<17>, <18>, <19>,
<20>, <21>;
clock-output-names = "apb2_i2c0", "apb2_i2c1",
"apb2_i2c2", "apb2_i2c3",
"apb2_uart0", "apb2_uart1",
......@@ -384,6 +405,9 @@
compatible = "allwinner,sun6i-a31-usb-clk";
reg = <0x01c200cc 0x4>;
clocks = <&osc24M>;
clock-indices = <8>, <9>, <10>,
<16>, <17>,
<18>;
clock-output-names = "usb_phy0", "usb_phy1", "usb_phy2",
"usb_ohci0", "usb_ohci1",
"usb_ohci2";
......
......@@ -267,6 +267,19 @@
compatible = "allwinner,sun7i-a20-ahb-gates-clk";
reg = <0x01c20060 0x8>;
clocks = <&ahb>;
clock-indices = <0>, <1>,
<2>, <3>, <4>,
<5>, <6>, <7>, <8>,
<9>, <10>, <11>, <12>,
<13>, <14>, <16>,
<17>, <18>, <20>, <21>,
<22>, <23>, <25>,
<28>, <32>, <33>, <34>,
<35>, <36>, <37>, <40>,
<41>, <42>, <43>,
<44>, <45>, <46>,
<47>, <49>, <50>,
<52>;
clock-output-names = "ahb_usb0", "ahb_ehci0",
"ahb_ohci0", "ahb_ehci1", "ahb_ohci1",
"ahb_ss", "ahb_dma", "ahb_bist", "ahb_mmc0",
......@@ -295,6 +308,10 @@
compatible = "allwinner,sun7i-a20-apb0-gates-clk";
reg = <0x01c20068 0x4>;
clocks = <&apb0>;
clock-indices = <0>, <1>,
<2>, <3>, <4>,
<5>, <6>, <7>,
<8>, <10>;
clock-output-names = "apb0_codec", "apb0_spdif",
"apb0_ac97", "apb0_iis0", "apb0_iis1",
"apb0_pio", "apb0_ir0", "apb0_ir1",
......@@ -314,6 +331,12 @@
compatible = "allwinner,sun7i-a20-apb1-gates-clk";
reg = <0x01c2006c 0x4>;
clocks = <&apb1>;
clock-indices = <0>, <1>,
<2>, <3>, <4>,
<5>, <6>, <7>,
<15>, <16>, <17>,
<18>, <19>, <20>,
<21>, <22>, <23>;
clock-output-names = "apb1_i2c0", "apb1_i2c1",
"apb1_i2c2", "apb1_i2c3", "apb1_can",
"apb1_scr", "apb1_ps20", "apb1_ps21",
......
......@@ -180,6 +180,15 @@
compatible = "allwinner,sun8i-a23-ahb1-gates-clk";
reg = <0x01c20060 0x8>;
clocks = <&ahb1>;
clock-indices = <1>, <6>,
<8>, <9>, <10>,
<13>, <14>,
<19>, <20>,
<21>, <24>, <26>,
<29>, <32>, <36>,
<40>, <44>, <46>,
<52>, <54>,
<57>;
clock-output-names = "ahb1_mipidsi", "ahb1_dma",
"ahb1_mmc0", "ahb1_mmc1", "ahb1_mmc2",
"ahb1_nand", "ahb1_sdram",
......@@ -196,6 +205,8 @@
compatible = "allwinner,sun8i-a23-apb1-gates-clk";
reg = <0x01c20068 0x4>;
clocks = <&apb1>;
clock-indices = <0>, <5>,
<12>, <13>;
clock-output-names = "apb1_codec", "apb1_pio",
"apb1_daudio0", "apb1_daudio1";
};
......@@ -213,6 +224,10 @@
compatible = "allwinner,sun8i-a23-apb2-gates-clk";
reg = <0x01c2006c 0x4>;
clocks = <&apb2>;
clock-indices = <0>, <1>,
<2>, <16>,
<17>, <18>,
<19>, <20>;
clock-output-names = "apb2_i2c0", "apb2_i2c1",
"apb2_i2c2", "apb2_uart0",
"apb2_uart1", "apb2_uart2",
......
......@@ -277,9 +277,12 @@
compatible = "allwinner,sun9i-a80-ahb0-gates-clk";
reg = <0x06000580 0x4>;
clocks = <&ahb0>;
clock-indices = <0>, <1>, <3>, <5>, <8>, <12>, <13>,
<14>, <15>, <16>, <18>, <20>, <21>,
<22>, <23>;
clock-indices = <0>, <1>, <3>,
<5>, <8>, <12>,
<13>, <14>,
<15>, <16>, <18>,
<20>, <21>, <22>,
<23>;
clock-output-names = "ahb0_fd", "ahb0_ve", "ahb0_gpu",
"ahb0_ss", "ahb0_sd", "ahb0_nand1",
"ahb0_nand0", "ahb0_sdram",
......@@ -293,7 +296,10 @@
compatible = "allwinner,sun9i-a80-ahb1-gates-clk";
reg = <0x06000584 0x4>;
clocks = <&ahb1>;
clock-indices = <0>, <1>, <17>, <21>, <22>, <23>, <24>;
clock-indices = <0>, <1>,
<17>, <21>,
<22>, <23>,
<24>;
clock-output-names = "ahb1_usbotg", "ahb1_usbhci",
"ahb1_gmac", "ahb1_msgbox",
"ahb1_spinlock", "ahb1_hstimer",
......@@ -305,8 +311,9 @@
compatible = "allwinner,sun9i-a80-ahb2-gates-clk";
reg = <0x06000588 0x4>;
clocks = <&ahb2>;
clock-indices = <0>, <1>, <2>, <4>, <5>, <7>, <8>,
<11>;
clock-indices = <0>, <1>,
<2>, <4>, <5>,
<7>, <8>, <11>;
clock-output-names = "ahb2_lcd0", "ahb2_lcd1",
"ahb2_edp", "ahb2_csi", "ahb2_hdmi",
"ahb2_de", "ahb2_mp", "ahb2_mipi_dsi";
......@@ -317,8 +324,10 @@
compatible = "allwinner,sun9i-a80-apb0-gates-clk";
reg = <0x06000590 0x4>;
clocks = <&apb0>;
clock-indices = <1>, <5>, <11>, <12>, <13>, <15>,
<17>, <18>, <19>;
clock-indices = <1>, <5>,
<11>, <12>, <13>,
<15>, <17>, <18>,
<19>;
clock-output-names = "apb0_spdif", "apb0_pio",
"apb0_ac97", "apb0_i2s0", "apb0_i2s1",
"apb0_lradc", "apb0_gpadc", "apb0_twd",
......@@ -330,8 +339,11 @@
compatible = "allwinner,sun9i-a80-apb1-gates-clk";
reg = <0x06000594 0x4>;
clocks = <&apb1>;
clock-indices = <0>, <1>, <2>, <3>, <4>,
<16>, <17>, <18>, <19>, <20>, <21>;
clock-indices = <0>, <1>,
<2>, <3>, <4>,
<16>, <17>,
<18>, <19>,
<20>, <21>;
clock-output-names = "apb1_i2c0", "apb1_i2c1",
"apb1_i2c2", "apb1_i2c3", "apb1_i2c4",
"apb1_uart0", "apb1_uart1",
......
......@@ -8,7 +8,6 @@
* Licensed under GPLv2 or later.
*/
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/of_platform.h>
......
......@@ -11,7 +11,6 @@
* published by the Free Software Foundation.
*/
#include <linux/clk-provider.h>
#include <linux/clocksource.h>
#include <linux/irqchip.h>
......
......@@ -16,7 +16,6 @@
#include <linux/pm_runtime.h>
#include <linux/pm_clock.h>
#include <linux/platform_device.h>
#include <linux/clk-provider.h>
#include <linux/of.h>
static struct dev_pm_domain keystone_pm_domain = {
......
......@@ -14,7 +14,6 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/clk-provider.h>
#include <linux/of_address.h>
#include <linux/of_fdt.h>
#include <linux/of_platform.h>
......
......@@ -12,8 +12,7 @@ obj-y := id.o io.o control.o mux.o devices.o fb.o serial.o timer.o pm.o \
hwmod-common = omap_hwmod.o omap_hwmod_reset.o \
omap_hwmod_common_data.o
clock-common = clock.o clock_common_data.o \
clkt_dpll.o clkt_clksel.o
clock-common = clock.o
secure-common = omap-smc.o omap-secure.o
obj-$(CONFIG_ARCH_OMAP2) += $(omap-2-3-common) $(hwmod-common)
......@@ -182,24 +181,17 @@ obj-$(CONFIG_SOC_DRA7XX) += $(clockdomain-common)
obj-$(CONFIG_SOC_DRA7XX) += clockdomains7xx_data.o
# Clock framework
obj-$(CONFIG_ARCH_OMAP2) += $(clock-common) clock2xxx.o
obj-$(CONFIG_ARCH_OMAP2) += $(clock-common)
obj-$(CONFIG_ARCH_OMAP2) += clkt2xxx_dpllcore.o
obj-$(CONFIG_ARCH_OMAP2) += clkt2xxx_virt_prcm_set.o
obj-$(CONFIG_ARCH_OMAP2) += clkt2xxx_dpll.o clkt_iclk.o
obj-$(CONFIG_SOC_OMAP2430) += clock2430.o
obj-$(CONFIG_ARCH_OMAP3) += $(clock-common) clock3xxx.o
obj-$(CONFIG_ARCH_OMAP3) += clock34xx.o clkt34xx_dpll3m2.o
obj-$(CONFIG_ARCH_OMAP3) += clock3517.o clock36xx.o
obj-$(CONFIG_ARCH_OMAP3) += dpll3xxx.o
obj-$(CONFIG_ARCH_OMAP3) += clkt_iclk.o
obj-$(CONFIG_ARCH_OMAP2) += clkt2xxx_dpll.o
obj-$(CONFIG_ARCH_OMAP3) += $(clock-common)
obj-$(CONFIG_ARCH_OMAP3) += clkt34xx_dpll3m2.o
obj-$(CONFIG_ARCH_OMAP4) += $(clock-common)
obj-$(CONFIG_ARCH_OMAP4) += dpll3xxx.o dpll44xx.o
obj-$(CONFIG_SOC_AM33XX) += $(clock-common) dpll3xxx.o
obj-$(CONFIG_SOC_AM33XX) += $(clock-common)
obj-$(CONFIG_SOC_OMAP5) += $(clock-common)
obj-$(CONFIG_SOC_OMAP5) += dpll3xxx.o dpll44xx.o
obj-$(CONFIG_SOC_DRA7XX) += $(clock-common)
obj-$(CONFIG_SOC_DRA7XX) += dpll3xxx.o dpll44xx.o
obj-$(CONFIG_SOC_AM43XX) += $(clock-common) dpll3xxx.o
obj-$(CONFIG_SOC_AM43XX) += $(clock-common)
# OMAP2 clock rate set data (old "OPP" data)
obj-$(CONFIG_SOC_OMAP2420) += opp2420_data.o
......
......@@ -23,12 +23,13 @@
#include "clock.h"
#include "clock3xxx.h"
#include "clock34xx.h"
#include "sdrc.h"
#include "sram.h"
#define CYCLES_PER_MHZ 1000000
struct clk *sdrc_ick_p, *arm_fck_p;
/*
* CORE DPLL (DPLL3) M2 divider rate programming functions
*
......@@ -60,12 +61,14 @@ int omap3_core_dpll_m2_set_rate(struct clk_hw *hw, unsigned long rate,
if (!clk || !rate)
return -EINVAL;
validrate = omap2_clksel_round_rate_div(clk, rate, &new_div);
new_div = DIV_ROUND_UP(parent_rate, rate);
validrate = parent_rate / new_div;
if (validrate != rate)
return -EINVAL;
sdrcrate = __clk_get_rate(sdrc_ick_p);
clkrate = __clk_get_rate(hw->clk);
sdrcrate = clk_get_rate(sdrc_ick_p);
clkrate = clk_hw_get_rate(hw);
if (rate > clkrate)
sdrcrate <<= ((rate / clkrate) >> 1);
else
......@@ -83,7 +86,7 @@ int omap3_core_dpll_m2_set_rate(struct clk_hw *hw, unsigned long rate,
/*
* XXX This only needs to be done when the CPU frequency changes
*/
_mpurate = __clk_get_rate(arm_fck_p) / CYCLES_PER_MHZ;
_mpurate = clk_get_rate(arm_fck_p) / CYCLES_PER_MHZ;
c = (_mpurate << SDRC_MPURATE_SCALE) >> SDRC_MPURATE_BASE_SHIFT;
c += 1; /* for safety */
c *= SDRC_MPURATE_LOOPS;
......
/*
* clkt_clksel.c - OMAP2/3/4 clksel clock functions
*
* Copyright (C) 2005-2008 Texas Instruments, Inc.
* Copyright (C) 2004-2010 Nokia Corporation
*
* Contacts:
* Richard Woodruff <r-woodruff2@ti.com>
* Paul Walmsley
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*
* clksel clocks are clocks that do not have a fixed parent, or that
* can divide their parent's rate, or possibly both at the same time, based
* on the contents of a hardware register bitfield.
*
* All of the various mux and divider settings can be encoded into
* struct clksel* data structures, and then these can be autogenerated
* from some hardware database for each new chip generation. This
* should avoid the need to write, review, and validate a lot of new
* clock code for each new chip, since it can be exported from the SoC
* design flow. This is now done on OMAP4.
*
* The fusion of mux and divider clocks is a software creation. In
* hardware reality, the multiplexer (parent selection) and the
* divider exist separately. XXX At some point these clksel clocks
* should be split into "divider" clocks and "mux" clocks to better
* match the hardware.
*
* (The name "clksel" comes from the name of the corresponding
* register field in the OMAP2/3 family of SoCs.)
*
* XXX Currently these clocks are only used in the OMAP2/3/4 code, but
* many of the OMAP1 clocks should be convertible to use this
* mechanism.
*/
#undef DEBUG
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/clk-provider.h>
#include <linux/io.h>
#include <linux/bug.h>
#include "clock.h"
/* Private functions */
/**
* _get_clksel_by_parent() - return clksel struct for a given clk & parent
* @clk: OMAP struct clk ptr to inspect
* @src_clk: OMAP struct clk ptr of the parent clk to search for
*
* Scan the struct clksel array associated with the clock to find
* the element associated with the supplied parent clock address.
* Returns a pointer to the struct clksel on success or NULL on error.
*/
static const struct clksel *_get_clksel_by_parent(struct clk_hw_omap *clk,
struct clk *src_clk)
{
const struct clksel *clks;
if (!src_clk)
return NULL;
for (clks = clk->clksel; clks->parent; clks++)
if (clks->parent == src_clk)
break; /* Found the requested parent */
if (!clks->parent) {
/* This indicates a data problem */
WARN(1, "clock: %s: could not find parent clock %s in clksel array\n",
__clk_get_name(clk->hw.clk), __clk_get_name(src_clk));
return NULL;
}
return clks;
}
/**
* _write_clksel_reg() - program a clock's clksel register in hardware
* @clk: struct clk * to program
* @v: clksel bitfield value to program (with LSB at bit 0)
*
* Shift the clksel register bitfield value @v to its appropriate
* location in the clksel register and write it in. This function
* will ensure that the write to the clksel_reg reaches its
* destination before returning -- important since PRM and CM register
* accesses can be quite slow compared to ARM cycles -- but does not
* take into account any time the hardware might take to switch the
* clock source.
*/
static void _write_clksel_reg(struct clk_hw_omap *clk, u32 field_val)
{
u32 v;
v = omap2_clk_readl(clk, clk->clksel_reg);
v &= ~clk->clksel_mask;
v |= field_val << __ffs(clk->clksel_mask);
omap2_clk_writel(v, clk, clk->clksel_reg);
v = omap2_clk_readl(clk, clk->clksel_reg); /* OCP barrier */
}
/**
* _clksel_to_divisor() - turn clksel field value into integer divider
* @clk: OMAP struct clk to use
* @field_val: register field value to find
*
* Given a struct clk of a rate-selectable clksel clock, and a register field
* value to search for, find the corresponding clock divisor. The register
* field value should be pre-masked and shifted down so the LSB is at bit 0
* before calling. Returns 0 on error or returns the actual integer divisor
* upon success.
*/
static u32 _clksel_to_divisor(struct clk_hw_omap *clk, u32 field_val)
{
const struct clksel *clks;
const struct clksel_rate *clkr;
struct clk *parent;
parent = __clk_get_parent(clk->hw.clk);
clks = _get_clksel_by_parent(clk, parent);
if (!clks)
return 0;
for (clkr = clks->rates; clkr->div; clkr++) {
if (!(clkr->flags & cpu_mask))
continue;
if (clkr->val == field_val)
break;
}
if (!clkr->div) {
/* This indicates a data error */
WARN(1, "clock: %s: could not find fieldval %d for parent %s\n",
__clk_get_name(clk->hw.clk), field_val,
__clk_get_name(parent));
return 0;
}
return clkr->div;
}
/**
* _divisor_to_clksel() - turn clksel integer divisor into a field value
* @clk: OMAP struct clk to use
* @div: integer divisor to search for
*
* Given a struct clk of a rate-selectable clksel clock, and a clock
* divisor, find the corresponding register field value. Returns the
* register field value _before_ left-shifting (i.e., LSB is at bit
* 0); or returns 0xFFFFFFFF (~0) upon error.
*/
static u32 _divisor_to_clksel(struct clk_hw_omap *clk, u32 div)
{
const struct clksel *clks;
const struct clksel_rate *clkr;
struct clk *parent;
/* should never happen */
WARN_ON(div == 0);
parent = __clk_get_parent(clk->hw.clk);
clks = _get_clksel_by_parent(clk, parent);
if (!clks)
return ~0;
for (clkr = clks->rates; clkr->div; clkr++) {
if (!(clkr->flags & cpu_mask))
continue;
if (clkr->div == div)
break;
}
if (!clkr->div) {
pr_err("clock: %s: could not find divisor %d for parent %s\n",
__clk_get_name(clk->hw.clk), div,
__clk_get_name(parent));
return ~0;
}
return clkr->val;
}
/**
* _read_divisor() - get current divisor applied to parent clock (from hdwr)
* @clk: OMAP struct clk to use.
*
* Read the current divisor register value for @clk that is programmed
* into the hardware, convert it into the actual divisor value, and
* return it; or return 0 on error.
*/
static u32 _read_divisor(struct clk_hw_omap *clk)
{
u32 v;
if (!clk->clksel || !clk->clksel_mask)
return 0;
v = omap2_clk_readl(clk, clk->clksel_reg);
v &= clk->clksel_mask;
v >>= __ffs(clk->clksel_mask);
return _clksel_to_divisor(clk, v);
}
/* Public functions */
/**
* omap2_clksel_round_rate_div() - find divisor for the given clock and rate
* @clk: OMAP struct clk to use
* @target_rate: desired clock rate
* @new_div: ptr to where we should store the divisor
*
* Finds 'best' divider value in an array based on the source and target
* rates. The divider array must be sorted with smallest divider first.
* This function is also used by the DPLL3 M2 divider code.
*
* Returns the rounded clock rate or returns 0xffffffff on error.
*/
u32 omap2_clksel_round_rate_div(struct clk_hw_omap *clk,
unsigned long target_rate,
u32 *new_div)
{
unsigned long test_rate;
const struct clksel *clks;
const struct clksel_rate *clkr;
u32 last_div = 0;
struct clk *parent;
unsigned long parent_rate;
const char *clk_name;
parent = __clk_get_parent(clk->hw.clk);
clk_name = __clk_get_name(clk->hw.clk);
parent_rate = __clk_get_rate(parent);
if (!clk->clksel || !clk->clksel_mask)
return ~0;
pr_debug("clock: clksel_round_rate_div: %s target_rate %ld\n",
clk_name, target_rate);
*new_div = 1;
clks = _get_clksel_by_parent(clk, parent);
if (!clks)
return ~0;
for (clkr = clks->rates; clkr->div; clkr++) {
if (!(clkr->flags & cpu_mask))
continue;
/* Sanity check */
if (clkr->div <= last_div)
pr_err("clock: %s: clksel_rate table not sorted\n",
clk_name);
last_div = clkr->div;
test_rate = parent_rate / clkr->div;
if (test_rate <= target_rate)
break; /* found it */
}
if (!clkr->div) {
pr_err("clock: %s: could not find divisor for target rate %ld for parent %s\n",
clk_name, target_rate, __clk_get_name(parent));
return ~0;
}
*new_div = clkr->div;
pr_debug("clock: new_div = %d, new_rate = %ld\n", *new_div,
(parent_rate / clkr->div));
return parent_rate / clkr->div;
}
/*
* Clocktype interface functions to the OMAP clock code
* (i.e., those used in struct clk field function pointers, etc.)
*/
/**
* omap2_clksel_find_parent_index() - return the array index of the current
* hardware parent of @hw
* @hw: struct clk_hw * to find the current hardware parent of
*
* Given a struct clk_hw pointer @hw to the 'hw' member of a struct
* clk_hw_omap record representing a source-selectable hardware clock,
* read the hardware register and determine what its parent is
* currently set to. Intended to be called only by the common clock
* framework struct clk_hw_ops.get_parent function pointer. Return
* the array index of this parent clock upon success -- there is no
* way to return an error, so if we encounter an error, just WARN()
* and pretend that we know that we're doing.
*/
u8 omap2_clksel_find_parent_index(struct clk_hw *hw)
{
struct clk_hw_omap *clk = to_clk_hw_omap(hw);
const struct clksel *clks;
const struct clksel_rate *clkr;
u32 r, found = 0;
struct clk *parent;
const char *clk_name;
int ret = 0, f = 0;
parent = __clk_get_parent(hw->clk);
clk_name = __clk_get_name(hw->clk);
/* XXX should be able to return an error */
WARN((!clk->clksel || !clk->clksel_mask),
"clock: %s: attempt to call on a non-clksel clock", clk_name);
r = omap2_clk_readl(clk, clk->clksel_reg) & clk->clksel_mask;
r >>= __ffs(clk->clksel_mask);
for (clks = clk->clksel; clks->parent && !found; clks++) {
for (clkr = clks->rates; clkr->div && !found; clkr++) {
if (!(clkr->flags & cpu_mask))
continue;
if (clkr->val == r) {
found = 1;
ret = f;
}
}
f++;
}
/* This indicates a data error */
WARN(!found, "clock: %s: init parent: could not find regval %0x\n",
clk_name, r);
return ret;
}
/**
* omap2_clksel_recalc() - function ptr to pass via struct clk .recalc field
* @clk: struct clk *
*
* This function is intended to be called only by the clock framework.
* Each clksel clock should have its struct clk .recalc field set to this
* function. Returns the clock's current rate, based on its parent's rate
* and its current divisor setting in the hardware.
*/
unsigned long omap2_clksel_recalc(struct clk_hw *hw, unsigned long parent_rate)
{
unsigned long rate;
u32 div = 0;
struct clk_hw_omap *clk = to_clk_hw_omap(hw);
if (!parent_rate)
return 0;
div = _read_divisor(clk);
if (!div)
rate = parent_rate;
else
rate = parent_rate / div;
pr_debug("%s: recalc'd %s's rate to %lu (div %d)\n", __func__,
__clk_get_name(hw->clk), rate, div);
return rate;
}
/**
* omap2_clksel_round_rate() - find rounded rate for the given clock and rate
* @clk: OMAP struct clk to use
* @target_rate: desired clock rate
*
* This function is intended to be called only by the clock framework.
* Finds best target rate based on the source clock and possible dividers.
* rates. The divider array must be sorted with smallest divider first.
*
* Returns the rounded clock rate or returns 0xffffffff on error.
*/
long omap2_clksel_round_rate(struct clk_hw *hw, unsigned long target_rate,
unsigned long *parent_rate)
{
struct clk_hw_omap *clk = to_clk_hw_omap(hw);
u32 new_div;
return omap2_clksel_round_rate_div(clk, target_rate, &new_div);
}
/**
* omap2_clksel_set_rate() - program clock rate in hardware
* @clk: struct clk * to program rate
* @rate: target rate to program
*
* This function is intended to be called only by the clock framework.
* Program @clk's rate to @rate in the hardware. The clock can be
* either enabled or disabled when this happens, although if the clock
* is enabled, some downstream devices may glitch or behave
* unpredictably when the clock rate is changed - this depends on the
* hardware. This function does not currently check the usecount of
* the clock, so if multiple drivers are using the clock, and the rate
* is changed, they will all be affected without any notification.
* Returns -EINVAL upon error, or 0 upon success.
*/
int omap2_clksel_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct clk_hw_omap *clk = to_clk_hw_omap(hw);
u32 field_val, validrate, new_div = 0;
if (!clk->clksel || !clk->clksel_mask)
return -EINVAL;
validrate = omap2_clksel_round_rate_div(clk, rate, &new_div);
if (validrate != rate)
return -EINVAL;
field_val = _divisor_to_clksel(clk, new_div);
if (field_val == ~0)
return -EINVAL;
_write_clksel_reg(clk, field_val);
pr_debug("clock: %s: set rate to %ld\n", __clk_get_name(hw->clk),
__clk_get_rate(hw->clk));
return 0;
}
/*
* Clksel parent setting function - not passed in struct clk function
* pointer - instead, the OMAP clock code currently assumes that any
* parent-setting clock is a clksel clock, and calls
* omap2_clksel_set_parent() by default
*/
/**
* omap2_clksel_set_parent() - change a clock's parent clock
* @clk: struct clk * of the child clock
* @new_parent: struct clk * of the new parent clock
*
* This function is intended to be called only by the clock framework.
* Change the parent clock of clock @clk to @new_parent. This is
* intended to be used while @clk is disabled. This function does not
* currently check the usecount of the clock, so if multiple drivers
* are using the clock, and the parent is changed, they will all be
* affected without any notification. Returns -EINVAL upon error, or
* 0 upon success.
*/
int omap2_clksel_set_parent(struct clk_hw *hw, u8 field_val)
{
struct clk_hw_omap *clk = to_clk_hw_omap(hw);
if (!clk->clksel || !clk->clksel_mask)
return -EINVAL;
_write_clksel_reg(clk, field_val);
return 0;
}
此差异已折叠。
......@@ -23,90 +23,6 @@
#include <linux/clk-provider.h>
#include <linux/clk/ti.h>
struct omap_clk {
u16 cpu;
struct clk_lookup lk;
};
#define CLK(dev, con, ck) \
{ \
.lk = { \
.dev_id = dev, \
.con_id = con, \
.clk = ck, \
}, \
}
struct clockdomain;
#define DEFINE_STRUCT_CLK(_name, _parent_array_name, _clkops_name) \
static struct clk_core _name##_core = { \
.name = #_name, \
.hw = &_name##_hw.hw, \
.parent_names = _parent_array_name, \
.num_parents = ARRAY_SIZE(_parent_array_name), \
.ops = &_clkops_name, \
}; \
static struct clk _name = { \
.core = &_name##_core, \
};
#define DEFINE_STRUCT_CLK_FLAGS(_name, _parent_array_name, \
_clkops_name, _flags) \
static struct clk_core _name##_core = { \
.name = #_name, \
.hw = &_name##_hw.hw, \
.parent_names = _parent_array_name, \
.num_parents = ARRAY_SIZE(_parent_array_name), \
.ops = &_clkops_name, \
.flags = _flags, \
}; \
static struct clk _name = { \
.core = &_name##_core, \
};
#define DEFINE_STRUCT_CLK_HW_OMAP(_name, _clkdm_name) \
static struct clk_hw_omap _name##_hw = { \
.hw = { \
.clk = &_name, \
}, \
.clkdm_name = _clkdm_name, \
};
#define DEFINE_CLK_OMAP_MUX(_name, _clkdm_name, _clksel, \
_clksel_reg, _clksel_mask, \
_parent_names, _ops) \
static struct clk _name; \
static struct clk_hw_omap _name##_hw = { \
.hw = { \
.clk = &_name, \
}, \
.clksel = _clksel, \
.clksel_reg = _clksel_reg, \
.clksel_mask = _clksel_mask, \
.clkdm_name = _clkdm_name, \
}; \
DEFINE_STRUCT_CLK(_name, _parent_names, _ops);
#define DEFINE_CLK_OMAP_MUX_GATE(_name, _clkdm_name, _clksel, \
_clksel_reg, _clksel_mask, \
_enable_reg, _enable_bit, \
_hwops, _parent_names, _ops) \
static struct clk _name; \
static struct clk_hw_omap _name##_hw = { \
.hw = { \
.clk = &_name, \
}, \
.ops = _hwops, \
.enable_reg = _enable_reg, \
.enable_bit = _enable_bit, \
.clksel = _clksel, \
.clksel_reg = _clksel_reg, \
.clksel_mask = _clksel_mask, \
.clkdm_name = _clkdm_name, \
}; \
DEFINE_STRUCT_CLK(_name, _parent_names, _ops);
/* struct clksel_rate.flags possibilities */
#define RATE_IN_242X (1 << 0)
#define RATE_IN_243X (1 << 1)
......@@ -127,38 +43,6 @@ struct clockdomain;
/* RATE_IN_3430ES2PLUS_36XX includes 34xx/35xx with ES >=2, and all 36xx/37xx */
#define RATE_IN_3430ES2PLUS_36XX (RATE_IN_3430ES2PLUS | RATE_IN_36XX)
/**
* struct clksel_rate - register bitfield values corresponding to clk divisors
* @val: register bitfield value (shifted to bit 0)
* @div: clock divisor corresponding to @val
* @flags: (see "struct clksel_rate.flags possibilities" above)
*
* @val should match the value of a read from struct clk.clksel_reg
* AND'ed with struct clk.clksel_mask, shifted right to bit 0.
*
* @div is the divisor that should be applied to the parent clock's rate
* to produce the current clock's rate.
*/
struct clksel_rate {
u32 val;
u8 div;
u16 flags;
};
/**
* struct clksel - available parent clocks, and a pointer to their divisors
* @parent: struct clk * to a possible parent clock
* @rates: available divisors for this parent clock
*
* A struct clksel is always associated with one or more struct clks
* and one or more struct clksel_rates.
*/
struct clksel {
struct clk *parent;
const struct clksel_rate *rates;
};
/* CM_CLKSEL2_PLL.CORE_CLK_SRC bits (2XXX) */
#define CORE_CLK_SRC_32K 0x0
#define CORE_CLK_SRC_DPLL 0x1
......@@ -180,105 +64,18 @@ struct clksel {
#define OMAP4XXX_EN_DPLL_FRBYPASS 0x6
#define OMAP4XXX_EN_DPLL_LOCKED 0x7
u32 omap3_dpll_autoidle_read(struct clk_hw_omap *clk);
void omap3_dpll_allow_idle(struct clk_hw_omap *clk);
void omap3_dpll_deny_idle(struct clk_hw_omap *clk);
void omap4_dpllmx_allow_gatectrl(struct clk_hw_omap *clk);
void omap4_dpllmx_deny_gatectrl(struct clk_hw_omap *clk);
void __init omap2_clk_disable_clkdm_control(void);
/* clkt_clksel.c public functions */
u32 omap2_clksel_round_rate_div(struct clk_hw_omap *clk,
unsigned long target_rate,
u32 *new_div);
u8 omap2_clksel_find_parent_index(struct clk_hw *hw);
unsigned long omap2_clksel_recalc(struct clk_hw *hw, unsigned long parent_rate);
long omap2_clksel_round_rate(struct clk_hw *hw, unsigned long target_rate,
unsigned long *parent_rate);
int omap2_clksel_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate);
int omap2_clksel_set_parent(struct clk_hw *hw, u8 field_val);
/* clkt_iclk.c public functions */
extern void omap2_clkt_iclk_allow_idle(struct clk_hw_omap *clk);
extern void omap2_clkt_iclk_deny_idle(struct clk_hw_omap *clk);
unsigned long omap2_get_dpll_rate(struct clk_hw_omap *clk);
void omap2_clk_dflt_find_companion(struct clk_hw_omap *clk,
void __iomem **other_reg,
u8 *other_bit);
void omap2_clk_dflt_find_idlest(struct clk_hw_omap *clk,
void __iomem **idlest_reg,
u8 *idlest_bit, u8 *idlest_val);
int omap2_clk_enable_autoidle_all(void);
int omap2_clk_allow_idle(struct clk *clk);
int omap2_clk_deny_idle(struct clk *clk);
int omap2_clk_switch_mpurate_at_boot(const char *mpurate_ck_name);
void omap2_clk_print_new_rates(const char *hfclkin_ck_name,
const char *core_ck_name,
const char *mpu_ck_name);
u32 omap2_clk_readl(struct clk_hw_omap *clk, void __iomem *reg);
void omap2_clk_writel(u32 val, struct clk_hw_omap *clk, void __iomem *reg);
extern u16 cpu_mask;
/*
* Clock features setup. Used instead of CPU type checks.
*/
struct ti_clk_features {
u32 flags;
long fint_min;
long fint_max;
long fint_band1_max;
long fint_band2_min;
u8 dpll_bypass_vals;
u8 cm_idlest_val;
};
#define TI_CLK_DPLL_HAS_FREQSEL (1 << 0)
#define TI_CLK_DPLL4_DENY_REPROGRAM (1 << 1)
extern struct ti_clk_features ti_clk_features;
extern const struct clkops clkops_omap2_dflt_wait;
extern const struct clkops clkops_omap2_dflt;
extern struct clk_functions omap2_clk_functions;
extern const struct clksel_rate gpt_32k_rates[];
extern const struct clksel_rate gpt_sys_rates[];
extern const struct clksel_rate gfx_l3_rates[];
extern const struct clksel_rate dsp_ick_rates[];
extern const struct clk_hw_omap_ops clkhwops_iclk_wait;
extern const struct clk_hw_omap_ops clkhwops_wait;
extern const struct clk_hw_omap_ops clkhwops_omap3430es2_ssi_wait;
extern const struct clk_hw_omap_ops clkhwops_omap3430es2_dss_usbhost_wait;
extern const struct clk_hw_omap_ops clkhwops_omap3430es2_hsotgusb_wait;
extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_module_wait;
extern const struct clk_hw_omap_ops clkhwops_apll54;
extern const struct clk_hw_omap_ops clkhwops_apll96;
/* clksel_rate blocks shared between OMAP44xx and AM33xx */
extern const struct clksel_rate div_1_0_rates[];
extern const struct clksel_rate div3_1to4_rates[];
extern const struct clksel_rate div_1_1_rates[];
extern const struct clksel_rate div_1_2_rates[];
extern const struct clksel_rate div_1_3_rates[];
extern const struct clksel_rate div_1_4_rates[];
extern const struct clksel_rate div31_1to31_rates[];
extern int omap2_clkops_enable_clkdm(struct clk_hw *hw);
extern void omap2_clkops_disable_clkdm(struct clk_hw *hw);
struct regmap;
int __init omap2_clk_provider_init(struct device_node *np, int index,
struct regmap *syscon, void __iomem *mem);
void __init omap2_clk_legacy_provider_init(int index, void __iomem *mem);
int __init omap2_clk_setup_ll_ops(void);
void __init ti_clk_init_features(void);
#endif
/*
* clock2430.c - OMAP2430-specific clock integration code
*
* Copyright (C) 2005-2008 Texas Instruments, Inc.
* Copyright (C) 2004-2010 Nokia Corporation
*
* Contacts:
* Richard Woodruff <r-woodruff2@ti.com>
* Paul Walmsley
*
* Based on earlier work by Tuukka Tikkanen, Tony Lindgren,
* Gordon McNutt and RidgeRun, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#undef DEBUG
#include <linux/kernel.h>
#include <linux/clk.h>
#include <linux/io.h>
#include "soc.h"
#include "iomap.h"
#include "clock.h"
#include "clock2xxx.h"
#include "cm2xxx.h"
#include "cm-regbits-24xx.h"
/**
* omap2430_clk_i2chs_find_idlest - return CM_IDLEST info for 2430 I2CHS
* @clk: struct clk * being enabled
* @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
* @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
* @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
*
* OMAP2430 I2CHS CM_IDLEST bits are in CM_IDLEST1_CORE, but the
* CM_*CLKEN bits are in CM_{I,F}CLKEN2_CORE. This custom function
* passes back the correct CM_IDLEST register address for I2CHS
* modules. No return value.
*/
static void omap2430_clk_i2chs_find_idlest(struct clk_hw_omap *clk,
void __iomem **idlest_reg,
u8 *idlest_bit,
u8 *idlest_val)
{
*idlest_reg = OMAP2430_CM_REGADDR(CORE_MOD, CM_IDLEST);
*idlest_bit = clk->enable_bit;
*idlest_val = OMAP24XX_CM_IDLEST_VAL;
}
/* 2430 I2CHS has non-standard IDLEST register */
const struct clk_hw_omap_ops clkhwops_omap2430_i2chs_wait = {
.find_idlest = omap2430_clk_i2chs_find_idlest,
.find_companion = omap2_clk_dflt_find_companion,
};
/*
* clock2xxx.c - OMAP2xxx-specific clock integration code
*
* Copyright (C) 2005-2008 Texas Instruments, Inc.
* Copyright (C) 2004-2010 Nokia Corporation
*
* Contacts:
* Richard Woodruff <r-woodruff2@ti.com>
* Paul Walmsley
*
* Based on earlier work by Tuukka Tikkanen, Tony Lindgren,
* Gordon McNutt and RidgeRun, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#undef DEBUG
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/clk.h>
#include <linux/io.h>
#include "soc.h"
#include "clock.h"
#include "clock2xxx.h"
#include "cm.h"
#include "cm-regbits-24xx.h"
struct clk_hw *dclk_hw;
/*
* Omap24xx specific clock functions
*/
/*
* Switch the MPU rate if specified on cmdline. We cannot do this
* early until cmdline is parsed. XXX This should be removed from the
* clock code and handled by the OPP layer code in the near future.
*/
static int __init omap2xxx_clk_arch_init(void)
{
int ret;
if (!cpu_is_omap24xx())
return 0;
ret = omap2_clk_switch_mpurate_at_boot("virt_prcm_set");
if (!ret)
omap2_clk_print_new_rates("sys_ck", "dpll_ck", "mpu_ck");
return ret;
}
omap_arch_initcall(omap2xxx_clk_arch_init);
/*
* OMAP3-specific clock framework functions
*
* Copyright (C) 2007-2008 Texas Instruments, Inc.
* Copyright (C) 2007-2011 Nokia Corporation
*
* Paul Walmsley
* Jouni Högander
*
* Parts of this code are based on code written by
* Richard Woodruff, Tony Lindgren, Tuukka Tikkanen, Karthik Dasu,
* Russell King
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#undef DEBUG
#include <linux/kernel.h>
#include <linux/clk.h>
#include <linux/io.h>
#include "clock.h"
#include "clock34xx.h"
#include "cm3xxx.h"
#include "cm-regbits-34xx.h"
/**
* omap3430es2_clk_ssi_find_idlest - return CM_IDLEST info for SSI
* @clk: struct clk * being enabled
* @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
* @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
* @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
*
* The OMAP3430ES2 SSI target CM_IDLEST bit is at a different shift
* from the CM_{I,F}CLKEN bit. Pass back the correct info via
* @idlest_reg and @idlest_bit. No return value.
*/
static void omap3430es2_clk_ssi_find_idlest(struct clk_hw_omap *clk,
void __iomem **idlest_reg,
u8 *idlest_bit,
u8 *idlest_val)
{
u32 r;
r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
*idlest_reg = (__force void __iomem *)r;
*idlest_bit = OMAP3430ES2_ST_SSI_IDLE_SHIFT;
*idlest_val = OMAP34XX_CM_IDLEST_VAL;
}
const struct clk_hw_omap_ops clkhwops_omap3430es2_ssi_wait = {
.find_idlest = omap3430es2_clk_ssi_find_idlest,
.find_companion = omap2_clk_dflt_find_companion,
};
const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_ssi_wait = {
.allow_idle = omap2_clkt_iclk_allow_idle,
.deny_idle = omap2_clkt_iclk_deny_idle,
.find_idlest = omap3430es2_clk_ssi_find_idlest,
.find_companion = omap2_clk_dflt_find_companion,
};
/**
* omap3430es2_clk_dss_usbhost_find_idlest - CM_IDLEST info for DSS, USBHOST
* @clk: struct clk * being enabled
* @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
* @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
* @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
*
* Some OMAP modules on OMAP3 ES2+ chips have both initiator and
* target IDLEST bits. For our purposes, we are concerned with the
* target IDLEST bits, which exist at a different bit position than
* the *CLKEN bit position for these modules (DSS and USBHOST) (The
* default find_idlest code assumes that they are at the same
* position.) No return value.
*/
static void omap3430es2_clk_dss_usbhost_find_idlest(struct clk_hw_omap *clk,
void __iomem **idlest_reg,
u8 *idlest_bit,
u8 *idlest_val)
{
u32 r;
r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
*idlest_reg = (__force void __iomem *)r;
/* USBHOST_IDLE has same shift */
*idlest_bit = OMAP3430ES2_ST_DSS_IDLE_SHIFT;
*idlest_val = OMAP34XX_CM_IDLEST_VAL;
}
const struct clk_hw_omap_ops clkhwops_omap3430es2_dss_usbhost_wait = {
.find_idlest = omap3430es2_clk_dss_usbhost_find_idlest,
.find_companion = omap2_clk_dflt_find_companion,
};
const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_dss_usbhost_wait = {
.allow_idle = omap2_clkt_iclk_allow_idle,
.deny_idle = omap2_clkt_iclk_deny_idle,
.find_idlest = omap3430es2_clk_dss_usbhost_find_idlest,
.find_companion = omap2_clk_dflt_find_companion,
};
/**
* omap3430es2_clk_hsotgusb_find_idlest - return CM_IDLEST info for HSOTGUSB
* @clk: struct clk * being enabled
* @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
* @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
* @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
*
* The OMAP3430ES2 HSOTGUSB target CM_IDLEST bit is at a different
* shift from the CM_{I,F}CLKEN bit. Pass back the correct info via
* @idlest_reg and @idlest_bit. No return value.
*/
static void omap3430es2_clk_hsotgusb_find_idlest(struct clk_hw_omap *clk,
void __iomem **idlest_reg,
u8 *idlest_bit,
u8 *idlest_val)
{
u32 r;
r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
*idlest_reg = (__force void __iomem *)r;
*idlest_bit = OMAP3430ES2_ST_HSOTGUSB_IDLE_SHIFT;
*idlest_val = OMAP34XX_CM_IDLEST_VAL;
}
const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_hsotgusb_wait = {
.allow_idle = omap2_clkt_iclk_allow_idle,
.deny_idle = omap2_clkt_iclk_deny_idle,
.find_idlest = omap3430es2_clk_hsotgusb_find_idlest,
.find_companion = omap2_clk_dflt_find_companion,
};
const struct clk_hw_omap_ops clkhwops_omap3430es2_hsotgusb_wait = {
.find_idlest = omap3430es2_clk_hsotgusb_find_idlest,
.find_companion = omap2_clk_dflt_find_companion,
};
/*
* OMAP34xx clock function prototypes and macros
*
* Copyright (C) 2007-2010 Texas Instruments, Inc.
* Copyright (C) 2007-2011 Nokia Corporation
*/
#ifndef __ARCH_ARM_MACH_OMAP2_CLOCK34XX_H
#define __ARCH_ARM_MACH_OMAP2_CLOCK34XX_H
extern const struct clkops clkops_omap3430es2_ssi_wait;
extern const struct clkops clkops_omap3430es2_iclk_ssi_wait;
extern const struct clkops clkops_omap3430es2_hsotgusb_wait;
extern const struct clkops clkops_omap3430es2_iclk_hsotgusb_wait;
extern const struct clkops clkops_omap3430es2_dss_usbhost_wait;
extern const struct clkops clkops_omap3430es2_iclk_dss_usbhost_wait;
#endif
/*
* OMAP3517/3505-specific clock framework functions
*
* Copyright (C) 2010 Texas Instruments, Inc.
* Copyright (C) 2011 Nokia Corporation
*
* Ranjith Lohithakshan
* Paul Walmsley
*
* Parts of this code are based on code written by
* Richard Woodruff, Tony Lindgren, Tuukka Tikkanen, Karthik Dasu,
* Russell King
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#undef DEBUG
#include <linux/kernel.h>
#include <linux/clk.h>
#include <linux/io.h>
#include "clock.h"
#include "clock3517.h"
#include "cm3xxx.h"
#include "cm-regbits-34xx.h"
/*
* In AM35xx IPSS, the {ICK,FCK} enable bits for modules are exported
* in the same register at a bit offset of 0x8. The EN_ACK for ICK is
* at an offset of 4 from ICK enable bit.
*/
#define AM35XX_IPSS_ICK_MASK 0xF
#define AM35XX_IPSS_ICK_EN_ACK_OFFSET 0x4
#define AM35XX_IPSS_ICK_FCK_OFFSET 0x8
#define AM35XX_IPSS_CLK_IDLEST_VAL 0
/**
* am35xx_clk_find_idlest - return clock ACK info for AM35XX IPSS
* @clk: struct clk * being enabled
* @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
* @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
* @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
*
* The interface clocks on AM35xx IPSS reflects the clock idle status
* in the enable register itsel at a bit offset of 4 from the enable
* bit. A value of 1 indicates that clock is enabled.
*/
static void am35xx_clk_find_idlest(struct clk_hw_omap *clk,
void __iomem **idlest_reg,
u8 *idlest_bit,
u8 *idlest_val)
{
*idlest_reg = (__force void __iomem *)(clk->enable_reg);
*idlest_bit = clk->enable_bit + AM35XX_IPSS_ICK_EN_ACK_OFFSET;
*idlest_val = AM35XX_IPSS_CLK_IDLEST_VAL;
}
/**
* am35xx_clk_find_companion - find companion clock to @clk
* @clk: struct clk * to find the companion clock of
* @other_reg: void __iomem ** to return the companion clock CM_*CLKEN va in
* @other_bit: u8 ** to return the companion clock bit shift in
*
* Some clocks don't have companion clocks. For example, modules with
* only an interface clock (such as HECC) don't have a companion
* clock. Right now, this code relies on the hardware exporting a bit
* in the correct companion register that indicates that the
* nonexistent 'companion clock' is active. Future patches will
* associate this type of code with per-module data structures to
* avoid this issue, and remove the casts. No return value.
*/
static void am35xx_clk_find_companion(struct clk_hw_omap *clk,
void __iomem **other_reg,
u8 *other_bit)
{
*other_reg = (__force void __iomem *)(clk->enable_reg);
if (clk->enable_bit & AM35XX_IPSS_ICK_MASK)
*other_bit = clk->enable_bit + AM35XX_IPSS_ICK_FCK_OFFSET;
else
*other_bit = clk->enable_bit - AM35XX_IPSS_ICK_FCK_OFFSET;
}
const struct clk_hw_omap_ops clkhwops_am35xx_ipss_module_wait = {
.find_idlest = am35xx_clk_find_idlest,
.find_companion = am35xx_clk_find_companion,
};
/**
* am35xx_clk_ipss_find_idlest - return CM_IDLEST info for IPSS
* @clk: struct clk * being enabled
* @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
* @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
* @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
*
* The IPSS target CM_IDLEST bit is at a different shift from the
* CM_{I,F}CLKEN bit. Pass back the correct info via @idlest_reg
* and @idlest_bit. No return value.
*/
static void am35xx_clk_ipss_find_idlest(struct clk_hw_omap *clk,
void __iomem **idlest_reg,
u8 *idlest_bit,
u8 *idlest_val)
{
u32 r;
r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
*idlest_reg = (__force void __iomem *)r;
*idlest_bit = AM35XX_ST_IPSS_SHIFT;
*idlest_val = OMAP34XX_CM_IDLEST_VAL;
}
const struct clk_hw_omap_ops clkhwops_am35xx_ipss_wait = {
.allow_idle = omap2_clkt_iclk_allow_idle,
.deny_idle = omap2_clkt_iclk_deny_idle,
.find_idlest = am35xx_clk_ipss_find_idlest,
.find_companion = omap2_clk_dflt_find_companion,
};
/*
* OMAP3517/3505 clock function prototypes and macros
*
* Copyright (C) 2010 Texas Instruments, Inc.
* Copyright (C) 2010 Nokia Corporation
*/
#ifndef __ARCH_ARM_MACH_OMAP2_CLOCK3517_H
#define __ARCH_ARM_MACH_OMAP2_CLOCK3517_H
extern const struct clkops clkops_am35xx_ipss_module_wait;
extern const struct clkops clkops_am35xx_ipss_wait;
#endif
/*
* OMAP36xx-specific clkops
*
* Copyright (C) 2010 Texas Instruments, Inc.
* Copyright (C) 2010 Nokia Corporation
*
* Mike Turquette
* Vijaykumar GN
* Paul Walmsley
*
* Parts of this code are based on code written by
* Richard Woodruff, Tony Lindgren, Tuukka Tikkanen, Karthik Dasu,
* Russell King
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#undef DEBUG
#include <linux/kernel.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/io.h>
#include "clock.h"
#include "clock36xx.h"
#define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw)
/**
* omap36xx_pwrdn_clk_enable_with_hsdiv_restore - enable clocks suffering
* from HSDivider PWRDN problem Implements Errata ID: i556.
* @clk: DPLL output struct clk
*
* 3630 only: dpll3_m3_ck, dpll4_m2_ck, dpll4_m3_ck, dpll4_m4_ck,
* dpll4_m5_ck & dpll4_m6_ck dividers gets loaded with reset
* valueafter their respective PWRDN bits are set. Any dummy write
* (Any other value different from the Read value) to the
* corresponding CM_CLKSEL register will refresh the dividers.
*/
int omap36xx_pwrdn_clk_enable_with_hsdiv_restore(struct clk_hw *clk)
{
struct clk_divider *parent;
struct clk_hw *parent_hw;
u32 dummy_v, orig_v;
struct clk_hw_omap *omap_clk = to_clk_hw_omap(clk);
int ret;
/* Clear PWRDN bit of HSDIVIDER */
ret = omap2_dflt_clk_enable(clk);
parent_hw = __clk_get_hw(__clk_get_parent(clk->clk));
parent = to_clk_divider(parent_hw);
/* Restore the dividers */
if (!ret) {
orig_v = omap2_clk_readl(omap_clk, parent->reg);
dummy_v = orig_v;
/* Write any other value different from the Read value */
dummy_v ^= (1 << parent->shift);
omap2_clk_writel(dummy_v, omap_clk, parent->reg);
/* Write the original divider */
omap2_clk_writel(orig_v, omap_clk, parent->reg);
}
return ret;
}
/*
* OMAP36xx clock function prototypes and macros
*
* Copyright (C) 2010 Texas Instruments, Inc.
* Copyright (C) 2010 Nokia Corporation
*/
#ifndef __ARCH_ARM_MACH_OMAP2_CLOCK36XX_H
#define __ARCH_ARM_MACH_OMAP2_CLOCK36XX_H
extern int omap36xx_pwrdn_clk_enable_with_hsdiv_restore(struct clk_hw *hw);
#endif
/*
* OMAP3-specific clock framework functions
*
* Copyright (C) 2007-2008 Texas Instruments, Inc.
* Copyright (C) 2007-2010 Nokia Corporation
*
* Paul Walmsley
* Jouni Högander
*
* Parts of this code are based on code written by
* Richard Woodruff, Tony Lindgren, Tuukka Tikkanen, Karthik Dasu
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#undef DEBUG
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/clk.h>
#include <linux/io.h>
#include "soc.h"
#include "clock.h"
#include "clock3xxx.h"
#include "prm2xxx_3xxx.h"
#include "prm-regbits-34xx.h"
#include "cm2xxx_3xxx.h"
#include "cm-regbits-34xx.h"
/*
* DPLL5_FREQ_FOR_USBHOST: USBHOST and USBTLL are the only clocks
* that are sourced by DPLL5, and both of these require this clock
* to be at 120 MHz for proper operation.
*/
#define DPLL5_FREQ_FOR_USBHOST 120000000
/* needed by omap3_core_dpll_m2_set_rate() */
struct clk *sdrc_ick_p, *arm_fck_p;
/**
* omap3_dpll4_set_rate - set rate for omap3 per-dpll
* @hw: clock to change
* @rate: target rate for clock
* @parent_rate: rate of the parent clock
*
* Check if the current SoC supports the per-dpll reprogram operation
* or not, and then do the rate change if supported. Returns -EINVAL
* if not supported, 0 for success, and potential error codes from the
* clock rate change.
*/
int omap3_dpll4_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
/*
* According to the 12-5 CDP code from TI, "Limitation 2.5"
* on 3430ES1 prevents us from changing DPLL multipliers or dividers
* on DPLL4.
*/
if (ti_clk_features.flags & TI_CLK_DPLL4_DENY_REPROGRAM) {
pr_err("clock: DPLL4 cannot change rate due to silicon 'Limitation 2.5' on 3430ES1.\n");
return -EINVAL;
}
return omap3_noncore_dpll_set_rate(hw, rate, parent_rate);
}
/**
* omap3_dpll4_set_rate_and_parent - set rate and parent for omap3 per-dpll
* @hw: clock to change
* @rate: target rate for clock
* @parent_rate: rate of the parent clock
* @index: parent index, 0 - reference clock, 1 - bypass clock
*
* Check if the current SoC support the per-dpll reprogram operation
* or not, and then do the rate + parent change if supported. Returns
* -EINVAL if not supported, 0 for success, and potential error codes
* from the clock rate change.
*/
int omap3_dpll4_set_rate_and_parent(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate, u8 index)
{
if (ti_clk_features.flags & TI_CLK_DPLL4_DENY_REPROGRAM) {
pr_err("clock: DPLL4 cannot change rate due to silicon 'Limitation 2.5' on 3430ES1.\n");
return -EINVAL;
}
return omap3_noncore_dpll_set_rate_and_parent(hw, rate, parent_rate,
index);
}
void __init omap3_clk_lock_dpll5(void)
{
struct clk *dpll5_clk;
struct clk *dpll5_m2_clk;
dpll5_clk = clk_get(NULL, "dpll5_ck");
clk_set_rate(dpll5_clk, DPLL5_FREQ_FOR_USBHOST);
clk_prepare_enable(dpll5_clk);
/* Program dpll5_m2_clk divider for no division */
dpll5_m2_clk = clk_get(NULL, "dpll5_m2_ck");
clk_prepare_enable(dpll5_m2_clk);
clk_set_rate(dpll5_m2_clk, DPLL5_FREQ_FOR_USBHOST);
clk_disable_unprepare(dpll5_m2_clk);
clk_disable_unprepare(dpll5_clk);
return;
}
/* Common clock code */
/*
* Switch the MPU rate if specified on cmdline. We cannot do this
* early until cmdline is parsed. XXX This should be removed from the
* clock code and handled by the OPP layer code in the near future.
*/
static int __init omap3xxx_clk_arch_init(void)
{
int ret;
if (!cpu_is_omap34xx())
return 0;
ret = omap2_clk_switch_mpurate_at_boot("dpll1_ck");
if (!ret)
omap2_clk_print_new_rates("osc_sys_ck", "core_ck", "arm_fck");
return ret;
}
omap_arch_initcall(omap3xxx_clk_arch_init);
/*
* OMAP4 clock function prototypes and macros
*
* Copyright (C) 2009 Texas Instruments, Inc.
* Copyright (C) 2010 Nokia Corporation
*/
#ifndef __ARCH_ARM_MACH_OMAP2_CLOCK44XX_H
#define __ARCH_ARM_MACH_OMAP2_CLOCK44XX_H
/*
* OMAP4430_REGM4XEN_MULT: If the CM_CLKMODE_DPLL_ABE.DPLL_REGM4XEN bit is
* set, then the DPLL's lock frequency is multiplied by 4 (OMAP4430 TRM
* vV Section 3.6.3.3.1 "DPLLs Output Clocks Parameters")
*/
#define OMAP4430_REGM4XEN_MULT 4
int omap4xxx_clk_init(void);
#endif
/*
* linux/arch/arm/mach-omap2/clock_common_data.c
*
* Copyright (C) 2005-2009 Texas Instruments, Inc.
* Copyright (C) 2004-2009 Nokia Corporation
*
* Contacts:
* Richard Woodruff <r-woodruff2@ti.com>
* Paul Walmsley
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This file contains clock data that is common to both the OMAP2xxx and
* OMAP3xxx clock definition files.
*/
#include "clock.h"
/* clksel_rate data common to 24xx/343x */
const struct clksel_rate gpt_32k_rates[] = {
{ .div = 1, .val = 0, .flags = RATE_IN_24XX | RATE_IN_3XXX },
{ .div = 0 }
};
const struct clksel_rate gpt_sys_rates[] = {
{ .div = 1, .val = 1, .flags = RATE_IN_24XX | RATE_IN_3XXX },
{ .div = 0 }
};
const struct clksel_rate gfx_l3_rates[] = {
{ .div = 1, .val = 1, .flags = RATE_IN_24XX | RATE_IN_3XXX },
{ .div = 2, .val = 2, .flags = RATE_IN_24XX | RATE_IN_3XXX },
{ .div = 3, .val = 3, .flags = RATE_IN_243X | RATE_IN_3XXX },
{ .div = 4, .val = 4, .flags = RATE_IN_243X | RATE_IN_3XXX },
{ .div = 0 }
};
const struct clksel_rate dsp_ick_rates[] = {
{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
{ .div = 2, .val = 2, .flags = RATE_IN_24XX },
{ .div = 3, .val = 3, .flags = RATE_IN_243X },
{ .div = 0 },
};
/* clksel_rate blocks shared between OMAP44xx and AM33xx */
const struct clksel_rate div_1_0_rates[] = {
{ .div = 1, .val = 0, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
{ .div = 0 },
};
const struct clksel_rate div3_1to4_rates[] = {
{ .div = 1, .val = 0, .flags = RATE_IN_4430 },
{ .div = 2, .val = 1, .flags = RATE_IN_4430 },
{ .div = 4, .val = 2, .flags = RATE_IN_4430 },
{ .div = 0 },
};
const struct clksel_rate div_1_1_rates[] = {
{ .div = 1, .val = 1, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
{ .div = 0 },
};
const struct clksel_rate div_1_2_rates[] = {
{ .div = 1, .val = 2, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
{ .div = 0 },
};
const struct clksel_rate div_1_3_rates[] = {
{ .div = 1, .val = 3, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
{ .div = 0 },
};
const struct clksel_rate div_1_4_rates[] = {
{ .div = 1, .val = 4, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
{ .div = 0 },
};
const struct clksel_rate div31_1to31_rates[] = {
{ .div = 1, .val = 1, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
{ .div = 2, .val = 2, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
{ .div = 3, .val = 3, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
{ .div = 4, .val = 4, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
{ .div = 5, .val = 5, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
{ .div = 6, .val = 6, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
{ .div = 7, .val = 7, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
{ .div = 8, .val = 8, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
{ .div = 9, .val = 9, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
{ .div = 10, .val = 10, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
{ .div = 11, .val = 11, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
{ .div = 12, .val = 12, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
{ .div = 13, .val = 13, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
{ .div = 14, .val = 14, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
{ .div = 15, .val = 15, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
{ .div = 16, .val = 16, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
{ .div = 17, .val = 17, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
{ .div = 18, .val = 18, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
{ .div = 19, .val = 19, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
{ .div = 20, .val = 20, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
{ .div = 21, .val = 21, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
{ .div = 22, .val = 22, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
{ .div = 23, .val = 23, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
{ .div = 24, .val = 24, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
{ .div = 25, .val = 25, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
{ .div = 26, .val = 26, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
{ .div = 27, .val = 27, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
{ .div = 28, .val = 28, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
{ .div = 29, .val = 29, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
{ .div = 30, .val = 30, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
{ .div = 31, .val = 31, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
{ .div = 0 },
};
......@@ -37,7 +37,6 @@
#include "clock.h"
#include "clock2xxx.h"
#include "clock3xxx.h"
#include "clock44xx.h"
#include "omap-pm.h"
#include "sdrc.h"
#include "control.h"
......@@ -723,6 +722,8 @@ int __init omap_clk_init(void)
ti_clk_init_features();
omap2_clk_setup_ll_ops();
if (of_have_populated_dt()) {
ret = omap_control_init();
if (ret)
......
......@@ -130,6 +130,7 @@
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/io.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/delay.h>
#include <linux/err.h>
......
......@@ -25,6 +25,7 @@
#include <linux/sysfs.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/irq.h>
#include <linux/time.h>
......
......@@ -16,7 +16,6 @@
#include <linux/of_platform.h>
#include <linux/cpu.h>
#include <linux/mbus.h>
#include <linux/clk-provider.h>
#include <linux/clocksource.h>
#include <asm/system_misc.h>
#include <asm/mach/arch.h>
......
......@@ -21,7 +21,6 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/clk-provider.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/serial_core.h>
......
......@@ -8,6 +8,7 @@ menuconfig ARCH_TEGRA
select HAVE_ARM_SCU if SMP
select HAVE_ARM_TWD if SMP
select PINCTRL
select PM_OPP
select ARCH_HAS_RESET_CONTROLLER
select RESET_CONTROLLER
select SOC_BUS
......
......@@ -72,21 +72,12 @@ void __init ux500_init_irq(void)
* Init clocks here so that they are available for system timer
* initialization.
*/
if (cpu_is_u8500_family()) {
u8500_of_clk_init(U8500_CLKRST1_BASE,
U8500_CLKRST2_BASE,
U8500_CLKRST3_BASE,
U8500_CLKRST5_BASE,
U8500_CLKRST6_BASE);
} else if (cpu_is_u9540()) {
u9540_clk_init(U8500_CLKRST1_BASE, U8500_CLKRST2_BASE,
U8500_CLKRST3_BASE, U8500_CLKRST5_BASE,
U8500_CLKRST6_BASE);
} else if (cpu_is_u8540()) {
u8540_clk_init(U8500_CLKRST1_BASE, U8500_CLKRST2_BASE,
U8500_CLKRST3_BASE, U8500_CLKRST5_BASE,
U8500_CLKRST6_BASE);
}
if (cpu_is_u8500_family())
u8500_clk_init();
else if (cpu_is_u9540())
u9540_clk_init();
else if (cpu_is_u8540())
u8540_clk_init();
}
static const char * __init ux500_get_machine(void)
......
......@@ -34,7 +34,6 @@
#include <linux/kexec.h>
#include <linux/crash_dump.h>
#include <linux/root_dev.h>
#include <linux/clk-provider.h>
#include <linux/cpu.h>
#include <linux/interrupt.h>
#include <linux/smp.h>
......
......@@ -35,6 +35,7 @@
#include <linux/init.h>
#include <linux/io.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/clkdev.h>
#include <linux/slab.h>
......@@ -389,12 +390,11 @@ static long alchemy_calc_div(unsigned long rate, unsigned long prate,
return div1;
}
static long alchemy_clk_fgcs_detr(struct clk_hw *hw, unsigned long rate,
unsigned long *best_parent_rate,
struct clk_hw **best_parent_clk,
int scale, int maxdiv)
static int alchemy_clk_fgcs_detr(struct clk_hw *hw,
struct clk_rate_request *req,
int scale, int maxdiv)
{
struct clk *pc, *bpc, *free;
struct clk_hw *pc, *bpc, *free;
long tdv, tpr, pr, nr, br, bpr, diff, lastdiff;
int j;
......@@ -408,7 +408,7 @@ static long alchemy_clk_fgcs_detr(struct clk_hw *hw, unsigned long rate,
* the one that gets closest to but not over the requested rate.
*/
for (j = 0; j < 7; j++) {
pc = clk_get_parent_by_index(hw->clk, j);
pc = clk_hw_get_parent_by_index(hw, j);
if (!pc)
break;
......@@ -416,20 +416,20 @@ static long alchemy_clk_fgcs_detr(struct clk_hw *hw, unsigned long rate,
* XXX: we would actually want clk_has_active_children()
* but this is a good-enough approximation for now.
*/
if (!__clk_is_prepared(pc)) {
if (!clk_hw_is_prepared(pc)) {
if (!free)
free = pc;
}
pr = clk_get_rate(pc);
if (pr < rate)
pr = clk_hw_get_rate(pc);
if (pr < req->rate)
continue;
/* what can hardware actually provide */
tdv = alchemy_calc_div(rate, pr, scale, maxdiv, NULL);
tdv = alchemy_calc_div(req->rate, pr, scale, maxdiv, NULL);
nr = pr / tdv;
diff = rate - nr;
if (nr > rate)
diff = req->rate - nr;
if (nr > req->rate)
continue;
if (diff < lastdiff) {
......@@ -448,15 +448,16 @@ static long alchemy_clk_fgcs_detr(struct clk_hw *hw, unsigned long rate,
*/
if (lastdiff && free) {
for (j = (maxdiv == 4) ? 1 : scale; j <= maxdiv; j += scale) {
tpr = rate * j;
tpr = req->rate * j;
if (tpr < 0)
break;
pr = clk_round_rate(free, tpr);
pr = clk_hw_round_rate(free, tpr);
tdv = alchemy_calc_div(rate, pr, scale, maxdiv, NULL);
tdv = alchemy_calc_div(req->rate, pr, scale, maxdiv,
NULL);
nr = pr / tdv;
diff = rate - nr;
if (nr > rate)
diff = req->rate - nr;
if (nr > req->rate)
continue;
if (diff < lastdiff) {
lastdiff = diff;
......@@ -469,9 +470,14 @@ static long alchemy_clk_fgcs_detr(struct clk_hw *hw, unsigned long rate,
}
}
*best_parent_rate = bpr;
*best_parent_clk = __clk_get_hw(bpc);
return br;
if (br < 0)
return br;
req->best_parent_rate = bpr;
req->best_parent_hw = bpc;
req->rate = br;
return 0;
}
static int alchemy_clk_fgv1_en(struct clk_hw *hw)
......@@ -562,14 +568,10 @@ static unsigned long alchemy_clk_fgv1_recalc(struct clk_hw *hw,
return parent_rate / v;
}
static long alchemy_clk_fgv1_detr(struct clk_hw *hw, unsigned long rate,
unsigned long min_rate,
unsigned long max_rate,
unsigned long *best_parent_rate,
struct clk_hw **best_parent_clk)
static int alchemy_clk_fgv1_detr(struct clk_hw *hw,
struct clk_rate_request *req)
{
return alchemy_clk_fgcs_detr(hw, rate, best_parent_rate,
best_parent_clk, 2, 512);
return alchemy_clk_fgcs_detr(hw, req, 2, 512);
}
/* Au1000, Au1100, Au15x0, Au12x0 */
......@@ -696,11 +698,8 @@ static unsigned long alchemy_clk_fgv2_recalc(struct clk_hw *hw,
return t;
}
static long alchemy_clk_fgv2_detr(struct clk_hw *hw, unsigned long rate,
unsigned long min_rate,
unsigned long max_rate,
unsigned long *best_parent_rate,
struct clk_hw **best_parent_clk)
static int alchemy_clk_fgv2_detr(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
int scale, maxdiv;
......@@ -713,8 +712,7 @@ static long alchemy_clk_fgv2_detr(struct clk_hw *hw, unsigned long rate,
maxdiv = 512;
}
return alchemy_clk_fgcs_detr(hw, rate, best_parent_rate,
best_parent_clk, scale, maxdiv);
return alchemy_clk_fgcs_detr(hw, req, scale, maxdiv);
}
/* Au1300 larger input mux, no separate disable bit, flexible divider */
......@@ -917,17 +915,13 @@ static int alchemy_clk_csrc_setr(struct clk_hw *hw, unsigned long rate,
return 0;
}
static long alchemy_clk_csrc_detr(struct clk_hw *hw, unsigned long rate,
unsigned long min_rate,
unsigned long max_rate,
unsigned long *best_parent_rate,
struct clk_hw **best_parent_clk)
static int alchemy_clk_csrc_detr(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
int scale = c->dt[2] == 3 ? 1 : 2; /* au1300 check */
return alchemy_clk_fgcs_detr(hw, rate, best_parent_rate,
best_parent_clk, scale, 4);
return alchemy_clk_fgcs_detr(hw, req, scale, 4);
}
static struct clk_ops alchemy_clkops_csrc = {
......
......@@ -12,6 +12,7 @@
*/
#include <linux/bitops.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/clkdev.h>
#include <linux/device.h>
......
......@@ -16,7 +16,6 @@
#include <linux/clkdev.h>
#include <linux/acpi.h>
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/pm.h>
#include "internal.h"
......
......@@ -11,7 +11,6 @@
*/
#include <linux/acpi.h>
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/clk-provider.h>
#include <linux/err.h>
......
......@@ -9,7 +9,7 @@ obj-$(CONFIG_COMMON_CLK) += clk-gate.o
obj-$(CONFIG_COMMON_CLK) += clk-mux.o
obj-$(CONFIG_COMMON_CLK) += clk-composite.o
obj-$(CONFIG_COMMON_CLK) += clk-fractional-divider.o
obj-$(CONFIG_COMMON_CLK) += clk-gpio-gate.o
obj-$(CONFIG_COMMON_CLK) += clk-gpio.o
ifeq ($(CONFIG_OF), y)
obj-$(CONFIG_COMMON_CLK) += clk-conf.o
endif
......
......@@ -614,17 +614,12 @@ void __init of_at91sam9x5_clk_main_setup(struct device_node *np,
int num_parents;
unsigned int irq;
const char *name = np->name;
int i;
num_parents = of_clk_get_parent_count(np);
if (num_parents <= 0 || num_parents > 2)
return;
for (i = 0; i < num_parents; ++i) {
parent_names[i] = of_clk_get_parent_name(np, i);
if (!parent_names[i])
return;
}
of_clk_parent_fill(np, parent_names, num_parents);
of_property_read_string(np, "clock-output-names", &name);
......
......@@ -222,7 +222,6 @@ of_at91_clk_master_setup(struct device_node *np, struct at91_pmc *pmc,
{
struct clk *clk;
int num_parents;
int i;
unsigned int irq;
const char *parent_names[MASTER_SOURCE_MAX];
const char *name = np->name;
......@@ -232,11 +231,7 @@ of_at91_clk_master_setup(struct device_node *np, struct at91_pmc *pmc,
if (num_parents <= 0 || num_parents > MASTER_SOURCE_MAX)
return;
for (i = 0; i < num_parents; ++i) {
parent_names[i] = of_clk_get_parent_name(np, i);
if (!parent_names[i])
return;
}
of_clk_parent_fill(np, parent_names, num_parents);
of_property_read_string(np, "clock-output-names", &name);
......
......@@ -134,7 +134,7 @@ at91_clk_register_peripheral(struct at91_pmc *pmc, const char *name,
static void clk_sam9x5_peripheral_autodiv(struct clk_sam9x5_peripheral *periph)
{
struct clk *parent;
struct clk_hw *parent;
unsigned long parent_rate;
int shift = 0;
......@@ -142,8 +142,8 @@ static void clk_sam9x5_peripheral_autodiv(struct clk_sam9x5_peripheral *periph)
return;
if (periph->range.max) {
parent = clk_get_parent_by_index(periph->hw.clk, 0);
parent_rate = __clk_get_rate(parent);
parent = clk_hw_get_parent_by_index(&periph->hw, 0);
parent_rate = clk_hw_get_rate(parent);
if (!parent_rate)
return;
......
......@@ -54,46 +54,47 @@ static unsigned long clk_programmable_recalc_rate(struct clk_hw *hw,
return parent_rate >> pres;
}
static long clk_programmable_determine_rate(struct clk_hw *hw,
unsigned long rate,
unsigned long min_rate,
unsigned long max_rate,
unsigned long *best_parent_rate,
struct clk_hw **best_parent_hw)
static int clk_programmable_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct clk *parent = NULL;
struct clk_hw *parent;
long best_rate = -EINVAL;
unsigned long parent_rate;
unsigned long tmp_rate;
int shift;
int i;
for (i = 0; i < __clk_get_num_parents(hw->clk); i++) {
parent = clk_get_parent_by_index(hw->clk, i);
for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
parent = clk_hw_get_parent_by_index(hw, i);
if (!parent)
continue;
parent_rate = __clk_get_rate(parent);
parent_rate = clk_hw_get_rate(parent);
for (shift = 0; shift < PROG_PRES_MASK; shift++) {
tmp_rate = parent_rate >> shift;
if (tmp_rate <= rate)
if (tmp_rate <= req->rate)
break;
}
if (tmp_rate > rate)
if (tmp_rate > req->rate)
continue;
if (best_rate < 0 || (rate - tmp_rate) < (rate - best_rate)) {
if (best_rate < 0 ||
(req->rate - tmp_rate) < (req->rate - best_rate)) {
best_rate = tmp_rate;
*best_parent_rate = parent_rate;
*best_parent_hw = __clk_get_hw(parent);
req->best_parent_rate = parent_rate;
req->best_parent_hw = parent;
}
if (!best_rate)
break;
}
return best_rate;
if (best_rate < 0)
return best_rate;
req->rate = best_rate;
return 0;
}
static int clk_programmable_set_parent(struct clk_hw *hw, u8 index)
......@@ -230,7 +231,6 @@ of_at91_clk_prog_setup(struct device_node *np, struct at91_pmc *pmc,
{
int num;
u32 id;
int i;
struct clk *clk;
int num_parents;
const char *parent_names[PROG_SOURCE_MAX];
......@@ -241,11 +241,7 @@ of_at91_clk_prog_setup(struct device_node *np, struct at91_pmc *pmc,
if (num_parents <= 0 || num_parents > PROG_SOURCE_MAX)
return;
for (i = 0; i < num_parents; ++i) {
parent_names[i] = of_clk_get_parent_name(np, i);
if (!parent_names[i])
return;
}
of_clk_parent_fill(np, parent_names, num_parents);
num = of_get_child_count(np);
if (!num || num > (PROG_ID_MAX + 1))
......
......@@ -10,8 +10,10 @@
*
*/
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/clkdev.h>
#include <linux/slab.h>
#include <linux/clk/at91_pmc.h>
#include <linux/delay.h>
#include <linux/of.h>
......@@ -371,17 +373,12 @@ void __init of_at91sam9x5_clk_slow_setup(struct device_node *np,
const char *parent_names[2];
int num_parents;
const char *name = np->name;
int i;
num_parents = of_clk_get_parent_count(np);
if (num_parents <= 0 || num_parents > 2)
return;
for (i = 0; i < num_parents; ++i) {
parent_names[i] = of_clk_get_parent_name(np, i);
if (!parent_names[i])
return;
}
of_clk_parent_fill(np, parent_names, num_parents);
of_property_read_string(np, "clock-output-names", &name);
......@@ -449,17 +446,12 @@ void __init of_at91sam9260_clk_slow_setup(struct device_node *np,
const char *parent_names[2];
int num_parents;
const char *name = np->name;
int i;
num_parents = of_clk_get_parent_count(np);
if (num_parents != 2)
return;
for (i = 0; i < num_parents; ++i) {
parent_names[i] = of_clk_get_parent_name(np, i);
if (!parent_names[i])
return;
}
of_clk_parent_fill(np, parent_names, num_parents);
of_property_read_string(np, "clock-output-names", &name);
......
......@@ -145,7 +145,6 @@ void __init of_at91sam9x5_clk_smd_setup(struct device_node *np,
struct at91_pmc *pmc)
{
struct clk *clk;
int i;
int num_parents;
const char *parent_names[SMD_SOURCE_MAX];
const char *name = np->name;
......@@ -154,11 +153,7 @@ void __init of_at91sam9x5_clk_smd_setup(struct device_node *np,
if (num_parents <= 0 || num_parents > SMD_SOURCE_MAX)
return;
for (i = 0; i < num_parents; i++) {
parent_names[i] = of_clk_get_parent_name(np, i);
if (!parent_names[i])
return;
}
of_clk_parent_fill(np, parent_names, num_parents);
of_property_read_string(np, "clock-output-names", &name);
......
......@@ -56,47 +56,43 @@ static unsigned long at91sam9x5_clk_usb_recalc_rate(struct clk_hw *hw,
return DIV_ROUND_CLOSEST(parent_rate, (usbdiv + 1));
}
static long at91sam9x5_clk_usb_determine_rate(struct clk_hw *hw,
unsigned long rate,
unsigned long min_rate,
unsigned long max_rate,
unsigned long *best_parent_rate,
struct clk_hw **best_parent_hw)
static int at91sam9x5_clk_usb_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct clk *parent = NULL;
struct clk_hw *parent;
long best_rate = -EINVAL;
unsigned long tmp_rate;
int best_diff = -1;
int tmp_diff;
int i;
for (i = 0; i < __clk_get_num_parents(hw->clk); i++) {
for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
int div;
parent = clk_get_parent_by_index(hw->clk, i);
parent = clk_hw_get_parent_by_index(hw, i);
if (!parent)
continue;
for (div = 1; div < SAM9X5_USB_MAX_DIV + 2; div++) {
unsigned long tmp_parent_rate;
tmp_parent_rate = rate * div;
tmp_parent_rate = __clk_round_rate(parent,
tmp_parent_rate = req->rate * div;
tmp_parent_rate = clk_hw_round_rate(parent,
tmp_parent_rate);
tmp_rate = DIV_ROUND_CLOSEST(tmp_parent_rate, div);
if (tmp_rate < rate)
tmp_diff = rate - tmp_rate;
if (tmp_rate < req->rate)
tmp_diff = req->rate - tmp_rate;
else
tmp_diff = tmp_rate - rate;
tmp_diff = tmp_rate - req->rate;
if (best_diff < 0 || best_diff > tmp_diff) {
best_rate = tmp_rate;
best_diff = tmp_diff;
*best_parent_rate = tmp_parent_rate;
*best_parent_hw = __clk_get_hw(parent);
req->best_parent_rate = tmp_parent_rate;
req->best_parent_hw = parent;
}
if (!best_diff || tmp_rate < rate)
if (!best_diff || tmp_rate < req->rate)
break;
}
......@@ -104,7 +100,11 @@ static long at91sam9x5_clk_usb_determine_rate(struct clk_hw *hw,
break;
}
return best_rate;
if (best_rate < 0)
return best_rate;
req->rate = best_rate;
return 0;
}
static int at91sam9x5_clk_usb_set_parent(struct clk_hw *hw, u8 index)
......@@ -273,7 +273,7 @@ static long at91rm9200_clk_usb_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
struct at91rm9200_clk_usb *usb = to_at91rm9200_clk_usb(hw);
struct clk *parent = __clk_get_parent(hw->clk);
struct clk_hw *parent = clk_hw_get_parent(hw);
unsigned long bestrate = 0;
int bestdiff = -1;
unsigned long tmprate;
......@@ -287,7 +287,7 @@ static long at91rm9200_clk_usb_round_rate(struct clk_hw *hw, unsigned long rate,
continue;
tmp_parent_rate = rate * usb->divisors[i];
tmp_parent_rate = __clk_round_rate(parent, tmp_parent_rate);
tmp_parent_rate = clk_hw_round_rate(parent, tmp_parent_rate);
tmprate = DIV_ROUND_CLOSEST(tmp_parent_rate, usb->divisors[i]);
if (tmprate < rate)
tmpdiff = rate - tmprate;
......@@ -373,7 +373,6 @@ void __init of_at91sam9x5_clk_usb_setup(struct device_node *np,
struct at91_pmc *pmc)
{
struct clk *clk;
int i;
int num_parents;
const char *parent_names[USB_SOURCE_MAX];
const char *name = np->name;
......@@ -382,11 +381,7 @@ void __init of_at91sam9x5_clk_usb_setup(struct device_node *np,
if (num_parents <= 0 || num_parents > USB_SOURCE_MAX)
return;
for (i = 0; i < num_parents; i++) {
parent_names[i] = of_clk_get_parent_name(np, i);
if (!parent_names[i])
return;
}
of_clk_parent_fill(np, parent_names, num_parents);
of_property_read_string(np, "clock-output-names", &name);
......
......@@ -125,7 +125,6 @@ static int pmc_irq_map(struct irq_domain *h, unsigned int virq,
irq_set_chip_and_handler(virq, &pmc_irq,
handle_level_irq);
set_irq_flags(virq, IRQF_VALID);
irq_set_chip_data(virq, pmc);
return 0;
......
......@@ -59,71 +59,63 @@ static inline void pmc_write(struct at91_pmc *pmc, int offset, u32 value)
int of_at91_get_clk_range(struct device_node *np, const char *propname,
struct clk_range *range);
extern void __init of_at91sam9260_clk_slow_setup(struct device_node *np,
struct at91_pmc *pmc);
extern void __init of_at91rm9200_clk_main_osc_setup(struct device_node *np,
struct at91_pmc *pmc);
extern void __init of_at91sam9x5_clk_main_rc_osc_setup(struct device_node *np,
struct at91_pmc *pmc);
extern void __init of_at91rm9200_clk_main_setup(struct device_node *np,
struct at91_pmc *pmc);
extern void __init of_at91sam9x5_clk_main_setup(struct device_node *np,
struct at91_pmc *pmc);
extern void __init of_at91rm9200_clk_pll_setup(struct device_node *np,
struct at91_pmc *pmc);
extern void __init of_at91sam9g45_clk_pll_setup(struct device_node *np,
struct at91_pmc *pmc);
extern void __init of_at91sam9g20_clk_pllb_setup(struct device_node *np,
struct at91_pmc *pmc);
extern void __init of_sama5d3_clk_pll_setup(struct device_node *np,
struct at91_pmc *pmc);
extern void __init of_at91sam9x5_clk_plldiv_setup(struct device_node *np,
struct at91_pmc *pmc);
extern void __init of_at91rm9200_clk_master_setup(struct device_node *np,
struct at91_pmc *pmc);
extern void __init of_at91sam9x5_clk_master_setup(struct device_node *np,
struct at91_pmc *pmc);
extern void __init of_at91rm9200_clk_sys_setup(struct device_node *np,
struct at91_pmc *pmc);
extern void __init of_at91rm9200_clk_periph_setup(struct device_node *np,
struct at91_pmc *pmc);
extern void __init of_at91sam9x5_clk_periph_setup(struct device_node *np,
struct at91_pmc *pmc);
extern void __init of_at91rm9200_clk_prog_setup(struct device_node *np,
struct at91_pmc *pmc);
extern void __init of_at91sam9g45_clk_prog_setup(struct device_node *np,
struct at91_pmc *pmc);
extern void __init of_at91sam9x5_clk_prog_setup(struct device_node *np,
struct at91_pmc *pmc);
#if defined(CONFIG_HAVE_AT91_UTMI)
extern void __init of_at91sam9x5_clk_utmi_setup(struct device_node *np,
struct at91_pmc *pmc);
#endif
#if defined(CONFIG_HAVE_AT91_USB_CLK)
extern void __init of_at91rm9200_clk_usb_setup(struct device_node *np,
struct at91_pmc *pmc);
extern void __init of_at91sam9x5_clk_usb_setup(struct device_node *np,
struct at91_pmc *pmc);
extern void __init of_at91sam9n12_clk_usb_setup(struct device_node *np,
struct at91_pmc *pmc);
#endif
#if defined(CONFIG_HAVE_AT91_SMD)
extern void __init of_at91sam9x5_clk_smd_setup(struct device_node *np,
struct at91_pmc *pmc);
#endif
#if defined(CONFIG_HAVE_AT91_H32MX)
extern void __init of_sama5d4_clk_h32mx_setup(struct device_node *np,
struct at91_pmc *pmc);
#endif
void of_at91sam9260_clk_slow_setup(struct device_node *np,
struct at91_pmc *pmc);
void of_at91rm9200_clk_main_osc_setup(struct device_node *np,
struct at91_pmc *pmc);
void of_at91sam9x5_clk_main_rc_osc_setup(struct device_node *np,
struct at91_pmc *pmc);
void of_at91rm9200_clk_main_setup(struct device_node *np,
struct at91_pmc *pmc);
void of_at91sam9x5_clk_main_setup(struct device_node *np,
struct at91_pmc *pmc);
void of_at91rm9200_clk_pll_setup(struct device_node *np,
struct at91_pmc *pmc);
void of_at91sam9g45_clk_pll_setup(struct device_node *np,
struct at91_pmc *pmc);
void of_at91sam9g20_clk_pllb_setup(struct device_node *np,
struct at91_pmc *pmc);
void of_sama5d3_clk_pll_setup(struct device_node *np,
struct at91_pmc *pmc);
void of_at91sam9x5_clk_plldiv_setup(struct device_node *np,
struct at91_pmc *pmc);
void of_at91rm9200_clk_master_setup(struct device_node *np,
struct at91_pmc *pmc);
void of_at91sam9x5_clk_master_setup(struct device_node *np,
struct at91_pmc *pmc);
void of_at91rm9200_clk_sys_setup(struct device_node *np,
struct at91_pmc *pmc);
void of_at91rm9200_clk_periph_setup(struct device_node *np,
struct at91_pmc *pmc);
void of_at91sam9x5_clk_periph_setup(struct device_node *np,
struct at91_pmc *pmc);
void of_at91rm9200_clk_prog_setup(struct device_node *np,
struct at91_pmc *pmc);
void of_at91sam9g45_clk_prog_setup(struct device_node *np,
struct at91_pmc *pmc);
void of_at91sam9x5_clk_prog_setup(struct device_node *np,
struct at91_pmc *pmc);
void of_at91sam9x5_clk_utmi_setup(struct device_node *np,
struct at91_pmc *pmc);
void of_at91rm9200_clk_usb_setup(struct device_node *np,
struct at91_pmc *pmc);
void of_at91sam9x5_clk_usb_setup(struct device_node *np,
struct at91_pmc *pmc);
void of_at91sam9n12_clk_usb_setup(struct device_node *np,
struct at91_pmc *pmc);
void of_at91sam9x5_clk_smd_setup(struct device_node *np,
struct at91_pmc *pmc);
void of_sama5d4_clk_h32mx_setup(struct device_node *np,
struct at91_pmc *pmc);
#endif /* __PMC_H_ */
......@@ -16,6 +16,7 @@
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/clk.h>
/*
* "Policies" affect the frequencies of bus clocks provided by a
......@@ -1010,25 +1011,23 @@ static long kona_peri_clk_round_rate(struct clk_hw *hw, unsigned long rate,
struct bcm_clk_div *div = &bcm_clk->u.peri->div;
if (!divider_exists(div))
return __clk_get_rate(hw->clk);
return clk_hw_get_rate(hw);
/* Quietly avoid a zero rate */
return round_rate(bcm_clk->ccu, div, &bcm_clk->u.peri->pre_div,
rate ? rate : 1, *parent_rate, NULL);
}
static long kona_peri_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
unsigned long min_rate,
unsigned long max_rate,
unsigned long *best_parent_rate, struct clk_hw **best_parent)
static int kona_peri_clk_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct kona_clk *bcm_clk = to_kona_clk(hw);
struct clk *clk = hw->clk;
struct clk *current_parent;
struct clk_hw *current_parent;
unsigned long parent_rate;
unsigned long best_delta;
unsigned long best_rate;
u32 parent_count;
long rate;
u32 which;
/*
......@@ -1037,18 +1036,25 @@ static long kona_peri_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
*/
WARN_ON_ONCE(bcm_clk->init_data.flags & CLK_SET_RATE_NO_REPARENT);
parent_count = (u32)bcm_clk->init_data.num_parents;
if (parent_count < 2)
return kona_peri_clk_round_rate(hw, rate, best_parent_rate);
if (parent_count < 2) {
rate = kona_peri_clk_round_rate(hw, req->rate,
&req->best_parent_rate);
if (rate < 0)
return rate;
req->rate = rate;
return 0;
}
/* Unless we can do better, stick with current parent */
current_parent = clk_get_parent(clk);
parent_rate = __clk_get_rate(current_parent);
best_rate = kona_peri_clk_round_rate(hw, rate, &parent_rate);
best_delta = abs(best_rate - rate);
current_parent = clk_hw_get_parent(hw);
parent_rate = clk_hw_get_rate(current_parent);
best_rate = kona_peri_clk_round_rate(hw, req->rate, &parent_rate);
best_delta = abs(best_rate - req->rate);
/* Check whether any other parent clock can produce a better result */
for (which = 0; which < parent_count; which++) {
struct clk *parent = clk_get_parent_by_index(clk, which);
struct clk_hw *parent = clk_hw_get_parent_by_index(hw, which);
unsigned long delta;
unsigned long other_rate;
......@@ -1057,18 +1063,20 @@ static long kona_peri_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
continue;
/* We don't support CLK_SET_RATE_PARENT */
parent_rate = __clk_get_rate(parent);
other_rate = kona_peri_clk_round_rate(hw, rate, &parent_rate);
delta = abs(other_rate - rate);
parent_rate = clk_hw_get_rate(parent);
other_rate = kona_peri_clk_round_rate(hw, req->rate,
&parent_rate);
delta = abs(other_rate - req->rate);
if (delta < best_delta) {
best_delta = delta;
best_rate = other_rate;
*best_parent = __clk_get_hw(parent);
*best_parent_rate = parent_rate;
req->best_parent_hw = parent;
req->best_parent_rate = parent_rate;
}
}
return best_rate;
req->rate = best_rate;
return 0;
}
static int kona_peri_clk_set_parent(struct clk_hw *hw, u8 index)
......@@ -1130,7 +1138,7 @@ static int kona_peri_clk_set_rate(struct clk_hw *hw, unsigned long rate,
if (parent_rate > (unsigned long)LONG_MAX)
return -EINVAL;
if (rate == __clk_get_rate(hw->clk))
if (rate == clk_hw_get_rate(hw))
return 0;
if (!divider_exists(div))
......@@ -1249,6 +1257,7 @@ bool __init kona_ccu_init(struct ccu_data *ccu)
unsigned long flags;
unsigned int which;
struct clk **clks = ccu->clk_data.clks;
struct kona_clk *kona_clks = ccu->kona_clks;
bool success = true;
flags = ccu_lock(ccu);
......@@ -1259,7 +1268,7 @@ bool __init kona_ccu_init(struct ccu_data *ccu)
if (!clks[which])
continue;
bcm_clk = to_kona_clk(__clk_get_hw(clks[which]));
bcm_clk = &kona_clks[which];
success &= __kona_clk_init(bcm_clk);
}
......
......@@ -61,7 +61,7 @@ berlin2_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
fbdiv = (val >> map->fbdiv_shift) & FBDIV_MASK;
rfdiv = (val >> map->rfdiv_shift) & RFDIV_MASK;
if (rfdiv == 0) {
pr_warn("%s has zero rfdiv\n", __clk_get_name(hw->clk));
pr_warn("%s has zero rfdiv\n", clk_hw_get_name(hw));
rfdiv = 1;
}
......@@ -70,7 +70,7 @@ berlin2_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
vcodiv = map->vcodiv[vcodivsel];
if (vcodiv == 0) {
pr_warn("%s has zero vcodiv (index %d)\n",
__clk_get_name(hw->clk), vcodivsel);
clk_hw_get_name(hw), vcodivsel);
vcodiv = 1;
}
......
......@@ -10,7 +10,6 @@
#include <linux/platform_device.h>
#include <linux/clk-provider.h>
#include <linux/clk.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/of.h>
......
......@@ -32,11 +32,6 @@ void __init bcm2835_init_clocks(void)
struct clk *clk;
int ret;
clk = clk_register_fixed_rate(NULL, "sys_pclk", NULL, CLK_IS_ROOT,
250000000);
if (IS_ERR(clk))
pr_err("sys_pclk not registered\n");
clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, CLK_IS_ROOT,
126000000);
if (IS_ERR(clk))
......
......@@ -10,6 +10,7 @@
* published by the Free Software Foundation.
*/
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/delay.h>
#include <linux/i2c.h>
......@@ -309,7 +310,7 @@ static long cdce706_divider_round_rate(struct clk_hw *hw, unsigned long rate,
if (!mul)
div = CDCE706_DIVIDER_DIVIDER_MAX;
if (__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT) {
if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
unsigned long best_diff = rate;
unsigned long best_div = 0;
struct clk *gp_clk = cdce->clkin_clk[cdce->clkin[0].parent];
......
......@@ -10,6 +10,7 @@
* Copyright (C) 2014, Topic Embedded Products
* Licenced under GPL
*/
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/delay.h>
#include <linux/module.h>
......
......@@ -9,7 +9,6 @@
* (at your option) any later version.
*/
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/clkdev.h>
#include <linux/io.h>
......
......@@ -55,78 +55,77 @@ static unsigned long clk_composite_recalc_rate(struct clk_hw *hw,
return rate_ops->recalc_rate(rate_hw, parent_rate);
}
static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate,
unsigned long min_rate,
unsigned long max_rate,
unsigned long *best_parent_rate,
struct clk_hw **best_parent_p)
static int clk_composite_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct clk_composite *composite = to_clk_composite(hw);
const struct clk_ops *rate_ops = composite->rate_ops;
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;
struct clk_hw *parent;
unsigned long parent_rate;
long tmp_rate, best_rate = 0;
unsigned long rate_diff;
unsigned long best_rate_diff = ULONG_MAX;
long rate;
int i;
if (rate_hw && rate_ops && rate_ops->determine_rate) {
__clk_hw_set_clk(rate_hw, hw);
return rate_ops->determine_rate(rate_hw, rate, min_rate,
max_rate,
best_parent_rate,
best_parent_p);
return rate_ops->determine_rate(rate_hw, req);
} else if (rate_hw && rate_ops && rate_ops->round_rate &&
mux_hw && mux_ops && mux_ops->set_parent) {
*best_parent_p = NULL;
req->best_parent_hw = NULL;
if (__clk_get_flags(hw->clk) & CLK_SET_RATE_NO_REPARENT) {
parent = clk_get_parent(mux_hw->clk);
*best_parent_p = __clk_get_hw(parent);
*best_parent_rate = __clk_get_rate(parent);
if (clk_hw_get_flags(hw) & CLK_SET_RATE_NO_REPARENT) {
parent = clk_hw_get_parent(mux_hw);
req->best_parent_hw = parent;
req->best_parent_rate = clk_hw_get_rate(parent);
return rate_ops->round_rate(rate_hw, rate,
best_parent_rate);
rate = rate_ops->round_rate(rate_hw, req->rate,
&req->best_parent_rate);
if (rate < 0)
return rate;
req->rate = rate;
return 0;
}
for (i = 0; i < __clk_get_num_parents(mux_hw->clk); i++) {
parent = clk_get_parent_by_index(mux_hw->clk, i);
for (i = 0; i < clk_hw_get_num_parents(mux_hw); i++) {
parent = clk_hw_get_parent_by_index(mux_hw, i);
if (!parent)
continue;
parent_rate = __clk_get_rate(parent);
parent_rate = clk_hw_get_rate(parent);
tmp_rate = rate_ops->round_rate(rate_hw, rate,
tmp_rate = rate_ops->round_rate(rate_hw, req->rate,
&parent_rate);
if (tmp_rate < 0)
continue;
rate_diff = abs(rate - tmp_rate);
rate_diff = abs(req->rate - tmp_rate);
if (!rate_diff || !*best_parent_p
if (!rate_diff || !req->best_parent_hw
|| best_rate_diff > rate_diff) {
*best_parent_p = __clk_get_hw(parent);
*best_parent_rate = parent_rate;
req->best_parent_hw = parent;
req->best_parent_rate = parent_rate;
best_rate_diff = rate_diff;
best_rate = tmp_rate;
}
if (!rate_diff)
return rate;
return 0;
}
return best_rate;
req->rate = best_rate;
return 0;
} else if (mux_hw && mux_ops && mux_ops->determine_rate) {
__clk_hw_set_clk(mux_hw, hw);
return mux_ops->determine_rate(mux_hw, rate, min_rate,
max_rate, best_parent_rate,
best_parent_p);
return mux_ops->determine_rate(mux_hw, req);
} else {
pr_err("clk: clk_composite_determine_rate function called, but no mux or rate callback set!\n");
return 0;
return -EINVAL;
}
}
......
......@@ -78,12 +78,14 @@ static unsigned int _get_table_div(const struct clk_div_table *table,
}
static unsigned int _get_div(const struct clk_div_table *table,
unsigned int val, unsigned long flags)
unsigned int val, unsigned long flags, u8 width)
{
if (flags & CLK_DIVIDER_ONE_BASED)
return val;
if (flags & CLK_DIVIDER_POWER_OF_TWO)
return 1 << val;
if (flags & CLK_DIVIDER_MAX_AT_ZERO)
return val ? val : div_mask(width) + 1;
if (table)
return _get_table_div(table, val);
return val + 1;
......@@ -101,12 +103,14 @@ static unsigned int _get_table_val(const struct clk_div_table *table,
}
static unsigned int _get_val(const struct clk_div_table *table,
unsigned int div, unsigned long flags)
unsigned int div, unsigned long flags, u8 width)
{
if (flags & CLK_DIVIDER_ONE_BASED)
return div;
if (flags & CLK_DIVIDER_POWER_OF_TWO)
return __ffs(div);
if (flags & CLK_DIVIDER_MAX_AT_ZERO)
return (div == div_mask(width) + 1) ? 0 : div;
if (table)
return _get_table_val(table, div);
return div - 1;
......@@ -117,13 +121,14 @@ unsigned long divider_recalc_rate(struct clk_hw *hw, unsigned long parent_rate,
const struct clk_div_table *table,
unsigned long flags)
{
struct clk_divider *divider = to_clk_divider(hw);
unsigned int div;
div = _get_div(table, val, flags);
div = _get_div(table, val, flags, divider->width);
if (!div) {
WARN(!(flags & CLK_DIVIDER_ALLOW_ZERO),
"%s: Zero divisor and CLK_DIVIDER_ALLOW_ZERO not set\n",
__clk_get_name(hw->clk));
clk_hw_get_name(hw));
return parent_rate;
}
......@@ -285,7 +290,7 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
maxdiv = _get_maxdiv(table, width, flags);
if (!(__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT)) {
if (!(clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)) {
parent_rate = *best_parent_rate;
bestdiv = _div_round(table, parent_rate, rate, flags);
bestdiv = bestdiv == 0 ? 1 : bestdiv;
......@@ -311,7 +316,7 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
*best_parent_rate = parent_rate_saved;
return i;
}
parent_rate = __clk_round_rate(__clk_get_parent(hw->clk),
parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw),
rate * i);
now = DIV_ROUND_UP(parent_rate, i);
if (_is_best_div(rate, now, best, flags)) {
......@@ -323,7 +328,7 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
if (!bestdiv) {
bestdiv = _get_maxdiv(table, width, flags);
*best_parent_rate = __clk_round_rate(__clk_get_parent(hw->clk), 1);
*best_parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw), 1);
}
return bestdiv;
......@@ -351,7 +356,8 @@ static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
if (divider->flags & CLK_DIVIDER_READ_ONLY) {
bestdiv = readl(divider->reg) >> divider->shift;
bestdiv &= div_mask(divider->width);
bestdiv = _get_div(divider->table, bestdiv, divider->flags);
bestdiv = _get_div(divider->table, bestdiv, divider->flags,
divider->width);
return DIV_ROUND_UP(*prate, bestdiv);
}
......@@ -370,7 +376,7 @@ int divider_get_val(unsigned long rate, unsigned long parent_rate,
if (!_is_valid_div(table, div, flags))
return -EINVAL;
value = _get_val(table, div, flags);
value = _get_val(table, div, flags, width);
return min_t(unsigned int, value, div_mask(width));
}
......@@ -389,6 +395,8 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
if (divider->lock)
spin_lock_irqsave(divider->lock, flags);
else
__acquire(divider->lock);
if (divider->flags & CLK_DIVIDER_HIWORD_MASK) {
val = div_mask(divider->width) << (divider->shift + 16);
......@@ -401,6 +409,8 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
if (divider->lock)
spin_unlock_irqrestore(divider->lock, flags);
else
__release(divider->lock);
return 0;
}
......
......@@ -6,7 +6,6 @@
* the terms of the GNU General Public License version 2 as published by the
* Free Software Foundation.
*/
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/clk-provider.h>
#include <linux/of.h>
......
......@@ -41,12 +41,11 @@ static long clk_factor_round_rate(struct clk_hw *hw, unsigned long rate,
{
struct clk_fixed_factor *fix = to_clk_fixed_factor(hw);
if (__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT) {
if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
unsigned long best_parent;
best_parent = (rate / fix->mult) * fix->div;
*prate = __clk_round_rate(__clk_get_parent(hw->clk),
best_parent);
*prate = clk_hw_round_rate(clk_hw_get_parent(hw), best_parent);
}
return (*prate / fix->div) * fix->mult;
......
......@@ -27,11 +27,15 @@ static unsigned long clk_fd_recalc_rate(struct clk_hw *hw,
if (fd->lock)
spin_lock_irqsave(fd->lock, flags);
else
__acquire(fd->lock);
val = clk_readl(fd->reg);
if (fd->lock)
spin_unlock_irqrestore(fd->lock, flags);
else
__release(fd->lock);
m = (val & fd->mmask) >> fd->mshift;
n = (val & fd->nmask) >> fd->nshift;
......@@ -80,6 +84,8 @@ static int clk_fd_set_rate(struct clk_hw *hw, unsigned long rate,
if (fd->lock)
spin_lock_irqsave(fd->lock, flags);
else
__acquire(fd->lock);
val = clk_readl(fd->reg);
val &= ~(fd->mmask | fd->nmask);
......@@ -88,6 +94,8 @@ static int clk_fd_set_rate(struct clk_hw *hw, unsigned long rate,
if (fd->lock)
spin_unlock_irqrestore(fd->lock, flags);
else
__release(fd->lock);
return 0;
}
......
......@@ -52,6 +52,8 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
if (gate->lock)
spin_lock_irqsave(gate->lock, flags);
else
__acquire(gate->lock);
if (gate->flags & CLK_GATE_HIWORD_MASK) {
reg = BIT(gate->bit_idx + 16);
......@@ -70,6 +72,8 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
if (gate->lock)
spin_unlock_irqrestore(gate->lock, flags);
else
__release(gate->lock);
}
static int clk_gate_enable(struct clk_hw *hw)
......
/*
* Copyright (C) 2013 - 2014 Texas Instruments Incorporated - http://www.ti.com
* Author: Jyri Sarha <jsarha@ti.com>
*
* Authors:
* Jyri Sarha <jsarha@ti.com>
* Sergej Sawazki <ce3a@gmx.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Gpio gated clock implementation
* Gpio controlled clock implementation
*/
#include <linux/clk-provider.h>
#include <linux/module.h>
#include <linux/export.h>
#include <linux/slab.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
......@@ -61,24 +64,55 @@ const struct clk_ops clk_gpio_gate_ops = {
EXPORT_SYMBOL_GPL(clk_gpio_gate_ops);
/**
* clk_register_gpio - register a gpip clock with the clock framework
* @dev: device that is registering this clock
* @name: name of this clock
* @parent_name: name of this clock's parent
* @gpio: gpio number to gate this clock
* @active_low: true if gpio should be set to 0 to enable clock
* @flags: clock flags
* DOC: basic clock multiplexer which can be controlled with a gpio output
* Traits of this clock:
* prepare - clk_prepare only ensures that parents are prepared
* rate - rate is only affected by parent switching. No clk_set_rate support
* parent - parent is adjustable through clk_set_parent
*/
struct clk *clk_register_gpio_gate(struct device *dev, const char *name,
const char *parent_name, unsigned gpio, bool active_low,
unsigned long flags)
static u8 clk_gpio_mux_get_parent(struct clk_hw *hw)
{
struct clk_gpio *clk = to_clk_gpio(hw);
return gpiod_get_value(clk->gpiod);
}
static int clk_gpio_mux_set_parent(struct clk_hw *hw, u8 index)
{
struct clk_gpio *clk = to_clk_gpio(hw);
gpiod_set_value(clk->gpiod, index);
return 0;
}
const struct clk_ops clk_gpio_mux_ops = {
.get_parent = clk_gpio_mux_get_parent,
.set_parent = clk_gpio_mux_set_parent,
.determine_rate = __clk_mux_determine_rate,
};
EXPORT_SYMBOL_GPL(clk_gpio_mux_ops);
static struct clk *clk_register_gpio(struct device *dev, const char *name,
const char * const *parent_names, u8 num_parents, unsigned gpio,
bool active_low, unsigned long flags,
const struct clk_ops *clk_gpio_ops)
{
struct clk_gpio *clk_gpio = NULL;
struct clk *clk = ERR_PTR(-EINVAL);
struct clk_init_data init = { NULL };
struct clk_gpio *clk_gpio;
struct clk *clk;
struct clk_init_data init = {};
unsigned long gpio_flags;
int err;
if (dev)
clk_gpio = devm_kzalloc(dev, sizeof(*clk_gpio), GFP_KERNEL);
else
clk_gpio = kzalloc(sizeof(*clk_gpio), GFP_KERNEL);
if (!clk_gpio)
return ERR_PTR(-ENOMEM);
if (active_low)
gpio_flags = GPIOF_ACTIVE_LOW | GPIOF_OUT_INIT_HIGH;
else
......@@ -88,69 +122,108 @@ struct clk *clk_register_gpio_gate(struct device *dev, const char *name,
err = devm_gpio_request_one(dev, gpio, gpio_flags, name);
else
err = gpio_request_one(gpio, gpio_flags, name);
if (err) {
pr_err("%s: %s: Error requesting clock control gpio %u\n",
__func__, name, gpio);
return ERR_PTR(err);
}
if (err != -EPROBE_DEFER)
pr_err("%s: %s: Error requesting clock control gpio %u\n",
__func__, name, gpio);
if (!dev)
kfree(clk_gpio);
if (dev)
clk_gpio = devm_kzalloc(dev, sizeof(struct clk_gpio),
GFP_KERNEL);
else
clk_gpio = kzalloc(sizeof(struct clk_gpio), GFP_KERNEL);
if (!clk_gpio) {
clk = ERR_PTR(-ENOMEM);
goto clk_register_gpio_gate_err;
return ERR_PTR(err);
}
init.name = name;
init.ops = &clk_gpio_gate_ops;
init.ops = clk_gpio_ops;
init.flags = flags | CLK_IS_BASIC;
init.parent_names = (parent_name ? &parent_name : NULL);
init.num_parents = (parent_name ? 1 : 0);
init.parent_names = parent_names;
init.num_parents = num_parents;
clk_gpio->gpiod = gpio_to_desc(gpio);
clk_gpio->hw.init = &init;
clk = clk_register(dev, &clk_gpio->hw);
if (dev)
clk = devm_clk_register(dev, &clk_gpio->hw);
else
clk = clk_register(NULL, &clk_gpio->hw);
if (!IS_ERR(clk))
return clk;
if (!dev)
if (!dev) {
gpiod_put(clk_gpio->gpiod);
kfree(clk_gpio);
clk_register_gpio_gate_err:
if (!dev)
gpio_free(gpio);
}
return clk;
}
/**
* clk_register_gpio_gate - register a gpio clock gate with the clock framework
* @dev: device that is registering this clock
* @name: name of this clock
* @parent_name: name of this clock's parent
* @gpio: gpio number to gate this clock
* @active_low: true if gpio should be set to 0 to enable clock
* @flags: clock flags
*/
struct clk *clk_register_gpio_gate(struct device *dev, const char *name,
const char *parent_name, unsigned gpio, bool active_low,
unsigned long flags)
{
return clk_register_gpio(dev, name,
(parent_name ? &parent_name : NULL),
(parent_name ? 1 : 0), gpio, active_low, flags,
&clk_gpio_gate_ops);
}
EXPORT_SYMBOL_GPL(clk_register_gpio_gate);
/**
* clk_register_gpio_mux - register a gpio clock mux with the clock framework
* @dev: device that is registering this clock
* @name: name of this clock
* @parent_names: names of this clock's parents
* @num_parents: number of parents listed in @parent_names
* @gpio: gpio number to gate this clock
* @active_low: true if gpio should be set to 0 to enable clock
* @flags: clock flags
*/
struct clk *clk_register_gpio_mux(struct device *dev, const char *name,
const char * const *parent_names, u8 num_parents, unsigned gpio,
bool active_low, unsigned long flags)
{
if (num_parents != 2) {
pr_err("mux-clock %s must have 2 parents\n", name);
return ERR_PTR(-EINVAL);
}
return clk_register_gpio(dev, name, parent_names, num_parents,
gpio, active_low, flags, &clk_gpio_mux_ops);
}
EXPORT_SYMBOL_GPL(clk_register_gpio_mux);
#ifdef CONFIG_OF
/**
* The clk_register_gpio_gate has to be delayed, because the EPROBE_DEFER
* clk_register_get() has to be delayed, because -EPROBE_DEFER
* can not be handled properly at of_clk_init() call time.
*/
struct clk_gpio_gate_delayed_register_data {
struct clk_gpio_delayed_register_data {
const char *gpio_name;
struct device_node *node;
struct mutex lock;
struct clk *clk;
struct clk *(*clk_register_get)(const char *name,
const char * const *parent_names, u8 num_parents,
unsigned gpio, bool active_low);
};
static struct clk *of_clk_gpio_gate_delayed_register_get(
struct of_phandle_args *clkspec,
void *_data)
static struct clk *of_clk_gpio_delayed_register_get(
struct of_phandle_args *clkspec, void *_data)
{
struct clk_gpio_gate_delayed_register_data *data = _data;
struct clk_gpio_delayed_register_data *data = _data;
struct clk *clk;
const char *clk_name = data->node->name;
const char *parent_name;
const char **parent_names;
int i, num_parents;
int gpio;
enum of_gpio_flags of_flags;
......@@ -161,47 +234,92 @@ static struct clk *of_clk_gpio_gate_delayed_register_get(
return data->clk;
}
gpio = of_get_named_gpio_flags(data->node, "enable-gpios", 0,
&of_flags);
gpio = of_get_named_gpio_flags(data->node, data->gpio_name, 0,
&of_flags);
if (gpio < 0) {
mutex_unlock(&data->lock);
if (gpio != -EPROBE_DEFER)
pr_err("%s: %s: Can't get 'enable-gpios' DT property\n",
__func__, clk_name);
if (gpio == -EPROBE_DEFER)
pr_debug("%s: %s: GPIOs not yet available, retry later\n",
data->node->name, __func__);
else
pr_err("%s: %s: Can't get '%s' DT property\n",
data->node->name, __func__,
data->gpio_name);
return ERR_PTR(gpio);
}
parent_name = of_clk_get_parent_name(data->node, 0);
num_parents = of_clk_get_parent_count(data->node);
clk = clk_register_gpio_gate(NULL, clk_name, parent_name, gpio,
of_flags & OF_GPIO_ACTIVE_LOW, 0);
if (IS_ERR(clk)) {
mutex_unlock(&data->lock);
return clk;
parent_names = kcalloc(num_parents, sizeof(char *), GFP_KERNEL);
if (!parent_names) {
clk = ERR_PTR(-ENOMEM);
goto out;
}
for (i = 0; i < num_parents; i++)
parent_names[i] = of_clk_get_parent_name(data->node, i);
clk = data->clk_register_get(data->node->name, parent_names,
num_parents, gpio, of_flags & OF_GPIO_ACTIVE_LOW);
if (IS_ERR(clk))
goto out;
data->clk = clk;
out:
mutex_unlock(&data->lock);
kfree(parent_names);
return clk;
}
/**
* of_gpio_gate_clk_setup() - Setup function for gpio controlled clock
*/
static void __init of_gpio_gate_clk_setup(struct device_node *node)
static struct clk *of_clk_gpio_gate_delayed_register_get(const char *name,
const char * const *parent_names, u8 num_parents,
unsigned gpio, bool active_low)
{
return clk_register_gpio_gate(NULL, name, parent_names[0],
gpio, active_low, 0);
}
static struct clk *of_clk_gpio_mux_delayed_register_get(const char *name,
const char * const *parent_names, u8 num_parents, unsigned gpio,
bool active_low)
{
return clk_register_gpio_mux(NULL, name, parent_names, num_parents,
gpio, active_low, 0);
}
static void __init of_gpio_clk_setup(struct device_node *node,
const char *gpio_name,
struct clk *(*clk_register_get)(const char *name,
const char * const *parent_names,
u8 num_parents,
unsigned gpio, bool active_low))
{
struct clk_gpio_gate_delayed_register_data *data;
struct clk_gpio_delayed_register_data *data;
data = kzalloc(sizeof(struct clk_gpio_gate_delayed_register_data),
GFP_KERNEL);
data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data)
return;
data->node = node;
data->gpio_name = gpio_name;
data->clk_register_get = clk_register_get;
mutex_init(&data->lock);
of_clk_add_provider(node, of_clk_gpio_gate_delayed_register_get, data);
of_clk_add_provider(node, of_clk_gpio_delayed_register_get, data);
}
static void __init of_gpio_gate_clk_setup(struct device_node *node)
{
of_gpio_clk_setup(node, "enable-gpios",
of_clk_gpio_gate_delayed_register_get);
}
CLK_OF_DECLARE(gpio_gate_clk, "gpio-gate-clock", of_gpio_gate_clk_setup);
void __init of_gpio_mux_clk_setup(struct device_node *node)
{
of_gpio_clk_setup(node, "select-gpios",
of_clk_gpio_mux_delayed_register_get);
}
CLK_OF_DECLARE(gpio_mux_clk, "gpio-mux-clock", of_gpio_mux_clk_setup);
#endif
......@@ -17,6 +17,7 @@
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/io.h>
#include <linux/of.h>
......
......@@ -10,6 +10,7 @@
* warranty of any kind, whether express or implied.
*/
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/io.h>
#include <linux/of_address.h>
......
......@@ -10,7 +10,6 @@
* Simple multiplexer clock implementation
*/
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/module.h>
#include <linux/slab.h>
......@@ -32,7 +31,7 @@
static u8 clk_mux_get_parent(struct clk_hw *hw)
{
struct clk_mux *mux = to_clk_mux(hw);
int num_parents = __clk_get_num_parents(hw->clk);
int num_parents = clk_hw_get_num_parents(hw);
u32 val;
/*
......@@ -85,6 +84,8 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
if (mux->lock)
spin_lock_irqsave(mux->lock, flags);
else
__acquire(mux->lock);
if (mux->flags & CLK_MUX_HIWORD_MASK) {
val = mux->mask << (mux->shift + 16);
......@@ -97,6 +98,8 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
if (mux->lock)
spin_unlock_irqrestore(mux->lock, flags);
else
__release(mux->lock);
return 0;
}
......
......@@ -8,8 +8,7 @@
#define pr_fmt(fmt) "Nomadik SRC clocks: " fmt
#include <linux/bitops.h>
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/clk-provider.h>
......
......@@ -18,7 +18,6 @@
*/
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/clk-provider.h>
#include <linux/mfd/palmas.h>
#include <linux/module.h>
......
......@@ -15,7 +15,6 @@
* more details.
*/
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/module.h>
#include <linux/slab.h>
......
......@@ -58,21 +58,17 @@ static struct s2mps11_clk *to_s2mps11_clk(struct clk_hw *hw)
static int s2mps11_clk_prepare(struct clk_hw *hw)
{
struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw);
int ret;
ret = regmap_update_bits(s2mps11->iodev->regmap_pmic,
return regmap_update_bits(s2mps11->iodev->regmap_pmic,
s2mps11->reg,
s2mps11->mask, s2mps11->mask);
return ret;
}
static void s2mps11_clk_unprepare(struct clk_hw *hw)
{
struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw);
int ret;
ret = regmap_update_bits(s2mps11->iodev->regmap_pmic, s2mps11->reg,
regmap_update_bits(s2mps11->iodev->regmap_pmic, s2mps11->reg,
s2mps11->mask, ~s2mps11->mask);
}
......@@ -186,15 +182,15 @@ static int s2mps11_clk_probe(struct platform_device *pdev)
struct clk_init_data *clks_init;
int i, ret = 0;
s2mps11_clks = devm_kzalloc(&pdev->dev, sizeof(*s2mps11_clk) *
S2MPS11_CLKS_NUM, GFP_KERNEL);
s2mps11_clks = devm_kcalloc(&pdev->dev, S2MPS11_CLKS_NUM,
sizeof(*s2mps11_clk), GFP_KERNEL);
if (!s2mps11_clks)
return -ENOMEM;
s2mps11_clk = s2mps11_clks;
clk_table = devm_kzalloc(&pdev->dev, sizeof(struct clk *) *
S2MPS11_CLKS_NUM, GFP_KERNEL);
clk_table = devm_kcalloc(&pdev->dev, S2MPS11_CLKS_NUM,
sizeof(struct clk *), GFP_KERNEL);
if (!clk_table)
return -ENOMEM;
......@@ -246,7 +242,7 @@ static int s2mps11_clk_probe(struct platform_device *pdev)
s2mps11_name(s2mps11_clk), NULL);
if (!s2mps11_clk->lookup) {
ret = -ENOMEM;
goto err_lup;
goto err_reg;
}
}
......@@ -265,16 +261,10 @@ static int s2mps11_clk_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, s2mps11_clks);
return ret;
err_lup:
devm_clk_unregister(&pdev->dev, s2mps11_clk->clk);
err_reg:
while (s2mps11_clk > s2mps11_clks) {
if (s2mps11_clk->lookup) {
clkdev_drop(s2mps11_clk->lookup);
devm_clk_unregister(&pdev->dev, s2mps11_clk->clk);
}
s2mps11_clk--;
}
while (--i >= 0)
clkdev_drop(s2mps11_clks[i].lookup);
return ret;
}
......@@ -322,7 +312,7 @@ static int __init s2mps11_clk_init(void)
}
subsys_initcall(s2mps11_clk_init);
static void __init s2mps11_clk_cleanup(void)
static void __exit s2mps11_clk_cleanup(void)
{
platform_driver_unregister(&s2mps11_clk_driver);
}
......
......@@ -18,7 +18,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/clkdev.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/delay.h>
#include <linux/err.h>
......@@ -439,7 +439,7 @@ static unsigned long si5351_pll_recalc_rate(struct clk_hw *hw,
dev_dbg(&hwdata->drvdata->client->dev,
"%s - %s: p1 = %lu, p2 = %lu, p3 = %lu, parent_rate = %lu, rate = %lu\n",
__func__, __clk_get_name(hwdata->hw.clk),
__func__, clk_hw_get_name(hw),
hwdata->params.p1, hwdata->params.p2, hwdata->params.p3,
parent_rate, (unsigned long)rate);
......@@ -497,7 +497,7 @@ static long si5351_pll_round_rate(struct clk_hw *hw, unsigned long rate,
dev_dbg(&hwdata->drvdata->client->dev,
"%s - %s: a = %lu, b = %lu, c = %lu, parent_rate = %lu, rate = %lu\n",
__func__, __clk_get_name(hwdata->hw.clk), a, b, c,
__func__, clk_hw_get_name(hw), a, b, c,
*parent_rate, rate);
return rate;
......@@ -521,7 +521,7 @@ static int si5351_pll_set_rate(struct clk_hw *hw, unsigned long rate,
dev_dbg(&hwdata->drvdata->client->dev,
"%s - %s: p1 = %lu, p2 = %lu, p3 = %lu, parent_rate = %lu, rate = %lu\n",
__func__, __clk_get_name(hwdata->hw.clk),
__func__, clk_hw_get_name(hw),
hwdata->params.p1, hwdata->params.p2, hwdata->params.p3,
parent_rate, rate);
......@@ -632,7 +632,7 @@ static unsigned long si5351_msynth_recalc_rate(struct clk_hw *hw,
dev_dbg(&hwdata->drvdata->client->dev,
"%s - %s: p1 = %lu, p2 = %lu, p3 = %lu, m = %lu, parent_rate = %lu, rate = %lu\n",
__func__, __clk_get_name(hwdata->hw.clk),
__func__, clk_hw_get_name(hw),
hwdata->params.p1, hwdata->params.p2, hwdata->params.p3,
m, parent_rate, (unsigned long)rate);
......@@ -663,7 +663,7 @@ static long si5351_msynth_round_rate(struct clk_hw *hw, unsigned long rate,
divby4 = 1;
/* multisync can set pll */
if (__clk_get_flags(hwdata->hw.clk) & CLK_SET_RATE_PARENT) {
if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
/*
* find largest integer divider for max
* vco frequency and given target rate
......@@ -745,7 +745,7 @@ static long si5351_msynth_round_rate(struct clk_hw *hw, unsigned long rate,
dev_dbg(&hwdata->drvdata->client->dev,
"%s - %s: a = %lu, b = %lu, c = %lu, divby4 = %d, parent_rate = %lu, rate = %lu\n",
__func__, __clk_get_name(hwdata->hw.clk), a, b, c, divby4,
__func__, clk_hw_get_name(hw), a, b, c, divby4,
*parent_rate, rate);
return rate;
......@@ -777,7 +777,7 @@ static int si5351_msynth_set_rate(struct clk_hw *hw, unsigned long rate,
dev_dbg(&hwdata->drvdata->client->dev,
"%s - %s: p1 = %lu, p2 = %lu, p3 = %lu, divby4 = %d, parent_rate = %lu, rate = %lu\n",
__func__, __clk_get_name(hwdata->hw.clk),
__func__, clk_hw_get_name(hw),
hwdata->params.p1, hwdata->params.p2, hwdata->params.p3,
divby4, parent_rate, rate);
......@@ -1013,7 +1013,7 @@ static long si5351_clkout_round_rate(struct clk_hw *hw, unsigned long rate,
rate = SI5351_CLKOUT_MIN_FREQ;
/* request frequency if multisync master */
if (__clk_get_flags(hwdata->hw.clk) & CLK_SET_RATE_PARENT) {
if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
/* use r divider for frequencies below 1MHz */
rdiv = SI5351_OUTPUT_CLK_DIV_1;
while (rate < SI5351_MULTISYNTH_MIN_FREQ &&
......@@ -1042,7 +1042,7 @@ static long si5351_clkout_round_rate(struct clk_hw *hw, unsigned long rate,
dev_dbg(&hwdata->drvdata->client->dev,
"%s - %s: rdiv = %u, parent_rate = %lu, rate = %lu\n",
__func__, __clk_get_name(hwdata->hw.clk), (1 << rdiv),
__func__, clk_hw_get_name(hw), (1 << rdiv),
*parent_rate, rate);
return rate;
......@@ -1093,7 +1093,7 @@ static int si5351_clkout_set_rate(struct clk_hw *hw, unsigned long rate,
dev_dbg(&hwdata->drvdata->client->dev,
"%s - %s: rdiv = %u, parent_rate = %lu, rate = %lu\n",
__func__, __clk_get_name(hwdata->hw.clk), (1 << rdiv),
__func__, clk_hw_get_name(hw), (1 << rdiv),
parent_rate, rate);
return 0;
......
......@@ -19,6 +19,7 @@
* GNU General Public License for more details.
*/
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/delay.h>
#include <linux/module.h>
......
......@@ -175,11 +175,10 @@ static long clk_apb_mul_round_rate(struct clk_hw *hw, unsigned long rate,
if (readl(base + STM32F4_RCC_CFGR) & BIT(am->bit_idx))
mult = 2;
if (__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT) {
if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
unsigned long best_parent = rate / mult;
*prate =
__clk_round_rate(__clk_get_parent(hw->clk), best_parent);
*prate = clk_hw_round_rate(clk_hw_get_parent(hw), best_parent);
}
return *prate * mult;
......
......@@ -20,7 +20,6 @@
*
*/
#include <linux/clk.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
......@@ -91,7 +90,7 @@ static int twl6040_clk_probe(struct platform_device *pdev)
clkdata->twl6040 = twl6040;
clkdata->mcpdm_fclk.init = &wm831x_clkout_init;
clkdata->clk = clk_register(&pdev->dev, &clkdata->mcpdm_fclk);
clkdata->clk = devm_clk_register(&pdev->dev, &clkdata->mcpdm_fclk);
if (IS_ERR(clkdata->clk))
return PTR_ERR(clkdata->clk);
......@@ -100,21 +99,11 @@ static int twl6040_clk_probe(struct platform_device *pdev)
return 0;
}
static int twl6040_clk_remove(struct platform_device *pdev)
{
struct twl6040_clk *clkdata = platform_get_drvdata(pdev);
clk_unregister(clkdata->clk);
return 0;
}
static struct platform_driver twl6040_clk_driver = {
.driver = {
.name = "twl6040-clk",
},
.probe = twl6040_clk_probe,
.remove = twl6040_clk_remove,
};
module_platform_driver(twl6040_clk_driver);
......
......@@ -5,8 +5,8 @@
* Author: Linus Walleij <linus.walleij@stericsson.com>
* Author: Jonas Aaberg <jonas.aberg@stericsson.com>
*/
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/clk-provider.h>
......
......@@ -12,7 +12,6 @@
*
*/
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/delay.h>
#include <linux/module.h>
......
......@@ -60,7 +60,6 @@ enum xgene_pll_type {
struct xgene_clk_pll {
struct clk_hw hw;
const char *name;
void __iomem *reg;
spinlock_t *lock;
u32 pll_offset;
......@@ -75,7 +74,7 @@ static int xgene_clk_pll_is_enabled(struct clk_hw *hw)
u32 data;
data = xgene_clk_read(pllclk->reg + pllclk->pll_offset);
pr_debug("%s pll %s\n", pllclk->name,
pr_debug("%s pll %s\n", clk_hw_get_name(hw),
data & REGSPEC_RESET_F1_MASK ? "disabled" : "enabled");
return data & REGSPEC_RESET_F1_MASK ? 0 : 1;
......@@ -113,7 +112,7 @@ static unsigned long xgene_clk_pll_recalc_rate(struct clk_hw *hw,
fref = parent_rate / nref;
fvco = fref * nfb;
}
pr_debug("%s pll recalc rate %ld parent %ld\n", pllclk->name,
pr_debug("%s pll recalc rate %ld parent %ld\n", clk_hw_get_name(hw),
fvco / nout, parent_rate);
return fvco / nout;
......@@ -146,7 +145,6 @@ static struct clk *xgene_register_clk_pll(struct device *dev,
init.parent_names = parent_name ? &parent_name : NULL;
init.num_parents = parent_name ? 1 : 0;
apmclk->name = name;
apmclk->reg = reg;
apmclk->lock = lock;
apmclk->pll_offset = pll_offset;
......@@ -210,7 +208,6 @@ struct xgene_dev_parameters {
struct xgene_clk {
struct clk_hw hw;
const char *name;
spinlock_t *lock;
struct xgene_dev_parameters param;
};
......@@ -228,7 +225,7 @@ static int xgene_clk_enable(struct clk_hw *hw)
spin_lock_irqsave(pclk->lock, flags);
if (pclk->param.csr_reg != NULL) {
pr_debug("%s clock enabled\n", pclk->name);
pr_debug("%s clock enabled\n", clk_hw_get_name(hw));
reg = __pa(pclk->param.csr_reg);
/* First enable the clock */
data = xgene_clk_read(pclk->param.csr_reg +
......@@ -237,7 +234,7 @@ static int xgene_clk_enable(struct clk_hw *hw)
xgene_clk_write(data, pclk->param.csr_reg +
pclk->param.reg_clk_offset);
pr_debug("%s clock PADDR base %pa clk offset 0x%08X mask 0x%08X value 0x%08X\n",
pclk->name, &reg,
clk_hw_get_name(hw), &reg,
pclk->param.reg_clk_offset, pclk->param.reg_clk_mask,
data);
......@@ -248,7 +245,7 @@ static int xgene_clk_enable(struct clk_hw *hw)
xgene_clk_write(data, pclk->param.csr_reg +
pclk->param.reg_csr_offset);
pr_debug("%s CSR RESET PADDR base %pa csr offset 0x%08X mask 0x%08X value 0x%08X\n",
pclk->name, &reg,
clk_hw_get_name(hw), &reg,
pclk->param.reg_csr_offset, pclk->param.reg_csr_mask,
data);
}
......@@ -269,7 +266,7 @@ static void xgene_clk_disable(struct clk_hw *hw)
spin_lock_irqsave(pclk->lock, flags);
if (pclk->param.csr_reg != NULL) {
pr_debug("%s clock disabled\n", pclk->name);
pr_debug("%s clock disabled\n", clk_hw_get_name(hw));
/* First put the CSR in reset */
data = xgene_clk_read(pclk->param.csr_reg +
pclk->param.reg_csr_offset);
......@@ -295,10 +292,10 @@ static int xgene_clk_is_enabled(struct clk_hw *hw)
u32 data = 0;
if (pclk->param.csr_reg != NULL) {
pr_debug("%s clock checking\n", pclk->name);
pr_debug("%s clock checking\n", clk_hw_get_name(hw));
data = xgene_clk_read(pclk->param.csr_reg +
pclk->param.reg_clk_offset);
pr_debug("%s clock is %s\n", pclk->name,
pr_debug("%s clock is %s\n", clk_hw_get_name(hw),
data & pclk->param.reg_clk_mask ? "enabled" :
"disabled");
}
......@@ -321,11 +318,13 @@ static unsigned long xgene_clk_recalc_rate(struct clk_hw *hw,
data &= (1 << pclk->param.reg_divider_width) - 1;
pr_debug("%s clock recalc rate %ld parent %ld\n",
pclk->name, parent_rate / data, parent_rate);
clk_hw_get_name(hw),
parent_rate / data, parent_rate);
return parent_rate / data;
} else {
pr_debug("%s clock recalc rate %ld parent %ld\n",
pclk->name, parent_rate, parent_rate);
clk_hw_get_name(hw), parent_rate, parent_rate);
return parent_rate;
}
}
......@@ -357,7 +356,7 @@ static int xgene_clk_set_rate(struct clk_hw *hw, unsigned long rate,
data |= divider;
xgene_clk_write(data, pclk->param.divider_reg +
pclk->param.reg_divider_offset);
pr_debug("%s clock set rate %ld\n", pclk->name,
pr_debug("%s clock set rate %ld\n", clk_hw_get_name(hw),
parent_rate / divider_save);
} else {
divider_save = 1;
......@@ -419,7 +418,6 @@ static struct clk *xgene_register_clk(struct device *dev,
init.parent_names = parent_name ? &parent_name : NULL;
init.num_parents = parent_name ? 1 : 0;
apmclk->name = name;
apmclk->lock = lock;
apmclk->hw.init = &init;
apmclk->param = *parameters;
......
此差异已折叠。
......@@ -4,8 +4,6 @@
* Copyright 2015 Yoshinori Sato <ysato@users.sourceforge.jp>
*/
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/clk-provider.h>
#include <linux/err.h>
#include <linux/of.h>
......@@ -15,7 +13,7 @@ static DEFINE_SPINLOCK(clklock);
static void __init h8300_div_clk_setup(struct device_node *node)
{
unsigned int num_parents;
int num_parents;
struct clk *clk;
const char *clk_name = node->name;
const char *parent_name;
......
此差异已折叠。
config COMMON_CLK_HI6220
bool "Hi6220 Clock Driver"
depends on ARCH_HISI || COMPILE_TEST
depends on (ARCH_HISI || COMPILE_TEST) && MAILBOX
default ARCH_HISI
help
Build the Hisilicon Hi6220 clock driver based on the common clock framework.
......@@ -7,4 +7,4 @@ obj-y += clk.o clkgate-separated.o clkdivider-hi6220.o
obj-$(CONFIG_ARCH_HI3xxx) += clk-hi3620.o
obj-$(CONFIG_ARCH_HIP04) += clk-hip04.o
obj-$(CONFIG_ARCH_HIX5HD2) += clk-hix5hd2.o
obj-$(CONFIG_COMMON_CLK_HI6220) += clk-hi6220.o
obj-$(CONFIG_COMMON_CLK_HI6220) += clk-hi6220.o clk-hi6220-stub.o
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册