18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * OMAP3 Clock init
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Copyright (C) 2013 Texas Instruments, Inc
58c2ecf20Sopenharmony_ci *     Tero Kristo (t-kristo@ti.com)
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * This program is free software; you can redistribute it and/or
88c2ecf20Sopenharmony_ci * modify it under the terms of the GNU General Public License as
98c2ecf20Sopenharmony_ci * published by the Free Software Foundation version 2.
108c2ecf20Sopenharmony_ci *
118c2ecf20Sopenharmony_ci * This program is distributed "as is" WITHOUT ANY WARRANTY of any
128c2ecf20Sopenharmony_ci * kind, whether express or implied; without even the implied warranty
138c2ecf20Sopenharmony_ci * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
148c2ecf20Sopenharmony_ci * GNU General Public License for more details.
158c2ecf20Sopenharmony_ci */
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci#include <linux/kernel.h>
188c2ecf20Sopenharmony_ci#include <linux/list.h>
198c2ecf20Sopenharmony_ci#include <linux/clk.h>
208c2ecf20Sopenharmony_ci#include <linux/clk-provider.h>
218c2ecf20Sopenharmony_ci#include <linux/clk/ti.h>
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci#include "clock.h"
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci#define OMAP3430ES2_ST_DSS_IDLE_SHIFT			1
268c2ecf20Sopenharmony_ci#define OMAP3430ES2_ST_HSOTGUSB_IDLE_SHIFT		5
278c2ecf20Sopenharmony_ci#define OMAP3430ES2_ST_SSI_IDLE_SHIFT			8
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci#define OMAP34XX_CM_IDLEST_VAL				1
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci/*
328c2ecf20Sopenharmony_ci * In AM35xx IPSS, the {ICK,FCK} enable bits for modules are exported
338c2ecf20Sopenharmony_ci * in the same register at a bit offset of 0x8. The EN_ACK for ICK is
348c2ecf20Sopenharmony_ci * at an offset of 4 from ICK enable bit.
358c2ecf20Sopenharmony_ci */
368c2ecf20Sopenharmony_ci#define AM35XX_IPSS_ICK_MASK			0xF
378c2ecf20Sopenharmony_ci#define AM35XX_IPSS_ICK_EN_ACK_OFFSET		0x4
388c2ecf20Sopenharmony_ci#define AM35XX_IPSS_ICK_FCK_OFFSET		0x8
398c2ecf20Sopenharmony_ci#define AM35XX_IPSS_CLK_IDLEST_VAL		0
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci#define AM35XX_ST_IPSS_SHIFT			5
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci/**
448c2ecf20Sopenharmony_ci * omap3430es2_clk_ssi_find_idlest - return CM_IDLEST info for SSI
458c2ecf20Sopenharmony_ci * @clk: struct clk * being enabled
468c2ecf20Sopenharmony_ci * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
478c2ecf20Sopenharmony_ci * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
488c2ecf20Sopenharmony_ci * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
498c2ecf20Sopenharmony_ci *
508c2ecf20Sopenharmony_ci * The OMAP3430ES2 SSI target CM_IDLEST bit is at a different shift
518c2ecf20Sopenharmony_ci * from the CM_{I,F}CLKEN bit.  Pass back the correct info via
528c2ecf20Sopenharmony_ci * @idlest_reg and @idlest_bit.  No return value.
538c2ecf20Sopenharmony_ci */
548c2ecf20Sopenharmony_cistatic void omap3430es2_clk_ssi_find_idlest(struct clk_hw_omap *clk,
558c2ecf20Sopenharmony_ci					    struct clk_omap_reg *idlest_reg,
568c2ecf20Sopenharmony_ci					    u8 *idlest_bit,
578c2ecf20Sopenharmony_ci					    u8 *idlest_val)
588c2ecf20Sopenharmony_ci{
598c2ecf20Sopenharmony_ci	memcpy(idlest_reg, &clk->enable_reg, sizeof(*idlest_reg));
608c2ecf20Sopenharmony_ci	idlest_reg->offset &= ~0xf0;
618c2ecf20Sopenharmony_ci	idlest_reg->offset |= 0x20;
628c2ecf20Sopenharmony_ci	*idlest_bit = OMAP3430ES2_ST_SSI_IDLE_SHIFT;
638c2ecf20Sopenharmony_ci	*idlest_val = OMAP34XX_CM_IDLEST_VAL;
648c2ecf20Sopenharmony_ci}
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ciconst struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_ssi_wait = {
678c2ecf20Sopenharmony_ci	.allow_idle	= omap2_clkt_iclk_allow_idle,
688c2ecf20Sopenharmony_ci	.deny_idle	= omap2_clkt_iclk_deny_idle,
698c2ecf20Sopenharmony_ci	.find_idlest	= omap3430es2_clk_ssi_find_idlest,
708c2ecf20Sopenharmony_ci	.find_companion	= omap2_clk_dflt_find_companion,
718c2ecf20Sopenharmony_ci};
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci/**
748c2ecf20Sopenharmony_ci * omap3430es2_clk_dss_usbhost_find_idlest - CM_IDLEST info for DSS, USBHOST
758c2ecf20Sopenharmony_ci * @clk: struct clk * being enabled
768c2ecf20Sopenharmony_ci * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
778c2ecf20Sopenharmony_ci * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
788c2ecf20Sopenharmony_ci * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
798c2ecf20Sopenharmony_ci *
808c2ecf20Sopenharmony_ci * Some OMAP modules on OMAP3 ES2+ chips have both initiator and
818c2ecf20Sopenharmony_ci * target IDLEST bits.  For our purposes, we are concerned with the
828c2ecf20Sopenharmony_ci * target IDLEST bits, which exist at a different bit position than
838c2ecf20Sopenharmony_ci * the *CLKEN bit position for these modules (DSS and USBHOST) (The
848c2ecf20Sopenharmony_ci * default find_idlest code assumes that they are at the same
858c2ecf20Sopenharmony_ci * position.)  No return value.
868c2ecf20Sopenharmony_ci */
878c2ecf20Sopenharmony_cistatic void
888c2ecf20Sopenharmony_ciomap3430es2_clk_dss_usbhost_find_idlest(struct clk_hw_omap *clk,
898c2ecf20Sopenharmony_ci					struct clk_omap_reg *idlest_reg,
908c2ecf20Sopenharmony_ci					u8 *idlest_bit, u8 *idlest_val)
918c2ecf20Sopenharmony_ci{
928c2ecf20Sopenharmony_ci	memcpy(idlest_reg, &clk->enable_reg, sizeof(*idlest_reg));
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci	idlest_reg->offset &= ~0xf0;
958c2ecf20Sopenharmony_ci	idlest_reg->offset |= 0x20;
968c2ecf20Sopenharmony_ci	/* USBHOST_IDLE has same shift */
978c2ecf20Sopenharmony_ci	*idlest_bit = OMAP3430ES2_ST_DSS_IDLE_SHIFT;
988c2ecf20Sopenharmony_ci	*idlest_val = OMAP34XX_CM_IDLEST_VAL;
998c2ecf20Sopenharmony_ci}
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ciconst struct clk_hw_omap_ops clkhwops_omap3430es2_dss_usbhost_wait = {
1028c2ecf20Sopenharmony_ci	.find_idlest	= omap3430es2_clk_dss_usbhost_find_idlest,
1038c2ecf20Sopenharmony_ci	.find_companion	= omap2_clk_dflt_find_companion,
1048c2ecf20Sopenharmony_ci};
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ciconst struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_dss_usbhost_wait = {
1078c2ecf20Sopenharmony_ci	.allow_idle	= omap2_clkt_iclk_allow_idle,
1088c2ecf20Sopenharmony_ci	.deny_idle	= omap2_clkt_iclk_deny_idle,
1098c2ecf20Sopenharmony_ci	.find_idlest	= omap3430es2_clk_dss_usbhost_find_idlest,
1108c2ecf20Sopenharmony_ci	.find_companion	= omap2_clk_dflt_find_companion,
1118c2ecf20Sopenharmony_ci};
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ci/**
1148c2ecf20Sopenharmony_ci * omap3430es2_clk_hsotgusb_find_idlest - return CM_IDLEST info for HSOTGUSB
1158c2ecf20Sopenharmony_ci * @clk: struct clk * being enabled
1168c2ecf20Sopenharmony_ci * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
1178c2ecf20Sopenharmony_ci * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
1188c2ecf20Sopenharmony_ci * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
1198c2ecf20Sopenharmony_ci *
1208c2ecf20Sopenharmony_ci * The OMAP3430ES2 HSOTGUSB target CM_IDLEST bit is at a different
1218c2ecf20Sopenharmony_ci * shift from the CM_{I,F}CLKEN bit.  Pass back the correct info via
1228c2ecf20Sopenharmony_ci * @idlest_reg and @idlest_bit.  No return value.
1238c2ecf20Sopenharmony_ci */
1248c2ecf20Sopenharmony_cistatic void
1258c2ecf20Sopenharmony_ciomap3430es2_clk_hsotgusb_find_idlest(struct clk_hw_omap *clk,
1268c2ecf20Sopenharmony_ci				     struct clk_omap_reg *idlest_reg,
1278c2ecf20Sopenharmony_ci				     u8 *idlest_bit,
1288c2ecf20Sopenharmony_ci				     u8 *idlest_val)
1298c2ecf20Sopenharmony_ci{
1308c2ecf20Sopenharmony_ci	memcpy(idlest_reg, &clk->enable_reg, sizeof(*idlest_reg));
1318c2ecf20Sopenharmony_ci	idlest_reg->offset &= ~0xf0;
1328c2ecf20Sopenharmony_ci	idlest_reg->offset |= 0x20;
1338c2ecf20Sopenharmony_ci	*idlest_bit = OMAP3430ES2_ST_HSOTGUSB_IDLE_SHIFT;
1348c2ecf20Sopenharmony_ci	*idlest_val = OMAP34XX_CM_IDLEST_VAL;
1358c2ecf20Sopenharmony_ci}
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ciconst struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_hsotgusb_wait = {
1388c2ecf20Sopenharmony_ci	.allow_idle	= omap2_clkt_iclk_allow_idle,
1398c2ecf20Sopenharmony_ci	.deny_idle	= omap2_clkt_iclk_deny_idle,
1408c2ecf20Sopenharmony_ci	.find_idlest	= omap3430es2_clk_hsotgusb_find_idlest,
1418c2ecf20Sopenharmony_ci	.find_companion	= omap2_clk_dflt_find_companion,
1428c2ecf20Sopenharmony_ci};
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci/**
1458c2ecf20Sopenharmony_ci * am35xx_clk_find_idlest - return clock ACK info for AM35XX IPSS
1468c2ecf20Sopenharmony_ci * @clk: struct clk * being enabled
1478c2ecf20Sopenharmony_ci * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
1488c2ecf20Sopenharmony_ci * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
1498c2ecf20Sopenharmony_ci * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
1508c2ecf20Sopenharmony_ci *
1518c2ecf20Sopenharmony_ci * The interface clocks on AM35xx IPSS reflects the clock idle status
1528c2ecf20Sopenharmony_ci * in the enable register itsel at a bit offset of 4 from the enable
1538c2ecf20Sopenharmony_ci * bit. A value of 1 indicates that clock is enabled.
1548c2ecf20Sopenharmony_ci */
1558c2ecf20Sopenharmony_cistatic void am35xx_clk_find_idlest(struct clk_hw_omap *clk,
1568c2ecf20Sopenharmony_ci				   struct clk_omap_reg *idlest_reg,
1578c2ecf20Sopenharmony_ci				   u8 *idlest_bit,
1588c2ecf20Sopenharmony_ci				   u8 *idlest_val)
1598c2ecf20Sopenharmony_ci{
1608c2ecf20Sopenharmony_ci	memcpy(idlest_reg, &clk->enable_reg, sizeof(*idlest_reg));
1618c2ecf20Sopenharmony_ci	*idlest_bit = clk->enable_bit + AM35XX_IPSS_ICK_EN_ACK_OFFSET;
1628c2ecf20Sopenharmony_ci	*idlest_val = AM35XX_IPSS_CLK_IDLEST_VAL;
1638c2ecf20Sopenharmony_ci}
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci/**
1668c2ecf20Sopenharmony_ci * am35xx_clk_find_companion - find companion clock to @clk
1678c2ecf20Sopenharmony_ci * @clk: struct clk * to find the companion clock of
1688c2ecf20Sopenharmony_ci * @other_reg: void __iomem ** to return the companion clock CM_*CLKEN va in
1698c2ecf20Sopenharmony_ci * @other_bit: u8 ** to return the companion clock bit shift in
1708c2ecf20Sopenharmony_ci *
1718c2ecf20Sopenharmony_ci * Some clocks don't have companion clocks.  For example, modules with
1728c2ecf20Sopenharmony_ci * only an interface clock (such as HECC) don't have a companion
1738c2ecf20Sopenharmony_ci * clock.  Right now, this code relies on the hardware exporting a bit
1748c2ecf20Sopenharmony_ci * in the correct companion register that indicates that the
1758c2ecf20Sopenharmony_ci * nonexistent 'companion clock' is active.  Future patches will
1768c2ecf20Sopenharmony_ci * associate this type of code with per-module data structures to
1778c2ecf20Sopenharmony_ci * avoid this issue, and remove the casts.  No return value.
1788c2ecf20Sopenharmony_ci */
1798c2ecf20Sopenharmony_cistatic void am35xx_clk_find_companion(struct clk_hw_omap *clk,
1808c2ecf20Sopenharmony_ci				      struct clk_omap_reg *other_reg,
1818c2ecf20Sopenharmony_ci				      u8 *other_bit)
1828c2ecf20Sopenharmony_ci{
1838c2ecf20Sopenharmony_ci	memcpy(other_reg, &clk->enable_reg, sizeof(*other_reg));
1848c2ecf20Sopenharmony_ci	if (clk->enable_bit & AM35XX_IPSS_ICK_MASK)
1858c2ecf20Sopenharmony_ci		*other_bit = clk->enable_bit + AM35XX_IPSS_ICK_FCK_OFFSET;
1868c2ecf20Sopenharmony_ci	else
1878c2ecf20Sopenharmony_ci	*other_bit = clk->enable_bit - AM35XX_IPSS_ICK_FCK_OFFSET;
1888c2ecf20Sopenharmony_ci}
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_ciconst struct clk_hw_omap_ops clkhwops_am35xx_ipss_module_wait = {
1918c2ecf20Sopenharmony_ci	.find_idlest	= am35xx_clk_find_idlest,
1928c2ecf20Sopenharmony_ci	.find_companion	= am35xx_clk_find_companion,
1938c2ecf20Sopenharmony_ci};
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci/**
1968c2ecf20Sopenharmony_ci * am35xx_clk_ipss_find_idlest - return CM_IDLEST info for IPSS
1978c2ecf20Sopenharmony_ci * @clk: struct clk * being enabled
1988c2ecf20Sopenharmony_ci * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
1998c2ecf20Sopenharmony_ci * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
2008c2ecf20Sopenharmony_ci * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
2018c2ecf20Sopenharmony_ci *
2028c2ecf20Sopenharmony_ci * The IPSS target CM_IDLEST bit is at a different shift from the
2038c2ecf20Sopenharmony_ci * CM_{I,F}CLKEN bit.  Pass back the correct info via @idlest_reg
2048c2ecf20Sopenharmony_ci * and @idlest_bit.  No return value.
2058c2ecf20Sopenharmony_ci */
2068c2ecf20Sopenharmony_cistatic void am35xx_clk_ipss_find_idlest(struct clk_hw_omap *clk,
2078c2ecf20Sopenharmony_ci					struct clk_omap_reg *idlest_reg,
2088c2ecf20Sopenharmony_ci					u8 *idlest_bit,
2098c2ecf20Sopenharmony_ci					u8 *idlest_val)
2108c2ecf20Sopenharmony_ci{
2118c2ecf20Sopenharmony_ci	memcpy(idlest_reg, &clk->enable_reg, sizeof(*idlest_reg));
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_ci	idlest_reg->offset &= ~0xf0;
2148c2ecf20Sopenharmony_ci	idlest_reg->offset |= 0x20;
2158c2ecf20Sopenharmony_ci	*idlest_bit = AM35XX_ST_IPSS_SHIFT;
2168c2ecf20Sopenharmony_ci	*idlest_val = OMAP34XX_CM_IDLEST_VAL;
2178c2ecf20Sopenharmony_ci}
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_ciconst struct clk_hw_omap_ops clkhwops_am35xx_ipss_wait = {
2208c2ecf20Sopenharmony_ci	.allow_idle	= omap2_clkt_iclk_allow_idle,
2218c2ecf20Sopenharmony_ci	.deny_idle	= omap2_clkt_iclk_deny_idle,
2228c2ecf20Sopenharmony_ci	.find_idlest	= am35xx_clk_ipss_find_idlest,
2238c2ecf20Sopenharmony_ci	.find_companion	= omap2_clk_dflt_find_companion,
2248c2ecf20Sopenharmony_ci};
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_cistatic struct ti_dt_clk omap3xxx_clks[] = {
2278c2ecf20Sopenharmony_ci	DT_CLK(NULL, "timer_32k_ck", "omap_32k_fck"),
2288c2ecf20Sopenharmony_ci	DT_CLK(NULL, "timer_sys_ck", "sys_ck"),
2298c2ecf20Sopenharmony_ci	{ .node_name = NULL },
2308c2ecf20Sopenharmony_ci};
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_cistatic struct ti_dt_clk omap36xx_omap3430es2plus_clks[] = {
2338c2ecf20Sopenharmony_ci	DT_CLK(NULL, "ssi_ssr_fck", "ssi_ssr_fck_3430es2"),
2348c2ecf20Sopenharmony_ci	DT_CLK(NULL, "ssi_sst_fck", "ssi_sst_fck_3430es2"),
2358c2ecf20Sopenharmony_ci	DT_CLK(NULL, "hsotgusb_ick", "hsotgusb_ick_3430es2"),
2368c2ecf20Sopenharmony_ci	DT_CLK(NULL, "ssi_ick", "ssi_ick_3430es2"),
2378c2ecf20Sopenharmony_ci	{ .node_name = NULL },
2388c2ecf20Sopenharmony_ci};
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_cistatic struct ti_dt_clk omap3430es1_clks[] = {
2418c2ecf20Sopenharmony_ci	DT_CLK(NULL, "ssi_ssr_fck", "ssi_ssr_fck_3430es1"),
2428c2ecf20Sopenharmony_ci	DT_CLK(NULL, "ssi_sst_fck", "ssi_sst_fck_3430es1"),
2438c2ecf20Sopenharmony_ci	DT_CLK(NULL, "hsotgusb_ick", "hsotgusb_ick_3430es1"),
2448c2ecf20Sopenharmony_ci	DT_CLK(NULL, "ssi_ick", "ssi_ick_3430es1"),
2458c2ecf20Sopenharmony_ci	DT_CLK(NULL, "dss1_alwon_fck", "dss1_alwon_fck_3430es1"),
2468c2ecf20Sopenharmony_ci	DT_CLK(NULL, "dss_ick", "dss_ick_3430es1"),
2478c2ecf20Sopenharmony_ci	{ .node_name = NULL },
2488c2ecf20Sopenharmony_ci};
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_cistatic struct ti_dt_clk omap36xx_am35xx_omap3430es2plus_clks[] = {
2518c2ecf20Sopenharmony_ci	DT_CLK(NULL, "dss1_alwon_fck", "dss1_alwon_fck_3430es2"),
2528c2ecf20Sopenharmony_ci	DT_CLK(NULL, "dss_ick", "dss_ick_3430es2"),
2538c2ecf20Sopenharmony_ci	{ .node_name = NULL },
2548c2ecf20Sopenharmony_ci};
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_cistatic struct ti_dt_clk am35xx_clks[] = {
2578c2ecf20Sopenharmony_ci	DT_CLK(NULL, "hsotgusb_ick", "hsotgusb_ick_am35xx"),
2588c2ecf20Sopenharmony_ci	DT_CLK(NULL, "hsotgusb_fck", "hsotgusb_fck_am35xx"),
2598c2ecf20Sopenharmony_ci	DT_CLK(NULL, "uart4_ick", "uart4_ick_am35xx"),
2608c2ecf20Sopenharmony_ci	DT_CLK(NULL, "uart4_fck", "uart4_fck_am35xx"),
2618c2ecf20Sopenharmony_ci	{ .node_name = NULL },
2628c2ecf20Sopenharmony_ci};
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_cistatic const char *enable_init_clks[] = {
2658c2ecf20Sopenharmony_ci	"sdrc_ick",
2668c2ecf20Sopenharmony_ci	"gpmc_fck",
2678c2ecf20Sopenharmony_ci	"omapctrl_ick",
2688c2ecf20Sopenharmony_ci};
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_cienum {
2718c2ecf20Sopenharmony_ci	OMAP3_SOC_AM35XX,
2728c2ecf20Sopenharmony_ci	OMAP3_SOC_OMAP3430_ES1,
2738c2ecf20Sopenharmony_ci	OMAP3_SOC_OMAP3430_ES2_PLUS,
2748c2ecf20Sopenharmony_ci	OMAP3_SOC_OMAP3630,
2758c2ecf20Sopenharmony_ci};
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_ci/**
2788c2ecf20Sopenharmony_ci * omap3_clk_lock_dpll5 - locks DPLL5
2798c2ecf20Sopenharmony_ci *
2808c2ecf20Sopenharmony_ci * Locks DPLL5 to a pre-defined frequency. This is required for proper
2818c2ecf20Sopenharmony_ci * operation of USB.
2828c2ecf20Sopenharmony_ci */
2838c2ecf20Sopenharmony_civoid __init omap3_clk_lock_dpll5(void)
2848c2ecf20Sopenharmony_ci{
2858c2ecf20Sopenharmony_ci	struct clk *dpll5_clk;
2868c2ecf20Sopenharmony_ci	struct clk *dpll5_m2_clk;
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ci	/*
2898c2ecf20Sopenharmony_ci	 * Errata sprz319f advisory 2.1 documents a USB host clock drift issue
2908c2ecf20Sopenharmony_ci	 * that can be worked around using specially crafted dpll5 settings
2918c2ecf20Sopenharmony_ci	 * with a dpll5_m2 divider set to 8. Set the dpll5 rate to 8x the USB
2928c2ecf20Sopenharmony_ci	 * host clock rate, its .set_rate handler() will detect that frequency
2938c2ecf20Sopenharmony_ci	 * and use the errata settings.
2948c2ecf20Sopenharmony_ci	 */
2958c2ecf20Sopenharmony_ci	dpll5_clk = clk_get(NULL, "dpll5_ck");
2968c2ecf20Sopenharmony_ci	clk_set_rate(dpll5_clk, OMAP3_DPLL5_FREQ_FOR_USBHOST * 8);
2978c2ecf20Sopenharmony_ci	clk_prepare_enable(dpll5_clk);
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci	/* Program dpll5_m2_clk divider */
3008c2ecf20Sopenharmony_ci	dpll5_m2_clk = clk_get(NULL, "dpll5_m2_ck");
3018c2ecf20Sopenharmony_ci	clk_prepare_enable(dpll5_m2_clk);
3028c2ecf20Sopenharmony_ci	clk_set_rate(dpll5_m2_clk, OMAP3_DPLL5_FREQ_FOR_USBHOST);
3038c2ecf20Sopenharmony_ci
3048c2ecf20Sopenharmony_ci	clk_disable_unprepare(dpll5_m2_clk);
3058c2ecf20Sopenharmony_ci	clk_disable_unprepare(dpll5_clk);
3068c2ecf20Sopenharmony_ci}
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_cistatic int __init omap3xxx_dt_clk_init(int soc_type)
3098c2ecf20Sopenharmony_ci{
3108c2ecf20Sopenharmony_ci	if (soc_type == OMAP3_SOC_AM35XX || soc_type == OMAP3_SOC_OMAP3630 ||
3118c2ecf20Sopenharmony_ci	    soc_type == OMAP3_SOC_OMAP3430_ES1 ||
3128c2ecf20Sopenharmony_ci	    soc_type == OMAP3_SOC_OMAP3430_ES2_PLUS)
3138c2ecf20Sopenharmony_ci		ti_dt_clocks_register(omap3xxx_clks);
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_ci	if (soc_type == OMAP3_SOC_AM35XX)
3168c2ecf20Sopenharmony_ci		ti_dt_clocks_register(am35xx_clks);
3178c2ecf20Sopenharmony_ci
3188c2ecf20Sopenharmony_ci	if (soc_type == OMAP3_SOC_OMAP3630 || soc_type == OMAP3_SOC_AM35XX ||
3198c2ecf20Sopenharmony_ci	    soc_type == OMAP3_SOC_OMAP3430_ES2_PLUS)
3208c2ecf20Sopenharmony_ci		ti_dt_clocks_register(omap36xx_am35xx_omap3430es2plus_clks);
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_ci	if (soc_type == OMAP3_SOC_OMAP3430_ES1)
3238c2ecf20Sopenharmony_ci		ti_dt_clocks_register(omap3430es1_clks);
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_ci	if (soc_type == OMAP3_SOC_OMAP3430_ES2_PLUS ||
3268c2ecf20Sopenharmony_ci	    soc_type == OMAP3_SOC_OMAP3630)
3278c2ecf20Sopenharmony_ci		ti_dt_clocks_register(omap36xx_omap3430es2plus_clks);
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_ci	omap2_clk_disable_autoidle_all();
3308c2ecf20Sopenharmony_ci
3318c2ecf20Sopenharmony_ci	ti_clk_add_aliases();
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_ci	omap2_clk_enable_init_clocks(enable_init_clks,
3348c2ecf20Sopenharmony_ci				     ARRAY_SIZE(enable_init_clks));
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_ci	pr_info("Clocking rate (Crystal/Core/MPU): %ld.%01ld/%ld/%ld MHz\n",
3378c2ecf20Sopenharmony_ci		(clk_get_rate(clk_get_sys(NULL, "osc_sys_ck")) / 1000000),
3388c2ecf20Sopenharmony_ci		(clk_get_rate(clk_get_sys(NULL, "osc_sys_ck")) / 100000) % 10,
3398c2ecf20Sopenharmony_ci		(clk_get_rate(clk_get_sys(NULL, "core_ck")) / 1000000),
3408c2ecf20Sopenharmony_ci		(clk_get_rate(clk_get_sys(NULL, "arm_fck")) / 1000000));
3418c2ecf20Sopenharmony_ci
3428c2ecf20Sopenharmony_ci	if (soc_type != OMAP3_SOC_OMAP3430_ES1)
3438c2ecf20Sopenharmony_ci		omap3_clk_lock_dpll5();
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_ci	return 0;
3468c2ecf20Sopenharmony_ci}
3478c2ecf20Sopenharmony_ci
3488c2ecf20Sopenharmony_ciint __init omap3430_dt_clk_init(void)
3498c2ecf20Sopenharmony_ci{
3508c2ecf20Sopenharmony_ci	return omap3xxx_dt_clk_init(OMAP3_SOC_OMAP3430_ES2_PLUS);
3518c2ecf20Sopenharmony_ci}
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_ciint __init omap3630_dt_clk_init(void)
3548c2ecf20Sopenharmony_ci{
3558c2ecf20Sopenharmony_ci	return omap3xxx_dt_clk_init(OMAP3_SOC_OMAP3630);
3568c2ecf20Sopenharmony_ci}
3578c2ecf20Sopenharmony_ci
3588c2ecf20Sopenharmony_ciint __init am35xx_dt_clk_init(void)
3598c2ecf20Sopenharmony_ci{
3608c2ecf20Sopenharmony_ci	return omap3xxx_dt_clk_init(OMAP3_SOC_AM35XX);
3618c2ecf20Sopenharmony_ci}
362