Commit ef748cb3 authored by Stephen Boyd's avatar Stephen Boyd

Merge branch 'for-4.13-ti-clkctrl' of https://github.com/t-kristo/linux-pm into clk-next

* 'for-4.13-ti-clkctrl' of https://github.com/t-kristo/linux-pm:
  clk: ti: omap4: add clkctrl clock data
  dt-bindings: clk: add omap4 clkctrl definitions
  clk: ti: add support for clkctrl clocks
  Documentation: dt-bindings: Add binding documentation for TI clkctrl clocks
parents 4dc6e1a3 1c881b5a
Texas Instruments clkctrl clock binding
Texas Instruments SoCs can have a clkctrl clock controller for each
interconnect target module. The clkctrl clock controller manages functional
and interface clocks for each module. Each clkctrl controller can also
gate one or more optional functional clocks for a module, and can have one
or more clock muxes. There is a clkctrl clock controller typically for each
interconnect target module on omap4 and later variants.
The clock consumers can specify the index of the clkctrl clock using
the hardware offset from the clkctrl instance register space. The optional
clocks can be specified by clkctrl hardware offset and the index of the
optional clock.
For more information, please see the Linux clock framework binding at
Documentation/devicetree/bindings/clock/clock-bindings.txt.
Required properties :
- compatible : shall be "ti,clkctrl"
- #clock-cells : shall contain 2 with the first entry being the instance
offset from the clock domain base and the second being the
clock index
Example: Clock controller node on omap 4430:
&cm2 {
l4per: cm@1400 {
cm_l4per@0 {
cm_l4per_clkctrl: clk@20 {
compatible = "ti,clkctrl";
reg = <0x20 0x1b0>;
#clock-cells = <2>;
};
};
};
};
Example: Preprocessor helper macros in dt-bindings/clock/ti-clkctrl.h
#define OMAP4_CLKCTRL_OFFSET 0x20
#define OMAP4_CLKCTRL_INDEX(offset) ((offset) - OMAP4_CLKCTRL_OFFSET)
#define MODULEMODE_HWCTRL 1
#define MODULEMODE_SWCTRL 2
#define OMAP4_GPTIMER10_CLKTRL OMAP4_CLKCTRL_INDEX(0x28)
#define OMAP4_GPTIMER11_CLKTRL OMAP4_CLKCTRL_INDEX(0x30)
#define OMAP4_GPTIMER2_CLKTRL OMAP4_CLKCTRL_INDEX(0x38)
...
#define OMAP4_GPIO2_CLKCTRL OMAP_CLKCTRL_INDEX(0x60)
Example: Clock consumer node for GPIO2:
&gpio2 {
clocks = <&cm_l4per_clkctrl OMAP4_GPIO2_CLKCTRL 0
&cm_l4per_clkctrl OMAP4_GPIO2_CLKCTRL 8>;
};
...@@ -3,7 +3,8 @@ ifeq ($(CONFIG_ARCH_OMAP2PLUS), y) ...@@ -3,7 +3,8 @@ ifeq ($(CONFIG_ARCH_OMAP2PLUS), y)
obj-y += clk.o autoidle.o clockdomain.o obj-y += clk.o autoidle.o clockdomain.o
clk-common = dpll.o composite.o divider.o gate.o \ clk-common = dpll.o composite.o divider.o gate.o \
fixed-factor.o mux.o apll.o \ fixed-factor.o mux.o apll.o \
clkt_dpll.o clkt_iclk.o clkt_dflt.o clkt_dpll.o clkt_iclk.o clkt_dflt.o \
clkctrl.o
obj-$(CONFIG_SOC_AM33XX) += $(clk-common) clk-33xx.o dpll3xxx.o obj-$(CONFIG_SOC_AM33XX) += $(clk-common) clk-33xx.o dpll3xxx.o
obj-$(CONFIG_SOC_TI81XX) += $(clk-common) fapll.o clk-814x.o clk-816x.o obj-$(CONFIG_SOC_TI81XX) += $(clk-common) fapll.o clk-814x.o clk-816x.o
obj-$(CONFIG_ARCH_OMAP2) += $(clk-common) interface.o clk-2xxx.o obj-$(CONFIG_ARCH_OMAP2) += $(clk-common) interface.o clk-2xxx.o
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/clkdev.h> #include <linux/clkdev.h>
#include <linux/clk/ti.h> #include <linux/clk/ti.h>
#include <dt-bindings/clock/omap4.h>
#include "clock.h" #include "clock.h"
...@@ -33,6 +34,668 @@ ...@@ -33,6 +34,668 @@
*/ */
#define OMAP4_DPLL_USB_DEFFREQ 960000000 #define OMAP4_DPLL_USB_DEFFREQ 960000000
static const struct omap_clkctrl_reg_data omap4_mpuss_clkctrl_regs[] __initconst = {
{ OMAP4_MPU_CLKCTRL, NULL, CLKF_HW_SUP, "dpll_mpu_m2_ck" },
{ 0 },
};
static const struct omap_clkctrl_reg_data omap4_tesla_clkctrl_regs[] __initconst = {
{ OMAP4_DSP_CLKCTRL, NULL, CLKF_HW_SUP, "dpll_iva_m4x2_ck" },
{ 0 },
};
static const char * const omap4_aess_fclk_parents[] __initconst = {
"abe_clk",
NULL,
};
static const struct omap_clkctrl_div_data omap4_aess_fclk_data __initconst = {
.max_div = 2,
};
static const struct omap_clkctrl_bit_data omap4_aess_bit_data[] __initconst = {
{ 24, TI_CLK_DIVIDER, omap4_aess_fclk_parents, &omap4_aess_fclk_data },
{ 0 },
};
static const char * const omap4_func_dmic_abe_gfclk_parents[] __initconst = {
"dmic_sync_mux_ck",
"pad_clks_ck",
"slimbus_clk",
NULL,
};
static const char * const omap4_dmic_sync_mux_ck_parents[] __initconst = {
"abe_24m_fclk",
"syc_clk_div_ck",
"func_24m_clk",
NULL,
};
static const struct omap_clkctrl_bit_data omap4_dmic_bit_data[] __initconst = {
{ 24, TI_CLK_MUX, omap4_func_dmic_abe_gfclk_parents, NULL },
{ 26, TI_CLK_MUX, omap4_dmic_sync_mux_ck_parents, NULL },
{ 0 },
};
static const char * const omap4_func_mcasp_abe_gfclk_parents[] __initconst = {
"mcasp_sync_mux_ck",
"pad_clks_ck",
"slimbus_clk",
NULL,
};
static const struct omap_clkctrl_bit_data omap4_mcasp_bit_data[] __initconst = {
{ 24, TI_CLK_MUX, omap4_func_mcasp_abe_gfclk_parents, NULL },
{ 26, TI_CLK_MUX, omap4_dmic_sync_mux_ck_parents, NULL },
{ 0 },
};
static const char * const omap4_func_mcbsp1_gfclk_parents[] __initconst = {
"mcbsp1_sync_mux_ck",
"pad_clks_ck",
"slimbus_clk",
NULL,
};
static const struct omap_clkctrl_bit_data omap4_mcbsp1_bit_data[] __initconst = {
{ 24, TI_CLK_MUX, omap4_func_mcbsp1_gfclk_parents, NULL },
{ 26, TI_CLK_MUX, omap4_dmic_sync_mux_ck_parents, NULL },
{ 0 },
};
static const char * const omap4_func_mcbsp2_gfclk_parents[] __initconst = {
"mcbsp2_sync_mux_ck",
"pad_clks_ck",
"slimbus_clk",
NULL,
};
static const struct omap_clkctrl_bit_data omap4_mcbsp2_bit_data[] __initconst = {
{ 24, TI_CLK_MUX, omap4_func_mcbsp2_gfclk_parents, NULL },
{ 26, TI_CLK_MUX, omap4_dmic_sync_mux_ck_parents, NULL },
{ 0 },
};
static const char * const omap4_func_mcbsp3_gfclk_parents[] __initconst = {
"mcbsp3_sync_mux_ck",
"pad_clks_ck",
"slimbus_clk",
NULL,
};
static const struct omap_clkctrl_bit_data omap4_mcbsp3_bit_data[] __initconst = {
{ 24, TI_CLK_MUX, omap4_func_mcbsp3_gfclk_parents, NULL },
{ 26, TI_CLK_MUX, omap4_dmic_sync_mux_ck_parents, NULL },
{ 0 },
};
static const char * const omap4_slimbus1_fclk_0_parents[] __initconst = {
"abe_24m_fclk",
NULL,
};
static const char * const omap4_slimbus1_fclk_1_parents[] __initconst = {
"func_24m_clk",
NULL,
};
static const char * const omap4_slimbus1_fclk_2_parents[] __initconst = {
"pad_clks_ck",
NULL,
};
static const char * const omap4_slimbus1_slimbus_clk_parents[] __initconst = {
"slimbus_clk",
NULL,
};
static const struct omap_clkctrl_bit_data omap4_slimbus1_bit_data[] __initconst = {
{ 8, TI_CLK_GATE, omap4_slimbus1_fclk_0_parents, NULL },
{ 9, TI_CLK_GATE, omap4_slimbus1_fclk_1_parents, NULL },
{ 10, TI_CLK_GATE, omap4_slimbus1_fclk_2_parents, NULL },
{ 11, TI_CLK_GATE, omap4_slimbus1_slimbus_clk_parents, NULL },
{ 0 },
};
static const char * const omap4_timer5_sync_mux_parents[] __initconst = {
"syc_clk_div_ck",
"sys_32k_ck",
NULL,
};
static const struct omap_clkctrl_bit_data omap4_timer5_bit_data[] __initconst = {
{ 24, TI_CLK_MUX, omap4_timer5_sync_mux_parents, NULL },
{ 0 },
};
static const struct omap_clkctrl_bit_data omap4_timer6_bit_data[] __initconst = {
{ 24, TI_CLK_MUX, omap4_timer5_sync_mux_parents, NULL },
{ 0 },
};
static const struct omap_clkctrl_bit_data omap4_timer7_bit_data[] __initconst = {
{ 24, TI_CLK_MUX, omap4_timer5_sync_mux_parents, NULL },
{ 0 },
};
static const struct omap_clkctrl_bit_data omap4_timer8_bit_data[] __initconst = {
{ 24, TI_CLK_MUX, omap4_timer5_sync_mux_parents, NULL },
{ 0 },
};
static const struct omap_clkctrl_reg_data omap4_abe_clkctrl_regs[] __initconst = {
{ OMAP4_L4_ABE_CLKCTRL, NULL, 0, "ocp_abe_iclk" },
{ OMAP4_AESS_CLKCTRL, omap4_aess_bit_data, CLKF_SW_SUP, "aess_fclk" },
{ OMAP4_MCPDM_CLKCTRL, NULL, CLKF_SW_SUP, "pad_clks_ck" },
{ OMAP4_DMIC_CLKCTRL, omap4_dmic_bit_data, CLKF_SW_SUP, "func_dmic_abe_gfclk" },
{ OMAP4_MCASP_CLKCTRL, omap4_mcasp_bit_data, CLKF_SW_SUP, "func_mcasp_abe_gfclk" },
{ OMAP4_MCBSP1_CLKCTRL, omap4_mcbsp1_bit_data, CLKF_SW_SUP, "func_mcbsp1_gfclk" },
{ OMAP4_MCBSP2_CLKCTRL, omap4_mcbsp2_bit_data, CLKF_SW_SUP, "func_mcbsp2_gfclk" },
{ OMAP4_MCBSP3_CLKCTRL, omap4_mcbsp3_bit_data, CLKF_SW_SUP, "func_mcbsp3_gfclk" },
{ OMAP4_SLIMBUS1_CLKCTRL, omap4_slimbus1_bit_data, CLKF_SW_SUP, "slimbus1_fclk_0" },
{ OMAP4_TIMER5_CLKCTRL, omap4_timer5_bit_data, CLKF_SW_SUP, "timer5_sync_mux" },
{ OMAP4_TIMER6_CLKCTRL, omap4_timer6_bit_data, CLKF_SW_SUP, "timer6_sync_mux" },
{ OMAP4_TIMER7_CLKCTRL, omap4_timer7_bit_data, CLKF_SW_SUP, "timer7_sync_mux" },
{ OMAP4_TIMER8_CLKCTRL, omap4_timer8_bit_data, CLKF_SW_SUP, "timer8_sync_mux" },
{ OMAP4_WD_TIMER3_CLKCTRL, NULL, CLKF_SW_SUP, "sys_32k_ck" },
{ 0 },
};
static const struct omap_clkctrl_reg_data omap4_l4_ao_clkctrl_regs[] __initconst = {
{ OMAP4_SMARTREFLEX_MPU_CLKCTRL, NULL, CLKF_SW_SUP, "l4_wkup_clk_mux_ck" },
{ OMAP4_SMARTREFLEX_IVA_CLKCTRL, NULL, CLKF_SW_SUP, "l4_wkup_clk_mux_ck" },
{ OMAP4_SMARTREFLEX_CORE_CLKCTRL, NULL, CLKF_SW_SUP, "l4_wkup_clk_mux_ck" },
{ 0 },
};
static const struct omap_clkctrl_reg_data omap4_l3_1_clkctrl_regs[] __initconst = {
{ OMAP4_L3_MAIN_1_CLKCTRL, NULL, 0, "l3_div_ck" },
{ 0 },
};
static const struct omap_clkctrl_reg_data omap4_l3_2_clkctrl_regs[] __initconst = {
{ OMAP4_L3_MAIN_2_CLKCTRL, NULL, 0, "l3_div_ck" },
{ OMAP4_GPMC_CLKCTRL, NULL, CLKF_HW_SUP, "l3_div_ck" },
{ OMAP4_OCMC_RAM_CLKCTRL, NULL, 0, "l3_div_ck" },
{ 0 },
};
static const struct omap_clkctrl_reg_data omap4_ducati_clkctrl_regs[] __initconst = {
{ OMAP4_IPU_CLKCTRL, NULL, CLKF_HW_SUP, "ducati_clk_mux_ck" },
{ 0 },
};
static const struct omap_clkctrl_reg_data omap4_l3_dma_clkctrl_regs[] __initconst = {
{ OMAP4_DMA_SYSTEM_CLKCTRL, NULL, 0, "l3_div_ck" },
{ 0 },
};
static const struct omap_clkctrl_reg_data omap4_l3_emif_clkctrl_regs[] __initconst = {
{ OMAP4_DMM_CLKCTRL, NULL, 0, "l3_div_ck" },
{ OMAP4_EMIF1_CLKCTRL, NULL, CLKF_HW_SUP, "ddrphy_ck" },
{ OMAP4_EMIF2_CLKCTRL, NULL, CLKF_HW_SUP, "ddrphy_ck" },
{ 0 },
};
static const struct omap_clkctrl_reg_data omap4_d2d_clkctrl_regs[] __initconst = {
{ OMAP4_C2C_CLKCTRL, NULL, 0, "div_core_ck" },
{ 0 },
};
static const struct omap_clkctrl_reg_data omap4_l4_cfg_clkctrl_regs[] __initconst = {
{ OMAP4_L4_CFG_CLKCTRL, NULL, 0, "l4_div_ck" },
{ OMAP4_SPINLOCK_CLKCTRL, NULL, 0, "l4_div_ck" },
{ OMAP4_MAILBOX_CLKCTRL, NULL, 0, "l4_div_ck" },
{ 0 },
};
static const struct omap_clkctrl_reg_data omap4_l3_instr_clkctrl_regs[] __initconst = {
{ OMAP4_L3_MAIN_3_CLKCTRL, NULL, CLKF_HW_SUP, "l3_div_ck" },
{ OMAP4_L3_INSTR_CLKCTRL, NULL, CLKF_HW_SUP, "l3_div_ck" },
{ OMAP4_OCP_WP_NOC_CLKCTRL, NULL, CLKF_HW_SUP, "l3_div_ck" },
{ 0 },
};
static const struct omap_clkctrl_reg_data omap4_ivahd_clkctrl_regs[] __initconst = {
{ OMAP4_IVA_CLKCTRL, NULL, CLKF_HW_SUP, "dpll_iva_m5x2_ck" },
{ OMAP4_SL2IF_CLKCTRL, NULL, CLKF_HW_SUP, "dpll_iva_m5x2_ck" },
{ 0 },
};
static const char * const omap4_iss_ctrlclk_parents[] __initconst = {
"func_96m_fclk",
NULL,
};
static const struct omap_clkctrl_bit_data omap4_iss_bit_data[] __initconst = {
{ 8, TI_CLK_GATE, omap4_iss_ctrlclk_parents, NULL },
{ 0 },
};
static const char * const omap4_fdif_fck_parents[] __initconst = {
"dpll_per_m4x2_ck",
NULL,
};
static const struct omap_clkctrl_div_data omap4_fdif_fck_data __initconst = {
.max_div = 4,
};
static const struct omap_clkctrl_bit_data omap4_fdif_bit_data[] __initconst = {
{ 24, TI_CLK_DIVIDER, omap4_fdif_fck_parents, &omap4_fdif_fck_data },
{ 0 },
};
static const struct omap_clkctrl_reg_data omap4_iss_clkctrl_regs[] __initconst = {
{ OMAP4_ISS_CLKCTRL, omap4_iss_bit_data, CLKF_SW_SUP, "ducati_clk_mux_ck" },
{ OMAP4_FDIF_CLKCTRL, omap4_fdif_bit_data, CLKF_SW_SUP, "fdif_fck" },
{ 0 },
};
static const char * const omap4_dss_dss_clk_parents[] __initconst = {
"dpll_per_m5x2_ck",
NULL,
};
static const char * const omap4_dss_48mhz_clk_parents[] __initconst = {
"func_48mc_fclk",
NULL,
};
static const char * const omap4_dss_sys_clk_parents[] __initconst = {
"syc_clk_div_ck",
NULL,
};
static const char * const omap4_dss_tv_clk_parents[] __initconst = {
"extalt_clkin_ck",
NULL,
};
static const struct omap_clkctrl_bit_data omap4_dss_core_bit_data[] __initconst = {
{ 8, TI_CLK_GATE, omap4_dss_dss_clk_parents, NULL },
{ 9, TI_CLK_GATE, omap4_dss_48mhz_clk_parents, NULL },
{ 10, TI_CLK_GATE, omap4_dss_sys_clk_parents, NULL },
{ 11, TI_CLK_GATE, omap4_dss_tv_clk_parents, NULL },
{ 0 },
};
static const struct omap_clkctrl_reg_data omap4_l3_dss_clkctrl_regs[] __initconst = {
{ OMAP4_DSS_CORE_CLKCTRL, omap4_dss_core_bit_data, CLKF_SW_SUP, "dss_dss_clk" },
{ 0 },
};
static const char * const omap4_sgx_clk_mux_parents[] __initconst = {
"dpll_core_m7x2_ck",
"dpll_per_m7x2_ck",
NULL,
};
static const struct omap_clkctrl_bit_data omap4_gpu_bit_data[] __initconst = {
{ 24, TI_CLK_MUX, omap4_sgx_clk_mux_parents, NULL },
{ 0 },
};
static const struct omap_clkctrl_reg_data omap4_l3_gfx_clkctrl_regs[] __initconst = {
{ OMAP4_GPU_CLKCTRL, omap4_gpu_bit_data, CLKF_SW_SUP, "sgx_clk_mux" },
{ 0 },
};
static const char * const omap4_hsmmc1_fclk_parents[] __initconst = {
"func_64m_fclk",
"func_96m_fclk",
NULL,
};
static const struct omap_clkctrl_bit_data omap4_mmc1_bit_data[] __initconst = {
{ 24, TI_CLK_MUX, omap4_hsmmc1_fclk_parents, NULL },
{ 0 },
};
static const struct omap_clkctrl_bit_data omap4_mmc2_bit_data[] __initconst = {
{ 24, TI_CLK_MUX, omap4_hsmmc1_fclk_parents, NULL },
{ 0 },
};
static const char * const omap4_hsi_fck_parents[] __initconst = {
"dpll_per_m2x2_ck",
NULL,
};
static const struct omap_clkctrl_div_data omap4_hsi_fck_data __initconst = {
.max_div = 4,
};
static const struct omap_clkctrl_bit_data omap4_hsi_bit_data[] __initconst = {
{ 24, TI_CLK_DIVIDER, omap4_hsi_fck_parents, &omap4_hsi_fck_data },
{ 0 },
};
static const char * const omap4_usb_host_hs_utmi_p1_clk_parents[] __initconst = {
"utmi_p1_gfclk",
NULL,
};
static const char * const omap4_usb_host_hs_utmi_p2_clk_parents[] __initconst = {
"utmi_p2_gfclk",
NULL,
};
static const char * const omap4_usb_host_hs_utmi_p3_clk_parents[] __initconst = {
"init_60m_fclk",
NULL,
};
static const char * const omap4_usb_host_hs_hsic480m_p1_clk_parents[] __initconst = {
"dpll_usb_m2_ck",
NULL,
};
static const char * const omap4_utmi_p1_gfclk_parents[] __initconst = {
"init_60m_fclk",
"xclk60mhsp1_ck",
NULL,
};
static const char * const omap4_utmi_p2_gfclk_parents[] __initconst = {
"init_60m_fclk",
"xclk60mhsp2_ck",
NULL,
};
static const struct omap_clkctrl_bit_data omap4_usb_host_hs_bit_data[] __initconst = {
{ 8, TI_CLK_GATE, omap4_usb_host_hs_utmi_p1_clk_parents, NULL },
{ 9, TI_CLK_GATE, omap4_usb_host_hs_utmi_p2_clk_parents, NULL },
{ 10, TI_CLK_GATE, omap4_usb_host_hs_utmi_p3_clk_parents, NULL },
{ 11, TI_CLK_GATE, omap4_usb_host_hs_utmi_p3_clk_parents, NULL },
{ 12, TI_CLK_GATE, omap4_usb_host_hs_utmi_p3_clk_parents, NULL },
{ 13, TI_CLK_GATE, omap4_usb_host_hs_hsic480m_p1_clk_parents, NULL },
{ 14, TI_CLK_GATE, omap4_usb_host_hs_hsic480m_p1_clk_parents, NULL },
{ 15, TI_CLK_GATE, omap4_dss_48mhz_clk_parents, NULL },
{ 24, TI_CLK_MUX, omap4_utmi_p1_gfclk_parents, NULL },
{ 25, TI_CLK_MUX, omap4_utmi_p2_gfclk_parents, NULL },
{ 0 },
};
static const char * const omap4_usb_otg_hs_xclk_parents[] __initconst = {
"otg_60m_gfclk",
NULL,
};
static const char * const omap4_otg_60m_gfclk_parents[] __initconst = {
"utmi_phy_clkout_ck",
"xclk60motg_ck",
NULL,
};
static const struct omap_clkctrl_bit_data omap4_usb_otg_hs_bit_data[] __initconst = {
{ 8, TI_CLK_GATE, omap4_usb_otg_hs_xclk_parents, NULL },
{ 24, TI_CLK_MUX, omap4_otg_60m_gfclk_parents, NULL },
{ 0 },
};
static const struct omap_clkctrl_bit_data omap4_usb_tll_hs_bit_data[] __initconst = {
{ 8, TI_CLK_GATE, omap4_usb_host_hs_utmi_p3_clk_parents, NULL },
{ 9, TI_CLK_GATE, omap4_usb_host_hs_utmi_p3_clk_parents, NULL },
{ 10, TI_CLK_GATE, omap4_usb_host_hs_utmi_p3_clk_parents, NULL },
{ 0 },
};
static const char * const omap4_ocp2scp_usb_phy_phy_48m_parents[] __initconst = {
"func_48m_fclk",
NULL,
};
static const struct omap_clkctrl_bit_data omap4_ocp2scp_usb_phy_bit_data[] __initconst = {
{ 8, TI_CLK_GATE, omap4_ocp2scp_usb_phy_phy_48m_parents, NULL },
{ 0 },
};
static const struct omap_clkctrl_reg_data omap4_l3_init_clkctrl_regs[] __initconst = {
{ OMAP4_MMC1_CLKCTRL, omap4_mmc1_bit_data, CLKF_SW_SUP, "hsmmc1_fclk" },
{ OMAP4_MMC2_CLKCTRL, omap4_mmc2_bit_data, CLKF_SW_SUP, "hsmmc2_fclk" },
{ OMAP4_HSI_CLKCTRL, omap4_hsi_bit_data, CLKF_HW_SUP, "hsi_fck" },
{ OMAP4_USB_HOST_HS_CLKCTRL, omap4_usb_host_hs_bit_data, CLKF_SW_SUP, "init_60m_fclk" },
{ OMAP4_USB_OTG_HS_CLKCTRL, omap4_usb_otg_hs_bit_data, CLKF_HW_SUP, "l3_div_ck" },
{ OMAP4_USB_TLL_HS_CLKCTRL, omap4_usb_tll_hs_bit_data, CLKF_HW_SUP, "l4_div_ck" },
{ OMAP4_USB_HOST_FS_CLKCTRL, NULL, CLKF_SW_SUP, "func_48mc_fclk" },
{ OMAP4_OCP2SCP_USB_PHY_CLKCTRL, omap4_ocp2scp_usb_phy_bit_data, CLKF_HW_SUP, "ocp2scp_usb_phy_phy_48m" },
{ 0 },
};
static const char * const omap4_cm2_dm10_mux_parents[] __initconst = {
"sys_clkin_ck",
"sys_32k_ck",
NULL,
};
static const struct omap_clkctrl_bit_data omap4_timer10_bit_data[] __initconst = {
{ 24, TI_CLK_MUX, omap4_cm2_dm10_mux_parents, NULL },
{ 0 },
};
static const struct omap_clkctrl_bit_data omap4_timer11_bit_data[] __initconst = {
{ 24, TI_CLK_MUX, omap4_cm2_dm10_mux_parents, NULL },
{ 0 },
};
static const struct omap_clkctrl_bit_data omap4_timer2_bit_data[] __initconst = {
{ 24, TI_CLK_MUX, omap4_cm2_dm10_mux_parents, NULL },
{ 0 },
};
static const struct omap_clkctrl_bit_data omap4_timer3_bit_data[] __initconst = {
{ 24, TI_CLK_MUX, omap4_cm2_dm10_mux_parents, NULL },
{ 0 },
};
static const struct omap_clkctrl_bit_data omap4_timer4_bit_data[] __initconst = {
{ 24, TI_CLK_MUX, omap4_cm2_dm10_mux_parents, NULL },
{ 0 },
};
static const struct omap_clkctrl_bit_data omap4_timer9_bit_data[] __initconst = {
{ 24, TI_CLK_MUX, omap4_cm2_dm10_mux_parents, NULL },
{ 0 },
};
static const char * const omap4_gpio2_dbclk_parents[] __initconst = {
"sys_32k_ck",
NULL,
};
static const struct omap_clkctrl_bit_data omap4_gpio2_bit_data[] __initconst = {
{ 8, TI_CLK_GATE, omap4_gpio2_dbclk_parents, NULL },
{ 0 },
};
static const struct omap_clkctrl_bit_data omap4_gpio3_bit_data[] __initconst = {
{ 8, TI_CLK_GATE, omap4_gpio2_dbclk_parents, NULL },
{ 0 },
};
static const struct omap_clkctrl_bit_data omap4_gpio4_bit_data[] __initconst = {
{ 8, TI_CLK_GATE, omap4_gpio2_dbclk_parents, NULL },
{ 0 },
};
static const struct omap_clkctrl_bit_data omap4_gpio5_bit_data[] __initconst = {
{ 8, TI_CLK_GATE, omap4_gpio2_dbclk_parents, NULL },
{ 0 },
};
static const struct omap_clkctrl_bit_data omap4_gpio6_bit_data[] __initconst = {
{ 8, TI_CLK_GATE, omap4_gpio2_dbclk_parents, NULL },
{ 0 },
};
static const char * const omap4_per_mcbsp4_gfclk_parents[] __initconst = {
"mcbsp4_sync_mux_ck",
"pad_clks_ck",
NULL,
};
static const char * const omap4_mcbsp4_sync_mux_ck_parents[] __initconst = {
"func_96m_fclk",
"per_abe_nc_fclk",
NULL,
};
static const struct omap_clkctrl_bit_data omap4_mcbsp4_bit_data[] __initconst = {
{ 24, TI_CLK_MUX, omap4_per_mcbsp4_gfclk_parents, NULL },
{ 25, TI_CLK_MUX, omap4_mcbsp4_sync_mux_ck_parents, NULL },
{ 0 },
};
static const char * const omap4_slimbus2_fclk_0_parents[] __initconst = {
"func_24mc_fclk",
NULL,
};
static const char * const omap4_slimbus2_fclk_1_parents[] __initconst = {
"per_abe_24m_fclk",
NULL,
};
static const char * const omap4_slimbus2_slimbus_clk_parents[] __initconst = {
"pad_slimbus_core_clks_ck",
NULL,
};
static const struct omap_clkctrl_bit_data omap4_slimbus2_bit_data[] __initconst = {
{ 8, TI_CLK_GATE, omap4_slimbus2_fclk_0_parents, NULL },
{ 9, TI_CLK_GATE, omap4_slimbus2_fclk_1_parents, NULL },
{ 10, TI_CLK_GATE, omap4_slimbus2_slimbus_clk_parents, NULL },
{ 0 },
};
static const struct omap_clkctrl_reg_data omap4_l4_per_clkctrl_regs[] __initconst = {
{ OMAP4_TIMER10_CLKCTRL, omap4_timer10_bit_data, CLKF_SW_SUP, "cm2_dm10_mux" },
{ OMAP4_TIMER11_CLKCTRL, omap4_timer11_bit_data, CLKF_SW_SUP, "cm2_dm11_mux" },
{ OMAP4_TIMER2_CLKCTRL, omap4_timer2_bit_data, CLKF_SW_SUP, "cm2_dm2_mux" },
{ OMAP4_TIMER3_CLKCTRL, omap4_timer3_bit_data, CLKF_SW_SUP, "cm2_dm3_mux" },
{ OMAP4_TIMER4_CLKCTRL, omap4_timer4_bit_data, CLKF_SW_SUP, "cm2_dm4_mux" },
{ OMAP4_TIMER9_CLKCTRL, omap4_timer9_bit_data, CLKF_SW_SUP, "cm2_dm9_mux" },
{ OMAP4_ELM_CLKCTRL, NULL, 0, "l4_div_ck" },
{ OMAP4_GPIO2_CLKCTRL, omap4_gpio2_bit_data, CLKF_HW_SUP, "l4_div_ck" },
{ OMAP4_GPIO3_CLKCTRL, omap4_gpio3_bit_data, CLKF_HW_SUP, "l4_div_ck" },
{ OMAP4_GPIO4_CLKCTRL, omap4_gpio4_bit_data, CLKF_HW_SUP, "l4_div_ck" },
{ OMAP4_GPIO5_CLKCTRL, omap4_gpio5_bit_data, CLKF_HW_SUP, "l4_div_ck" },
{ OMAP4_GPIO6_CLKCTRL, omap4_gpio6_bit_data, CLKF_HW_SUP, "l4_div_ck" },
{ OMAP4_HDQ1W_CLKCTRL, NULL, CLKF_SW_SUP, "func_12m_fclk" },
{ OMAP4_I2C1_CLKCTRL, NULL, CLKF_SW_SUP, "func_96m_fclk" },
{ OMAP4_I2C2_CLKCTRL, NULL, CLKF_SW_SUP, "func_96m_fclk" },
{ OMAP4_I2C3_CLKCTRL, NULL, CLKF_SW_SUP, "func_96m_fclk" },
{ OMAP4_I2C4_CLKCTRL, NULL, CLKF_SW_SUP, "func_96m_fclk" },
{ OMAP4_L4_PER_CLKCTRL, NULL, 0, "l4_div_ck" },
{ OMAP4_MCBSP4_CLKCTRL, omap4_mcbsp4_bit_data, CLKF_SW_SUP, "per_mcbsp4_gfclk" },
{ OMAP4_MCSPI1_CLKCTRL, NULL, CLKF_SW_SUP, "func_48m_fclk" },
{ OMAP4_MCSPI2_CLKCTRL, NULL, CLKF_SW_SUP, "func_48m_fclk" },
{ OMAP4_MCSPI3_CLKCTRL, NULL, CLKF_SW_SUP, "func_48m_fclk" },
{ OMAP4_MCSPI4_CLKCTRL, NULL, CLKF_SW_SUP, "func_48m_fclk" },
{ OMAP4_MMC3_CLKCTRL, NULL, CLKF_SW_SUP, "func_48m_fclk" },
{ OMAP4_MMC4_CLKCTRL, NULL, CLKF_SW_SUP, "func_48m_fclk" },
{ OMAP4_SLIMBUS2_CLKCTRL, omap4_slimbus2_bit_data, CLKF_SW_SUP, "slimbus2_fclk_0" },
{ OMAP4_UART1_CLKCTRL, NULL, CLKF_SW_SUP, "func_48m_fclk" },
{ OMAP4_UART2_CLKCTRL, NULL, CLKF_SW_SUP, "func_48m_fclk" },
{ OMAP4_UART3_CLKCTRL, NULL, CLKF_SW_SUP, "func_48m_fclk" },
{ OMAP4_UART4_CLKCTRL, NULL, CLKF_SW_SUP, "func_48m_fclk" },
{ OMAP4_MMC5_CLKCTRL, NULL, CLKF_SW_SUP, "func_48m_fclk" },
{ 0 },
};
static const struct omap_clkctrl_bit_data omap4_gpio1_bit_data[] __initconst = {
{ 8, TI_CLK_GATE, omap4_gpio2_dbclk_parents, NULL },
{ 0 },
};
static const struct omap_clkctrl_bit_data omap4_timer1_bit_data[] __initconst = {
{ 24, TI_CLK_MUX, omap4_cm2_dm10_mux_parents, NULL },
{ 0 },
};
static const struct omap_clkctrl_reg_data omap4_l4_wkup_clkctrl_regs[] __initconst = {
{ OMAP4_L4_WKUP_CLKCTRL, NULL, 0, "l4_wkup_clk_mux_ck" },
{ OMAP4_WD_TIMER2_CLKCTRL, NULL, CLKF_SW_SUP, "sys_32k_ck" },
{ OMAP4_GPIO1_CLKCTRL, omap4_gpio1_bit_data, CLKF_HW_SUP, "l4_wkup_clk_mux_ck" },
{ OMAP4_TIMER1_CLKCTRL, omap4_timer1_bit_data, CLKF_SW_SUP, "dmt1_clk_mux" },
{ OMAP4_COUNTER_32K_CLKCTRL, NULL, 0, "sys_32k_ck" },
{ OMAP4_KBD_CLKCTRL, NULL, CLKF_SW_SUP, "sys_32k_ck" },
{ 0 },
};
static const char * const omap4_pmd_stm_clock_mux_ck_parents[] __initconst = {
"sys_clkin_ck",
"dpll_core_m6x2_ck",
"tie_low_clock_ck",
NULL,
};
static const char * const omap4_trace_clk_div_div_ck_parents[] __initconst = {
"pmd_trace_clk_mux_ck",
NULL,
};
static const int omap4_trace_clk_div_div_ck_divs[] __initconst = {
0,
1,
2,
0,
4,
-1,
};
static const struct omap_clkctrl_div_data omap4_trace_clk_div_div_ck_data __initconst = {
.dividers = omap4_trace_clk_div_div_ck_divs,
};
static const char * const omap4_stm_clk_div_ck_parents[] __initconst = {
"pmd_stm_clock_mux_ck",
NULL,
};
static const struct omap_clkctrl_div_data omap4_stm_clk_div_ck_data __initconst = {
.max_div = 64,
};
static const struct omap_clkctrl_bit_data omap4_debugss_bit_data[] __initconst = {
{ 20, TI_CLK_MUX, omap4_pmd_stm_clock_mux_ck_parents, NULL },
{ 22, TI_CLK_MUX, omap4_pmd_stm_clock_mux_ck_parents, NULL },
{ 24, TI_CLK_DIVIDER, omap4_trace_clk_div_div_ck_parents, &omap4_trace_clk_div_div_ck_data },
{ 27, TI_CLK_DIVIDER, omap4_stm_clk_div_ck_parents, &omap4_stm_clk_div_ck_data },
{ 0 },
};
static const struct omap_clkctrl_reg_data omap4_emu_sys_clkctrl_regs[] __initconst = {
{ OMAP4_DEBUGSS_CLKCTRL, omap4_debugss_bit_data, 0, "trace_clk_div_ck" },
{ 0 },
};
const struct omap_clkctrl_data omap4_clkctrl_data[] __initconst = {
{ 0x4a004320, omap4_mpuss_clkctrl_regs },
{ 0x4a004420, omap4_tesla_clkctrl_regs },
{ 0x4a004520, omap4_abe_clkctrl_regs },
{ 0x4a008620, omap4_l4_ao_clkctrl_regs },
{ 0x4a008720, omap4_l3_1_clkctrl_regs },
{ 0x4a008820, omap4_l3_2_clkctrl_regs },
{ 0x4a008920, omap4_ducati_clkctrl_regs },
{ 0x4a008a20, omap4_l3_dma_clkctrl_regs },
{ 0x4a008b20, omap4_l3_emif_clkctrl_regs },
{ 0x4a008c20, omap4_d2d_clkctrl_regs },
{ 0x4a008d20, omap4_l4_cfg_clkctrl_regs },
{ 0x4a008e20, omap4_l3_instr_clkctrl_regs },
{ 0x4a008f20, omap4_ivahd_clkctrl_regs },
{ 0x4a009020, omap4_iss_clkctrl_regs },
{ 0x4a009120, omap4_l3_dss_clkctrl_regs },
{ 0x4a009220, omap4_l3_gfx_clkctrl_regs },
{ 0x4a009320, omap4_l3_init_clkctrl_regs },
{ 0x4a009420, omap4_l4_per_clkctrl_regs },
{ 0x4a307820, omap4_l4_wkup_clkctrl_regs },
{ 0x4a307a20, omap4_emu_sys_clkctrl_regs },
{ 0 },
};
static struct ti_dt_clk omap44xx_clks[] = { static struct ti_dt_clk omap44xx_clks[] = {
DT_CLK("smp_twd", NULL, "mpu_periphclk"), DT_CLK("smp_twd", NULL, "mpu_periphclk"),
DT_CLK("omapdss_dss", "ick", "dss_fck"), DT_CLK("omapdss_dss", "ick", "dss_fck"),
......
/*
* OMAP clkctrl clock support
*
* Copyright (C) 2017 Texas Instruments, Inc.
*
* Tero Kristo <t-kristo@ti.com>
*
* 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 program is distributed "as is" WITHOUT ANY WARRANTY of any
* kind, whether express or implied; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/clk-provider.h>
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/clk/ti.h>
#include <linux/delay.h>
#include "clock.h"
#define NO_IDLEST 0x1
#define OMAP4_MODULEMODE_MASK 0x3
#define MODULEMODE_HWCTRL 0x1
#define MODULEMODE_SWCTRL 0x2
#define OMAP4_IDLEST_MASK (0x3 << 16)
#define OMAP4_IDLEST_SHIFT 16
#define CLKCTRL_IDLEST_FUNCTIONAL 0x0
#define CLKCTRL_IDLEST_INTERFACE_IDLE 0x2
#define CLKCTRL_IDLEST_DISABLED 0x3
/* These timeouts are in us */
#define OMAP4_MAX_MODULE_READY_TIME 2000
#define OMAP4_MAX_MODULE_DISABLE_TIME 5000
static bool _early_timeout = true;
struct omap_clkctrl_provider {
void __iomem *base;
struct list_head clocks;
};
struct omap_clkctrl_clk {
struct clk_hw *clk;
u16 reg_offset;
int bit_offset;
struct list_head node;
};
union omap4_timeout {
u32 cycles;
ktime_t start;
};
static const struct omap_clkctrl_data default_clkctrl_data[] __initconst = {
{ 0 },
};
static u32 _omap4_idlest(u32 val)
{
val &= OMAP4_IDLEST_MASK;
val >>= OMAP4_IDLEST_SHIFT;
return val;
}
static bool _omap4_is_idle(u32 val)
{
val = _omap4_idlest(val);
return val == CLKCTRL_IDLEST_DISABLED;
}
static bool _omap4_is_ready(u32 val)
{
val = _omap4_idlest(val);
return val == CLKCTRL_IDLEST_FUNCTIONAL ||
val == CLKCTRL_IDLEST_INTERFACE_IDLE;
}
static bool _omap4_is_timeout(union omap4_timeout *time, u32 timeout)
{
if (unlikely(_early_timeout)) {
if (time->cycles++ < timeout) {
udelay(1);
return false;
}
} else {
if (!ktime_to_ns(time->start)) {
time->start = ktime_get();
return false;
}
if (ktime_us_delta(ktime_get(), time->start) < timeout) {
cpu_relax();
return false;
}
}
return true;
}
static int __init _omap4_disable_early_timeout(void)
{
_early_timeout = false;
return 0;
}
arch_initcall(_omap4_disable_early_timeout);
static int _omap4_clkctrl_clk_enable(struct clk_hw *hw)
{
struct clk_hw_omap *clk = to_clk_hw_omap(hw);
u32 val;
int ret;
union omap4_timeout timeout = { 0 };
if (!clk->enable_bit)
return 0;
if (clk->clkdm) {
ret = ti_clk_ll_ops->clkdm_clk_enable(clk->clkdm, hw->clk);
if (ret) {
WARN(1,
"%s: could not enable %s's clockdomain %s: %d\n",
__func__, clk_hw_get_name(hw),
clk->clkdm_name, ret);
return ret;
}
}
val = ti_clk_ll_ops->clk_readl(&clk->enable_reg);
val &= ~OMAP4_MODULEMODE_MASK;
val |= clk->enable_bit;
ti_clk_ll_ops->clk_writel(val, &clk->enable_reg);
if (clk->flags & NO_IDLEST)
return 0;
/* Wait until module is enabled */
while (!_omap4_is_ready(ti_clk_ll_ops->clk_readl(&clk->enable_reg))) {
if (_omap4_is_timeout(&timeout, OMAP4_MAX_MODULE_READY_TIME)) {
pr_err("%s: failed to enable\n", clk_hw_get_name(hw));
return -EBUSY;
}
}
return 0;
}
static void _omap4_clkctrl_clk_disable(struct clk_hw *hw)
{
struct clk_hw_omap *clk = to_clk_hw_omap(hw);
u32 val;
union omap4_timeout timeout = { 0 };
if (!clk->enable_bit)
return;
val = ti_clk_ll_ops->clk_readl(&clk->enable_reg);
val &= ~OMAP4_MODULEMODE_MASK;
ti_clk_ll_ops->clk_writel(val, &clk->enable_reg);
if (clk->flags & NO_IDLEST)
goto exit;
/* Wait until module is disabled */
while (!_omap4_is_idle(ti_clk_ll_ops->clk_readl(&clk->enable_reg))) {
if (_omap4_is_timeout(&timeout,
OMAP4_MAX_MODULE_DISABLE_TIME)) {
pr_err("%s: failed to disable\n", clk_hw_get_name(hw));
break;
}
}
exit:
if (clk->clkdm)
ti_clk_ll_ops->clkdm_clk_disable(clk->clkdm, hw->clk);
}
static int _omap4_clkctrl_clk_is_enabled(struct clk_hw *hw)
{
struct clk_hw_omap *clk = to_clk_hw_omap(hw);
u32 val;
val = ti_clk_ll_ops->clk_readl(&clk->enable_reg);
if (val & clk->enable_bit)
return 1;
return 0;
}
static const struct clk_ops omap4_clkctrl_clk_ops = {
.enable = _omap4_clkctrl_clk_enable,
.disable = _omap4_clkctrl_clk_disable,
.is_enabled = _omap4_clkctrl_clk_is_enabled,
};
static struct clk_hw *_ti_omap4_clkctrl_xlate(struct of_phandle_args *clkspec,
void *data)
{
struct omap_clkctrl_provider *provider = data;
struct omap_clkctrl_clk *entry;
if (clkspec->args_count != 2)
return ERR_PTR(-EINVAL);
pr_debug("%s: looking for %x:%x\n", __func__,
clkspec->args[0], clkspec->args[1]);
list_for_each_entry(entry, &provider->clocks, node) {
if (entry->reg_offset == clkspec->args[0] &&
entry->bit_offset == clkspec->args[1])
break;
}
if (!entry)
return ERR_PTR(-EINVAL);
return entry->clk;
}
static int __init
_ti_clkctrl_clk_register(struct omap_clkctrl_provider *provider,
struct device_node *node, struct clk_hw *clk_hw,
u16 offset, u8 bit, const char * const *parents,
int num_parents, const struct clk_ops *ops)
{
struct clk_init_data init = { NULL };
struct clk *clk;
struct omap_clkctrl_clk *clkctrl_clk;
int ret = 0;
init.name = kasprintf(GFP_KERNEL, "%s:%s:%04x:%d", node->parent->name,
node->name, offset, bit);
clkctrl_clk = kzalloc(sizeof(*clkctrl_clk), GFP_KERNEL);
if (!init.name || !clkctrl_clk) {
ret = -ENOMEM;
goto cleanup;
}
clk_hw->init = &init;
init.parent_names = parents;
init.num_parents = num_parents;
init.ops = ops;
init.flags = CLK_IS_BASIC;
clk = ti_clk_register(NULL, clk_hw, init.name);
if (IS_ERR_OR_NULL(clk)) {
ret = -EINVAL;
goto cleanup;
}
clkctrl_clk->reg_offset = offset;
clkctrl_clk->bit_offset = bit;
clkctrl_clk->clk = clk_hw;
list_add(&clkctrl_clk->node, &provider->clocks);
return 0;
cleanup:
kfree(init.name);
kfree(clkctrl_clk);
return ret;
}
static void __init
_ti_clkctrl_setup_gate(struct omap_clkctrl_provider *provider,
struct device_node *node, u16 offset,
const struct omap_clkctrl_bit_data *data,
void __iomem *reg)
{
struct clk_hw_omap *clk_hw;
clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL);
if (!clk_hw)
return;
clk_hw->enable_bit = data->bit;
clk_hw->enable_reg.ptr = reg;
if (_ti_clkctrl_clk_register(provider, node, &clk_hw->hw, offset,
data->bit, data->parents, 1,
&omap_gate_clk_ops))
kfree(clk_hw);
}
static void __init
_ti_clkctrl_setup_mux(struct omap_clkctrl_provider *provider,
struct device_node *node, u16 offset,
const struct omap_clkctrl_bit_data *data,
void __iomem *reg)
{
struct clk_omap_mux *mux;
int num_parents = 0;
const char * const *pname;
mux = kzalloc(sizeof(*mux), GFP_KERNEL);
if (!mux)
return;
pname = data->parents;
while (*pname) {
num_parents++;
pname++;
}
mux->mask = num_parents;
mux->mask = (1 << fls(mux->mask)) - 1;
mux->shift = data->bit;
mux->reg.ptr = reg;
if (_ti_clkctrl_clk_register(provider, node, &mux->hw, offset,
data->bit, data->parents, num_parents,
&ti_clk_mux_ops))
kfree(mux);
}
static void __init
_ti_clkctrl_setup_div(struct omap_clkctrl_provider *provider,
struct device_node *node, u16 offset,
const struct omap_clkctrl_bit_data *data,
void __iomem *reg)
{
struct clk_omap_divider *div;
const struct omap_clkctrl_div_data *div_data = data->data;
div = kzalloc(sizeof(*div), GFP_KERNEL);
if (!div)
return;
div->reg.ptr = reg;
div->shift = data->bit;
if (ti_clk_parse_divider_data((int *)div_data->dividers,
div_data->max_div, 0, 0,
&div->width, &div->table)) {
pr_err("%s: Data parsing for %s:%04x:%d failed\n", __func__,
node->name, offset, data->bit);
kfree(div);
return;
}
if (_ti_clkctrl_clk_register(provider, node, &div->hw, offset,
data->bit, data->parents, 1,
&ti_clk_divider_ops))
kfree(div);
}
static void __init
_ti_clkctrl_setup_subclks(struct omap_clkctrl_provider *provider,
struct device_node *node,
const struct omap_clkctrl_reg_data *data,
void __iomem *reg)
{
const struct omap_clkctrl_bit_data *bits = data->bit_data;
if (!bits)
return;
while (bits->bit) {
switch (bits->type) {
case TI_CLK_GATE:
_ti_clkctrl_setup_gate(provider, node, data->offset,
bits, reg);
break;
case TI_CLK_DIVIDER:
_ti_clkctrl_setup_div(provider, node, data->offset,
bits, reg);
break;
case TI_CLK_MUX:
_ti_clkctrl_setup_mux(provider, node, data->offset,
bits, reg);
break;
default:
pr_err("%s: bad subclk type: %d\n", __func__,
bits->type);
return;
}
bits++;
}
}
static void __init _ti_omap4_clkctrl_setup(struct device_node *node)
{
struct omap_clkctrl_provider *provider;
const struct omap_clkctrl_data *data = default_clkctrl_data;
const struct omap_clkctrl_reg_data *reg_data;
struct clk_init_data init = { NULL };
struct clk_hw_omap *hw;
struct clk *clk;
struct omap_clkctrl_clk *clkctrl_clk;
const __be32 *addrp;
u32 addr;
addrp = of_get_address(node, 0, NULL, NULL);
addr = (u32)of_translate_address(node, addrp);
#ifdef CONFIG_ARCH_OMAP4
if (of_machine_is_compatible("ti,omap4"))
data = omap4_clkctrl_data;
#endif
while (data->addr) {
if (addr == data->addr)
break;
data++;
}
if (!data->addr) {
pr_err("%s not found from clkctrl data.\n", node->name);
return;
}
provider = kzalloc(sizeof(*provider), GFP_KERNEL);
if (!provider)
return;
provider->base = of_iomap(node, 0);
INIT_LIST_HEAD(&provider->clocks);
/* Generate clocks */
reg_data = data->regs;
while (reg_data->parent) {
hw = kzalloc(sizeof(*hw), GFP_KERNEL);
if (!hw)
return;
hw->enable_reg.ptr = provider->base + reg_data->offset;
_ti_clkctrl_setup_subclks(provider, node, reg_data,
hw->enable_reg.ptr);
if (reg_data->flags & CLKF_SW_SUP)
hw->enable_bit = MODULEMODE_SWCTRL;
if (reg_data->flags & CLKF_HW_SUP)
hw->enable_bit = MODULEMODE_HWCTRL;
if (reg_data->flags & CLKF_NO_IDLEST)
hw->flags |= NO_IDLEST;
init.parent_names = &reg_data->parent;
init.num_parents = 1;
init.flags = 0;
init.name = kasprintf(GFP_KERNEL, "%s:%s:%04x:%d",
node->parent->name, node->name,
reg_data->offset, 0);
clkctrl_clk = kzalloc(sizeof(*clkctrl_clk), GFP_KERNEL);
if (!init.name || !clkctrl_clk)
goto cleanup;
init.ops = &omap4_clkctrl_clk_ops;
hw->hw.init = &init;
clk = ti_clk_register(NULL, &hw->hw, init.name);
if (IS_ERR_OR_NULL(clk))
goto cleanup;
clkctrl_clk->reg_offset = reg_data->offset;
clkctrl_clk->clk = &hw->hw;
list_add(&clkctrl_clk->node, &provider->clocks);
reg_data++;
}
of_clk_add_hw_provider(node, _ti_omap4_clkctrl_xlate, provider);
return;
cleanup:
kfree(hw);
kfree(init.name);
kfree(clkctrl_clk);
}
CLK_OF_DECLARE(ti_omap4_clkctrl_clock, "ti,clkctrl",
_ti_omap4_clkctrl_setup);
...@@ -203,6 +203,37 @@ struct ti_dt_clk { ...@@ -203,6 +203,37 @@ struct ti_dt_clk {
.node_name = name, \ .node_name = name, \
} }
/* CLKCTRL type definitions */
struct omap_clkctrl_div_data {
const int *dividers;
int max_div;
};
struct omap_clkctrl_bit_data {
u8 bit;
u8 type;
const char * const *parents;
const void *data;
};
struct omap_clkctrl_reg_data {
u16 offset;
const struct omap_clkctrl_bit_data *bit_data;
u16 flags;
const char *parent;
};
struct omap_clkctrl_data {
u32 addr;
const struct omap_clkctrl_reg_data *regs;
};
extern const struct omap_clkctrl_data omap4_clkctrl_data[];
#define CLKF_SW_SUP BIT(0)
#define CLKF_HW_SUP BIT(1)
#define CLKF_NO_IDLEST BIT(2)
typedef void (*ti_of_clk_init_cb_t)(struct clk_hw *, struct device_node *); typedef void (*ti_of_clk_init_cb_t)(struct clk_hw *, struct device_node *);
struct clk *ti_clk_register_gate(struct ti_clk *setup); struct clk *ti_clk_register_gate(struct ti_clk *setup);
......
/*
* Copyright 2017 Texas Instruments, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __DT_BINDINGS_CLK_OMAP4_H
#define __DT_BINDINGS_CLK_OMAP4_H
#define OMAP4_CLKCTRL_OFFSET 0x20
#define OMAP4_CLKCTRL_INDEX(offset) ((offset) - OMAP4_CLKCTRL_OFFSET)
/* mpuss clocks */
#define OMAP4_MPU_CLKCTRL OMAP4_CLKCTRL_INDEX(0x20)
/* tesla clocks */
#define OMAP4_DSP_CLKCTRL OMAP4_CLKCTRL_INDEX(0x20)
/* abe clocks */
#define OMAP4_L4_ABE_CLKCTRL OMAP4_CLKCTRL_INDEX(0x20)
#define OMAP4_AESS_CLKCTRL OMAP4_CLKCTRL_INDEX(0x28)
#define OMAP4_MCPDM_CLKCTRL OMAP4_CLKCTRL_INDEX(0x30)
#define OMAP4_DMIC_CLKCTRL OMAP4_CLKCTRL_INDEX(0x38)
#define OMAP4_MCASP_CLKCTRL OMAP4_CLKCTRL_INDEX(0x40)
#define OMAP4_MCBSP1_CLKCTRL OMAP4_CLKCTRL_INDEX(0x48)
#define OMAP4_MCBSP2_CLKCTRL OMAP4_CLKCTRL_INDEX(0x50)
#define OMAP4_MCBSP3_CLKCTRL OMAP4_CLKCTRL_INDEX(0x58)
#define OMAP4_SLIMBUS1_CLKCTRL OMAP4_CLKCTRL_INDEX(0x60)
#define OMAP4_TIMER5_CLKCTRL OMAP4_CLKCTRL_INDEX(0x68)
#define OMAP4_TIMER6_CLKCTRL OMAP4_CLKCTRL_INDEX(0x70)
#define OMAP4_TIMER7_CLKCTRL OMAP4_CLKCTRL_INDEX(0x78)
#define OMAP4_TIMER8_CLKCTRL OMAP4_CLKCTRL_INDEX(0x80)
#define OMAP4_WD_TIMER3_CLKCTRL OMAP4_CLKCTRL_INDEX(0x88)
/* l4_ao clocks */
#define OMAP4_SMARTREFLEX_MPU_CLKCTRL OMAP4_CLKCTRL_INDEX(0x28)
#define OMAP4_SMARTREFLEX_IVA_CLKCTRL OMAP4_CLKCTRL_INDEX(0x30)
#define OMAP4_SMARTREFLEX_CORE_CLKCTRL OMAP4_CLKCTRL_INDEX(0x38)
/* l3_1 clocks */
#define OMAP4_L3_MAIN_1_CLKCTRL OMAP4_CLKCTRL_INDEX(0x20)
/* l3_2 clocks */
#define OMAP4_L3_MAIN_2_CLKCTRL OMAP4_CLKCTRL_INDEX(0x20)
#define OMAP4_GPMC_CLKCTRL OMAP4_CLKCTRL_INDEX(0x28)
#define OMAP4_OCMC_RAM_CLKCTRL OMAP4_CLKCTRL_INDEX(0x30)
/* ducati clocks */
#define OMAP4_IPU_CLKCTRL OMAP4_CLKCTRL_INDEX(0x20)
/* l3_dma clocks */
#define OMAP4_DMA_SYSTEM_CLKCTRL OMAP4_CLKCTRL_INDEX(0x20)
/* l3_emif clocks */
#define OMAP4_DMM_CLKCTRL OMAP4_CLKCTRL_INDEX(0x20)
#define OMAP4_EMIF1_CLKCTRL OMAP4_CLKCTRL_INDEX(0x30)
#define OMAP4_EMIF2_CLKCTRL OMAP4_CLKCTRL_INDEX(0x38)
/* d2d clocks */
#define OMAP4_C2C_CLKCTRL OMAP4_CLKCTRL_INDEX(0x20)
/* l4_cfg clocks */
#define OMAP4_L4_CFG_CLKCTRL OMAP4_CLKCTRL_INDEX(0x20)
#define OMAP4_SPINLOCK_CLKCTRL OMAP4_CLKCTRL_INDEX(0x28)
#define OMAP4_MAILBOX_CLKCTRL OMAP4_CLKCTRL_INDEX(0x30)
/* l3_instr clocks */
#define OMAP4_L3_MAIN_3_CLKCTRL OMAP4_CLKCTRL_INDEX(0x20)
#define OMAP4_L3_INSTR_CLKCTRL OMAP4_CLKCTRL_INDEX(0x28)
#define OMAP4_OCP_WP_NOC_CLKCTRL OMAP4_CLKCTRL_INDEX(0x40)
/* ivahd clocks */
#define OMAP4_IVA_CLKCTRL OMAP4_CLKCTRL_INDEX(0x20)
#define OMAP4_SL2IF_CLKCTRL OMAP4_CLKCTRL_INDEX(0x28)
/* iss clocks */
#define OMAP4_ISS_CLKCTRL OMAP4_CLKCTRL_INDEX(0x20)
#define OMAP4_FDIF_CLKCTRL OMAP4_CLKCTRL_INDEX(0x28)
/* l3_dss clocks */
#define OMAP4_DSS_CORE_CLKCTRL OMAP4_CLKCTRL_INDEX(0x20)
/* l3_gfx clocks */
#define OMAP4_GPU_CLKCTRL OMAP4_CLKCTRL_INDEX(0x20)
/* l3_init clocks */
#define OMAP4_MMC1_CLKCTRL OMAP4_CLKCTRL_INDEX(0x28)
#define OMAP4_MMC2_CLKCTRL OMAP4_CLKCTRL_INDEX(0x30)
#define OMAP4_HSI_CLKCTRL OMAP4_CLKCTRL_INDEX(0x38)
#define OMAP4_USB_HOST_HS_CLKCTRL OMAP4_CLKCTRL_INDEX(0x58)
#define OMAP4_USB_OTG_HS_CLKCTRL OMAP4_CLKCTRL_INDEX(0x60)
#define OMAP4_USB_TLL_HS_CLKCTRL OMAP4_CLKCTRL_INDEX(0x68)
#define OMAP4_USB_HOST_FS_CLKCTRL OMAP4_CLKCTRL_INDEX(0xd0)
#define OMAP4_OCP2SCP_USB_PHY_CLKCTRL OMAP4_CLKCTRL_INDEX(0xe0)
/* l4_per clocks */
#define OMAP4_TIMER10_CLKCTRL OMAP4_CLKCTRL_INDEX(0x28)
#define OMAP4_TIMER11_CLKCTRL OMAP4_CLKCTRL_INDEX(0x30)
#define OMAP4_TIMER2_CLKCTRL OMAP4_CLKCTRL_INDEX(0x38)
#define OMAP4_TIMER3_CLKCTRL OMAP4_CLKCTRL_INDEX(0x40)
#define OMAP4_TIMER4_CLKCTRL OMAP4_CLKCTRL_INDEX(0x48)
#define OMAP4_TIMER9_CLKCTRL OMAP4_CLKCTRL_INDEX(0x50)
#define OMAP4_ELM_CLKCTRL OMAP4_CLKCTRL_INDEX(0x58)
#define OMAP4_GPIO2_CLKCTRL OMAP4_CLKCTRL_INDEX(0x60)
#define OMAP4_GPIO3_CLKCTRL OMAP4_CLKCTRL_INDEX(0x68)
#define OMAP4_GPIO4_CLKCTRL OMAP4_CLKCTRL_INDEX(0x70)
#define OMAP4_GPIO5_CLKCTRL OMAP4_CLKCTRL_INDEX(0x78)
#define OMAP4_GPIO6_CLKCTRL OMAP4_CLKCTRL_INDEX(0x80)
#define OMAP4_HDQ1W_CLKCTRL OMAP4_CLKCTRL_INDEX(0x88)
#define OMAP4_I2C1_CLKCTRL OMAP4_CLKCTRL_INDEX(0xa0)
#define OMAP4_I2C2_CLKCTRL OMAP4_CLKCTRL_INDEX(0xa8)
#define OMAP4_I2C3_CLKCTRL OMAP4_CLKCTRL_INDEX(0xb0)
#define OMAP4_I2C4_CLKCTRL OMAP4_CLKCTRL_INDEX(0xb8)
#define OMAP4_L4_PER_CLKCTRL OMAP4_CLKCTRL_INDEX(0xc0)
#define OMAP4_MCBSP4_CLKCTRL OMAP4_CLKCTRL_INDEX(0xe0)
#define OMAP4_MCSPI1_CLKCTRL OMAP4_CLKCTRL_INDEX(0xf0)
#define OMAP4_MCSPI2_CLKCTRL OMAP4_CLKCTRL_INDEX(0xf8)
#define OMAP4_MCSPI3_CLKCTRL OMAP4_CLKCTRL_INDEX(0x100)
#define OMAP4_MCSPI4_CLKCTRL OMAP4_CLKCTRL_INDEX(0x108)
#define OMAP4_MMC3_CLKCTRL OMAP4_CLKCTRL_INDEX(0x120)
#define OMAP4_MMC4_CLKCTRL OMAP4_CLKCTRL_INDEX(0x128)
#define OMAP4_SLIMBUS2_CLKCTRL OMAP4_CLKCTRL_INDEX(0x138)
#define OMAP4_UART1_CLKCTRL OMAP4_CLKCTRL_INDEX(0x140)
#define OMAP4_UART2_CLKCTRL OMAP4_CLKCTRL_INDEX(0x148)
#define OMAP4_UART3_CLKCTRL OMAP4_CLKCTRL_INDEX(0x150)
#define OMAP4_UART4_CLKCTRL OMAP4_CLKCTRL_INDEX(0x158)
#define OMAP4_MMC5_CLKCTRL OMAP4_CLKCTRL_INDEX(0x160)
/* l4_wkup clocks */
#define OMAP4_L4_WKUP_CLKCTRL OMAP4_CLKCTRL_INDEX(0x20)
#define OMAP4_WD_TIMER2_CLKCTRL OMAP4_CLKCTRL_INDEX(0x30)
#define OMAP4_GPIO1_CLKCTRL OMAP4_CLKCTRL_INDEX(0x38)
#define OMAP4_TIMER1_CLKCTRL OMAP4_CLKCTRL_INDEX(0x40)
#define OMAP4_COUNTER_32K_CLKCTRL OMAP4_CLKCTRL_INDEX(0x50)
#define OMAP4_KBD_CLKCTRL OMAP4_CLKCTRL_INDEX(0x78)
/* emu_sys clocks */
#define OMAP4_DEBUGSS_CLKCTRL OMAP4_CLKCTRL_INDEX(0x20)
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment