 0944799156
			
		
	
	
	0944799156
	
	
	
		
			
			A subsequent patch will add a generic PWM API driver for the Tegra PWFM controller, supporting all four PWM devices with a single PWM chip. The device will be named tegra-pwm and only one clock needs to be provided. Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de> Signed-off-by: Stephen Warren <swarren@nvidia.com>
		
			
				
	
	
		
			3104 lines
		
	
	
	
		
			90 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			3104 lines
		
	
	
	
		
			90 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * arch/arm/mach-tegra/tegra30_clocks.c
 | |
|  *
 | |
|  * Copyright (c) 2010-2011 NVIDIA CORPORATION.  All rights reserved.
 | |
|  *
 | |
|  * This program is free software; you can redistribute it and/or modify
 | |
|  * it under the terms of the GNU General Public License as published by
 | |
|  * the Free Software Foundation; version 2 of the License.
 | |
|  *
 | |
|  * 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.
 | |
|  *
 | |
|  * You should have received a copy of the GNU General Public License along
 | |
|  * with this program; if not, write to the Free Software Foundation, Inc.,
 | |
|  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| #include <linux/kernel.h>
 | |
| #include <linux/module.h>
 | |
| #include <linux/list.h>
 | |
| #include <linux/spinlock.h>
 | |
| #include <linux/delay.h>
 | |
| #include <linux/err.h>
 | |
| #include <linux/io.h>
 | |
| #include <linux/clk.h>
 | |
| #include <linux/cpufreq.h>
 | |
| #include <linux/syscore_ops.h>
 | |
| 
 | |
| #include <asm/clkdev.h>
 | |
| 
 | |
| #include <mach/iomap.h>
 | |
| 
 | |
| #include "clock.h"
 | |
| #include "fuse.h"
 | |
| 
 | |
| #define USE_PLL_LOCK_BITS 0
 | |
| 
 | |
| #define RST_DEVICES_L			0x004
 | |
| #define RST_DEVICES_H			0x008
 | |
| #define RST_DEVICES_U			0x00C
 | |
| #define RST_DEVICES_V			0x358
 | |
| #define RST_DEVICES_W			0x35C
 | |
| #define RST_DEVICES_SET_L		0x300
 | |
| #define RST_DEVICES_CLR_L		0x304
 | |
| #define RST_DEVICES_SET_V		0x430
 | |
| #define RST_DEVICES_CLR_V		0x434
 | |
| #define RST_DEVICES_NUM			5
 | |
| 
 | |
| #define CLK_OUT_ENB_L			0x010
 | |
| #define CLK_OUT_ENB_H			0x014
 | |
| #define CLK_OUT_ENB_U			0x018
 | |
| #define CLK_OUT_ENB_V			0x360
 | |
| #define CLK_OUT_ENB_W			0x364
 | |
| #define CLK_OUT_ENB_SET_L		0x320
 | |
| #define CLK_OUT_ENB_CLR_L		0x324
 | |
| #define CLK_OUT_ENB_SET_V		0x440
 | |
| #define CLK_OUT_ENB_CLR_V		0x444
 | |
| #define CLK_OUT_ENB_NUM			5
 | |
| 
 | |
| #define RST_DEVICES_V_SWR_CPULP_RST_DIS	(0x1 << 1)
 | |
| #define CLK_OUT_ENB_V_CLK_ENB_CPULP_EN	(0x1 << 1)
 | |
| 
 | |
| #define PERIPH_CLK_TO_BIT(c)		(1 << (c->u.periph.clk_num % 32))
 | |
| #define PERIPH_CLK_TO_RST_REG(c)	\
 | |
| 	periph_clk_to_reg((c), RST_DEVICES_L, RST_DEVICES_V, 4)
 | |
| #define PERIPH_CLK_TO_RST_SET_REG(c)	\
 | |
| 	periph_clk_to_reg((c), RST_DEVICES_SET_L, RST_DEVICES_SET_V, 8)
 | |
| #define PERIPH_CLK_TO_RST_CLR_REG(c)	\
 | |
| 	periph_clk_to_reg((c), RST_DEVICES_CLR_L, RST_DEVICES_CLR_V, 8)
 | |
| 
 | |
| #define PERIPH_CLK_TO_ENB_REG(c)	\
 | |
| 	periph_clk_to_reg((c), CLK_OUT_ENB_L, CLK_OUT_ENB_V, 4)
 | |
| #define PERIPH_CLK_TO_ENB_SET_REG(c)	\
 | |
| 	periph_clk_to_reg((c), CLK_OUT_ENB_SET_L, CLK_OUT_ENB_SET_V, 8)
 | |
| #define PERIPH_CLK_TO_ENB_CLR_REG(c)	\
 | |
| 	periph_clk_to_reg((c), CLK_OUT_ENB_CLR_L, CLK_OUT_ENB_CLR_V, 8)
 | |
| 
 | |
| #define CLK_MASK_ARM			0x44
 | |
| #define MISC_CLK_ENB			0x48
 | |
| 
 | |
| #define OSC_CTRL			0x50
 | |
| #define OSC_CTRL_OSC_FREQ_MASK		(0xF<<28)
 | |
| #define OSC_CTRL_OSC_FREQ_13MHZ		(0x0<<28)
 | |
| #define OSC_CTRL_OSC_FREQ_19_2MHZ	(0x4<<28)
 | |
| #define OSC_CTRL_OSC_FREQ_12MHZ		(0x8<<28)
 | |
| #define OSC_CTRL_OSC_FREQ_26MHZ		(0xC<<28)
 | |
| #define OSC_CTRL_OSC_FREQ_16_8MHZ	(0x1<<28)
 | |
| #define OSC_CTRL_OSC_FREQ_38_4MHZ	(0x5<<28)
 | |
| #define OSC_CTRL_OSC_FREQ_48MHZ		(0x9<<28)
 | |
| #define OSC_CTRL_MASK			(0x3f2 | OSC_CTRL_OSC_FREQ_MASK)
 | |
| 
 | |
| #define OSC_CTRL_PLL_REF_DIV_MASK	(3<<26)
 | |
| #define OSC_CTRL_PLL_REF_DIV_1		(0<<26)
 | |
| #define OSC_CTRL_PLL_REF_DIV_2		(1<<26)
 | |
| #define OSC_CTRL_PLL_REF_DIV_4		(2<<26)
 | |
| 
 | |
| #define OSC_FREQ_DET			0x58
 | |
| #define OSC_FREQ_DET_TRIG		(1<<31)
 | |
| 
 | |
| #define OSC_FREQ_DET_STATUS		0x5C
 | |
| #define OSC_FREQ_DET_BUSY		(1<<31)
 | |
| #define OSC_FREQ_DET_CNT_MASK		0xFFFF
 | |
| 
 | |
| #define PERIPH_CLK_SOURCE_I2S1		0x100
 | |
| #define PERIPH_CLK_SOURCE_EMC		0x19c
 | |
| #define PERIPH_CLK_SOURCE_OSC		0x1fc
 | |
| #define PERIPH_CLK_SOURCE_NUM1 \
 | |
| 	((PERIPH_CLK_SOURCE_OSC - PERIPH_CLK_SOURCE_I2S1) / 4)
 | |
| 
 | |
| #define PERIPH_CLK_SOURCE_G3D2		0x3b0
 | |
| #define PERIPH_CLK_SOURCE_SE		0x42c
 | |
| #define PERIPH_CLK_SOURCE_NUM2 \
 | |
| 	((PERIPH_CLK_SOURCE_SE - PERIPH_CLK_SOURCE_G3D2) / 4 + 1)
 | |
| 
 | |
| #define AUDIO_DLY_CLK			0x49c
 | |
| #define AUDIO_SYNC_CLK_SPDIF		0x4b4
 | |
| #define PERIPH_CLK_SOURCE_NUM3 \
 | |
| 	((AUDIO_SYNC_CLK_SPDIF - AUDIO_DLY_CLK) / 4 + 1)
 | |
| 
 | |
| #define PERIPH_CLK_SOURCE_NUM		(PERIPH_CLK_SOURCE_NUM1 + \
 | |
| 					 PERIPH_CLK_SOURCE_NUM2 + \
 | |
| 					 PERIPH_CLK_SOURCE_NUM3)
 | |
| 
 | |
| #define CPU_SOFTRST_CTRL		0x380
 | |
| 
 | |
| #define PERIPH_CLK_SOURCE_DIVU71_MASK	0xFF
 | |
| #define PERIPH_CLK_SOURCE_DIVU16_MASK	0xFFFF
 | |
| #define PERIPH_CLK_SOURCE_DIV_SHIFT	0
 | |
| #define PERIPH_CLK_SOURCE_DIVIDLE_SHIFT	8
 | |
| #define PERIPH_CLK_SOURCE_DIVIDLE_VAL	50
 | |
| #define PERIPH_CLK_UART_DIV_ENB		(1<<24)
 | |
| #define PERIPH_CLK_VI_SEL_EX_SHIFT	24
 | |
| #define PERIPH_CLK_VI_SEL_EX_MASK	(0x3<<PERIPH_CLK_VI_SEL_EX_SHIFT)
 | |
| #define PERIPH_CLK_NAND_DIV_EX_ENB	(1<<8)
 | |
| #define PERIPH_CLK_DTV_POLARITY_INV	(1<<25)
 | |
| 
 | |
| #define AUDIO_SYNC_SOURCE_MASK		0x0F
 | |
| #define AUDIO_SYNC_DISABLE_BIT		0x10
 | |
| #define AUDIO_SYNC_TAP_NIBBLE_SHIFT(c)	((c->reg_shift - 24) * 4)
 | |
| 
 | |
| #define PLL_BASE			0x0
 | |
| #define PLL_BASE_BYPASS			(1<<31)
 | |
| #define PLL_BASE_ENABLE			(1<<30)
 | |
| #define PLL_BASE_REF_ENABLE		(1<<29)
 | |
| #define PLL_BASE_OVERRIDE		(1<<28)
 | |
| #define PLL_BASE_LOCK			(1<<27)
 | |
| #define PLL_BASE_DIVP_MASK		(0x7<<20)
 | |
| #define PLL_BASE_DIVP_SHIFT		20
 | |
| #define PLL_BASE_DIVN_MASK		(0x3FF<<8)
 | |
| #define PLL_BASE_DIVN_SHIFT		8
 | |
| #define PLL_BASE_DIVM_MASK		(0x1F)
 | |
| #define PLL_BASE_DIVM_SHIFT		0
 | |
| 
 | |
| #define PLL_OUT_RATIO_MASK		(0xFF<<8)
 | |
| #define PLL_OUT_RATIO_SHIFT		8
 | |
| #define PLL_OUT_OVERRIDE		(1<<2)
 | |
| #define PLL_OUT_CLKEN			(1<<1)
 | |
| #define PLL_OUT_RESET_DISABLE		(1<<0)
 | |
| 
 | |
| #define PLL_MISC(c)			\
 | |
| 	(((c)->flags & PLL_ALT_MISC_REG) ? 0x4 : 0xc)
 | |
| #define PLL_MISC_LOCK_ENABLE(c)	\
 | |
| 	(((c)->flags & (PLLU | PLLD)) ? (1<<22) : (1<<18))
 | |
| 
 | |
| #define PLL_MISC_DCCON_SHIFT		20
 | |
| #define PLL_MISC_CPCON_SHIFT		8
 | |
| #define PLL_MISC_CPCON_MASK		(0xF<<PLL_MISC_CPCON_SHIFT)
 | |
| #define PLL_MISC_LFCON_SHIFT		4
 | |
| #define PLL_MISC_LFCON_MASK		(0xF<<PLL_MISC_LFCON_SHIFT)
 | |
| #define PLL_MISC_VCOCON_SHIFT		0
 | |
| #define PLL_MISC_VCOCON_MASK		(0xF<<PLL_MISC_VCOCON_SHIFT)
 | |
| #define PLLD_MISC_CLKENABLE		(1<<30)
 | |
| 
 | |
| #define PLLU_BASE_POST_DIV		(1<<20)
 | |
| 
 | |
| #define PLLD_BASE_DSIB_MUX_SHIFT	25
 | |
| #define PLLD_BASE_DSIB_MUX_MASK		(1<<PLLD_BASE_DSIB_MUX_SHIFT)
 | |
| #define PLLD_BASE_CSI_CLKENABLE		(1<<26)
 | |
| #define PLLD_MISC_DSI_CLKENABLE		(1<<30)
 | |
| #define PLLD_MISC_DIV_RST		(1<<23)
 | |
| #define PLLD_MISC_DCCON_SHIFT		12
 | |
| 
 | |
| #define PLLDU_LFCON_SET_DIVN		600
 | |
| 
 | |
| /* FIXME: OUT_OF_TABLE_CPCON per pll */
 | |
| #define OUT_OF_TABLE_CPCON		0x8
 | |
| 
 | |
| #define SUPER_CLK_MUX			0x00
 | |
| #define SUPER_STATE_SHIFT		28
 | |
| #define SUPER_STATE_MASK		(0xF << SUPER_STATE_SHIFT)
 | |
| #define SUPER_STATE_STANDBY		(0x0 << SUPER_STATE_SHIFT)
 | |
| #define SUPER_STATE_IDLE		(0x1 << SUPER_STATE_SHIFT)
 | |
| #define SUPER_STATE_RUN			(0x2 << SUPER_STATE_SHIFT)
 | |
| #define SUPER_STATE_IRQ			(0x3 << SUPER_STATE_SHIFT)
 | |
| #define SUPER_STATE_FIQ			(0x4 << SUPER_STATE_SHIFT)
 | |
| #define SUPER_LP_DIV2_BYPASS		(0x1 << 16)
 | |
| #define SUPER_SOURCE_MASK		0xF
 | |
| #define	SUPER_FIQ_SOURCE_SHIFT		12
 | |
| #define	SUPER_IRQ_SOURCE_SHIFT		8
 | |
| #define	SUPER_RUN_SOURCE_SHIFT		4
 | |
| #define	SUPER_IDLE_SOURCE_SHIFT		0
 | |
| 
 | |
| #define SUPER_CLK_DIVIDER		0x04
 | |
| #define SUPER_CLOCK_DIV_U71_SHIFT	16
 | |
| #define SUPER_CLOCK_DIV_U71_MASK	(0xff << SUPER_CLOCK_DIV_U71_SHIFT)
 | |
| /* guarantees safe cpu backup */
 | |
| #define SUPER_CLOCK_DIV_U71_MIN		0x2
 | |
| 
 | |
| #define BUS_CLK_DISABLE			(1<<3)
 | |
| #define BUS_CLK_DIV_MASK		0x3
 | |
| 
 | |
| #define PMC_CTRL			0x0
 | |
|  #define PMC_CTRL_BLINK_ENB		(1 << 7)
 | |
| 
 | |
| #define PMC_DPD_PADS_ORIDE		0x1c
 | |
|  #define PMC_DPD_PADS_ORIDE_BLINK_ENB	(1 << 20)
 | |
| 
 | |
| #define PMC_BLINK_TIMER_DATA_ON_SHIFT	0
 | |
| #define PMC_BLINK_TIMER_DATA_ON_MASK	0x7fff
 | |
| #define PMC_BLINK_TIMER_ENB		(1 << 15)
 | |
| #define PMC_BLINK_TIMER_DATA_OFF_SHIFT	16
 | |
| #define PMC_BLINK_TIMER_DATA_OFF_MASK	0xffff
 | |
| 
 | |
| #define PMC_PLLP_WB0_OVERRIDE				0xf8
 | |
| #define PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE		(1 << 12)
 | |
| 
 | |
| #define UTMIP_PLL_CFG2					0x488
 | |
| #define UTMIP_PLL_CFG2_STABLE_COUNT(x)			(((x) & 0xfff) << 6)
 | |
| #define UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(x)		(((x) & 0x3f) << 18)
 | |
| #define UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN	(1 << 0)
 | |
| #define UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN	(1 << 2)
 | |
| #define UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERDOWN	(1 << 4)
 | |
| 
 | |
| #define UTMIP_PLL_CFG1					0x484
 | |
| #define UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(x)		(((x) & 0x1f) << 27)
 | |
| #define UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(x)		(((x) & 0xfff) << 0)
 | |
| #define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN	(1 << 14)
 | |
| #define UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN	(1 << 12)
 | |
| #define UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN		(1 << 16)
 | |
| 
 | |
| #define PLLE_BASE_CML_ENABLE		(1<<31)
 | |
| #define PLLE_BASE_ENABLE		(1<<30)
 | |
| #define PLLE_BASE_DIVCML_SHIFT		24
 | |
| #define PLLE_BASE_DIVCML_MASK		(0xf<<PLLE_BASE_DIVCML_SHIFT)
 | |
| #define PLLE_BASE_DIVP_SHIFT		16
 | |
| #define PLLE_BASE_DIVP_MASK		(0x3f<<PLLE_BASE_DIVP_SHIFT)
 | |
| #define PLLE_BASE_DIVN_SHIFT		8
 | |
| #define PLLE_BASE_DIVN_MASK		(0xFF<<PLLE_BASE_DIVN_SHIFT)
 | |
| #define PLLE_BASE_DIVM_SHIFT		0
 | |
| #define PLLE_BASE_DIVM_MASK		(0xFF<<PLLE_BASE_DIVM_SHIFT)
 | |
| #define PLLE_BASE_DIV_MASK		\
 | |
| 	(PLLE_BASE_DIVCML_MASK | PLLE_BASE_DIVP_MASK | \
 | |
| 	 PLLE_BASE_DIVN_MASK | PLLE_BASE_DIVM_MASK)
 | |
| #define PLLE_BASE_DIV(m, n, p, cml)		\
 | |
| 	 (((cml)<<PLLE_BASE_DIVCML_SHIFT) | ((p)<<PLLE_BASE_DIVP_SHIFT) | \
 | |
| 	  ((n)<<PLLE_BASE_DIVN_SHIFT) | ((m)<<PLLE_BASE_DIVM_SHIFT))
 | |
| 
 | |
| #define PLLE_MISC_SETUP_BASE_SHIFT	16
 | |
| #define PLLE_MISC_SETUP_BASE_MASK	(0xFFFF<<PLLE_MISC_SETUP_BASE_SHIFT)
 | |
| #define PLLE_MISC_READY			(1<<15)
 | |
| #define PLLE_MISC_LOCK			(1<<11)
 | |
| #define PLLE_MISC_LOCK_ENABLE		(1<<9)
 | |
| #define PLLE_MISC_SETUP_EX_SHIFT	2
 | |
| #define PLLE_MISC_SETUP_EX_MASK		(0x3<<PLLE_MISC_SETUP_EX_SHIFT)
 | |
| #define PLLE_MISC_SETUP_MASK		\
 | |
| 	  (PLLE_MISC_SETUP_BASE_MASK | PLLE_MISC_SETUP_EX_MASK)
 | |
| #define PLLE_MISC_SETUP_VALUE		\
 | |
| 	  ((0x7<<PLLE_MISC_SETUP_BASE_SHIFT) | (0x0<<PLLE_MISC_SETUP_EX_SHIFT))
 | |
| 
 | |
| #define PLLE_SS_CTRL			0x68
 | |
| #define	PLLE_SS_INCINTRV_SHIFT		24
 | |
| #define	PLLE_SS_INCINTRV_MASK		(0x3f<<PLLE_SS_INCINTRV_SHIFT)
 | |
| #define	PLLE_SS_INC_SHIFT		16
 | |
| #define	PLLE_SS_INC_MASK		(0xff<<PLLE_SS_INC_SHIFT)
 | |
| #define	PLLE_SS_MAX_SHIFT		0
 | |
| #define	PLLE_SS_MAX_MASK		(0x1ff<<PLLE_SS_MAX_SHIFT)
 | |
| #define PLLE_SS_COEFFICIENTS_MASK	\
 | |
| 	(PLLE_SS_INCINTRV_MASK | PLLE_SS_INC_MASK | PLLE_SS_MAX_MASK)
 | |
| #define PLLE_SS_COEFFICIENTS_12MHZ	\
 | |
| 	((0x18<<PLLE_SS_INCINTRV_SHIFT) | (0x1<<PLLE_SS_INC_SHIFT) | \
 | |
| 	 (0x24<<PLLE_SS_MAX_SHIFT))
 | |
| #define PLLE_SS_DISABLE			((1<<12) | (1<<11) | (1<<10))
 | |
| 
 | |
| #define PLLE_AUX			0x48c
 | |
| #define PLLE_AUX_PLLP_SEL		(1<<2)
 | |
| #define PLLE_AUX_CML_SATA_ENABLE	(1<<1)
 | |
| #define PLLE_AUX_CML_PCIE_ENABLE	(1<<0)
 | |
| 
 | |
| #define	PMC_SATA_PWRGT			0x1ac
 | |
| #define PMC_SATA_PWRGT_PLLE_IDDQ_VALUE	(1<<5)
 | |
| #define PMC_SATA_PWRGT_PLLE_IDDQ_SWCTL	(1<<4)
 | |
| 
 | |
| #define ROUND_DIVIDER_UP	0
 | |
| #define ROUND_DIVIDER_DOWN	1
 | |
| 
 | |
| /* FIXME: recommended safety delay after lock is detected */
 | |
| #define PLL_POST_LOCK_DELAY		100
 | |
| 
 | |
| /**
 | |
| * Structure defining the fields for USB UTMI clocks Parameters.
 | |
| */
 | |
| struct utmi_clk_param {
 | |
| 	/* Oscillator Frequency in KHz */
 | |
| 	u32 osc_frequency;
 | |
| 	/* UTMIP PLL Enable Delay Count  */
 | |
| 	u8 enable_delay_count;
 | |
| 	/* UTMIP PLL Stable count */
 | |
| 	u8 stable_count;
 | |
| 	/*  UTMIP PLL Active delay count */
 | |
| 	u8 active_delay_count;
 | |
| 	/* UTMIP PLL Xtal frequency count */
 | |
| 	u8 xtal_freq_count;
 | |
| };
 | |
| 
 | |
| static const struct utmi_clk_param utmi_parameters[] = {
 | |
| 	{
 | |
| 		.osc_frequency = 13000000,
 | |
| 		.enable_delay_count = 0x02,
 | |
| 		.stable_count = 0x33,
 | |
| 		.active_delay_count = 0x05,
 | |
| 		.xtal_freq_count = 0x7F
 | |
| 	},
 | |
| 	{
 | |
| 		.osc_frequency = 19200000,
 | |
| 		.enable_delay_count = 0x03,
 | |
| 		.stable_count = 0x4B,
 | |
| 		.active_delay_count = 0x06,
 | |
| 		.xtal_freq_count = 0xBB},
 | |
| 	{
 | |
| 		.osc_frequency = 12000000,
 | |
| 		.enable_delay_count = 0x02,
 | |
| 		.stable_count = 0x2F,
 | |
| 		.active_delay_count = 0x04,
 | |
| 		.xtal_freq_count = 0x76
 | |
| 	},
 | |
| 	{
 | |
| 		.osc_frequency = 26000000,
 | |
| 		.enable_delay_count = 0x04,
 | |
| 		.stable_count = 0x66,
 | |
| 		.active_delay_count = 0x09,
 | |
| 		.xtal_freq_count = 0xFE
 | |
| 	},
 | |
| 	{
 | |
| 		.osc_frequency = 16800000,
 | |
| 		.enable_delay_count = 0x03,
 | |
| 		.stable_count = 0x41,
 | |
| 		.active_delay_count = 0x0A,
 | |
| 		.xtal_freq_count = 0xA4
 | |
| 	},
 | |
| };
 | |
| 
 | |
| static void __iomem *reg_clk_base = IO_ADDRESS(TEGRA_CLK_RESET_BASE);
 | |
| static void __iomem *reg_pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
 | |
| static void __iomem *misc_gp_hidrev_base = IO_ADDRESS(TEGRA_APB_MISC_BASE);
 | |
| 
 | |
| #define MISC_GP_HIDREV                  0x804
 | |
| 
 | |
| /*
 | |
|  * Some peripheral clocks share an enable bit, so refcount the enable bits
 | |
|  * in registers CLK_ENABLE_L, ... CLK_ENABLE_W
 | |
|  */
 | |
| static int tegra_periph_clk_enable_refcount[CLK_OUT_ENB_NUM * 32];
 | |
| 
 | |
| #define clk_writel(value, reg) \
 | |
| 	__raw_writel(value, (u32)reg_clk_base + (reg))
 | |
| #define clk_readl(reg) \
 | |
| 	__raw_readl((u32)reg_clk_base + (reg))
 | |
| #define pmc_writel(value, reg) \
 | |
| 	__raw_writel(value, (u32)reg_pmc_base + (reg))
 | |
| #define pmc_readl(reg) \
 | |
| 	__raw_readl((u32)reg_pmc_base + (reg))
 | |
| #define chipid_readl() \
 | |
| 	__raw_readl((u32)misc_gp_hidrev_base + MISC_GP_HIDREV)
 | |
| 
 | |
| #define clk_writel_delay(value, reg)					\
 | |
| 	do {								\
 | |
| 		__raw_writel((value), (u32)reg_clk_base + (reg));	\
 | |
| 		udelay(2);						\
 | |
| 	} while (0)
 | |
| 
 | |
| 
 | |
| static inline int clk_set_div(struct clk *c, u32 n)
 | |
| {
 | |
| 	return clk_set_rate(c, (clk_get_rate(c->parent) + n-1) / n);
 | |
| }
 | |
| 
 | |
| static inline u32 periph_clk_to_reg(
 | |
| 	struct clk *c, u32 reg_L, u32 reg_V, int offs)
 | |
| {
 | |
| 	u32 reg = c->u.periph.clk_num / 32;
 | |
| 	BUG_ON(reg >= RST_DEVICES_NUM);
 | |
| 	if (reg < 3)
 | |
| 		reg = reg_L + (reg * offs);
 | |
| 	else
 | |
| 		reg = reg_V + ((reg - 3) * offs);
 | |
| 	return reg;
 | |
| }
 | |
| 
 | |
| static unsigned long clk_measure_input_freq(void)
 | |
| {
 | |
| 	u32 clock_autodetect;
 | |
| 	clk_writel(OSC_FREQ_DET_TRIG | 1, OSC_FREQ_DET);
 | |
| 	do {} while (clk_readl(OSC_FREQ_DET_STATUS) & OSC_FREQ_DET_BUSY);
 | |
| 	clock_autodetect = clk_readl(OSC_FREQ_DET_STATUS);
 | |
| 	if (clock_autodetect >= 732 - 3 && clock_autodetect <= 732 + 3) {
 | |
| 		return 12000000;
 | |
| 	} else if (clock_autodetect >= 794 - 3 && clock_autodetect <= 794 + 3) {
 | |
| 		return 13000000;
 | |
| 	} else if (clock_autodetect >= 1172 - 3 && clock_autodetect <= 1172 + 3) {
 | |
| 		return 19200000;
 | |
| 	} else if (clock_autodetect >= 1587 - 3 && clock_autodetect <= 1587 + 3) {
 | |
| 		return 26000000;
 | |
| 	} else if (clock_autodetect >= 1025 - 3 && clock_autodetect <= 1025 + 3) {
 | |
| 		return 16800000;
 | |
| 	} else if (clock_autodetect >= 2344 - 3 && clock_autodetect <= 2344 + 3) {
 | |
| 		return 38400000;
 | |
| 	} else if (clock_autodetect >= 2928 - 3 && clock_autodetect <= 2928 + 3) {
 | |
| 		return 48000000;
 | |
| 	} else {
 | |
| 		pr_err("%s: Unexpected clock autodetect value %d", __func__,
 | |
| 			clock_autodetect);
 | |
| 		BUG();
 | |
| 		return 0;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| static int clk_div71_get_divider(unsigned long parent_rate, unsigned long rate,
 | |
| 				 u32 flags, u32 round_mode)
 | |
| {
 | |
| 	s64 divider_u71 = parent_rate;
 | |
| 	if (!rate)
 | |
| 		return -EINVAL;
 | |
| 
 | |
| 	if (!(flags & DIV_U71_INT))
 | |
| 		divider_u71 *= 2;
 | |
| 	if (round_mode == ROUND_DIVIDER_UP)
 | |
| 		divider_u71 += rate - 1;
 | |
| 	do_div(divider_u71, rate);
 | |
| 	if (flags & DIV_U71_INT)
 | |
| 		divider_u71 *= 2;
 | |
| 
 | |
| 	if (divider_u71 - 2 < 0)
 | |
| 		return 0;
 | |
| 
 | |
| 	if (divider_u71 - 2 > 255)
 | |
| 		return -EINVAL;
 | |
| 
 | |
| 	return divider_u71 - 2;
 | |
| }
 | |
| 
 | |
| static int clk_div16_get_divider(unsigned long parent_rate, unsigned long rate)
 | |
| {
 | |
| 	s64 divider_u16;
 | |
| 
 | |
| 	divider_u16 = parent_rate;
 | |
| 	if (!rate)
 | |
| 		return -EINVAL;
 | |
| 	divider_u16 += rate - 1;
 | |
| 	do_div(divider_u16, rate);
 | |
| 
 | |
| 	if (divider_u16 - 1 < 0)
 | |
| 		return 0;
 | |
| 
 | |
| 	if (divider_u16 - 1 > 0xFFFF)
 | |
| 		return -EINVAL;
 | |
| 
 | |
| 	return divider_u16 - 1;
 | |
| }
 | |
| 
 | |
| /* clk_m functions */
 | |
| static unsigned long tegra30_clk_m_autodetect_rate(struct clk *c)
 | |
| {
 | |
| 	u32 osc_ctrl = clk_readl(OSC_CTRL);
 | |
| 	u32 auto_clock_control = osc_ctrl & ~OSC_CTRL_OSC_FREQ_MASK;
 | |
| 	u32 pll_ref_div = osc_ctrl & OSC_CTRL_PLL_REF_DIV_MASK;
 | |
| 
 | |
| 	c->rate = clk_measure_input_freq();
 | |
| 	switch (c->rate) {
 | |
| 	case 12000000:
 | |
| 		auto_clock_control |= OSC_CTRL_OSC_FREQ_12MHZ;
 | |
| 		BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1);
 | |
| 		break;
 | |
| 	case 13000000:
 | |
| 		auto_clock_control |= OSC_CTRL_OSC_FREQ_13MHZ;
 | |
| 		BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1);
 | |
| 		break;
 | |
| 	case 19200000:
 | |
| 		auto_clock_control |= OSC_CTRL_OSC_FREQ_19_2MHZ;
 | |
| 		BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1);
 | |
| 		break;
 | |
| 	case 26000000:
 | |
| 		auto_clock_control |= OSC_CTRL_OSC_FREQ_26MHZ;
 | |
| 		BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1);
 | |
| 		break;
 | |
| 	case 16800000:
 | |
| 		auto_clock_control |= OSC_CTRL_OSC_FREQ_16_8MHZ;
 | |
| 		BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1);
 | |
| 		break;
 | |
| 	case 38400000:
 | |
| 		auto_clock_control |= OSC_CTRL_OSC_FREQ_38_4MHZ;
 | |
| 		BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_2);
 | |
| 		break;
 | |
| 	case 48000000:
 | |
| 		auto_clock_control |= OSC_CTRL_OSC_FREQ_48MHZ;
 | |
| 		BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_4);
 | |
| 		break;
 | |
| 	default:
 | |
| 		pr_err("%s: Unexpected clock rate %ld", __func__, c->rate);
 | |
| 		BUG();
 | |
| 	}
 | |
| 	clk_writel(auto_clock_control, OSC_CTRL);
 | |
| 	return c->rate;
 | |
| }
 | |
| 
 | |
| static void tegra30_clk_m_init(struct clk *c)
 | |
| {
 | |
| 	pr_debug("%s on clock %s\n", __func__, c->name);
 | |
| 	tegra30_clk_m_autodetect_rate(c);
 | |
| }
 | |
| 
 | |
| static int tegra30_clk_m_enable(struct clk *c)
 | |
| {
 | |
| 	pr_debug("%s on clock %s\n", __func__, c->name);
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static void tegra30_clk_m_disable(struct clk *c)
 | |
| {
 | |
| 	pr_debug("%s on clock %s\n", __func__, c->name);
 | |
| 	WARN(1, "Attempting to disable main SoC clock\n");
 | |
| }
 | |
| 
 | |
| static struct clk_ops tegra_clk_m_ops = {
 | |
| 	.init		= tegra30_clk_m_init,
 | |
| 	.enable		= tegra30_clk_m_enable,
 | |
| 	.disable	= tegra30_clk_m_disable,
 | |
| };
 | |
| 
 | |
| static struct clk_ops tegra_clk_m_div_ops = {
 | |
| 	.enable		= tegra30_clk_m_enable,
 | |
| };
 | |
| 
 | |
| /* PLL reference divider functions */
 | |
| static void tegra30_pll_ref_init(struct clk *c)
 | |
| {
 | |
| 	u32 pll_ref_div = clk_readl(OSC_CTRL) & OSC_CTRL_PLL_REF_DIV_MASK;
 | |
| 	pr_debug("%s on clock %s\n", __func__, c->name);
 | |
| 
 | |
| 	switch (pll_ref_div) {
 | |
| 	case OSC_CTRL_PLL_REF_DIV_1:
 | |
| 		c->div = 1;
 | |
| 		break;
 | |
| 	case OSC_CTRL_PLL_REF_DIV_2:
 | |
| 		c->div = 2;
 | |
| 		break;
 | |
| 	case OSC_CTRL_PLL_REF_DIV_4:
 | |
| 		c->div = 4;
 | |
| 		break;
 | |
| 	default:
 | |
| 		pr_err("%s: Invalid pll ref divider %d", __func__, pll_ref_div);
 | |
| 		BUG();
 | |
| 	}
 | |
| 	c->mul = 1;
 | |
| 	c->state = ON;
 | |
| }
 | |
| 
 | |
| static struct clk_ops tegra_pll_ref_ops = {
 | |
| 	.init		= tegra30_pll_ref_init,
 | |
| 	.enable		= tegra30_clk_m_enable,
 | |
| 	.disable	= tegra30_clk_m_disable,
 | |
| };
 | |
| 
 | |
| /* super clock functions */
 | |
| /* "super clocks" on tegra30 have two-stage muxes, fractional 7.1 divider and
 | |
|  * clock skipping super divider.  We will ignore the clock skipping divider,
 | |
|  * since we can't lower the voltage when using the clock skip, but we can if
 | |
|  * we lower the PLL frequency. We will use 7.1 divider for CPU super-clock
 | |
|  * only when its parent is a fixed rate PLL, since we can't change PLL rate
 | |
|  * in this case.
 | |
|  */
 | |
| static void tegra30_super_clk_init(struct clk *c)
 | |
| {
 | |
| 	u32 val;
 | |
| 	int source;
 | |
| 	int shift;
 | |
| 	const struct clk_mux_sel *sel;
 | |
| 	val = clk_readl(c->reg + SUPER_CLK_MUX);
 | |
| 	c->state = ON;
 | |
| 	BUG_ON(((val & SUPER_STATE_MASK) != SUPER_STATE_RUN) &&
 | |
| 		((val & SUPER_STATE_MASK) != SUPER_STATE_IDLE));
 | |
| 	shift = ((val & SUPER_STATE_MASK) == SUPER_STATE_IDLE) ?
 | |
| 		SUPER_IDLE_SOURCE_SHIFT : SUPER_RUN_SOURCE_SHIFT;
 | |
| 	source = (val >> shift) & SUPER_SOURCE_MASK;
 | |
| 	if (c->flags & DIV_2)
 | |
| 		source |= val & SUPER_LP_DIV2_BYPASS;
 | |
| 	for (sel = c->inputs; sel->input != NULL; sel++) {
 | |
| 		if (sel->value == source)
 | |
| 			break;
 | |
| 	}
 | |
| 	BUG_ON(sel->input == NULL);
 | |
| 	c->parent = sel->input;
 | |
| 
 | |
| 	if (c->flags & DIV_U71) {
 | |
| 		/* Init safe 7.1 divider value (does not affect PLLX path) */
 | |
| 		clk_writel(SUPER_CLOCK_DIV_U71_MIN << SUPER_CLOCK_DIV_U71_SHIFT,
 | |
| 			   c->reg + SUPER_CLK_DIVIDER);
 | |
| 		c->mul = 2;
 | |
| 		c->div = 2;
 | |
| 		if (!(c->parent->flags & PLLX))
 | |
| 			c->div += SUPER_CLOCK_DIV_U71_MIN;
 | |
| 	} else
 | |
| 		clk_writel(0, c->reg + SUPER_CLK_DIVIDER);
 | |
| }
 | |
| 
 | |
| static int tegra30_super_clk_enable(struct clk *c)
 | |
| {
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static void tegra30_super_clk_disable(struct clk *c)
 | |
| {
 | |
| 	/* since tegra 3 has 2 CPU super clocks - low power lp-mode clock and
 | |
| 	   geared up g-mode super clock - mode switch may request to disable
 | |
| 	   either of them; accept request with no affect on h/w */
 | |
| }
 | |
| 
 | |
| static int tegra30_super_clk_set_parent(struct clk *c, struct clk *p)
 | |
| {
 | |
| 	u32 val;
 | |
| 	const struct clk_mux_sel *sel;
 | |
| 	int shift;
 | |
| 
 | |
| 	val = clk_readl(c->reg + SUPER_CLK_MUX);
 | |
| 	BUG_ON(((val & SUPER_STATE_MASK) != SUPER_STATE_RUN) &&
 | |
| 		((val & SUPER_STATE_MASK) != SUPER_STATE_IDLE));
 | |
| 	shift = ((val & SUPER_STATE_MASK) == SUPER_STATE_IDLE) ?
 | |
| 		SUPER_IDLE_SOURCE_SHIFT : SUPER_RUN_SOURCE_SHIFT;
 | |
| 	for (sel = c->inputs; sel->input != NULL; sel++) {
 | |
| 		if (sel->input == p) {
 | |
| 			/* For LP mode super-clock switch between PLLX direct
 | |
| 			   and divided-by-2 outputs is allowed only when other
 | |
| 			   than PLLX clock source is current parent */
 | |
| 			if ((c->flags & DIV_2) && (p->flags & PLLX) &&
 | |
| 			    ((sel->value ^ val) & SUPER_LP_DIV2_BYPASS)) {
 | |
| 				if (c->parent->flags & PLLX)
 | |
| 					return -EINVAL;
 | |
| 				val ^= SUPER_LP_DIV2_BYPASS;
 | |
| 				clk_writel_delay(val, c->reg);
 | |
| 			}
 | |
| 			val &= ~(SUPER_SOURCE_MASK << shift);
 | |
| 			val |= (sel->value & SUPER_SOURCE_MASK) << shift;
 | |
| 
 | |
| 			/* 7.1 divider for CPU super-clock does not affect
 | |
| 			   PLLX path */
 | |
| 			if (c->flags & DIV_U71) {
 | |
| 				u32 div = 0;
 | |
| 				if (!(p->flags & PLLX)) {
 | |
| 					div = clk_readl(c->reg +
 | |
| 							SUPER_CLK_DIVIDER);
 | |
| 					div &= SUPER_CLOCK_DIV_U71_MASK;
 | |
| 					div >>= SUPER_CLOCK_DIV_U71_SHIFT;
 | |
| 				}
 | |
| 				c->div = div + 2;
 | |
| 				c->mul = 2;
 | |
| 			}
 | |
| 
 | |
| 			if (c->refcnt)
 | |
| 				clk_enable(p);
 | |
| 
 | |
| 			clk_writel_delay(val, c->reg);
 | |
| 
 | |
| 			if (c->refcnt && c->parent)
 | |
| 				clk_disable(c->parent);
 | |
| 
 | |
| 			clk_reparent(c, p);
 | |
| 			return 0;
 | |
| 		}
 | |
| 	}
 | |
| 	return -EINVAL;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Do not use super clocks "skippers", since dividing using a clock skipper
 | |
|  * does not allow the voltage to be scaled down. Instead adjust the rate of
 | |
|  * the parent clock. This requires that the parent of a super clock have no
 | |
|  * other children, otherwise the rate will change underneath the other
 | |
|  * children. Special case: if fixed rate PLL is CPU super clock parent the
 | |
|  * rate of this PLL can't be changed, and it has many other children. In
 | |
|  * this case use 7.1 fractional divider to adjust the super clock rate.
 | |
|  */
 | |
| static int tegra30_super_clk_set_rate(struct clk *c, unsigned long rate)
 | |
| {
 | |
| 	if ((c->flags & DIV_U71) && (c->parent->flags & PLL_FIXED)) {
 | |
| 		int div = clk_div71_get_divider(c->parent->u.pll.fixed_rate,
 | |
| 					rate, c->flags, ROUND_DIVIDER_DOWN);
 | |
| 		div = max(div, SUPER_CLOCK_DIV_U71_MIN);
 | |
| 
 | |
| 		clk_writel(div << SUPER_CLOCK_DIV_U71_SHIFT,
 | |
| 			   c->reg + SUPER_CLK_DIVIDER);
 | |
| 		c->div = div + 2;
 | |
| 		c->mul = 2;
 | |
| 		return 0;
 | |
| 	}
 | |
| 	return clk_set_rate(c->parent, rate);
 | |
| }
 | |
| 
 | |
| static struct clk_ops tegra_super_ops = {
 | |
| 	.init			= tegra30_super_clk_init,
 | |
| 	.enable			= tegra30_super_clk_enable,
 | |
| 	.disable		= tegra30_super_clk_disable,
 | |
| 	.set_parent		= tegra30_super_clk_set_parent,
 | |
| 	.set_rate		= tegra30_super_clk_set_rate,
 | |
| };
 | |
| 
 | |
| static int tegra30_twd_clk_set_rate(struct clk *c, unsigned long rate)
 | |
| {
 | |
| 	/* The input value 'rate' is the clock rate of the CPU complex. */
 | |
| 	c->rate = (rate * c->mul) / c->div;
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static struct clk_ops tegra30_twd_ops = {
 | |
| 	.set_rate	= tegra30_twd_clk_set_rate,
 | |
| };
 | |
| 
 | |
| /* Blink output functions */
 | |
| 
 | |
| static void tegra30_blink_clk_init(struct clk *c)
 | |
| {
 | |
| 	u32 val;
 | |
| 
 | |
| 	val = pmc_readl(PMC_CTRL);
 | |
| 	c->state = (val & PMC_CTRL_BLINK_ENB) ? ON : OFF;
 | |
| 	c->mul = 1;
 | |
| 	val = pmc_readl(c->reg);
 | |
| 
 | |
| 	if (val & PMC_BLINK_TIMER_ENB) {
 | |
| 		unsigned int on_off;
 | |
| 
 | |
| 		on_off = (val >> PMC_BLINK_TIMER_DATA_ON_SHIFT) &
 | |
| 			PMC_BLINK_TIMER_DATA_ON_MASK;
 | |
| 		val >>= PMC_BLINK_TIMER_DATA_OFF_SHIFT;
 | |
| 		val &= PMC_BLINK_TIMER_DATA_OFF_MASK;
 | |
| 		on_off += val;
 | |
| 		/* each tick in the blink timer is 4 32KHz clocks */
 | |
| 		c->div = on_off * 4;
 | |
| 	} else {
 | |
| 		c->div = 1;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| static int tegra30_blink_clk_enable(struct clk *c)
 | |
| {
 | |
| 	u32 val;
 | |
| 
 | |
| 	val = pmc_readl(PMC_DPD_PADS_ORIDE);
 | |
| 	pmc_writel(val | PMC_DPD_PADS_ORIDE_BLINK_ENB, PMC_DPD_PADS_ORIDE);
 | |
| 
 | |
| 	val = pmc_readl(PMC_CTRL);
 | |
| 	pmc_writel(val | PMC_CTRL_BLINK_ENB, PMC_CTRL);
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static void tegra30_blink_clk_disable(struct clk *c)
 | |
| {
 | |
| 	u32 val;
 | |
| 
 | |
| 	val = pmc_readl(PMC_CTRL);
 | |
| 	pmc_writel(val & ~PMC_CTRL_BLINK_ENB, PMC_CTRL);
 | |
| 
 | |
| 	val = pmc_readl(PMC_DPD_PADS_ORIDE);
 | |
| 	pmc_writel(val & ~PMC_DPD_PADS_ORIDE_BLINK_ENB, PMC_DPD_PADS_ORIDE);
 | |
| }
 | |
| 
 | |
| static int tegra30_blink_clk_set_rate(struct clk *c, unsigned long rate)
 | |
| {
 | |
| 	unsigned long parent_rate = clk_get_rate(c->parent);
 | |
| 	if (rate >= parent_rate) {
 | |
| 		c->div = 1;
 | |
| 		pmc_writel(0, c->reg);
 | |
| 	} else {
 | |
| 		unsigned int on_off;
 | |
| 		u32 val;
 | |
| 
 | |
| 		on_off = DIV_ROUND_UP(parent_rate / 8, rate);
 | |
| 		c->div = on_off * 8;
 | |
| 
 | |
| 		val = (on_off & PMC_BLINK_TIMER_DATA_ON_MASK) <<
 | |
| 			PMC_BLINK_TIMER_DATA_ON_SHIFT;
 | |
| 		on_off &= PMC_BLINK_TIMER_DATA_OFF_MASK;
 | |
| 		on_off <<= PMC_BLINK_TIMER_DATA_OFF_SHIFT;
 | |
| 		val |= on_off;
 | |
| 		val |= PMC_BLINK_TIMER_ENB;
 | |
| 		pmc_writel(val, c->reg);
 | |
| 	}
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static struct clk_ops tegra_blink_clk_ops = {
 | |
| 	.init			= &tegra30_blink_clk_init,
 | |
| 	.enable			= &tegra30_blink_clk_enable,
 | |
| 	.disable		= &tegra30_blink_clk_disable,
 | |
| 	.set_rate		= &tegra30_blink_clk_set_rate,
 | |
| };
 | |
| 
 | |
| /* PLL Functions */
 | |
| static int tegra30_pll_clk_wait_for_lock(struct clk *c, u32 lock_reg,
 | |
| 					 u32 lock_bit)
 | |
| {
 | |
| #if USE_PLL_LOCK_BITS
 | |
| 	int i;
 | |
| 	for (i = 0; i < c->u.pll.lock_delay; i++) {
 | |
| 		if (clk_readl(lock_reg) & lock_bit) {
 | |
| 			udelay(PLL_POST_LOCK_DELAY);
 | |
| 			return 0;
 | |
| 		}
 | |
| 		udelay(2);		/* timeout = 2 * lock time */
 | |
| 	}
 | |
| 	pr_err("Timed out waiting for lock bit on pll %s", c->name);
 | |
| 	return -1;
 | |
| #endif
 | |
| 	udelay(c->u.pll.lock_delay);
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| static void tegra30_utmi_param_configure(struct clk *c)
 | |
| {
 | |
| 	u32 reg;
 | |
| 	int i;
 | |
| 	unsigned long main_rate =
 | |
| 		clk_get_rate(c->parent->parent);
 | |
| 
 | |
| 	for (i = 0; i < ARRAY_SIZE(utmi_parameters); i++) {
 | |
| 		if (main_rate == utmi_parameters[i].osc_frequency)
 | |
| 			break;
 | |
| 	}
 | |
| 
 | |
| 	if (i >= ARRAY_SIZE(utmi_parameters)) {
 | |
| 		pr_err("%s: Unexpected main rate %lu\n", __func__, main_rate);
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	reg = clk_readl(UTMIP_PLL_CFG2);
 | |
| 
 | |
| 	/* Program UTMIP PLL stable and active counts */
 | |
| 	/* [FIXME] arclk_rst.h says WRONG! This should be 1ms -> 0x50 Check! */
 | |
| 	reg &= ~UTMIP_PLL_CFG2_STABLE_COUNT(~0);
 | |
| 	reg |= UTMIP_PLL_CFG2_STABLE_COUNT(
 | |
| 			utmi_parameters[i].stable_count);
 | |
| 
 | |
| 	reg &= ~UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(~0);
 | |
| 
 | |
| 	reg |= UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(
 | |
| 			utmi_parameters[i].active_delay_count);
 | |
| 
 | |
| 	/* Remove power downs from UTMIP PLL control bits */
 | |
| 	reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN;
 | |
| 	reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN;
 | |
| 	reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERDOWN;
 | |
| 
 | |
| 	clk_writel(reg, UTMIP_PLL_CFG2);
 | |
| 
 | |
| 	/* Program UTMIP PLL delay and oscillator frequency counts */
 | |
| 	reg = clk_readl(UTMIP_PLL_CFG1);
 | |
| 	reg &= ~UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(~0);
 | |
| 
 | |
| 	reg |= UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(
 | |
| 		utmi_parameters[i].enable_delay_count);
 | |
| 
 | |
| 	reg &= ~UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(~0);
 | |
| 	reg |= UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(
 | |
| 		utmi_parameters[i].xtal_freq_count);
 | |
| 
 | |
| 	/* Remove power downs from UTMIP PLL control bits */
 | |
| 	reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN;
 | |
| 	reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN;
 | |
| 	reg &= ~UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN;
 | |
| 
 | |
| 	clk_writel(reg, UTMIP_PLL_CFG1);
 | |
| }
 | |
| 
 | |
| static void tegra30_pll_clk_init(struct clk *c)
 | |
| {
 | |
| 	u32 val = clk_readl(c->reg + PLL_BASE);
 | |
| 
 | |
| 	c->state = (val & PLL_BASE_ENABLE) ? ON : OFF;
 | |
| 
 | |
| 	if (c->flags & PLL_FIXED && !(val & PLL_BASE_OVERRIDE)) {
 | |
| 		const struct clk_pll_freq_table *sel;
 | |
| 		unsigned long input_rate = clk_get_rate(c->parent);
 | |
| 		for (sel = c->u.pll.freq_table; sel->input_rate != 0; sel++) {
 | |
| 			if (sel->input_rate == input_rate &&
 | |
| 				sel->output_rate == c->u.pll.fixed_rate) {
 | |
| 				c->mul = sel->n;
 | |
| 				c->div = sel->m * sel->p;
 | |
| 				return;
 | |
| 			}
 | |
| 		}
 | |
| 		pr_err("Clock %s has unknown fixed frequency\n", c->name);
 | |
| 		BUG();
 | |
| 	} else if (val & PLL_BASE_BYPASS) {
 | |
| 		c->mul = 1;
 | |
| 		c->div = 1;
 | |
| 	} else {
 | |
| 		c->mul = (val & PLL_BASE_DIVN_MASK) >> PLL_BASE_DIVN_SHIFT;
 | |
| 		c->div = (val & PLL_BASE_DIVM_MASK) >> PLL_BASE_DIVM_SHIFT;
 | |
| 		if (c->flags & PLLU)
 | |
| 			c->div *= (val & PLLU_BASE_POST_DIV) ? 1 : 2;
 | |
| 		else
 | |
| 			c->div *= (0x1 << ((val & PLL_BASE_DIVP_MASK) >>
 | |
| 					PLL_BASE_DIVP_SHIFT));
 | |
| 		if (c->flags & PLL_FIXED) {
 | |
| 			unsigned long rate = clk_get_rate_locked(c);
 | |
| 			BUG_ON(rate != c->u.pll.fixed_rate);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if (c->flags & PLLU)
 | |
| 		tegra30_utmi_param_configure(c);
 | |
| }
 | |
| 
 | |
| static int tegra30_pll_clk_enable(struct clk *c)
 | |
| {
 | |
| 	u32 val;
 | |
| 	pr_debug("%s on clock %s\n", __func__, c->name);
 | |
| 
 | |
| #if USE_PLL_LOCK_BITS
 | |
| 	val = clk_readl(c->reg + PLL_MISC(c));
 | |
| 	val |= PLL_MISC_LOCK_ENABLE(c);
 | |
| 	clk_writel(val, c->reg + PLL_MISC(c));
 | |
| #endif
 | |
| 	val = clk_readl(c->reg + PLL_BASE);
 | |
| 	val &= ~PLL_BASE_BYPASS;
 | |
| 	val |= PLL_BASE_ENABLE;
 | |
| 	clk_writel(val, c->reg + PLL_BASE);
 | |
| 
 | |
| 	if (c->flags & PLLM) {
 | |
| 		val = pmc_readl(PMC_PLLP_WB0_OVERRIDE);
 | |
| 		val |= PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE;
 | |
| 		pmc_writel(val, PMC_PLLP_WB0_OVERRIDE);
 | |
| 	}
 | |
| 
 | |
| 	tegra30_pll_clk_wait_for_lock(c, c->reg + PLL_BASE, PLL_BASE_LOCK);
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static void tegra30_pll_clk_disable(struct clk *c)
 | |
| {
 | |
| 	u32 val;
 | |
| 	pr_debug("%s on clock %s\n", __func__, c->name);
 | |
| 
 | |
| 	val = clk_readl(c->reg);
 | |
| 	val &= ~(PLL_BASE_BYPASS | PLL_BASE_ENABLE);
 | |
| 	clk_writel(val, c->reg);
 | |
| 
 | |
| 	if (c->flags & PLLM) {
 | |
| 		val = pmc_readl(PMC_PLLP_WB0_OVERRIDE);
 | |
| 		val &= ~PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE;
 | |
| 		pmc_writel(val, PMC_PLLP_WB0_OVERRIDE);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| static int tegra30_pll_clk_set_rate(struct clk *c, unsigned long rate)
 | |
| {
 | |
| 	u32 val, p_div, old_base;
 | |
| 	unsigned long input_rate;
 | |
| 	const struct clk_pll_freq_table *sel;
 | |
| 	struct clk_pll_freq_table cfg;
 | |
| 
 | |
| 	pr_debug("%s: %s %lu\n", __func__, c->name, rate);
 | |
| 
 | |
| 	if (c->flags & PLL_FIXED) {
 | |
| 		int ret = 0;
 | |
| 		if (rate != c->u.pll.fixed_rate) {
 | |
| 			pr_err("%s: Can not change %s fixed rate %lu to %lu\n",
 | |
| 			       __func__, c->name, c->u.pll.fixed_rate, rate);
 | |
| 			ret = -EINVAL;
 | |
| 		}
 | |
| 		return ret;
 | |
| 	}
 | |
| 
 | |
| 	if (c->flags & PLLM) {
 | |
| 		if (rate != clk_get_rate_locked(c)) {
 | |
| 			pr_err("%s: Can not change memory %s rate in flight\n",
 | |
| 			       __func__, c->name);
 | |
| 			return -EINVAL;
 | |
| 		}
 | |
| 		return 0;
 | |
| 	}
 | |
| 
 | |
| 	p_div = 0;
 | |
| 	input_rate = clk_get_rate(c->parent);
 | |
| 
 | |
| 	/* Check if the target rate is tabulated */
 | |
| 	for (sel = c->u.pll.freq_table; sel->input_rate != 0; sel++) {
 | |
| 		if (sel->input_rate == input_rate && sel->output_rate == rate) {
 | |
| 			if (c->flags & PLLU) {
 | |
| 				BUG_ON(sel->p < 1 || sel->p > 2);
 | |
| 				if (sel->p == 1)
 | |
| 					p_div = PLLU_BASE_POST_DIV;
 | |
| 			} else {
 | |
| 				BUG_ON(sel->p < 1);
 | |
| 				for (val = sel->p; val > 1; val >>= 1)
 | |
| 					p_div++;
 | |
| 				p_div <<= PLL_BASE_DIVP_SHIFT;
 | |
| 			}
 | |
| 			break;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/* Configure out-of-table rate */
 | |
| 	if (sel->input_rate == 0) {
 | |
| 		unsigned long cfreq;
 | |
| 		BUG_ON(c->flags & PLLU);
 | |
| 		sel = &cfg;
 | |
| 
 | |
| 		switch (input_rate) {
 | |
| 		case 12000000:
 | |
| 		case 26000000:
 | |
| 			cfreq = (rate <= 1000000 * 1000) ? 1000000 : 2000000;
 | |
| 			break;
 | |
| 		case 13000000:
 | |
| 			cfreq = (rate <= 1000000 * 1000) ? 1000000 : 2600000;
 | |
| 			break;
 | |
| 		case 16800000:
 | |
| 		case 19200000:
 | |
| 			cfreq = (rate <= 1200000 * 1000) ? 1200000 : 2400000;
 | |
| 			break;
 | |
| 		default:
 | |
| 			pr_err("%s: Unexpected reference rate %lu\n",
 | |
| 			       __func__, input_rate);
 | |
| 			BUG();
 | |
| 		}
 | |
| 
 | |
| 		/* Raise VCO to guarantee 0.5% accuracy */
 | |
| 		for (cfg.output_rate = rate; cfg.output_rate < 200 * cfreq;
 | |
| 		      cfg.output_rate <<= 1)
 | |
| 			p_div++;
 | |
| 
 | |
| 		cfg.p = 0x1 << p_div;
 | |
| 		cfg.m = input_rate / cfreq;
 | |
| 		cfg.n = cfg.output_rate / cfreq;
 | |
| 		cfg.cpcon = OUT_OF_TABLE_CPCON;
 | |
| 
 | |
| 		if ((cfg.m > (PLL_BASE_DIVM_MASK >> PLL_BASE_DIVM_SHIFT)) ||
 | |
| 		    (cfg.n > (PLL_BASE_DIVN_MASK >> PLL_BASE_DIVN_SHIFT)) ||
 | |
| 		    (p_div > (PLL_BASE_DIVP_MASK >> PLL_BASE_DIVP_SHIFT)) ||
 | |
| 		    (cfg.output_rate > c->u.pll.vco_max)) {
 | |
| 			pr_err("%s: Failed to set %s out-of-table rate %lu\n",
 | |
| 			       __func__, c->name, rate);
 | |
| 			return -EINVAL;
 | |
| 		}
 | |
| 		p_div <<= PLL_BASE_DIVP_SHIFT;
 | |
| 	}
 | |
| 
 | |
| 	c->mul = sel->n;
 | |
| 	c->div = sel->m * sel->p;
 | |
| 
 | |
| 	old_base = val = clk_readl(c->reg + PLL_BASE);
 | |
| 	val &= ~(PLL_BASE_DIVM_MASK | PLL_BASE_DIVN_MASK |
 | |
| 		 ((c->flags & PLLU) ? PLLU_BASE_POST_DIV : PLL_BASE_DIVP_MASK));
 | |
| 	val |= (sel->m << PLL_BASE_DIVM_SHIFT) |
 | |
| 		(sel->n << PLL_BASE_DIVN_SHIFT) | p_div;
 | |
| 	if (val == old_base)
 | |
| 		return 0;
 | |
| 
 | |
| 	if (c->state == ON) {
 | |
| 		tegra30_pll_clk_disable(c);
 | |
| 		val &= ~(PLL_BASE_BYPASS | PLL_BASE_ENABLE);
 | |
| 	}
 | |
| 	clk_writel(val, c->reg + PLL_BASE);
 | |
| 
 | |
| 	if (c->flags & PLL_HAS_CPCON) {
 | |
| 		val = clk_readl(c->reg + PLL_MISC(c));
 | |
| 		val &= ~PLL_MISC_CPCON_MASK;
 | |
| 		val |= sel->cpcon << PLL_MISC_CPCON_SHIFT;
 | |
| 		if (c->flags & (PLLU | PLLD)) {
 | |
| 			val &= ~PLL_MISC_LFCON_MASK;
 | |
| 			if (sel->n >= PLLDU_LFCON_SET_DIVN)
 | |
| 				val |= 0x1 << PLL_MISC_LFCON_SHIFT;
 | |
| 		} else if (c->flags & (PLLX | PLLM)) {
 | |
| 			val &= ~(0x1 << PLL_MISC_DCCON_SHIFT);
 | |
| 			if (rate >= (c->u.pll.vco_max >> 1))
 | |
| 				val |= 0x1 << PLL_MISC_DCCON_SHIFT;
 | |
| 		}
 | |
| 		clk_writel(val, c->reg + PLL_MISC(c));
 | |
| 	}
 | |
| 
 | |
| 	if (c->state == ON)
 | |
| 		tegra30_pll_clk_enable(c);
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static struct clk_ops tegra_pll_ops = {
 | |
| 	.init			= tegra30_pll_clk_init,
 | |
| 	.enable			= tegra30_pll_clk_enable,
 | |
| 	.disable		= tegra30_pll_clk_disable,
 | |
| 	.set_rate		= tegra30_pll_clk_set_rate,
 | |
| };
 | |
| 
 | |
| static int
 | |
| tegra30_plld_clk_cfg_ex(struct clk *c, enum tegra_clk_ex_param p, u32 setting)
 | |
| {
 | |
| 	u32 val, mask, reg;
 | |
| 
 | |
| 	switch (p) {
 | |
| 	case TEGRA_CLK_PLLD_CSI_OUT_ENB:
 | |
| 		mask = PLLD_BASE_CSI_CLKENABLE;
 | |
| 		reg = c->reg + PLL_BASE;
 | |
| 		break;
 | |
| 	case TEGRA_CLK_PLLD_DSI_OUT_ENB:
 | |
| 		mask = PLLD_MISC_DSI_CLKENABLE;
 | |
| 		reg = c->reg + PLL_MISC(c);
 | |
| 		break;
 | |
| 	case TEGRA_CLK_PLLD_MIPI_MUX_SEL:
 | |
| 		if (!(c->flags & PLL_ALT_MISC_REG)) {
 | |
| 			mask = PLLD_BASE_DSIB_MUX_MASK;
 | |
| 			reg = c->reg + PLL_BASE;
 | |
| 			break;
 | |
| 		}
 | |
| 	/* fall through - error since PLLD2 does not have MUX_SEL control */
 | |
| 	default:
 | |
| 		return -EINVAL;
 | |
| 	}
 | |
| 
 | |
| 	val = clk_readl(reg);
 | |
| 	if (setting)
 | |
| 		val |= mask;
 | |
| 	else
 | |
| 		val &= ~mask;
 | |
| 	clk_writel(val, reg);
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static struct clk_ops tegra_plld_ops = {
 | |
| 	.init			= tegra30_pll_clk_init,
 | |
| 	.enable			= tegra30_pll_clk_enable,
 | |
| 	.disable		= tegra30_pll_clk_disable,
 | |
| 	.set_rate		= tegra30_pll_clk_set_rate,
 | |
| 	.clk_cfg_ex		= tegra30_plld_clk_cfg_ex,
 | |
| };
 | |
| 
 | |
| static void tegra30_plle_clk_init(struct clk *c)
 | |
| {
 | |
| 	u32 val;
 | |
| 
 | |
| 	val = clk_readl(PLLE_AUX);
 | |
| 	c->parent = (val & PLLE_AUX_PLLP_SEL) ?
 | |
| 		tegra_get_clock_by_name("pll_p") :
 | |
| 		tegra_get_clock_by_name("pll_ref");
 | |
| 
 | |
| 	val = clk_readl(c->reg + PLL_BASE);
 | |
| 	c->state = (val & PLLE_BASE_ENABLE) ? ON : OFF;
 | |
| 	c->mul = (val & PLLE_BASE_DIVN_MASK) >> PLLE_BASE_DIVN_SHIFT;
 | |
| 	c->div = (val & PLLE_BASE_DIVM_MASK) >> PLLE_BASE_DIVM_SHIFT;
 | |
| 	c->div *= (val & PLLE_BASE_DIVP_MASK) >> PLLE_BASE_DIVP_SHIFT;
 | |
| }
 | |
| 
 | |
| static void tegra30_plle_clk_disable(struct clk *c)
 | |
| {
 | |
| 	u32 val;
 | |
| 	pr_debug("%s on clock %s\n", __func__, c->name);
 | |
| 
 | |
| 	val = clk_readl(c->reg + PLL_BASE);
 | |
| 	val &= ~(PLLE_BASE_CML_ENABLE | PLLE_BASE_ENABLE);
 | |
| 	clk_writel(val, c->reg + PLL_BASE);
 | |
| }
 | |
| 
 | |
| static void tegra30_plle_training(struct clk *c)
 | |
| {
 | |
| 	u32 val;
 | |
| 
 | |
| 	/* PLLE is already disabled, and setup cleared;
 | |
| 	 * create falling edge on PLLE IDDQ input */
 | |
| 	val = pmc_readl(PMC_SATA_PWRGT);
 | |
| 	val |= PMC_SATA_PWRGT_PLLE_IDDQ_VALUE;
 | |
| 	pmc_writel(val, PMC_SATA_PWRGT);
 | |
| 
 | |
| 	val = pmc_readl(PMC_SATA_PWRGT);
 | |
| 	val |= PMC_SATA_PWRGT_PLLE_IDDQ_SWCTL;
 | |
| 	pmc_writel(val, PMC_SATA_PWRGT);
 | |
| 
 | |
| 	val = pmc_readl(PMC_SATA_PWRGT);
 | |
| 	val &= ~PMC_SATA_PWRGT_PLLE_IDDQ_VALUE;
 | |
| 	pmc_writel(val, PMC_SATA_PWRGT);
 | |
| 
 | |
| 	do {
 | |
| 		val = clk_readl(c->reg + PLL_MISC(c));
 | |
| 	} while (!(val & PLLE_MISC_READY));
 | |
| }
 | |
| 
 | |
| static int tegra30_plle_configure(struct clk *c, bool force_training)
 | |
| {
 | |
| 	u32 val;
 | |
| 	const struct clk_pll_freq_table *sel;
 | |
| 	unsigned long rate = c->u.pll.fixed_rate;
 | |
| 	unsigned long input_rate = clk_get_rate(c->parent);
 | |
| 
 | |
| 	for (sel = c->u.pll.freq_table; sel->input_rate != 0; sel++) {
 | |
| 		if (sel->input_rate == input_rate && sel->output_rate == rate)
 | |
| 			break;
 | |
| 	}
 | |
| 
 | |
| 	if (sel->input_rate == 0)
 | |
| 		return -ENOSYS;
 | |
| 
 | |
| 	/* disable PLLE, clear setup fiels */
 | |
| 	tegra30_plle_clk_disable(c);
 | |
| 
 | |
| 	val = clk_readl(c->reg + PLL_MISC(c));
 | |
| 	val &= ~(PLLE_MISC_LOCK_ENABLE | PLLE_MISC_SETUP_MASK);
 | |
| 	clk_writel(val, c->reg + PLL_MISC(c));
 | |
| 
 | |
| 	/* training */
 | |
| 	val = clk_readl(c->reg + PLL_MISC(c));
 | |
| 	if (force_training || (!(val & PLLE_MISC_READY)))
 | |
| 		tegra30_plle_training(c);
 | |
| 
 | |
| 	/* configure dividers, setup, disable SS */
 | |
| 	val = clk_readl(c->reg + PLL_BASE);
 | |
| 	val &= ~PLLE_BASE_DIV_MASK;
 | |
| 	val |= PLLE_BASE_DIV(sel->m, sel->n, sel->p, sel->cpcon);
 | |
| 	clk_writel(val, c->reg + PLL_BASE);
 | |
| 	c->mul = sel->n;
 | |
| 	c->div = sel->m * sel->p;
 | |
| 
 | |
| 	val = clk_readl(c->reg + PLL_MISC(c));
 | |
| 	val |= PLLE_MISC_SETUP_VALUE;
 | |
| 	val |= PLLE_MISC_LOCK_ENABLE;
 | |
| 	clk_writel(val, c->reg + PLL_MISC(c));
 | |
| 
 | |
| 	val = clk_readl(PLLE_SS_CTRL);
 | |
| 	val |= PLLE_SS_DISABLE;
 | |
| 	clk_writel(val, PLLE_SS_CTRL);
 | |
| 
 | |
| 	/* enable and lock PLLE*/
 | |
| 	val = clk_readl(c->reg + PLL_BASE);
 | |
| 	val |= (PLLE_BASE_CML_ENABLE | PLLE_BASE_ENABLE);
 | |
| 	clk_writel(val, c->reg + PLL_BASE);
 | |
| 
 | |
| 	tegra30_pll_clk_wait_for_lock(c, c->reg + PLL_MISC(c), PLLE_MISC_LOCK);
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static int tegra30_plle_clk_enable(struct clk *c)
 | |
| {
 | |
| 	pr_debug("%s on clock %s\n", __func__, c->name);
 | |
| 	return tegra30_plle_configure(c, !c->set);
 | |
| }
 | |
| 
 | |
| static struct clk_ops tegra_plle_ops = {
 | |
| 	.init			= tegra30_plle_clk_init,
 | |
| 	.enable			= tegra30_plle_clk_enable,
 | |
| 	.disable		= tegra30_plle_clk_disable,
 | |
| };
 | |
| 
 | |
| /* Clock divider ops */
 | |
| static void tegra30_pll_div_clk_init(struct clk *c)
 | |
| {
 | |
| 	if (c->flags & DIV_U71) {
 | |
| 		u32 divu71;
 | |
| 		u32 val = clk_readl(c->reg);
 | |
| 		val >>= c->reg_shift;
 | |
| 		c->state = (val & PLL_OUT_CLKEN) ? ON : OFF;
 | |
| 		if (!(val & PLL_OUT_RESET_DISABLE))
 | |
| 			c->state = OFF;
 | |
| 
 | |
| 		divu71 = (val & PLL_OUT_RATIO_MASK) >> PLL_OUT_RATIO_SHIFT;
 | |
| 		c->div = (divu71 + 2);
 | |
| 		c->mul = 2;
 | |
| 	} else if (c->flags & DIV_2) {
 | |
| 		c->state = ON;
 | |
| 		if (c->flags & (PLLD | PLLX)) {
 | |
| 			c->div = 2;
 | |
| 			c->mul = 1;
 | |
| 		} else
 | |
| 			BUG();
 | |
| 	} else {
 | |
| 		c->state = ON;
 | |
| 		c->div = 1;
 | |
| 		c->mul = 1;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| static int tegra30_pll_div_clk_enable(struct clk *c)
 | |
| {
 | |
| 	u32 val;
 | |
| 	u32 new_val;
 | |
| 
 | |
| 	pr_debug("%s: %s\n", __func__, c->name);
 | |
| 	if (c->flags & DIV_U71) {
 | |
| 		val = clk_readl(c->reg);
 | |
| 		new_val = val >> c->reg_shift;
 | |
| 		new_val &= 0xFFFF;
 | |
| 
 | |
| 		new_val |= PLL_OUT_CLKEN | PLL_OUT_RESET_DISABLE;
 | |
| 
 | |
| 		val &= ~(0xFFFF << c->reg_shift);
 | |
| 		val |= new_val << c->reg_shift;
 | |
| 		clk_writel_delay(val, c->reg);
 | |
| 		return 0;
 | |
| 	} else if (c->flags & DIV_2) {
 | |
| 		return 0;
 | |
| 	}
 | |
| 	return -EINVAL;
 | |
| }
 | |
| 
 | |
| static void tegra30_pll_div_clk_disable(struct clk *c)
 | |
| {
 | |
| 	u32 val;
 | |
| 	u32 new_val;
 | |
| 
 | |
| 	pr_debug("%s: %s\n", __func__, c->name);
 | |
| 	if (c->flags & DIV_U71) {
 | |
| 		val = clk_readl(c->reg);
 | |
| 		new_val = val >> c->reg_shift;
 | |
| 		new_val &= 0xFFFF;
 | |
| 
 | |
| 		new_val &= ~(PLL_OUT_CLKEN | PLL_OUT_RESET_DISABLE);
 | |
| 
 | |
| 		val &= ~(0xFFFF << c->reg_shift);
 | |
| 		val |= new_val << c->reg_shift;
 | |
| 		clk_writel_delay(val, c->reg);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| static int tegra30_pll_div_clk_set_rate(struct clk *c, unsigned long rate)
 | |
| {
 | |
| 	u32 val;
 | |
| 	u32 new_val;
 | |
| 	int divider_u71;
 | |
| 	unsigned long parent_rate = clk_get_rate(c->parent);
 | |
| 
 | |
| 	pr_debug("%s: %s %lu\n", __func__, c->name, rate);
 | |
| 	if (c->flags & DIV_U71) {
 | |
| 		divider_u71 = clk_div71_get_divider(
 | |
| 			parent_rate, rate, c->flags, ROUND_DIVIDER_UP);
 | |
| 		if (divider_u71 >= 0) {
 | |
| 			val = clk_readl(c->reg);
 | |
| 			new_val = val >> c->reg_shift;
 | |
| 			new_val &= 0xFFFF;
 | |
| 			if (c->flags & DIV_U71_FIXED)
 | |
| 				new_val |= PLL_OUT_OVERRIDE;
 | |
| 			new_val &= ~PLL_OUT_RATIO_MASK;
 | |
| 			new_val |= divider_u71 << PLL_OUT_RATIO_SHIFT;
 | |
| 
 | |
| 			val &= ~(0xFFFF << c->reg_shift);
 | |
| 			val |= new_val << c->reg_shift;
 | |
| 			clk_writel_delay(val, c->reg);
 | |
| 			c->div = divider_u71 + 2;
 | |
| 			c->mul = 2;
 | |
| 			return 0;
 | |
| 		}
 | |
| 	} else if (c->flags & DIV_2)
 | |
| 		return clk_set_rate(c->parent, rate * 2);
 | |
| 
 | |
| 	return -EINVAL;
 | |
| }
 | |
| 
 | |
| static long tegra30_pll_div_clk_round_rate(struct clk *c, unsigned long rate)
 | |
| {
 | |
| 	int divider;
 | |
| 	unsigned long parent_rate = clk_get_rate(c->parent);
 | |
| 	pr_debug("%s: %s %lu\n", __func__, c->name, rate);
 | |
| 
 | |
| 	if (c->flags & DIV_U71) {
 | |
| 		divider = clk_div71_get_divider(
 | |
| 			parent_rate, rate, c->flags, ROUND_DIVIDER_UP);
 | |
| 		if (divider < 0)
 | |
| 			return divider;
 | |
| 		return DIV_ROUND_UP(parent_rate * 2, divider + 2);
 | |
| 	} else if (c->flags & DIV_2)
 | |
| 		/* no rounding - fixed DIV_2 dividers pass rate to parent PLL */
 | |
| 		return rate;
 | |
| 
 | |
| 	return -EINVAL;
 | |
| }
 | |
| 
 | |
| static struct clk_ops tegra_pll_div_ops = {
 | |
| 	.init			= tegra30_pll_div_clk_init,
 | |
| 	.enable			= tegra30_pll_div_clk_enable,
 | |
| 	.disable		= tegra30_pll_div_clk_disable,
 | |
| 	.set_rate		= tegra30_pll_div_clk_set_rate,
 | |
| 	.round_rate		= tegra30_pll_div_clk_round_rate,
 | |
| };
 | |
| 
 | |
| /* Periph clk ops */
 | |
| static inline u32 periph_clk_source_mask(struct clk *c)
 | |
| {
 | |
| 	if (c->flags & MUX8)
 | |
| 		return 7 << 29;
 | |
| 	else if (c->flags & MUX_PWM)
 | |
| 		return 3 << 28;
 | |
| 	else if (c->flags & MUX_CLK_OUT)
 | |
| 		return 3 << (c->u.periph.clk_num + 4);
 | |
| 	else if (c->flags & PLLD)
 | |
| 		return PLLD_BASE_DSIB_MUX_MASK;
 | |
| 	else
 | |
| 		return 3 << 30;
 | |
| }
 | |
| 
 | |
| static inline u32 periph_clk_source_shift(struct clk *c)
 | |
| {
 | |
| 	if (c->flags & MUX8)
 | |
| 		return 29;
 | |
| 	else if (c->flags & MUX_PWM)
 | |
| 		return 28;
 | |
| 	else if (c->flags & MUX_CLK_OUT)
 | |
| 		return c->u.periph.clk_num + 4;
 | |
| 	else if (c->flags & PLLD)
 | |
| 		return PLLD_BASE_DSIB_MUX_SHIFT;
 | |
| 	else
 | |
| 		return 30;
 | |
| }
 | |
| 
 | |
| static void tegra30_periph_clk_init(struct clk *c)
 | |
| {
 | |
| 	u32 val = clk_readl(c->reg);
 | |
| 	const struct clk_mux_sel *mux = 0;
 | |
| 	const struct clk_mux_sel *sel;
 | |
| 	if (c->flags & MUX) {
 | |
| 		for (sel = c->inputs; sel->input != NULL; sel++) {
 | |
| 			if (((val & periph_clk_source_mask(c)) >>
 | |
| 			    periph_clk_source_shift(c)) == sel->value)
 | |
| 				mux = sel;
 | |
| 		}
 | |
| 		BUG_ON(!mux);
 | |
| 
 | |
| 		c->parent = mux->input;
 | |
| 	} else {
 | |
| 		c->parent = c->inputs[0].input;
 | |
| 	}
 | |
| 
 | |
| 	if (c->flags & DIV_U71) {
 | |
| 		u32 divu71 = val & PERIPH_CLK_SOURCE_DIVU71_MASK;
 | |
| 		if ((c->flags & DIV_U71_UART) &&
 | |
| 		    (!(val & PERIPH_CLK_UART_DIV_ENB))) {
 | |
| 			divu71 = 0;
 | |
| 		}
 | |
| 		if (c->flags & DIV_U71_IDLE) {
 | |
| 			val &= ~(PERIPH_CLK_SOURCE_DIVU71_MASK <<
 | |
| 				PERIPH_CLK_SOURCE_DIVIDLE_SHIFT);
 | |
| 			val |= (PERIPH_CLK_SOURCE_DIVIDLE_VAL <<
 | |
| 				PERIPH_CLK_SOURCE_DIVIDLE_SHIFT);
 | |
| 			clk_writel(val, c->reg);
 | |
| 		}
 | |
| 		c->div = divu71 + 2;
 | |
| 		c->mul = 2;
 | |
| 	} else if (c->flags & DIV_U16) {
 | |
| 		u32 divu16 = val & PERIPH_CLK_SOURCE_DIVU16_MASK;
 | |
| 		c->div = divu16 + 1;
 | |
| 		c->mul = 1;
 | |
| 	} else {
 | |
| 		c->div = 1;
 | |
| 		c->mul = 1;
 | |
| 	}
 | |
| 
 | |
| 	c->state = ON;
 | |
| 	if (!(clk_readl(PERIPH_CLK_TO_ENB_REG(c)) & PERIPH_CLK_TO_BIT(c)))
 | |
| 		c->state = OFF;
 | |
| 	if (!(c->flags & PERIPH_NO_RESET))
 | |
| 		if (clk_readl(PERIPH_CLK_TO_RST_REG(c)) & PERIPH_CLK_TO_BIT(c))
 | |
| 			c->state = OFF;
 | |
| }
 | |
| 
 | |
| static int tegra30_periph_clk_enable(struct clk *c)
 | |
| {
 | |
| 	pr_debug("%s on clock %s\n", __func__, c->name);
 | |
| 
 | |
| 	tegra_periph_clk_enable_refcount[c->u.periph.clk_num]++;
 | |
| 	if (tegra_periph_clk_enable_refcount[c->u.periph.clk_num] > 1)
 | |
| 		return 0;
 | |
| 
 | |
| 	clk_writel_delay(PERIPH_CLK_TO_BIT(c), PERIPH_CLK_TO_ENB_SET_REG(c));
 | |
| 	if (!(c->flags & PERIPH_NO_RESET) &&
 | |
| 		 !(c->flags & PERIPH_MANUAL_RESET)) {
 | |
| 		if (clk_readl(PERIPH_CLK_TO_RST_REG(c)) &
 | |
| 			 PERIPH_CLK_TO_BIT(c)) {
 | |
| 			udelay(5);	/* reset propagation delay */
 | |
| 			clk_writel(PERIPH_CLK_TO_BIT(c),
 | |
| 				 PERIPH_CLK_TO_RST_CLR_REG(c));
 | |
| 		}
 | |
| 	}
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static void tegra30_periph_clk_disable(struct clk *c)
 | |
| {
 | |
| 	unsigned long val;
 | |
| 	pr_debug("%s on clock %s\n", __func__, c->name);
 | |
| 
 | |
| 	if (c->refcnt)
 | |
| 		tegra_periph_clk_enable_refcount[c->u.periph.clk_num]--;
 | |
| 
 | |
| 	if (tegra_periph_clk_enable_refcount[c->u.periph.clk_num] == 0) {
 | |
| 		/* If peripheral is in the APB bus then read the APB bus to
 | |
| 		 * flush the write operation in apb bus. This will avoid the
 | |
| 		 * peripheral access after disabling clock*/
 | |
| 		if (c->flags & PERIPH_ON_APB)
 | |
| 			val = chipid_readl();
 | |
| 
 | |
| 		clk_writel_delay(
 | |
| 			PERIPH_CLK_TO_BIT(c), PERIPH_CLK_TO_ENB_CLR_REG(c));
 | |
| 	}
 | |
| }
 | |
| 
 | |
| static void tegra30_periph_clk_reset(struct clk *c, bool assert)
 | |
| {
 | |
| 	unsigned long val;
 | |
| 	pr_debug("%s %s on clock %s\n", __func__,
 | |
| 		 assert ? "assert" : "deassert", c->name);
 | |
| 
 | |
| 	if (!(c->flags & PERIPH_NO_RESET)) {
 | |
| 		if (assert) {
 | |
| 			/* If peripheral is in the APB bus then read the APB
 | |
| 			 * bus to flush the write operation in apb bus. This
 | |
| 			 * will avoid the peripheral access after disabling
 | |
| 			 * clock */
 | |
| 			if (c->flags & PERIPH_ON_APB)
 | |
| 				val = chipid_readl();
 | |
| 
 | |
| 			clk_writel(PERIPH_CLK_TO_BIT(c),
 | |
| 				   PERIPH_CLK_TO_RST_SET_REG(c));
 | |
| 		} else
 | |
| 			clk_writel(PERIPH_CLK_TO_BIT(c),
 | |
| 				   PERIPH_CLK_TO_RST_CLR_REG(c));
 | |
| 	}
 | |
| }
 | |
| 
 | |
| static int tegra30_periph_clk_set_parent(struct clk *c, struct clk *p)
 | |
| {
 | |
| 	u32 val;
 | |
| 	const struct clk_mux_sel *sel;
 | |
| 	pr_debug("%s: %s %s\n", __func__, c->name, p->name);
 | |
| 
 | |
| 	if (!(c->flags & MUX))
 | |
| 		return (p == c->parent) ? 0 : (-EINVAL);
 | |
| 
 | |
| 	for (sel = c->inputs; sel->input != NULL; sel++) {
 | |
| 		if (sel->input == p) {
 | |
| 			val = clk_readl(c->reg);
 | |
| 			val &= ~periph_clk_source_mask(c);
 | |
| 			val |= (sel->value << periph_clk_source_shift(c));
 | |
| 
 | |
| 			if (c->refcnt)
 | |
| 				clk_enable(p);
 | |
| 
 | |
| 			clk_writel_delay(val, c->reg);
 | |
| 
 | |
| 			if (c->refcnt && c->parent)
 | |
| 				clk_disable(c->parent);
 | |
| 
 | |
| 			clk_reparent(c, p);
 | |
| 			return 0;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return -EINVAL;
 | |
| }
 | |
| 
 | |
| static int tegra30_periph_clk_set_rate(struct clk *c, unsigned long rate)
 | |
| {
 | |
| 	u32 val;
 | |
| 	int divider;
 | |
| 	unsigned long parent_rate = clk_get_rate(c->parent);
 | |
| 
 | |
| 	if (c->flags & DIV_U71) {
 | |
| 		divider = clk_div71_get_divider(
 | |
| 			parent_rate, rate, c->flags, ROUND_DIVIDER_UP);
 | |
| 		if (divider >= 0) {
 | |
| 			val = clk_readl(c->reg);
 | |
| 			val &= ~PERIPH_CLK_SOURCE_DIVU71_MASK;
 | |
| 			val |= divider;
 | |
| 			if (c->flags & DIV_U71_UART) {
 | |
| 				if (divider)
 | |
| 					val |= PERIPH_CLK_UART_DIV_ENB;
 | |
| 				else
 | |
| 					val &= ~PERIPH_CLK_UART_DIV_ENB;
 | |
| 			}
 | |
| 			clk_writel_delay(val, c->reg);
 | |
| 			c->div = divider + 2;
 | |
| 			c->mul = 2;
 | |
| 			return 0;
 | |
| 		}
 | |
| 	} else if (c->flags & DIV_U16) {
 | |
| 		divider = clk_div16_get_divider(parent_rate, rate);
 | |
| 		if (divider >= 0) {
 | |
| 			val = clk_readl(c->reg);
 | |
| 			val &= ~PERIPH_CLK_SOURCE_DIVU16_MASK;
 | |
| 			val |= divider;
 | |
| 			clk_writel_delay(val, c->reg);
 | |
| 			c->div = divider + 1;
 | |
| 			c->mul = 1;
 | |
| 			return 0;
 | |
| 		}
 | |
| 	} else if (parent_rate <= rate) {
 | |
| 		c->div = 1;
 | |
| 		c->mul = 1;
 | |
| 		return 0;
 | |
| 	}
 | |
| 	return -EINVAL;
 | |
| }
 | |
| 
 | |
| static long tegra30_periph_clk_round_rate(struct clk *c,
 | |
| 	unsigned long rate)
 | |
| {
 | |
| 	int divider;
 | |
| 	unsigned long parent_rate = clk_get_rate(c->parent);
 | |
| 	pr_debug("%s: %s %lu\n", __func__, c->name, rate);
 | |
| 
 | |
| 	if (c->flags & DIV_U71) {
 | |
| 		divider = clk_div71_get_divider(
 | |
| 			parent_rate, rate, c->flags, ROUND_DIVIDER_UP);
 | |
| 		if (divider < 0)
 | |
| 			return divider;
 | |
| 
 | |
| 		return DIV_ROUND_UP(parent_rate * 2, divider + 2);
 | |
| 	} else if (c->flags & DIV_U16) {
 | |
| 		divider = clk_div16_get_divider(parent_rate, rate);
 | |
| 		if (divider < 0)
 | |
| 			return divider;
 | |
| 		return DIV_ROUND_UP(parent_rate, divider + 1);
 | |
| 	}
 | |
| 	return -EINVAL;
 | |
| }
 | |
| 
 | |
| static struct clk_ops tegra_periph_clk_ops = {
 | |
| 	.init			= &tegra30_periph_clk_init,
 | |
| 	.enable			= &tegra30_periph_clk_enable,
 | |
| 	.disable		= &tegra30_periph_clk_disable,
 | |
| 	.set_parent		= &tegra30_periph_clk_set_parent,
 | |
| 	.set_rate		= &tegra30_periph_clk_set_rate,
 | |
| 	.round_rate		= &tegra30_periph_clk_round_rate,
 | |
| 	.reset			= &tegra30_periph_clk_reset,
 | |
| };
 | |
| 
 | |
| 
 | |
| /* Periph extended clock configuration ops */
 | |
| static int
 | |
| tegra30_vi_clk_cfg_ex(struct clk *c, enum tegra_clk_ex_param p, u32 setting)
 | |
| {
 | |
| 	if (p == TEGRA_CLK_VI_INP_SEL) {
 | |
| 		u32 val = clk_readl(c->reg);
 | |
| 		val &= ~PERIPH_CLK_VI_SEL_EX_MASK;
 | |
| 		val |= (setting << PERIPH_CLK_VI_SEL_EX_SHIFT) &
 | |
| 			PERIPH_CLK_VI_SEL_EX_MASK;
 | |
| 		clk_writel(val, c->reg);
 | |
| 		return 0;
 | |
| 	}
 | |
| 	return -EINVAL;
 | |
| }
 | |
| 
 | |
| static struct clk_ops tegra_vi_clk_ops = {
 | |
| 	.init			= &tegra30_periph_clk_init,
 | |
| 	.enable			= &tegra30_periph_clk_enable,
 | |
| 	.disable		= &tegra30_periph_clk_disable,
 | |
| 	.set_parent		= &tegra30_periph_clk_set_parent,
 | |
| 	.set_rate		= &tegra30_periph_clk_set_rate,
 | |
| 	.round_rate		= &tegra30_periph_clk_round_rate,
 | |
| 	.clk_cfg_ex		= &tegra30_vi_clk_cfg_ex,
 | |
| 	.reset			= &tegra30_periph_clk_reset,
 | |
| };
 | |
| 
 | |
| static int
 | |
| tegra30_nand_clk_cfg_ex(struct clk *c, enum tegra_clk_ex_param p, u32 setting)
 | |
| {
 | |
| 	if (p == TEGRA_CLK_NAND_PAD_DIV2_ENB) {
 | |
| 		u32 val = clk_readl(c->reg);
 | |
| 		if (setting)
 | |
| 			val |= PERIPH_CLK_NAND_DIV_EX_ENB;
 | |
| 		else
 | |
| 			val &= ~PERIPH_CLK_NAND_DIV_EX_ENB;
 | |
| 		clk_writel(val, c->reg);
 | |
| 		return 0;
 | |
| 	}
 | |
| 	return -EINVAL;
 | |
| }
 | |
| 
 | |
| static struct clk_ops tegra_nand_clk_ops = {
 | |
| 	.init			= &tegra30_periph_clk_init,
 | |
| 	.enable			= &tegra30_periph_clk_enable,
 | |
| 	.disable		= &tegra30_periph_clk_disable,
 | |
| 	.set_parent		= &tegra30_periph_clk_set_parent,
 | |
| 	.set_rate		= &tegra30_periph_clk_set_rate,
 | |
| 	.round_rate		= &tegra30_periph_clk_round_rate,
 | |
| 	.clk_cfg_ex		= &tegra30_nand_clk_cfg_ex,
 | |
| 	.reset			= &tegra30_periph_clk_reset,
 | |
| };
 | |
| 
 | |
| 
 | |
| static int
 | |
| tegra30_dtv_clk_cfg_ex(struct clk *c, enum tegra_clk_ex_param p, u32 setting)
 | |
| {
 | |
| 	if (p == TEGRA_CLK_DTV_INVERT) {
 | |
| 		u32 val = clk_readl(c->reg);
 | |
| 		if (setting)
 | |
| 			val |= PERIPH_CLK_DTV_POLARITY_INV;
 | |
| 		else
 | |
| 			val &= ~PERIPH_CLK_DTV_POLARITY_INV;
 | |
| 		clk_writel(val, c->reg);
 | |
| 		return 0;
 | |
| 	}
 | |
| 	return -EINVAL;
 | |
| }
 | |
| 
 | |
| static struct clk_ops tegra_dtv_clk_ops = {
 | |
| 	.init			= &tegra30_periph_clk_init,
 | |
| 	.enable			= &tegra30_periph_clk_enable,
 | |
| 	.disable		= &tegra30_periph_clk_disable,
 | |
| 	.set_parent		= &tegra30_periph_clk_set_parent,
 | |
| 	.set_rate		= &tegra30_periph_clk_set_rate,
 | |
| 	.round_rate		= &tegra30_periph_clk_round_rate,
 | |
| 	.clk_cfg_ex		= &tegra30_dtv_clk_cfg_ex,
 | |
| 	.reset			= &tegra30_periph_clk_reset,
 | |
| };
 | |
| 
 | |
| static int tegra30_dsib_clk_set_parent(struct clk *c, struct clk *p)
 | |
| {
 | |
| 	const struct clk_mux_sel *sel;
 | |
| 	struct clk *d = tegra_get_clock_by_name("pll_d");
 | |
| 
 | |
| 	pr_debug("%s: %s %s\n", __func__, c->name, p->name);
 | |
| 
 | |
| 	for (sel = c->inputs; sel->input != NULL; sel++) {
 | |
| 		if (sel->input == p) {
 | |
| 			if (c->refcnt)
 | |
| 				clk_enable(p);
 | |
| 
 | |
| 			/* The DSIB parent selection bit is in PLLD base
 | |
| 			   register - can not do direct r-m-w, must be
 | |
| 			   protected by PLLD lock */
 | |
| 			tegra_clk_cfg_ex(
 | |
| 				d, TEGRA_CLK_PLLD_MIPI_MUX_SEL, sel->value);
 | |
| 
 | |
| 			if (c->refcnt && c->parent)
 | |
| 				clk_disable(c->parent);
 | |
| 
 | |
| 			clk_reparent(c, p);
 | |
| 			return 0;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return -EINVAL;
 | |
| }
 | |
| 
 | |
| static struct clk_ops tegra_dsib_clk_ops = {
 | |
| 	.init			= &tegra30_periph_clk_init,
 | |
| 	.enable			= &tegra30_periph_clk_enable,
 | |
| 	.disable		= &tegra30_periph_clk_disable,
 | |
| 	.set_parent		= &tegra30_dsib_clk_set_parent,
 | |
| 	.set_rate		= &tegra30_periph_clk_set_rate,
 | |
| 	.round_rate		= &tegra30_periph_clk_round_rate,
 | |
| 	.reset			= &tegra30_periph_clk_reset,
 | |
| };
 | |
| 
 | |
| /* pciex clock support only reset function */
 | |
| static struct clk_ops tegra_pciex_clk_ops = {
 | |
| 	.reset    = tegra30_periph_clk_reset,
 | |
| };
 | |
| 
 | |
| /* Output clock ops */
 | |
| 
 | |
| static DEFINE_SPINLOCK(clk_out_lock);
 | |
| 
 | |
| static void tegra30_clk_out_init(struct clk *c)
 | |
| {
 | |
| 	const struct clk_mux_sel *mux = 0;
 | |
| 	const struct clk_mux_sel *sel;
 | |
| 	u32 val = pmc_readl(c->reg);
 | |
| 
 | |
| 	c->state = (val & (0x1 << c->u.periph.clk_num)) ? ON : OFF;
 | |
| 	c->mul = 1;
 | |
| 	c->div = 1;
 | |
| 
 | |
| 	for (sel = c->inputs; sel->input != NULL; sel++) {
 | |
| 		if (((val & periph_clk_source_mask(c)) >>
 | |
| 		     periph_clk_source_shift(c)) == sel->value)
 | |
| 			mux = sel;
 | |
| 	}
 | |
| 	BUG_ON(!mux);
 | |
| 	c->parent = mux->input;
 | |
| }
 | |
| 
 | |
| static int tegra30_clk_out_enable(struct clk *c)
 | |
| {
 | |
| 	u32 val;
 | |
| 	unsigned long flags;
 | |
| 
 | |
| 	pr_debug("%s on clock %s\n", __func__, c->name);
 | |
| 
 | |
| 	spin_lock_irqsave(&clk_out_lock, flags);
 | |
| 	val = pmc_readl(c->reg);
 | |
| 	val |= (0x1 << c->u.periph.clk_num);
 | |
| 	pmc_writel(val, c->reg);
 | |
| 	spin_unlock_irqrestore(&clk_out_lock, flags);
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static void tegra30_clk_out_disable(struct clk *c)
 | |
| {
 | |
| 	u32 val;
 | |
| 	unsigned long flags;
 | |
| 
 | |
| 	pr_debug("%s on clock %s\n", __func__, c->name);
 | |
| 
 | |
| 	spin_lock_irqsave(&clk_out_lock, flags);
 | |
| 	val = pmc_readl(c->reg);
 | |
| 	val &= ~(0x1 << c->u.periph.clk_num);
 | |
| 	pmc_writel(val, c->reg);
 | |
| 	spin_unlock_irqrestore(&clk_out_lock, flags);
 | |
| }
 | |
| 
 | |
| static int tegra30_clk_out_set_parent(struct clk *c, struct clk *p)
 | |
| {
 | |
| 	u32 val;
 | |
| 	unsigned long flags;
 | |
| 	const struct clk_mux_sel *sel;
 | |
| 
 | |
| 	pr_debug("%s: %s %s\n", __func__, c->name, p->name);
 | |
| 
 | |
| 	for (sel = c->inputs; sel->input != NULL; sel++) {
 | |
| 		if (sel->input == p) {
 | |
| 			if (c->refcnt)
 | |
| 				clk_enable(p);
 | |
| 
 | |
| 			spin_lock_irqsave(&clk_out_lock, flags);
 | |
| 			val = pmc_readl(c->reg);
 | |
| 			val &= ~periph_clk_source_mask(c);
 | |
| 			val |= (sel->value << periph_clk_source_shift(c));
 | |
| 			pmc_writel(val, c->reg);
 | |
| 			spin_unlock_irqrestore(&clk_out_lock, flags);
 | |
| 
 | |
| 			if (c->refcnt && c->parent)
 | |
| 				clk_disable(c->parent);
 | |
| 
 | |
| 			clk_reparent(c, p);
 | |
| 			return 0;
 | |
| 		}
 | |
| 	}
 | |
| 	return -EINVAL;
 | |
| }
 | |
| 
 | |
| static struct clk_ops tegra_clk_out_ops = {
 | |
| 	.init			= &tegra30_clk_out_init,
 | |
| 	.enable			= &tegra30_clk_out_enable,
 | |
| 	.disable		= &tegra30_clk_out_disable,
 | |
| 	.set_parent		= &tegra30_clk_out_set_parent,
 | |
| };
 | |
| 
 | |
| 
 | |
| /* Clock doubler ops */
 | |
| static void tegra30_clk_double_init(struct clk *c)
 | |
| {
 | |
| 	u32 val = clk_readl(c->reg);
 | |
| 	c->mul = val & (0x1 << c->reg_shift) ? 1 : 2;
 | |
| 	c->div = 1;
 | |
| 	c->state = ON;
 | |
| 	if (!(clk_readl(PERIPH_CLK_TO_ENB_REG(c)) & PERIPH_CLK_TO_BIT(c)))
 | |
| 		c->state = OFF;
 | |
| };
 | |
| 
 | |
| static int tegra30_clk_double_set_rate(struct clk *c, unsigned long rate)
 | |
| {
 | |
| 	u32 val;
 | |
| 	unsigned long parent_rate = clk_get_rate(c->parent);
 | |
| 	if (rate == parent_rate) {
 | |
| 		val = clk_readl(c->reg) | (0x1 << c->reg_shift);
 | |
| 		clk_writel(val, c->reg);
 | |
| 		c->mul = 1;
 | |
| 		c->div = 1;
 | |
| 		return 0;
 | |
| 	} else if (rate == 2 * parent_rate) {
 | |
| 		val = clk_readl(c->reg) & (~(0x1 << c->reg_shift));
 | |
| 		clk_writel(val, c->reg);
 | |
| 		c->mul = 2;
 | |
| 		c->div = 1;
 | |
| 		return 0;
 | |
| 	}
 | |
| 	return -EINVAL;
 | |
| }
 | |
| 
 | |
| static struct clk_ops tegra_clk_double_ops = {
 | |
| 	.init			= &tegra30_clk_double_init,
 | |
| 	.enable			= &tegra30_periph_clk_enable,
 | |
| 	.disable		= &tegra30_periph_clk_disable,
 | |
| 	.set_rate		= &tegra30_clk_double_set_rate,
 | |
| };
 | |
| 
 | |
| /* Audio sync clock ops */
 | |
| static int tegra30_sync_source_set_rate(struct clk *c, unsigned long rate)
 | |
| {
 | |
| 	c->rate = rate;
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static struct clk_ops tegra_sync_source_ops = {
 | |
| 	.set_rate		= &tegra30_sync_source_set_rate,
 | |
| };
 | |
| 
 | |
| static void tegra30_audio_sync_clk_init(struct clk *c)
 | |
| {
 | |
| 	int source;
 | |
| 	const struct clk_mux_sel *sel;
 | |
| 	u32 val = clk_readl(c->reg);
 | |
| 	c->state = (val & AUDIO_SYNC_DISABLE_BIT) ? OFF : ON;
 | |
| 	source = val & AUDIO_SYNC_SOURCE_MASK;
 | |
| 	for (sel = c->inputs; sel->input != NULL; sel++)
 | |
| 		if (sel->value == source)
 | |
| 			break;
 | |
| 	BUG_ON(sel->input == NULL);
 | |
| 	c->parent = sel->input;
 | |
| }
 | |
| 
 | |
| static int tegra30_audio_sync_clk_enable(struct clk *c)
 | |
| {
 | |
| 	u32 val = clk_readl(c->reg);
 | |
| 	clk_writel((val & (~AUDIO_SYNC_DISABLE_BIT)), c->reg);
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static void tegra30_audio_sync_clk_disable(struct clk *c)
 | |
| {
 | |
| 	u32 val = clk_readl(c->reg);
 | |
| 	clk_writel((val | AUDIO_SYNC_DISABLE_BIT), c->reg);
 | |
| }
 | |
| 
 | |
| static int tegra30_audio_sync_clk_set_parent(struct clk *c, struct clk *p)
 | |
| {
 | |
| 	u32 val;
 | |
| 	const struct clk_mux_sel *sel;
 | |
| 	for (sel = c->inputs; sel->input != NULL; sel++) {
 | |
| 		if (sel->input == p) {
 | |
| 			val = clk_readl(c->reg);
 | |
| 			val &= ~AUDIO_SYNC_SOURCE_MASK;
 | |
| 			val |= sel->value;
 | |
| 
 | |
| 			if (c->refcnt)
 | |
| 				clk_enable(p);
 | |
| 
 | |
| 			clk_writel(val, c->reg);
 | |
| 
 | |
| 			if (c->refcnt && c->parent)
 | |
| 				clk_disable(c->parent);
 | |
| 
 | |
| 			clk_reparent(c, p);
 | |
| 			return 0;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return -EINVAL;
 | |
| }
 | |
| 
 | |
| static struct clk_ops tegra_audio_sync_clk_ops = {
 | |
| 	.init       = tegra30_audio_sync_clk_init,
 | |
| 	.enable     = tegra30_audio_sync_clk_enable,
 | |
| 	.disable    = tegra30_audio_sync_clk_disable,
 | |
| 	.set_parent = tegra30_audio_sync_clk_set_parent,
 | |
| };
 | |
| 
 | |
| /* cml0 (pcie), and cml1 (sata) clock ops */
 | |
| static void tegra30_cml_clk_init(struct clk *c)
 | |
| {
 | |
| 	u32 val = clk_readl(c->reg);
 | |
| 	c->state = val & (0x1 << c->u.periph.clk_num) ? ON : OFF;
 | |
| }
 | |
| 
 | |
| static int tegra30_cml_clk_enable(struct clk *c)
 | |
| {
 | |
| 	u32 val = clk_readl(c->reg);
 | |
| 	val |= (0x1 << c->u.periph.clk_num);
 | |
| 	clk_writel(val, c->reg);
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static void tegra30_cml_clk_disable(struct clk *c)
 | |
| {
 | |
| 	u32 val = clk_readl(c->reg);
 | |
| 	val &= ~(0x1 << c->u.periph.clk_num);
 | |
| 	clk_writel(val, c->reg);
 | |
| }
 | |
| 
 | |
| static struct clk_ops tegra_cml_clk_ops = {
 | |
| 	.init			= &tegra30_cml_clk_init,
 | |
| 	.enable			= &tegra30_cml_clk_enable,
 | |
| 	.disable		= &tegra30_cml_clk_disable,
 | |
| };
 | |
| 
 | |
| /* Clock definitions */
 | |
| static struct clk tegra_clk_32k = {
 | |
| 	.name = "clk_32k",
 | |
| 	.rate = 32768,
 | |
| 	.ops  = NULL,
 | |
| 	.max_rate = 32768,
 | |
| };
 | |
| 
 | |
| static struct clk tegra_clk_m = {
 | |
| 	.name      = "clk_m",
 | |
| 	.flags     = ENABLE_ON_INIT,
 | |
| 	.ops       = &tegra_clk_m_ops,
 | |
| 	.reg       = 0x1fc,
 | |
| 	.reg_shift = 28,
 | |
| 	.max_rate  = 48000000,
 | |
| };
 | |
| 
 | |
| static struct clk tegra_clk_m_div2 = {
 | |
| 	.name      = "clk_m_div2",
 | |
| 	.ops       = &tegra_clk_m_div_ops,
 | |
| 	.parent    = &tegra_clk_m,
 | |
| 	.mul       = 1,
 | |
| 	.div       = 2,
 | |
| 	.state     = ON,
 | |
| 	.max_rate  = 24000000,
 | |
| };
 | |
| 
 | |
| static struct clk tegra_clk_m_div4 = {
 | |
| 	.name      = "clk_m_div4",
 | |
| 	.ops       = &tegra_clk_m_div_ops,
 | |
| 	.parent    = &tegra_clk_m,
 | |
| 	.mul       = 1,
 | |
| 	.div       = 4,
 | |
| 	.state     = ON,
 | |
| 	.max_rate  = 12000000,
 | |
| };
 | |
| 
 | |
| static struct clk tegra_pll_ref = {
 | |
| 	.name      = "pll_ref",
 | |
| 	.flags     = ENABLE_ON_INIT,
 | |
| 	.ops       = &tegra_pll_ref_ops,
 | |
| 	.parent    = &tegra_clk_m,
 | |
| 	.max_rate  = 26000000,
 | |
| };
 | |
| 
 | |
| static struct clk_pll_freq_table tegra_pll_c_freq_table[] = {
 | |
| 	{ 12000000, 1040000000, 520,  6, 1, 8},
 | |
| 	{ 13000000, 1040000000, 480,  6, 1, 8},
 | |
| 	{ 16800000, 1040000000, 495,  8, 1, 8},		/* actual: 1039.5 MHz */
 | |
| 	{ 19200000, 1040000000, 325,  6, 1, 6},
 | |
| 	{ 26000000, 1040000000, 520, 13, 1, 8},
 | |
| 
 | |
| 	{ 12000000, 832000000, 416,  6, 1, 8},
 | |
| 	{ 13000000, 832000000, 832, 13, 1, 8},
 | |
| 	{ 16800000, 832000000, 396,  8, 1, 8},		/* actual: 831.6 MHz */
 | |
| 	{ 19200000, 832000000, 260,  6, 1, 8},
 | |
| 	{ 26000000, 832000000, 416, 13, 1, 8},
 | |
| 
 | |
| 	{ 12000000, 624000000, 624, 12, 1, 8},
 | |
| 	{ 13000000, 624000000, 624, 13, 1, 8},
 | |
| 	{ 16800000, 600000000, 520, 14, 1, 8},
 | |
| 	{ 19200000, 624000000, 520, 16, 1, 8},
 | |
| 	{ 26000000, 624000000, 624, 26, 1, 8},
 | |
| 
 | |
| 	{ 12000000, 600000000, 600, 12, 1, 8},
 | |
| 	{ 13000000, 600000000, 600, 13, 1, 8},
 | |
| 	{ 16800000, 600000000, 500, 14, 1, 8},
 | |
| 	{ 19200000, 600000000, 375, 12, 1, 6},
 | |
| 	{ 26000000, 600000000, 600, 26, 1, 8},
 | |
| 
 | |
| 	{ 12000000, 520000000, 520, 12, 1, 8},
 | |
| 	{ 13000000, 520000000, 520, 13, 1, 8},
 | |
| 	{ 16800000, 520000000, 495, 16, 1, 8},		/* actual: 519.75 MHz */
 | |
| 	{ 19200000, 520000000, 325, 12, 1, 6},
 | |
| 	{ 26000000, 520000000, 520, 26, 1, 8},
 | |
| 
 | |
| 	{ 12000000, 416000000, 416, 12, 1, 8},
 | |
| 	{ 13000000, 416000000, 416, 13, 1, 8},
 | |
| 	{ 16800000, 416000000, 396, 16, 1, 8},		/* actual: 415.8 MHz */
 | |
| 	{ 19200000, 416000000, 260, 12, 1, 6},
 | |
| 	{ 26000000, 416000000, 416, 26, 1, 8},
 | |
| 	{ 0, 0, 0, 0, 0, 0 },
 | |
| };
 | |
| 
 | |
| static struct clk tegra_pll_c = {
 | |
| 	.name      = "pll_c",
 | |
| 	.flags	   = PLL_HAS_CPCON,
 | |
| 	.ops       = &tegra_pll_ops,
 | |
| 	.reg       = 0x80,
 | |
| 	.parent    = &tegra_pll_ref,
 | |
| 	.max_rate  = 1400000000,
 | |
| 	.u.pll = {
 | |
| 		.input_min = 2000000,
 | |
| 		.input_max = 31000000,
 | |
| 		.cf_min    = 1000000,
 | |
| 		.cf_max    = 6000000,
 | |
| 		.vco_min   = 20000000,
 | |
| 		.vco_max   = 1400000000,
 | |
| 		.freq_table = tegra_pll_c_freq_table,
 | |
| 		.lock_delay = 300,
 | |
| 	},
 | |
| };
 | |
| 
 | |
| static struct clk tegra_pll_c_out1 = {
 | |
| 	.name      = "pll_c_out1",
 | |
| 	.ops       = &tegra_pll_div_ops,
 | |
| 	.flags     = DIV_U71,
 | |
| 	.parent    = &tegra_pll_c,
 | |
| 	.reg       = 0x84,
 | |
| 	.reg_shift = 0,
 | |
| 	.max_rate  = 700000000,
 | |
| };
 | |
| 
 | |
| static struct clk_pll_freq_table tegra_pll_m_freq_table[] = {
 | |
| 	{ 12000000, 666000000, 666, 12, 1, 8},
 | |
| 	{ 13000000, 666000000, 666, 13, 1, 8},
 | |
| 	{ 16800000, 666000000, 555, 14, 1, 8},
 | |
| 	{ 19200000, 666000000, 555, 16, 1, 8},
 | |
| 	{ 26000000, 666000000, 666, 26, 1, 8},
 | |
| 	{ 12000000, 600000000, 600, 12, 1, 8},
 | |
| 	{ 13000000, 600000000, 600, 13, 1, 8},
 | |
| 	{ 16800000, 600000000, 500, 14, 1, 8},
 | |
| 	{ 19200000, 600000000, 375, 12, 1, 6},
 | |
| 	{ 26000000, 600000000, 600, 26, 1, 8},
 | |
| 	{ 0, 0, 0, 0, 0, 0 },
 | |
| };
 | |
| 
 | |
| static struct clk tegra_pll_m = {
 | |
| 	.name      = "pll_m",
 | |
| 	.flags     = PLL_HAS_CPCON | PLLM,
 | |
| 	.ops       = &tegra_pll_ops,
 | |
| 	.reg       = 0x90,
 | |
| 	.parent    = &tegra_pll_ref,
 | |
| 	.max_rate  = 800000000,
 | |
| 	.u.pll = {
 | |
| 		.input_min = 2000000,
 | |
| 		.input_max = 31000000,
 | |
| 		.cf_min    = 1000000,
 | |
| 		.cf_max    = 6000000,
 | |
| 		.vco_min   = 20000000,
 | |
| 		.vco_max   = 1200000000,
 | |
| 		.freq_table = tegra_pll_m_freq_table,
 | |
| 		.lock_delay = 300,
 | |
| 	},
 | |
| };
 | |
| 
 | |
| static struct clk tegra_pll_m_out1 = {
 | |
| 	.name      = "pll_m_out1",
 | |
| 	.ops       = &tegra_pll_div_ops,
 | |
| 	.flags     = DIV_U71,
 | |
| 	.parent    = &tegra_pll_m,
 | |
| 	.reg       = 0x94,
 | |
| 	.reg_shift = 0,
 | |
| 	.max_rate  = 600000000,
 | |
| };
 | |
| 
 | |
| static struct clk_pll_freq_table tegra_pll_p_freq_table[] = {
 | |
| 	{ 12000000, 216000000, 432, 12, 2, 8},
 | |
| 	{ 13000000, 216000000, 432, 13, 2, 8},
 | |
| 	{ 16800000, 216000000, 360, 14, 2, 8},
 | |
| 	{ 19200000, 216000000, 360, 16, 2, 8},
 | |
| 	{ 26000000, 216000000, 432, 26, 2, 8},
 | |
| 	{ 0, 0, 0, 0, 0, 0 },
 | |
| };
 | |
| 
 | |
| static struct clk tegra_pll_p = {
 | |
| 	.name      = "pll_p",
 | |
| 	.flags     = ENABLE_ON_INIT | PLL_FIXED | PLL_HAS_CPCON,
 | |
| 	.ops       = &tegra_pll_ops,
 | |
| 	.reg       = 0xa0,
 | |
| 	.parent    = &tegra_pll_ref,
 | |
| 	.max_rate  = 432000000,
 | |
| 	.u.pll = {
 | |
| 		.input_min = 2000000,
 | |
| 		.input_max = 31000000,
 | |
| 		.cf_min    = 1000000,
 | |
| 		.cf_max    = 6000000,
 | |
| 		.vco_min   = 20000000,
 | |
| 		.vco_max   = 1400000000,
 | |
| 		.freq_table = tegra_pll_p_freq_table,
 | |
| 		.lock_delay = 300,
 | |
| 		.fixed_rate = 408000000,
 | |
| 	},
 | |
| };
 | |
| 
 | |
| static struct clk tegra_pll_p_out1 = {
 | |
| 	.name      = "pll_p_out1",
 | |
| 	.ops       = &tegra_pll_div_ops,
 | |
| 	.flags     = ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED,
 | |
| 	.parent    = &tegra_pll_p,
 | |
| 	.reg       = 0xa4,
 | |
| 	.reg_shift = 0,
 | |
| 	.max_rate  = 432000000,
 | |
| };
 | |
| 
 | |
| static struct clk tegra_pll_p_out2 = {
 | |
| 	.name      = "pll_p_out2",
 | |
| 	.ops       = &tegra_pll_div_ops,
 | |
| 	.flags     = ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED,
 | |
| 	.parent    = &tegra_pll_p,
 | |
| 	.reg       = 0xa4,
 | |
| 	.reg_shift = 16,
 | |
| 	.max_rate  = 432000000,
 | |
| };
 | |
| 
 | |
| static struct clk tegra_pll_p_out3 = {
 | |
| 	.name      = "pll_p_out3",
 | |
| 	.ops       = &tegra_pll_div_ops,
 | |
| 	.flags     = ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED,
 | |
| 	.parent    = &tegra_pll_p,
 | |
| 	.reg       = 0xa8,
 | |
| 	.reg_shift = 0,
 | |
| 	.max_rate  = 432000000,
 | |
| };
 | |
| 
 | |
| static struct clk tegra_pll_p_out4 = {
 | |
| 	.name      = "pll_p_out4",
 | |
| 	.ops       = &tegra_pll_div_ops,
 | |
| 	.flags     = ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED,
 | |
| 	.parent    = &tegra_pll_p,
 | |
| 	.reg       = 0xa8,
 | |
| 	.reg_shift = 16,
 | |
| 	.max_rate  = 432000000,
 | |
| };
 | |
| 
 | |
| static struct clk_pll_freq_table tegra_pll_a_freq_table[] = {
 | |
| 	{ 9600000, 564480000, 294, 5, 1, 4},
 | |
| 	{ 9600000, 552960000, 288, 5, 1, 4},
 | |
| 	{ 9600000, 24000000,  5,   2, 1, 1},
 | |
| 
 | |
| 	{ 28800000, 56448000, 49, 25, 1, 1},
 | |
| 	{ 28800000, 73728000, 64, 25, 1, 1},
 | |
| 	{ 28800000, 24000000,  5,  6, 1, 1},
 | |
| 	{ 0, 0, 0, 0, 0, 0 },
 | |
| };
 | |
| 
 | |
| static struct clk tegra_pll_a = {
 | |
| 	.name      = "pll_a",
 | |
| 	.flags     = PLL_HAS_CPCON,
 | |
| 	.ops       = &tegra_pll_ops,
 | |
| 	.reg       = 0xb0,
 | |
| 	.parent    = &tegra_pll_p_out1,
 | |
| 	.max_rate  = 700000000,
 | |
| 	.u.pll = {
 | |
| 		.input_min = 2000000,
 | |
| 		.input_max = 31000000,
 | |
| 		.cf_min    = 1000000,
 | |
| 		.cf_max    = 6000000,
 | |
| 		.vco_min   = 20000000,
 | |
| 		.vco_max   = 1400000000,
 | |
| 		.freq_table = tegra_pll_a_freq_table,
 | |
| 		.lock_delay = 300,
 | |
| 	},
 | |
| };
 | |
| 
 | |
| static struct clk tegra_pll_a_out0 = {
 | |
| 	.name      = "pll_a_out0",
 | |
| 	.ops       = &tegra_pll_div_ops,
 | |
| 	.flags     = DIV_U71,
 | |
| 	.parent    = &tegra_pll_a,
 | |
| 	.reg       = 0xb4,
 | |
| 	.reg_shift = 0,
 | |
| 	.max_rate  = 100000000,
 | |
| };
 | |
| 
 | |
| static struct clk_pll_freq_table tegra_pll_d_freq_table[] = {
 | |
| 	{ 12000000, 216000000, 216, 12, 1, 4},
 | |
| 	{ 13000000, 216000000, 216, 13, 1, 4},
 | |
| 	{ 16800000, 216000000, 180, 14, 1, 4},
 | |
| 	{ 19200000, 216000000, 180, 16, 1, 4},
 | |
| 	{ 26000000, 216000000, 216, 26, 1, 4},
 | |
| 
 | |
| 	{ 12000000, 594000000, 594, 12, 1, 8},
 | |
| 	{ 13000000, 594000000, 594, 13, 1, 8},
 | |
| 	{ 16800000, 594000000, 495, 14, 1, 8},
 | |
| 	{ 19200000, 594000000, 495, 16, 1, 8},
 | |
| 	{ 26000000, 594000000, 594, 26, 1, 8},
 | |
| 
 | |
| 	{ 12000000, 1000000000, 1000, 12, 1, 12},
 | |
| 	{ 13000000, 1000000000, 1000, 13, 1, 12},
 | |
| 	{ 19200000, 1000000000, 625,  12, 1, 8},
 | |
| 	{ 26000000, 1000000000, 1000, 26, 1, 12},
 | |
| 
 | |
| 	{ 0, 0, 0, 0, 0, 0 },
 | |
| };
 | |
| 
 | |
| static struct clk tegra_pll_d = {
 | |
| 	.name      = "pll_d",
 | |
| 	.flags     = PLL_HAS_CPCON | PLLD,
 | |
| 	.ops       = &tegra_plld_ops,
 | |
| 	.reg       = 0xd0,
 | |
| 	.parent    = &tegra_pll_ref,
 | |
| 	.max_rate  = 1000000000,
 | |
| 	.u.pll = {
 | |
| 		.input_min = 2000000,
 | |
| 		.input_max = 40000000,
 | |
| 		.cf_min    = 1000000,
 | |
| 		.cf_max    = 6000000,
 | |
| 		.vco_min   = 40000000,
 | |
| 		.vco_max   = 1000000000,
 | |
| 		.freq_table = tegra_pll_d_freq_table,
 | |
| 		.lock_delay = 1000,
 | |
| 	},
 | |
| };
 | |
| 
 | |
| static struct clk tegra_pll_d_out0 = {
 | |
| 	.name      = "pll_d_out0",
 | |
| 	.ops       = &tegra_pll_div_ops,
 | |
| 	.flags     = DIV_2 | PLLD,
 | |
| 	.parent    = &tegra_pll_d,
 | |
| 	.max_rate  = 500000000,
 | |
| };
 | |
| 
 | |
| static struct clk tegra_pll_d2 = {
 | |
| 	.name      = "pll_d2",
 | |
| 	.flags     = PLL_HAS_CPCON | PLL_ALT_MISC_REG | PLLD,
 | |
| 	.ops       = &tegra_plld_ops,
 | |
| 	.reg       = 0x4b8,
 | |
| 	.parent    = &tegra_pll_ref,
 | |
| 	.max_rate  = 1000000000,
 | |
| 	.u.pll = {
 | |
| 		.input_min = 2000000,
 | |
| 		.input_max = 40000000,
 | |
| 		.cf_min    = 1000000,
 | |
| 		.cf_max    = 6000000,
 | |
| 		.vco_min   = 40000000,
 | |
| 		.vco_max   = 1000000000,
 | |
| 		.freq_table = tegra_pll_d_freq_table,
 | |
| 		.lock_delay = 1000,
 | |
| 	},
 | |
| };
 | |
| 
 | |
| static struct clk tegra_pll_d2_out0 = {
 | |
| 	.name      = "pll_d2_out0",
 | |
| 	.ops       = &tegra_pll_div_ops,
 | |
| 	.flags     = DIV_2 | PLLD,
 | |
| 	.parent    = &tegra_pll_d2,
 | |
| 	.max_rate  = 500000000,
 | |
| };
 | |
| 
 | |
| static struct clk_pll_freq_table tegra_pll_u_freq_table[] = {
 | |
| 	{ 12000000, 480000000, 960, 12, 2, 12},
 | |
| 	{ 13000000, 480000000, 960, 13, 2, 12},
 | |
| 	{ 16800000, 480000000, 400, 7,  2, 5},
 | |
| 	{ 19200000, 480000000, 200, 4,  2, 3},
 | |
| 	{ 26000000, 480000000, 960, 26, 2, 12},
 | |
| 	{ 0, 0, 0, 0, 0, 0 },
 | |
| };
 | |
| 
 | |
| static struct clk tegra_pll_u = {
 | |
| 	.name      = "pll_u",
 | |
| 	.flags     = PLL_HAS_CPCON | PLLU,
 | |
| 	.ops       = &tegra_pll_ops,
 | |
| 	.reg       = 0xc0,
 | |
| 	.parent    = &tegra_pll_ref,
 | |
| 	.max_rate  = 480000000,
 | |
| 	.u.pll = {
 | |
| 		.input_min = 2000000,
 | |
| 		.input_max = 40000000,
 | |
| 		.cf_min    = 1000000,
 | |
| 		.cf_max    = 6000000,
 | |
| 		.vco_min   = 480000000,
 | |
| 		.vco_max   = 960000000,
 | |
| 		.freq_table = tegra_pll_u_freq_table,
 | |
| 		.lock_delay = 1000,
 | |
| 	},
 | |
| };
 | |
| 
 | |
| static struct clk_pll_freq_table tegra_pll_x_freq_table[] = {
 | |
| 	/* 1.7 GHz */
 | |
| 	{ 12000000, 1700000000, 850,  6,  1, 8},
 | |
| 	{ 13000000, 1700000000, 915,  7,  1, 8},	/* actual: 1699.2 MHz */
 | |
| 	{ 16800000, 1700000000, 708,  7,  1, 8},	/* actual: 1699.2 MHz */
 | |
| 	{ 19200000, 1700000000, 885,  10, 1, 8},	/* actual: 1699.2 MHz */
 | |
| 	{ 26000000, 1700000000, 850,  13, 1, 8},
 | |
| 
 | |
| 	/* 1.6 GHz */
 | |
| 	{ 12000000, 1600000000, 800,  6,  1, 8},
 | |
| 	{ 13000000, 1600000000, 738,  6,  1, 8},	/* actual: 1599.0 MHz */
 | |
| 	{ 16800000, 1600000000, 857,  9,  1, 8},	/* actual: 1599.7 MHz */
 | |
| 	{ 19200000, 1600000000, 500,  6,  1, 8},
 | |
| 	{ 26000000, 1600000000, 800,  13, 1, 8},
 | |
| 
 | |
| 	/* 1.5 GHz */
 | |
| 	{ 12000000, 1500000000, 750,  6,  1, 8},
 | |
| 	{ 13000000, 1500000000, 923,  8,  1, 8},	/* actual: 1499.8 MHz */
 | |
| 	{ 16800000, 1500000000, 625,  7,  1, 8},
 | |
| 	{ 19200000, 1500000000, 625,  8,  1, 8},
 | |
| 	{ 26000000, 1500000000, 750,  13, 1, 8},
 | |
| 
 | |
| 	/* 1.4 GHz */
 | |
| 	{ 12000000, 1400000000, 700,  6,  1, 8},
 | |
| 	{ 13000000, 1400000000, 969,  9,  1, 8},	/* actual: 1399.7 MHz */
 | |
| 	{ 16800000, 1400000000, 1000, 12, 1, 8},
 | |
| 	{ 19200000, 1400000000, 875,  12, 1, 8},
 | |
| 	{ 26000000, 1400000000, 700,  13, 1, 8},
 | |
| 
 | |
| 	/* 1.3 GHz */
 | |
| 	{ 12000000, 1300000000, 975,  9,  1, 8},
 | |
| 	{ 13000000, 1300000000, 1000, 10, 1, 8},
 | |
| 	{ 16800000, 1300000000, 928,  12, 1, 8},	/* actual: 1299.2 MHz */
 | |
| 	{ 19200000, 1300000000, 812,  12, 1, 8},	/* actual: 1299.2 MHz */
 | |
| 	{ 26000000, 1300000000, 650,  13, 1, 8},
 | |
| 
 | |
| 	/* 1.2 GHz */
 | |
| 	{ 12000000, 1200000000, 1000, 10, 1, 8},
 | |
| 	{ 13000000, 1200000000, 923,  10, 1, 8},	/* actual: 1199.9 MHz */
 | |
| 	{ 16800000, 1200000000, 1000, 14, 1, 8},
 | |
| 	{ 19200000, 1200000000, 1000, 16, 1, 8},
 | |
| 	{ 26000000, 1200000000, 600,  13, 1, 8},
 | |
| 
 | |
| 	/* 1.1 GHz */
 | |
| 	{ 12000000, 1100000000, 825,  9,  1, 8},
 | |
| 	{ 13000000, 1100000000, 846,  10, 1, 8},	/* actual: 1099.8 MHz */
 | |
| 	{ 16800000, 1100000000, 982,  15, 1, 8},	/* actual: 1099.8 MHz */
 | |
| 	{ 19200000, 1100000000, 859,  15, 1, 8},	/* actual: 1099.5 MHz */
 | |
| 	{ 26000000, 1100000000, 550,  13, 1, 8},
 | |
| 
 | |
| 	/* 1 GHz */
 | |
| 	{ 12000000, 1000000000, 1000, 12, 1, 8},
 | |
| 	{ 13000000, 1000000000, 1000, 13, 1, 8},
 | |
| 	{ 16800000, 1000000000, 833,  14, 1, 8},	/* actual: 999.6 MHz */
 | |
| 	{ 19200000, 1000000000, 625,  12, 1, 8},
 | |
| 	{ 26000000, 1000000000, 1000, 26, 1, 8},
 | |
| 
 | |
| 	{ 0, 0, 0, 0, 0, 0 },
 | |
| };
 | |
| 
 | |
| static struct clk tegra_pll_x = {
 | |
| 	.name      = "pll_x",
 | |
| 	.flags     = PLL_HAS_CPCON | PLL_ALT_MISC_REG | PLLX,
 | |
| 	.ops       = &tegra_pll_ops,
 | |
| 	.reg       = 0xe0,
 | |
| 	.parent    = &tegra_pll_ref,
 | |
| 	.max_rate  = 1700000000,
 | |
| 	.u.pll = {
 | |
| 		.input_min = 2000000,
 | |
| 		.input_max = 31000000,
 | |
| 		.cf_min    = 1000000,
 | |
| 		.cf_max    = 6000000,
 | |
| 		.vco_min   = 20000000,
 | |
| 		.vco_max   = 1700000000,
 | |
| 		.freq_table = tegra_pll_x_freq_table,
 | |
| 		.lock_delay = 300,
 | |
| 	},
 | |
| };
 | |
| 
 | |
| static struct clk tegra_pll_x_out0 = {
 | |
| 	.name      = "pll_x_out0",
 | |
| 	.ops       = &tegra_pll_div_ops,
 | |
| 	.flags     = DIV_2 | PLLX,
 | |
| 	.parent    = &tegra_pll_x,
 | |
| 	.max_rate  = 850000000,
 | |
| };
 | |
| 
 | |
| 
 | |
| static struct clk_pll_freq_table tegra_pll_e_freq_table[] = {
 | |
| 	/* PLLE special case: use cpcon field to store cml divider value */
 | |
| 	{ 12000000,  100000000, 150, 1,  18, 11},
 | |
| 	{ 216000000, 100000000, 200, 18, 24, 13},
 | |
| 	{ 0, 0, 0, 0, 0, 0 },
 | |
| };
 | |
| 
 | |
| static struct clk tegra_pll_e = {
 | |
| 	.name      = "pll_e",
 | |
| 	.flags     = PLL_ALT_MISC_REG,
 | |
| 	.ops       = &tegra_plle_ops,
 | |
| 	.reg       = 0xe8,
 | |
| 	.max_rate  = 100000000,
 | |
| 	.u.pll = {
 | |
| 		.input_min = 12000000,
 | |
| 		.input_max = 216000000,
 | |
| 		.cf_min    = 12000000,
 | |
| 		.cf_max    = 12000000,
 | |
| 		.vco_min   = 1200000000,
 | |
| 		.vco_max   = 2400000000U,
 | |
| 		.freq_table = tegra_pll_e_freq_table,
 | |
| 		.lock_delay = 300,
 | |
| 		.fixed_rate = 100000000,
 | |
| 	},
 | |
| };
 | |
| 
 | |
| static struct clk tegra_cml0_clk = {
 | |
| 	.name      = "cml0",
 | |
| 	.parent    = &tegra_pll_e,
 | |
| 	.ops       = &tegra_cml_clk_ops,
 | |
| 	.reg       = PLLE_AUX,
 | |
| 	.max_rate  = 100000000,
 | |
| 	.u.periph  = {
 | |
| 		.clk_num = 0,
 | |
| 	},
 | |
| };
 | |
| 
 | |
| static struct clk tegra_cml1_clk = {
 | |
| 	.name      = "cml1",
 | |
| 	.parent    = &tegra_pll_e,
 | |
| 	.ops       = &tegra_cml_clk_ops,
 | |
| 	.reg       = PLLE_AUX,
 | |
| 	.max_rate  = 100000000,
 | |
| 	.u.periph  = {
 | |
| 		.clk_num   = 1,
 | |
| 	},
 | |
| };
 | |
| 
 | |
| static struct clk tegra_pciex_clk = {
 | |
| 	.name      = "pciex",
 | |
| 	.parent    = &tegra_pll_e,
 | |
| 	.ops       = &tegra_pciex_clk_ops,
 | |
| 	.max_rate  = 100000000,
 | |
| 	.u.periph  = {
 | |
| 		.clk_num   = 74,
 | |
| 	},
 | |
| };
 | |
| 
 | |
| /* Audio sync clocks */
 | |
| #define SYNC_SOURCE(_id)				\
 | |
| 	{						\
 | |
| 		.name      = #_id "_sync",		\
 | |
| 		.rate      = 24000000,			\
 | |
| 		.max_rate  = 24000000,			\
 | |
| 		.ops       = &tegra_sync_source_ops	\
 | |
| 	}
 | |
| static struct clk tegra_sync_source_list[] = {
 | |
| 	SYNC_SOURCE(spdif_in),
 | |
| 	SYNC_SOURCE(i2s0),
 | |
| 	SYNC_SOURCE(i2s1),
 | |
| 	SYNC_SOURCE(i2s2),
 | |
| 	SYNC_SOURCE(i2s3),
 | |
| 	SYNC_SOURCE(i2s4),
 | |
| 	SYNC_SOURCE(vimclk),
 | |
| };
 | |
| 
 | |
| static struct clk_mux_sel mux_audio_sync_clk[] = {
 | |
| 	{ .input = &tegra_sync_source_list[0],	.value = 0},
 | |
| 	{ .input = &tegra_sync_source_list[1],	.value = 1},
 | |
| 	{ .input = &tegra_sync_source_list[2],	.value = 2},
 | |
| 	{ .input = &tegra_sync_source_list[3],	.value = 3},
 | |
| 	{ .input = &tegra_sync_source_list[4],	.value = 4},
 | |
| 	{ .input = &tegra_sync_source_list[5],	.value = 5},
 | |
| 	{ .input = &tegra_pll_a_out0,		.value = 6},
 | |
| 	{ .input = &tegra_sync_source_list[6],	.value = 7},
 | |
| 	{ 0, 0 }
 | |
| };
 | |
| 
 | |
| #define AUDIO_SYNC_CLK(_id, _index)			\
 | |
| 	{						\
 | |
| 		.name      = #_id,			\
 | |
| 		.inputs    = mux_audio_sync_clk,	\
 | |
| 		.reg       = 0x4A0 + (_index) * 4,	\
 | |
| 		.max_rate  = 24000000,			\
 | |
| 		.ops       = &tegra_audio_sync_clk_ops	\
 | |
| 	}
 | |
| static struct clk tegra_clk_audio_list[] = {
 | |
| 	AUDIO_SYNC_CLK(audio0, 0),
 | |
| 	AUDIO_SYNC_CLK(audio1, 1),
 | |
| 	AUDIO_SYNC_CLK(audio2, 2),
 | |
| 	AUDIO_SYNC_CLK(audio3, 3),
 | |
| 	AUDIO_SYNC_CLK(audio4, 4),
 | |
| 	AUDIO_SYNC_CLK(audio, 5),	/* SPDIF */
 | |
| };
 | |
| 
 | |
| #define AUDIO_SYNC_2X_CLK(_id, _index)				\
 | |
| 	{							\
 | |
| 		.name      = #_id "_2x",			\
 | |
| 		.flags     = PERIPH_NO_RESET,			\
 | |
| 		.max_rate  = 48000000,				\
 | |
| 		.ops       = &tegra_clk_double_ops,		\
 | |
| 		.reg       = 0x49C,				\
 | |
| 		.reg_shift = 24 + (_index),			\
 | |
| 		.parent    = &tegra_clk_audio_list[(_index)],	\
 | |
| 		.u.periph = {					\
 | |
| 			.clk_num = 113 + (_index),		\
 | |
| 		},						\
 | |
| 	}
 | |
| static struct clk tegra_clk_audio_2x_list[] = {
 | |
| 	AUDIO_SYNC_2X_CLK(audio0, 0),
 | |
| 	AUDIO_SYNC_2X_CLK(audio1, 1),
 | |
| 	AUDIO_SYNC_2X_CLK(audio2, 2),
 | |
| 	AUDIO_SYNC_2X_CLK(audio3, 3),
 | |
| 	AUDIO_SYNC_2X_CLK(audio4, 4),
 | |
| 	AUDIO_SYNC_2X_CLK(audio, 5),	/* SPDIF */
 | |
| };
 | |
| 
 | |
| #define MUX_I2S_SPDIF(_id, _index)					\
 | |
| static struct clk_mux_sel mux_pllaout0_##_id##_2x_pllp_clkm[] = {	\
 | |
| 	{.input = &tegra_pll_a_out0, .value = 0},			\
 | |
| 	{.input = &tegra_clk_audio_2x_list[(_index)], .value = 1},	\
 | |
| 	{.input = &tegra_pll_p, .value = 2},				\
 | |
| 	{.input = &tegra_clk_m, .value = 3},				\
 | |
| 	{ 0, 0},							\
 | |
| }
 | |
| MUX_I2S_SPDIF(audio0, 0);
 | |
| MUX_I2S_SPDIF(audio1, 1);
 | |
| MUX_I2S_SPDIF(audio2, 2);
 | |
| MUX_I2S_SPDIF(audio3, 3);
 | |
| MUX_I2S_SPDIF(audio4, 4);
 | |
| MUX_I2S_SPDIF(audio, 5);		/* SPDIF */
 | |
| 
 | |
| /* External clock outputs (through PMC) */
 | |
| #define MUX_EXTERN_OUT(_id)						\
 | |
| static struct clk_mux_sel mux_clkm_clkm2_clkm4_extern##_id[] = {	\
 | |
| 	{.input = &tegra_clk_m,		.value = 0},			\
 | |
| 	{.input = &tegra_clk_m_div2,	.value = 1},			\
 | |
| 	{.input = &tegra_clk_m_div4,	.value = 2},			\
 | |
| 	{.input = NULL,			.value = 3}, /* placeholder */	\
 | |
| 	{ 0, 0},							\
 | |
| }
 | |
| MUX_EXTERN_OUT(1);
 | |
| MUX_EXTERN_OUT(2);
 | |
| MUX_EXTERN_OUT(3);
 | |
| 
 | |
| static struct clk_mux_sel *mux_extern_out_list[] = {
 | |
| 	mux_clkm_clkm2_clkm4_extern1,
 | |
| 	mux_clkm_clkm2_clkm4_extern2,
 | |
| 	mux_clkm_clkm2_clkm4_extern3,
 | |
| };
 | |
| 
 | |
| #define CLK_OUT_CLK(_id)					\
 | |
| 	{							\
 | |
| 		.name      = "clk_out_" #_id,			\
 | |
| 		.lookup    = {					\
 | |
| 			.dev_id    = "clk_out_" #_id,		\
 | |
| 			.con_id	   = "extern" #_id,		\
 | |
| 		},						\
 | |
| 		.ops       = &tegra_clk_out_ops,		\
 | |
| 		.reg       = 0x1a8,				\
 | |
| 		.inputs    = mux_clkm_clkm2_clkm4_extern##_id,	\
 | |
| 		.flags     = MUX_CLK_OUT,			\
 | |
| 		.max_rate  = 216000000,				\
 | |
| 		.u.periph = {					\
 | |
| 			.clk_num   = (_id - 1) * 8 + 2,		\
 | |
| 		},						\
 | |
| 	}
 | |
| static struct clk tegra_clk_out_list[] = {
 | |
| 	CLK_OUT_CLK(1),
 | |
| 	CLK_OUT_CLK(2),
 | |
| 	CLK_OUT_CLK(3),
 | |
| };
 | |
| 
 | |
| /* called after peripheral external clocks are initialized */
 | |
| static void init_clk_out_mux(void)
 | |
| {
 | |
| 	int i;
 | |
| 	struct clk *c;
 | |
| 
 | |
| 	/* output clock con_id is the name of peripheral
 | |
| 	   external clock connected to input 3 of the output mux */
 | |
| 	for (i = 0; i < ARRAY_SIZE(tegra_clk_out_list); i++) {
 | |
| 		c = tegra_get_clock_by_name(
 | |
| 			tegra_clk_out_list[i].lookup.con_id);
 | |
| 		if (!c)
 | |
| 			pr_err("%s: could not find clk %s\n", __func__,
 | |
| 			       tegra_clk_out_list[i].lookup.con_id);
 | |
| 		mux_extern_out_list[i][3].input = c;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /* Peripheral muxes */
 | |
| static struct clk_mux_sel mux_sclk[] = {
 | |
| 	{ .input = &tegra_clk_m,	.value = 0},
 | |
| 	{ .input = &tegra_pll_c_out1,	.value = 1},
 | |
| 	{ .input = &tegra_pll_p_out4,	.value = 2},
 | |
| 	{ .input = &tegra_pll_p_out3,	.value = 3},
 | |
| 	{ .input = &tegra_pll_p_out2,	.value = 4},
 | |
| 	/* { .input = &tegra_clk_d,	.value = 5}, - no use on tegra30 */
 | |
| 	{ .input = &tegra_clk_32k,	.value = 6},
 | |
| 	{ .input = &tegra_pll_m_out1,	.value = 7},
 | |
| 	{ 0, 0},
 | |
| };
 | |
| 
 | |
| static struct clk tegra_clk_sclk = {
 | |
| 	.name	= "sclk",
 | |
| 	.inputs	= mux_sclk,
 | |
| 	.reg	= 0x28,
 | |
| 	.ops	= &tegra_super_ops,
 | |
| 	.max_rate = 334000000,
 | |
| 	.min_rate = 40000000,
 | |
| };
 | |
| 
 | |
| static struct clk tegra_clk_blink = {
 | |
| 	.name		= "blink",
 | |
| 	.parent		= &tegra_clk_32k,
 | |
| 	.reg		= 0x40,
 | |
| 	.ops		= &tegra_blink_clk_ops,
 | |
| 	.max_rate	= 32768,
 | |
| };
 | |
| 
 | |
| static struct clk_mux_sel mux_pllm_pllc_pllp_plla[] = {
 | |
| 	{ .input = &tegra_pll_m, .value = 0},
 | |
| 	{ .input = &tegra_pll_c, .value = 1},
 | |
| 	{ .input = &tegra_pll_p, .value = 2},
 | |
| 	{ .input = &tegra_pll_a_out0, .value = 3},
 | |
| 	{ 0, 0},
 | |
| };
 | |
| 
 | |
| static struct clk_mux_sel mux_pllp_pllc_pllm_clkm[] = {
 | |
| 	{ .input = &tegra_pll_p, .value = 0},
 | |
| 	{ .input = &tegra_pll_c, .value = 1},
 | |
| 	{ .input = &tegra_pll_m, .value = 2},
 | |
| 	{ .input = &tegra_clk_m, .value = 3},
 | |
| 	{ 0, 0},
 | |
| };
 | |
| 
 | |
| static struct clk_mux_sel mux_pllp_clkm[] = {
 | |
| 	{ .input = &tegra_pll_p, .value = 0},
 | |
| 	{ .input = &tegra_clk_m, .value = 3},
 | |
| 	{ 0, 0},
 | |
| };
 | |
| 
 | |
| static struct clk_mux_sel mux_pllp_plld_pllc_clkm[] = {
 | |
| 	{.input = &tegra_pll_p, .value = 0},
 | |
| 	{.input = &tegra_pll_d_out0, .value = 1},
 | |
| 	{.input = &tegra_pll_c, .value = 2},
 | |
| 	{.input = &tegra_clk_m, .value = 3},
 | |
| 	{ 0, 0},
 | |
| };
 | |
| 
 | |
| static struct clk_mux_sel mux_pllp_pllm_plld_plla_pllc_plld2_clkm[] = {
 | |
| 	{.input = &tegra_pll_p, .value = 0},
 | |
| 	{.input = &tegra_pll_m, .value = 1},
 | |
| 	{.input = &tegra_pll_d_out0, .value = 2},
 | |
| 	{.input = &tegra_pll_a_out0, .value = 3},
 | |
| 	{.input = &tegra_pll_c, .value = 4},
 | |
| 	{.input = &tegra_pll_d2_out0, .value = 5},
 | |
| 	{.input = &tegra_clk_m, .value = 6},
 | |
| 	{ 0, 0},
 | |
| };
 | |
| 
 | |
| static struct clk_mux_sel mux_plla_pllc_pllp_clkm[] = {
 | |
| 	{ .input = &tegra_pll_a_out0, .value = 0},
 | |
| 	/* { .input = &tegra_pll_c, .value = 1}, no use on tegra30 */
 | |
| 	{ .input = &tegra_pll_p, .value = 2},
 | |
| 	{ .input = &tegra_clk_m, .value = 3},
 | |
| 	{ 0, 0},
 | |
| };
 | |
| 
 | |
| static struct clk_mux_sel mux_pllp_pllc_clk32_clkm[] = {
 | |
| 	{.input = &tegra_pll_p,     .value = 0},
 | |
| 	{.input = &tegra_pll_c,     .value = 1},
 | |
| 	{.input = &tegra_clk_32k,   .value = 2},
 | |
| 	{.input = &tegra_clk_m,     .value = 3},
 | |
| 	{ 0, 0},
 | |
| };
 | |
| 
 | |
| static struct clk_mux_sel mux_pllp_pllc_clkm_clk32[] = {
 | |
| 	{.input = &tegra_pll_p,     .value = 0},
 | |
| 	{.input = &tegra_pll_c,     .value = 1},
 | |
| 	{.input = &tegra_clk_m,     .value = 2},
 | |
| 	{.input = &tegra_clk_32k,   .value = 3},
 | |
| 	{ 0, 0},
 | |
| };
 | |
| 
 | |
| static struct clk_mux_sel mux_pllp_pllc_pllm[] = {
 | |
| 	{.input = &tegra_pll_p,     .value = 0},
 | |
| 	{.input = &tegra_pll_c,     .value = 1},
 | |
| 	{.input = &tegra_pll_m,     .value = 2},
 | |
| 	{ 0, 0},
 | |
| };
 | |
| 
 | |
| static struct clk_mux_sel mux_clk_m[] = {
 | |
| 	{ .input = &tegra_clk_m, .value = 0},
 | |
| 	{ 0, 0},
 | |
| };
 | |
| 
 | |
| static struct clk_mux_sel mux_pllp_out3[] = {
 | |
| 	{ .input = &tegra_pll_p_out3, .value = 0},
 | |
| 	{ 0, 0},
 | |
| };
 | |
| 
 | |
| static struct clk_mux_sel mux_plld_out0[] = {
 | |
| 	{ .input = &tegra_pll_d_out0, .value = 0},
 | |
| 	{ 0, 0},
 | |
| };
 | |
| 
 | |
| static struct clk_mux_sel mux_plld_out0_plld2_out0[] = {
 | |
| 	{ .input = &tegra_pll_d_out0,  .value = 0},
 | |
| 	{ .input = &tegra_pll_d2_out0, .value = 1},
 | |
| 	{ 0, 0},
 | |
| };
 | |
| 
 | |
| static struct clk_mux_sel mux_clk_32k[] = {
 | |
| 	{ .input = &tegra_clk_32k, .value = 0},
 | |
| 	{ 0, 0},
 | |
| };
 | |
| 
 | |
| static struct clk_mux_sel mux_plla_clk32_pllp_clkm_plle[] = {
 | |
| 	{ .input = &tegra_pll_a_out0, .value = 0},
 | |
| 	{ .input = &tegra_clk_32k,    .value = 1},
 | |
| 	{ .input = &tegra_pll_p,      .value = 2},
 | |
| 	{ .input = &tegra_clk_m,      .value = 3},
 | |
| 	{ .input = &tegra_pll_e,      .value = 4},
 | |
| 	{ 0, 0},
 | |
| };
 | |
| 
 | |
| static struct clk_mux_sel mux_cclk_g[] = {
 | |
| 	{ .input = &tegra_clk_m,        .value = 0},
 | |
| 	{ .input = &tegra_pll_c,        .value = 1},
 | |
| 	{ .input = &tegra_clk_32k,      .value = 2},
 | |
| 	{ .input = &tegra_pll_m,        .value = 3},
 | |
| 	{ .input = &tegra_pll_p,        .value = 4},
 | |
| 	{ .input = &tegra_pll_p_out4,   .value = 5},
 | |
| 	{ .input = &tegra_pll_p_out3,   .value = 6},
 | |
| 	{ .input = &tegra_pll_x,        .value = 8},
 | |
| 	{ 0, 0},
 | |
| };
 | |
| 
 | |
| static struct clk tegra_clk_cclk_g = {
 | |
| 	.name	= "cclk_g",
 | |
| 	.flags	= DIV_U71 | DIV_U71_INT,
 | |
| 	.inputs = mux_cclk_g,
 | |
| 	.reg	= 0x368,
 | |
| 	.ops	= &tegra_super_ops,
 | |
| 	.max_rate = 1700000000,
 | |
| };
 | |
| 
 | |
| static struct clk tegra30_clk_twd = {
 | |
| 	.parent	  = &tegra_clk_cclk_g,
 | |
| 	.name     = "twd",
 | |
| 	.ops      = &tegra30_twd_ops,
 | |
| 	.max_rate = 1400000000,	/* Same as tegra_clk_cpu_cmplx.max_rate */
 | |
| 	.mul      = 1,
 | |
| 	.div      = 2,
 | |
| };
 | |
| 
 | |
| #define PERIPH_CLK(_name, _dev, _con, _clk_num, _reg, _max, _inputs, _flags) \
 | |
| 	{						\
 | |
| 		.name      = _name,			\
 | |
| 		.lookup    = {				\
 | |
| 			.dev_id    = _dev,		\
 | |
| 			.con_id	   = _con,		\
 | |
| 		},					\
 | |
| 		.ops       = &tegra_periph_clk_ops,	\
 | |
| 		.reg       = _reg,			\
 | |
| 		.inputs    = _inputs,			\
 | |
| 		.flags     = _flags,			\
 | |
| 		.max_rate  = _max,			\
 | |
| 		.u.periph = {				\
 | |
| 			.clk_num   = _clk_num,		\
 | |
| 		},					\
 | |
| 	}
 | |
| 
 | |
| #define PERIPH_CLK_EX(_name, _dev, _con, _clk_num, _reg, _max, _inputs,	\
 | |
| 			_flags, _ops)					\
 | |
| 	{						\
 | |
| 		.name      = _name,			\
 | |
| 		.lookup    = {				\
 | |
| 			.dev_id    = _dev,		\
 | |
| 			.con_id	   = _con,		\
 | |
| 		},					\
 | |
| 		.ops       = _ops,			\
 | |
| 		.reg       = _reg,			\
 | |
| 		.inputs    = _inputs,			\
 | |
| 		.flags     = _flags,			\
 | |
| 		.max_rate  = _max,			\
 | |
| 		.u.periph = {				\
 | |
| 			.clk_num   = _clk_num,		\
 | |
| 		},					\
 | |
| 	}
 | |
| 
 | |
| #define SHARED_CLK(_name, _dev, _con, _parent, _id, _div, _mode)\
 | |
| 	{						\
 | |
| 		.name      = _name,			\
 | |
| 		.lookup    = {				\
 | |
| 			.dev_id    = _dev,		\
 | |
| 			.con_id    = _con,		\
 | |
| 		},					\
 | |
| 		.ops       = &tegra_clk_shared_bus_ops,	\
 | |
| 		.parent = _parent,			\
 | |
| 		.u.shared_bus_user = {			\
 | |
| 			.client_id = _id,		\
 | |
| 			.client_div = _div,		\
 | |
| 			.mode = _mode,			\
 | |
| 		},					\
 | |
| 	}
 | |
| struct clk tegra_list_clks[] = {
 | |
| 	PERIPH_CLK("apbdma",	"tegra-apbdma",		NULL,	34,	0,	26000000,  mux_clk_m,			0),
 | |
| 	PERIPH_CLK("rtc",	"rtc-tegra",		NULL,	4,	0,	32768,     mux_clk_32k,			PERIPH_NO_RESET | PERIPH_ON_APB),
 | |
| 	PERIPH_CLK("kbc",	"tegra-kbc",		NULL,	36,	0,	32768,     mux_clk_32k,			PERIPH_NO_RESET | PERIPH_ON_APB),
 | |
| 	PERIPH_CLK("timer",	"timer",		NULL,	5,	0,	26000000,  mux_clk_m,			0),
 | |
| 	PERIPH_CLK("kfuse",	"kfuse-tegra",		NULL,	40,	0,	26000000,  mux_clk_m,			0),
 | |
| 	PERIPH_CLK("fuse",	"fuse-tegra",		"fuse",	39,	0,	26000000,  mux_clk_m,			PERIPH_ON_APB),
 | |
| 	PERIPH_CLK("fuse_burn",	"fuse-tegra",		"fuse_burn",	39,	0,	26000000,  mux_clk_m,		PERIPH_ON_APB),
 | |
| 	PERIPH_CLK("apbif",	"tegra30-ahub",		"apbif", 107,	0,	26000000,  mux_clk_m,			0),
 | |
| 	PERIPH_CLK("i2s0",	"tegra30-i2s.0",	NULL,	30,	0x1d8,	26000000,  mux_pllaout0_audio0_2x_pllp_clkm,	MUX | DIV_U71 | PERIPH_ON_APB),
 | |
| 	PERIPH_CLK("i2s1",	"tegra30-i2s.1",	NULL,	11,	0x100,	26000000,  mux_pllaout0_audio1_2x_pllp_clkm,	MUX | DIV_U71 | PERIPH_ON_APB),
 | |
| 	PERIPH_CLK("i2s2",	"tegra30-i2s.2",	NULL,	18,	0x104,	26000000,  mux_pllaout0_audio2_2x_pllp_clkm,	MUX | DIV_U71 | PERIPH_ON_APB),
 | |
| 	PERIPH_CLK("i2s3",	"tegra30-i2s.3",	NULL,	101,	0x3bc,	26000000,  mux_pllaout0_audio3_2x_pllp_clkm,	MUX | DIV_U71 | PERIPH_ON_APB),
 | |
| 	PERIPH_CLK("i2s4",	"tegra30-i2s.4",	NULL,	102,	0x3c0,	26000000,  mux_pllaout0_audio4_2x_pllp_clkm,	MUX | DIV_U71 | PERIPH_ON_APB),
 | |
| 	PERIPH_CLK("spdif_out",	"tegra30-spdif",	"spdif_out",	10,	0x108,	100000000, mux_pllaout0_audio_2x_pllp_clkm,	MUX | DIV_U71 | PERIPH_ON_APB),
 | |
| 	PERIPH_CLK("spdif_in",	"tegra30-spdif",	"spdif_in",	10,	0x10c,	100000000, mux_pllp_pllc_pllm,		MUX | DIV_U71 | PERIPH_ON_APB),
 | |
| 	PERIPH_CLK("pwm",	"tegra-pwm",		NULL,	17,	0x110,	432000000, mux_pllp_pllc_clk32_clkm,	MUX | MUX_PWM | DIV_U71 | PERIPH_ON_APB),
 | |
| 	PERIPH_CLK("d_audio",	"tegra30-ahub",		"d_audio", 106,	0x3d0,	48000000,  mux_plla_pllc_pllp_clkm,	MUX | DIV_U71),
 | |
| 	PERIPH_CLK("dam0",	"tegra30-dam.0",	NULL,   108,	0x3d8,	48000000,  mux_plla_pllc_pllp_clkm,	MUX | DIV_U71),
 | |
| 	PERIPH_CLK("dam1",	"tegra30-dam.1",	NULL,   109,	0x3dc,	48000000,  mux_plla_pllc_pllp_clkm,	MUX | DIV_U71),
 | |
| 	PERIPH_CLK("dam2",	"tegra30-dam.2",	NULL,   110,	0x3e0,	48000000,  mux_plla_pllc_pllp_clkm,	MUX | DIV_U71),
 | |
| 	PERIPH_CLK("hda",	"tegra30-hda",		"hda",   125,	0x428,	108000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
 | |
| 	PERIPH_CLK("hda2codec_2x",	"tegra30-hda",	"hda2codec",   111,	0x3e4,	48000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
 | |
| 	PERIPH_CLK("hda2hdmi",	"tegra30-hda",		"hda2hdmi",	128,	0,	48000000,  mux_clk_m,			0),
 | |
| 	PERIPH_CLK("sbc1",	"spi_tegra.0",		NULL,	41,	0x134,	160000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | PERIPH_ON_APB),
 | |
| 	PERIPH_CLK("sbc2",	"spi_tegra.1",		NULL,	44,	0x118,	160000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | PERIPH_ON_APB),
 | |
| 	PERIPH_CLK("sbc3",	"spi_tegra.2",		NULL,	46,	0x11c,	160000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | PERIPH_ON_APB),
 | |
| 	PERIPH_CLK("sbc4",	"spi_tegra.3",		NULL,	68,	0x1b4,	160000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | PERIPH_ON_APB),
 | |
| 	PERIPH_CLK("sbc5",	"spi_tegra.4",		NULL,	104,	0x3c8,	160000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | PERIPH_ON_APB),
 | |
| 	PERIPH_CLK("sbc6",	"spi_tegra.5",		NULL,	105,	0x3cc,	160000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | PERIPH_ON_APB),
 | |
| 	PERIPH_CLK("sata_oob",	"tegra_sata_oob",	NULL,	123,	0x420,	216000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
 | |
| 	PERIPH_CLK("sata",	"tegra_sata",		NULL,	124,	0x424,	216000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
 | |
| 	PERIPH_CLK("sata_cold",	"tegra_sata_cold",	NULL,	129,	0,	48000000,  mux_clk_m,			0),
 | |
| 	PERIPH_CLK_EX("ndflash", "tegra_nand",		NULL,	13,	0x160,	240000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71,	&tegra_nand_clk_ops),
 | |
| 	PERIPH_CLK("ndspeed",	"tegra_nand_speed",	NULL,	80,	0x3f8,	240000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
 | |
| 	PERIPH_CLK("vfir",	"vfir",			NULL,	7,	0x168,	72000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | PERIPH_ON_APB),
 | |
| 	PERIPH_CLK("sdmmc1",	"sdhci-tegra.0",	NULL,	14,	0x150,	208000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* scales with voltage */
 | |
| 	PERIPH_CLK("sdmmc2",	"sdhci-tegra.1",	NULL,	9,	0x154,	104000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* scales with voltage */
 | |
| 	PERIPH_CLK("sdmmc3",	"sdhci-tegra.2",	NULL,	69,	0x1bc,	208000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* scales with voltage */
 | |
| 	PERIPH_CLK("sdmmc4",	"sdhci-tegra.3",	NULL,	15,	0x164,	104000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* scales with voltage */
 | |
| 	PERIPH_CLK("vcp",	"tegra-avp",		"vcp",	29,	0,	250000000, mux_clk_m,			0),
 | |
| 	PERIPH_CLK("bsea",	"tegra-avp",		"bsea",	62,	0,	250000000, mux_clk_m,			0),
 | |
| 	PERIPH_CLK("bsev",	"tegra-aes",		"bsev",	63,	0,	250000000, mux_clk_m,			0),
 | |
| 	PERIPH_CLK("vde",	"vde",			NULL,	61,	0x1c8,	520000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | DIV_U71_INT),
 | |
| 	PERIPH_CLK("csite",	"csite",		NULL,	73,	0x1d4,	144000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* max rate ??? */
 | |
| 	PERIPH_CLK("la",	"la",			NULL,	76,	0x1f8,	26000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
 | |
| 	PERIPH_CLK("owr",	"tegra_w1",		NULL,	71,	0x1cc,	26000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | PERIPH_ON_APB),
 | |
| 	PERIPH_CLK("nor",	"nor",			NULL,	42,	0x1d0,	127000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* requires min voltage */
 | |
| 	PERIPH_CLK("mipi",	"mipi",			NULL,	50,	0x174,	60000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | PERIPH_ON_APB), /* scales with voltage */
 | |
| 	PERIPH_CLK("i2c1",	"tegra-i2c.0",		NULL,	12,	0x124,	26000000,  mux_pllp_clkm,		MUX | DIV_U16 | PERIPH_ON_APB),
 | |
| 	PERIPH_CLK("i2c2",	"tegra-i2c.1",		NULL,	54,	0x198,	26000000,  mux_pllp_clkm,		MUX | DIV_U16 | PERIPH_ON_APB),
 | |
| 	PERIPH_CLK("i2c3",	"tegra-i2c.2",		NULL,	67,	0x1b8,	26000000,  mux_pllp_clkm,		MUX | DIV_U16 | PERIPH_ON_APB),
 | |
| 	PERIPH_CLK("i2c4",	"tegra-i2c.3",		NULL,	103,	0x3c4,	26000000,  mux_pllp_clkm,		MUX | DIV_U16 | PERIPH_ON_APB),
 | |
| 	PERIPH_CLK("i2c5",	"tegra-i2c.4",		NULL,	47,	0x128,	26000000,  mux_pllp_clkm,		MUX | DIV_U16 | PERIPH_ON_APB),
 | |
| 	PERIPH_CLK("uarta",	"tegra-uart.0",		NULL,	6,	0x178,	800000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB),
 | |
| 	PERIPH_CLK("uartb",	"tegra-uart.1",		NULL,	7,	0x17c,	800000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB),
 | |
| 	PERIPH_CLK("uartc",	"tegra-uart.2",		NULL,	55,	0x1a0,	800000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB),
 | |
| 	PERIPH_CLK("uartd",	"tegra-uart.3",		NULL,	65,	0x1c0,	800000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB),
 | |
| 	PERIPH_CLK("uarte",	"tegra-uart.4",		NULL,	66,	0x1c4,	800000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB),
 | |
| 	PERIPH_CLK_EX("vi",	"tegra_camera",		"vi",	20,	0x148,	425000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71 | DIV_U71_INT,	&tegra_vi_clk_ops),
 | |
| 	PERIPH_CLK("3d",	"3d",			NULL,	24,	0x158,	520000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71 | DIV_U71_INT | DIV_U71_IDLE | PERIPH_MANUAL_RESET),
 | |
| 	PERIPH_CLK("3d2",       "3d2",			NULL,	98,	0x3b0,	520000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71 | DIV_U71_INT | DIV_U71_IDLE | PERIPH_MANUAL_RESET),
 | |
| 	PERIPH_CLK("2d",	"2d",			NULL,	21,	0x15c,	520000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71 | DIV_U71_INT | DIV_U71_IDLE),
 | |
| 	PERIPH_CLK("vi_sensor",	"tegra_camera",		"vi_sensor",	20,	0x1a8,	150000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71 | PERIPH_NO_RESET),
 | |
| 	PERIPH_CLK("epp",	"epp",			NULL,	19,	0x16c,	520000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71 | DIV_U71_INT),
 | |
| 	PERIPH_CLK("mpe",	"mpe",			NULL,	60,	0x170,	520000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71 | DIV_U71_INT),
 | |
| 	PERIPH_CLK("host1x",	"host1x",		NULL,	28,	0x180,	260000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71 | DIV_U71_INT),
 | |
| 	PERIPH_CLK("cve",	"cve",			NULL,	49,	0x140,	250000000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71), /* requires min voltage */
 | |
| 	PERIPH_CLK("tvo",	"tvo",			NULL,	49,	0x188,	250000000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71), /* requires min voltage */
 | |
| 	PERIPH_CLK_EX("dtv",	"dtv",			NULL,	79,	0x1dc,	250000000, mux_clk_m,			0,		&tegra_dtv_clk_ops),
 | |
| 	PERIPH_CLK("hdmi",	"hdmi",			NULL,	51,	0x18c,	148500000, mux_pllp_pllm_plld_plla_pllc_plld2_clkm,	MUX | MUX8 | DIV_U71),
 | |
| 	PERIPH_CLK("tvdac",	"tvdac",		NULL,	53,	0x194,	220000000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71), /* requires min voltage */
 | |
| 	PERIPH_CLK("disp1",	"tegradc.0",		NULL,	27,	0x138,	600000000, mux_pllp_pllm_plld_plla_pllc_plld2_clkm,	MUX | MUX8),
 | |
| 	PERIPH_CLK("disp2",	"tegradc.1",		NULL,	26,	0x13c,	600000000, mux_pllp_pllm_plld_plla_pllc_plld2_clkm,	MUX | MUX8),
 | |
| 	PERIPH_CLK("usbd",	"fsl-tegra-udc",	NULL,	22,	0,	480000000, mux_clk_m,			0), /* requires min voltage */
 | |
| 	PERIPH_CLK("usb2",	"tegra-ehci.1",		NULL,	58,	0,	480000000, mux_clk_m,			0), /* requires min voltage */
 | |
| 	PERIPH_CLK("usb3",	"tegra-ehci.2",		NULL,	59,	0,	480000000, mux_clk_m,			0), /* requires min voltage */
 | |
| 	PERIPH_CLK("dsia",	"tegradc.0",		"dsia",	48,	0,	500000000, mux_plld_out0,		0),
 | |
| 	PERIPH_CLK_EX("dsib",	"tegradc.1",		"dsib",	82,	0xd0,	500000000, mux_plld_out0_plld2_out0,	MUX | PLLD,	&tegra_dsib_clk_ops),
 | |
| 	PERIPH_CLK("csi",	"tegra_camera",		"csi",	52,	0,	102000000, mux_pllp_out3,		0),
 | |
| 	PERIPH_CLK("isp",	"tegra_camera",		"isp",	23,	0,	150000000, mux_clk_m,			0), /* same frequency as VI */
 | |
| 	PERIPH_CLK("csus",	"tegra_camera",		"csus",	92,	0,	150000000, mux_clk_m,			PERIPH_NO_RESET),
 | |
| 
 | |
| 	PERIPH_CLK("tsensor",	"tegra-tsensor",	NULL,	100,	0x3b8,	216000000, mux_pllp_pllc_clkm_clk32,	MUX | DIV_U71),
 | |
| 	PERIPH_CLK("actmon",	"actmon",		NULL,	119,	0x3e8,	216000000, mux_pllp_pllc_clk32_clkm,	MUX | DIV_U71),
 | |
| 	PERIPH_CLK("extern1",	"extern1",		NULL,	120,	0x3ec,	216000000, mux_plla_clk32_pllp_clkm_plle,	MUX | MUX8 | DIV_U71),
 | |
| 	PERIPH_CLK("extern2",	"extern2",		NULL,	121,	0x3f0,	216000000, mux_plla_clk32_pllp_clkm_plle,	MUX | MUX8 | DIV_U71),
 | |
| 	PERIPH_CLK("extern3",	"extern3",		NULL,	122,	0x3f4,	216000000, mux_plla_clk32_pllp_clkm_plle,	MUX | MUX8 | DIV_U71),
 | |
| 	PERIPH_CLK("i2cslow",	"i2cslow",		NULL,	81,	0x3fc,	26000000,  mux_pllp_pllc_clk32_clkm,	MUX | DIV_U71 | PERIPH_ON_APB),
 | |
| 	PERIPH_CLK("pcie",	"tegra-pcie",		"pcie",	70,	0,	250000000, mux_clk_m,			0),
 | |
| 	PERIPH_CLK("afi",	"tegra-pcie",		"afi",	72,	0,	250000000, mux_clk_m,			0),
 | |
| 	PERIPH_CLK("se",	"se",			NULL,	127,	0x42c,	520000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | DIV_U71_INT),
 | |
| };
 | |
| 
 | |
| #define CLK_DUPLICATE(_name, _dev, _con)		\
 | |
| 	{						\
 | |
| 		.name	= _name,			\
 | |
| 		.lookup	= {				\
 | |
| 			.dev_id	= _dev,			\
 | |
| 			.con_id		= _con,		\
 | |
| 		},					\
 | |
| 	}
 | |
| 
 | |
| /* Some clocks may be used by different drivers depending on the board
 | |
|  * configuration.  List those here to register them twice in the clock lookup
 | |
|  * table under two names.
 | |
|  */
 | |
| struct clk_duplicate tegra_clk_duplicates[] = {
 | |
| 	CLK_DUPLICATE("uarta",  "serial8250.0", NULL),
 | |
| 	CLK_DUPLICATE("uartb",  "serial8250.1", NULL),
 | |
| 	CLK_DUPLICATE("uartc",  "serial8250.2", NULL),
 | |
| 	CLK_DUPLICATE("uartd",  "serial8250.3", NULL),
 | |
| 	CLK_DUPLICATE("uarte",  "serial8250.4", NULL),
 | |
| 	CLK_DUPLICATE("usbd", "utmip-pad", NULL),
 | |
| 	CLK_DUPLICATE("usbd", "tegra-ehci.0", NULL),
 | |
| 	CLK_DUPLICATE("usbd", "tegra-otg", NULL),
 | |
| 	CLK_DUPLICATE("hdmi", "tegradc.0", "hdmi"),
 | |
| 	CLK_DUPLICATE("hdmi", "tegradc.1", "hdmi"),
 | |
| 	CLK_DUPLICATE("dsib", "tegradc.0", "dsib"),
 | |
| 	CLK_DUPLICATE("dsia", "tegradc.1", "dsia"),
 | |
| 	CLK_DUPLICATE("bsev", "tegra-avp", "bsev"),
 | |
| 	CLK_DUPLICATE("bsev", "nvavp", "bsev"),
 | |
| 	CLK_DUPLICATE("vde", "tegra-aes", "vde"),
 | |
| 	CLK_DUPLICATE("bsea", "tegra-aes", "bsea"),
 | |
| 	CLK_DUPLICATE("bsea", "nvavp", "bsea"),
 | |
| 	CLK_DUPLICATE("cml1", "tegra_sata_cml", NULL),
 | |
| 	CLK_DUPLICATE("cml0", "tegra_pcie", "cml"),
 | |
| 	CLK_DUPLICATE("pciex", "tegra_pcie", "pciex"),
 | |
| 	CLK_DUPLICATE("i2c1", "tegra-i2c-slave.0", NULL),
 | |
| 	CLK_DUPLICATE("i2c2", "tegra-i2c-slave.1", NULL),
 | |
| 	CLK_DUPLICATE("i2c3", "tegra-i2c-slave.2", NULL),
 | |
| 	CLK_DUPLICATE("i2c4", "tegra-i2c-slave.3", NULL),
 | |
| 	CLK_DUPLICATE("i2c5", "tegra-i2c-slave.4", NULL),
 | |
| 	CLK_DUPLICATE("sbc1", "spi_slave_tegra.0", NULL),
 | |
| 	CLK_DUPLICATE("sbc2", "spi_slave_tegra.1", NULL),
 | |
| 	CLK_DUPLICATE("sbc3", "spi_slave_tegra.2", NULL),
 | |
| 	CLK_DUPLICATE("sbc4", "spi_slave_tegra.3", NULL),
 | |
| 	CLK_DUPLICATE("sbc5", "spi_slave_tegra.4", NULL),
 | |
| 	CLK_DUPLICATE("sbc6", "spi_slave_tegra.5", NULL),
 | |
| 	CLK_DUPLICATE("twd", "smp_twd", NULL),
 | |
| 	CLK_DUPLICATE("vcp", "nvavp", "vcp"),
 | |
| 	CLK_DUPLICATE("i2s0", NULL, "i2s0"),
 | |
| 	CLK_DUPLICATE("i2s1", NULL, "i2s1"),
 | |
| 	CLK_DUPLICATE("i2s2", NULL, "i2s2"),
 | |
| 	CLK_DUPLICATE("i2s3", NULL, "i2s3"),
 | |
| 	CLK_DUPLICATE("i2s4", NULL, "i2s4"),
 | |
| 	CLK_DUPLICATE("dam0", NULL, "dam0"),
 | |
| 	CLK_DUPLICATE("dam1", NULL, "dam1"),
 | |
| 	CLK_DUPLICATE("dam2", NULL, "dam2"),
 | |
| 	CLK_DUPLICATE("spdif_in", NULL, "spdif_in"),
 | |
| };
 | |
| 
 | |
| struct clk *tegra_ptr_clks[] = {
 | |
| 	&tegra_clk_32k,
 | |
| 	&tegra_clk_m,
 | |
| 	&tegra_clk_m_div2,
 | |
| 	&tegra_clk_m_div4,
 | |
| 	&tegra_pll_ref,
 | |
| 	&tegra_pll_m,
 | |
| 	&tegra_pll_m_out1,
 | |
| 	&tegra_pll_c,
 | |
| 	&tegra_pll_c_out1,
 | |
| 	&tegra_pll_p,
 | |
| 	&tegra_pll_p_out1,
 | |
| 	&tegra_pll_p_out2,
 | |
| 	&tegra_pll_p_out3,
 | |
| 	&tegra_pll_p_out4,
 | |
| 	&tegra_pll_a,
 | |
| 	&tegra_pll_a_out0,
 | |
| 	&tegra_pll_d,
 | |
| 	&tegra_pll_d_out0,
 | |
| 	&tegra_pll_d2,
 | |
| 	&tegra_pll_d2_out0,
 | |
| 	&tegra_pll_u,
 | |
| 	&tegra_pll_x,
 | |
| 	&tegra_pll_x_out0,
 | |
| 	&tegra_pll_e,
 | |
| 	&tegra_clk_cclk_g,
 | |
| 	&tegra_cml0_clk,
 | |
| 	&tegra_cml1_clk,
 | |
| 	&tegra_pciex_clk,
 | |
| 	&tegra_clk_sclk,
 | |
| 	&tegra_clk_blink,
 | |
| 	&tegra30_clk_twd,
 | |
| };
 | |
| 
 | |
| 
 | |
| static void tegra30_init_one_clock(struct clk *c)
 | |
| {
 | |
| 	clk_init(c);
 | |
| 	INIT_LIST_HEAD(&c->shared_bus_list);
 | |
| 	if (!c->lookup.dev_id && !c->lookup.con_id)
 | |
| 		c->lookup.con_id = c->name;
 | |
| 	c->lookup.clk = c;
 | |
| 	clkdev_add(&c->lookup);
 | |
| }
 | |
| 
 | |
| void __init tegra30_init_clocks(void)
 | |
| {
 | |
| 	int i;
 | |
| 	struct clk *c;
 | |
| 
 | |
| 	for (i = 0; i < ARRAY_SIZE(tegra_ptr_clks); i++)
 | |
| 		tegra30_init_one_clock(tegra_ptr_clks[i]);
 | |
| 
 | |
| 	for (i = 0; i < ARRAY_SIZE(tegra_list_clks); i++)
 | |
| 		tegra30_init_one_clock(&tegra_list_clks[i]);
 | |
| 
 | |
| 	for (i = 0; i < ARRAY_SIZE(tegra_clk_duplicates); i++) {
 | |
| 		c = tegra_get_clock_by_name(tegra_clk_duplicates[i].name);
 | |
| 		if (!c) {
 | |
| 			pr_err("%s: Unknown duplicate clock %s\n", __func__,
 | |
| 				tegra_clk_duplicates[i].name);
 | |
| 			continue;
 | |
| 		}
 | |
| 
 | |
| 		tegra_clk_duplicates[i].lookup.clk = c;
 | |
| 		clkdev_add(&tegra_clk_duplicates[i].lookup);
 | |
| 	}
 | |
| 
 | |
| 	for (i = 0; i < ARRAY_SIZE(tegra_sync_source_list); i++)
 | |
| 		tegra30_init_one_clock(&tegra_sync_source_list[i]);
 | |
| 	for (i = 0; i < ARRAY_SIZE(tegra_clk_audio_list); i++)
 | |
| 		tegra30_init_one_clock(&tegra_clk_audio_list[i]);
 | |
| 	for (i = 0; i < ARRAY_SIZE(tegra_clk_audio_2x_list); i++)
 | |
| 		tegra30_init_one_clock(&tegra_clk_audio_2x_list[i]);
 | |
| 
 | |
| 	init_clk_out_mux();
 | |
| 	for (i = 0; i < ARRAY_SIZE(tegra_clk_out_list); i++)
 | |
| 		tegra30_init_one_clock(&tegra_clk_out_list[i]);
 | |
| 
 | |
| }
 |