Commit c1cc3db8 authored by Byungho Min's avatar Byungho Min Committed by Ben Dooks

ARM: S5PC100: Clock and PLL support

S5PC100 has 4 PLLs (APLL,MPLL,EPLL,HPLL) and 3 clock domains. Clock scheme is
implemented here.
Signed-off-by: default avatarByungho Min <bhmin@samsung.com>
[ben-linux@fluff.org: edited title]
Signed-off-by: default avatarBen Dooks <ben-linux@fluff.org>
parent c9b870e7
/* arch/arm/plat-s5pc1xx/include/plat/pll.h
*
* Copyright 2009 Samsung Electronics Co.
* Byungho Min <bhmin@samsung.com>
*
* S5PC1XX PLL code
*
* Based on plat-s3c64xx/include/plat/pll.h
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#define S5P_PLL_MDIV_MASK ((1 << (25-16+1)) - 1)
#define S5P_PLL_PDIV_MASK ((1 << (13-8+1)) - 1)
#define S5P_PLL_SDIV_MASK ((1 << (2-0+1)) - 1)
#define S5P_PLL_MDIV_SHIFT (16)
#define S5P_PLL_PDIV_SHIFT (8)
#define S5P_PLL_SDIV_SHIFT (0)
#include <asm/div64.h>
static inline unsigned long s5pc1xx_get_pll(unsigned long baseclk,
u32 pllcon)
{
u32 mdiv, pdiv, sdiv;
u64 fvco = baseclk;
mdiv = (pllcon >> S5P_PLL_MDIV_SHIFT) & S5P_PLL_MDIV_MASK;
pdiv = (pllcon >> S5P_PLL_PDIV_SHIFT) & S5P_PLL_PDIV_MASK;
sdiv = (pllcon >> S5P_PLL_SDIV_SHIFT) & S5P_PLL_SDIV_MASK;
fvco *= mdiv;
do_div(fvco, (pdiv << sdiv));
return (unsigned long)fvco;
}
/* arch/arm/plat-s5pc1xx/include/plat/regs-clock.h
*
* Copyright 2009 Samsung Electronics Co.
* Byungho Min <bhmin@samsung.com>
*
* S5PC1XX clock register definitions
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __PLAT_REGS_CLOCK_H
#define __PLAT_REGS_CLOCK_H __FILE__
#define S5PC1XX_CLKREG(x) (S5PC1XX_VA_CLK + (x))
#define S5PC1XX_APLL_LOCK S5PC1XX_CLKREG(0x00)
#define S5PC1XX_MPLL_LOCK S5PC1XX_CLKREG(0x04)
#define S5PC1XX_EPLL_LOCK S5PC1XX_CLKREG(0x08)
#define S5PC100_HPLL_LOCK S5PC1XX_CLKREG(0x0C)
#define S5PC1XX_APLL_CON S5PC1XX_CLKREG(0x100)
#define S5PC1XX_MPLL_CON S5PC1XX_CLKREG(0x104)
#define S5PC1XX_EPLL_CON S5PC1XX_CLKREG(0x108)
#define S5PC100_HPLL_CON S5PC1XX_CLKREG(0x10C)
#define S5PC1XX_CLK_SRC0 S5PC1XX_CLKREG(0x200)
#define S5PC1XX_CLK_SRC1 S5PC1XX_CLKREG(0x204)
#define S5PC1XX_CLK_SRC2 S5PC1XX_CLKREG(0x208)
#define S5PC1XX_CLK_SRC3 S5PC1XX_CLKREG(0x20C)
#define S5PC1XX_CLK_DIV0 S5PC1XX_CLKREG(0x300)
#define S5PC1XX_CLK_DIV1 S5PC1XX_CLKREG(0x304)
#define S5PC1XX_CLK_DIV2 S5PC1XX_CLKREG(0x308)
#define S5PC1XX_CLK_DIV3 S5PC1XX_CLKREG(0x30C)
#define S5PC1XX_CLK_DIV4 S5PC1XX_CLKREG(0x310)
#define S5PC100_CLK_OUT S5PC1XX_CLKREG(0x400)
#define S5PC100_CLKGATE_D00 S5PC1XX_CLKREG(0x500)
#define S5PC100_CLKGATE_D01 S5PC1XX_CLKREG(0x504)
#define S5PC100_CLKGATE_D02 S5PC1XX_CLKREG(0x508)
#define S5PC100_CLKGATE_D10 S5PC1XX_CLKREG(0x520)
#define S5PC100_CLKGATE_D11 S5PC1XX_CLKREG(0x524)
#define S5PC100_CLKGATE_D12 S5PC1XX_CLKREG(0x528)
#define S5PC100_CLKGATE_D13 S5PC1XX_CLKREG(0x52C)
#define S5PC100_CLKGATE_D14 S5PC1XX_CLKREG(0x530)
#define S5PC100_CLKGATE_D15 S5PC1XX_CLKREG(0x534)
#define S5PC100_CLKGATE_D20 S5PC1XX_CLKREG(0x540)
#define S5PC100_SCLKGATE0 S5PC1XX_CLKREG(0x560)
#define S5PC100_SCLKGATE1 S5PC1XX_CLKREG(0x564)
#define S5PC100_OTHERS S5PC1XX_CLKREG(0x8200)
#define S5PC1XX_EPLL_EN (1<<31)
#define S5PC1XX_EPLL_MASK 0xffffffff
#define S5PC1XX_EPLLVAL(_m, _p, _s) ((_m) << 16 | ((_p) << 8) | ((_s)))
/* CLKSRC0 */
#define S5PC1XX_CLKSRC0_APLL_MASK (0x1<<0)
#define S5PC1XX_CLKSRC0_APLL_SHIFT (0)
#define S5PC1XX_CLKSRC0_MPLL_MASK (0x1<<4)
#define S5PC1XX_CLKSRC0_MPLL_SHIFT (4)
#define S5PC1XX_CLKSRC0_EPLL_MASK (0x1<<8)
#define S5PC1XX_CLKSRC0_EPLL_SHIFT (8)
#define S5PC100_CLKSRC0_HPLL_MASK (0x1<<12)
#define S5PC100_CLKSRC0_HPLL_SHIFT (12)
#define S5PC100_CLKSRC0_AMMUX_MASK (0x1<<16)
#define S5PC100_CLKSRC0_AMMUX_SHIFT (16)
#define S5PC100_CLKSRC0_HREF_MASK (0x1<<20)
#define S5PC100_CLKSRC0_HREF_SHIFT (20)
#define S5PC1XX_CLKSRC0_ONENAND_MASK (0x1<<24)
#define S5PC1XX_CLKSRC0_ONENAND_SHIFT (24)
/* CLKSRC1 */
#define S5PC100_CLKSRC1_UART_MASK (0x1<<0)
#define S5PC100_CLKSRC1_UART_SHIFT (0)
#define S5PC100_CLKSRC1_SPI0_MASK (0x3<<4)
#define S5PC100_CLKSRC1_SPI0_SHIFT (4)
#define S5PC100_CLKSRC1_SPI1_MASK (0x3<<8)
#define S5PC100_CLKSRC1_SPI1_SHIFT (8)
#define S5PC100_CLKSRC1_SPI2_MASK (0x3<<12)
#define S5PC100_CLKSRC1_SPI2_SHIFT (12)
#define S5PC100_CLKSRC1_IRDA_MASK (0x3<<16)
#define S5PC100_CLKSRC1_IRDA_SHIFT (16)
#define S5PC100_CLKSRC1_UHOST_MASK (0x3<<20)
#define S5PC100_CLKSRC1_UHOST_SHIFT (20)
#define S5PC100_CLKSRC1_CLK48M_MASK (0x1<<24)
#define S5PC100_CLKSRC1_CLK48M_SHIFT (24)
/* CLKSRC2 */
#define S5PC100_CLKSRC2_MMC0_MASK (0x3<<0)
#define S5PC100_CLKSRC2_MMC0_SHIFT (0)
#define S5PC100_CLKSRC2_MMC1_MASK (0x3<<4)
#define S5PC100_CLKSRC2_MMC1_SHIFT (4)
#define S5PC100_CLKSRC2_MMC2_MASK (0x3<<8)
#define S5PC100_CLKSRC2_MMC2_SHIFT (8)
#define S5PC100_CLKSRC2_LCD_MASK (0x3<<12)
#define S5PC100_CLKSRC2_LCD_SHIFT (12)
#define S5PC100_CLKSRC2_FIMC0_MASK (0x3<<16)
#define S5PC100_CLKSRC2_FIMC0_SHIFT (16)
#define S5PC100_CLKSRC2_FIMC1_MASK (0x3<<20)
#define S5PC100_CLKSRC2_FIMC1_SHIFT (20)
#define S5PC100_CLKSRC2_FIMC2_MASK (0x3<<24)
#define S5PC100_CLKSRC2_FIMC2_SHIFT (24)
#define S5PC100_CLKSRC2_MIXER_MASK (0x3<<28)
#define S5PC100_CLKSRC2_MIXER_SHIFT (28)
/* CLKSRC3 */
#define S5PC100_CLKSRC3_PWI_MASK (0x3<<0)
#define S5PC100_CLKSRC3_PWI_SHIFT (0)
#define S5PC100_CLKSRC3_HCLKD2_MASK (0x1<<4)
#define S5PC100_CLKSRC3_HCLKD2_SHIFT (4)
#define S5PC100_CLKSRC3_I2SD2_MASK (0x3<<8)
#define S5PC100_CLKSRC3_I2SD2_SHIFT (8)
#define S5PC100_CLKSRC3_AUDIO0_MASK (0x7<<12)
#define S5PC100_CLKSRC3_AUDIO0_SHIFT (12)
#define S5PC100_CLKSRC3_AUDIO1_MASK (0x7<<16)
#define S5PC100_CLKSRC3_AUDIO1_SHIFT (16)
#define S5PC100_CLKSRC3_AUDIO2_MASK (0x7<<20)
#define S5PC100_CLKSRC3_AUDIO2_SHIFT (20)
#define S5PC100_CLKSRC3_SPDIF_MASK (0x3<<24)
#define S5PC100_CLKSRC3_SPDIF_SHIFT (24)
/* CLKDIV0 */
#define S5PC1XX_CLKDIV0_APLL_MASK (0x1<<0)
#define S5PC1XX_CLKDIV0_APLL_SHIFT (0)
#define S5PC100_CLKDIV0_ARM_MASK (0x7<<4)
#define S5PC100_CLKDIV0_ARM_SHIFT (4)
#define S5PC100_CLKDIV0_D0_MASK (0x7<<8)
#define S5PC100_CLKDIV0_D0_SHIFT (8)
#define S5PC100_CLKDIV0_PCLKD0_MASK (0x7<<12)
#define S5PC100_CLKDIV0_PCLKD0_SHIFT (12)
#define S5PC100_CLKDIV0_SECSS_MASK (0x7<<16)
#define S5PC100_CLKDIV0_SECSS_SHIFT (16)
/* CLKDIV1 */
#define S5PC100_CLKDIV1_AM_MASK (0x7<<0)
#define S5PC100_CLKDIV1_AM_SHIFT (0)
#define S5PC100_CLKDIV1_MPLL_MASK (0x3<<4)
#define S5PC100_CLKDIV1_MPLL_SHIFT (4)
#define S5PC100_CLKDIV1_MPLL2_MASK (0x1<<8)
#define S5PC100_CLKDIV1_MPLL2_SHIFT (8)
#define S5PC100_CLKDIV1_D1_MASK (0x7<<12)
#define S5PC100_CLKDIV1_D1_SHIFT (12)
#define S5PC100_CLKDIV1_PCLKD1_MASK (0x7<<16)
#define S5PC100_CLKDIV1_PCLKD1_SHIFT (16)
#define S5PC100_CLKDIV1_ONENAND_MASK (0x3<<20)
#define S5PC100_CLKDIV1_ONENAND_SHIFT (20)
#define S5PC100_CLKDIV1_CAM_MASK (0x1F<<24)
#define S5PC100_CLKDIV1_CAM_SHIFT (24)
/* CLKDIV2 */
#define S5PC100_CLKDIV2_UART_MASK (0x7<<0)
#define S5PC100_CLKDIV2_UART_SHIFT (0)
#define S5PC100_CLKDIV2_SPI0_MASK (0xf<<4)
#define S5PC100_CLKDIV2_SPI0_SHIFT (4)
#define S5PC100_CLKDIV2_SPI1_MASK (0xf<<8)
#define S5PC100_CLKDIV2_SPI1_SHIFT (8)
#define S5PC100_CLKDIV2_SPI2_MASK (0xf<<12)
#define S5PC100_CLKDIV2_SPI2_SHIFT (12)
#define S5PC100_CLKDIV2_IRDA_MASK (0xf<<16)
#define S5PC100_CLKDIV2_IRDA_SHIFT (16)
#define S5PC100_CLKDIV2_UHOST_MASK (0xf<<20)
#define S5PC100_CLKDIV2_UHOST_SHIFT (20)
/* CLKDIV3 */
#define S5PC100_CLKDIV3_MMC0_MASK (0xf<<0)
#define S5PC100_CLKDIV3_MMC0_SHIFT (0)
#define S5PC100_CLKDIV3_MMC1_MASK (0xf<<4)
#define S5PC100_CLKDIV3_MMC1_SHIFT (4)
#define S5PC100_CLKDIV3_MMC2_MASK (0xf<<8)
#define S5PC100_CLKDIV3_MMC2_SHIFT (8)
#define S5PC100_CLKDIV3_LCD_MASK (0xf<<12)
#define S5PC100_CLKDIV3_LCD_SHIFT (12)
#define S5PC100_CLKDIV3_FIMC0_MASK (0xf<<16)
#define S5PC100_CLKDIV3_FIMC0_SHIFT (16)
#define S5PC100_CLKDIV3_FIMC1_MASK (0xf<<20)
#define S5PC100_CLKDIV3_FIMC1_SHIFT (20)
#define S5PC100_CLKDIV3_FIMC2_MASK (0xf<<24)
#define S5PC100_CLKDIV3_FIMC2_SHIFT (24)
#define S5PC100_CLKDIV3_HDMI_MASK (0xf<<28)
#define S5PC100_CLKDIV3_HDMI_SHIFT (28)
/* CLKDIV4 */
#define S5PC100_CLKDIV4_PWI_MASK (0x7<<0)
#define S5PC100_CLKDIV4_PWI_SHIFT (0)
#define S5PC100_CLKDIV4_HCLKD2_MASK (0x7<<4)
#define S5PC100_CLKDIV4_HCLKD2_SHIFT (4)
#define S5PC100_CLKDIV4_I2SD2_MASK (0xf<<8)
#define S5PC100_CLKDIV4_I2SD2_SHIFT (8)
#define S5PC100_CLKDIV4_AUDIO0_MASK (0xf<<12)
#define S5PC100_CLKDIV4_AUDIO0_SHIFT (12)
#define S5PC100_CLKDIV4_AUDIO1_MASK (0xf<<16)
#define S5PC100_CLKDIV4_AUDIO1_SHIFT (16)
#define S5PC100_CLKDIV4_AUDIO2_MASK (0xf<<20)
#define S5PC100_CLKDIV4_AUDIO2_SHIFT (20)
/* HCLKD0/PCLKD0 Clock Gate 0 Registers */
#define S5PC100_CLKGATE_D00_INTC (1<<0)
#define S5PC100_CLKGATE_D00_TZIC (1<<1)
#define S5PC100_CLKGATE_D00_CFCON (1<<2)
#define S5PC100_CLKGATE_D00_MDMA (1<<3)
#define S5PC100_CLKGATE_D00_G2D (1<<4)
#define S5PC100_CLKGATE_D00_SECSS (1<<5)
#define S5PC100_CLKGATE_D00_CSSYS (1<<6)
/* HCLKD0/PCLKD0 Clock Gate 1 Registers */
#define S5PC100_CLKGATE_D01_DMC (1<<0)
#define S5PC100_CLKGATE_D01_SROMC (1<<1)
#define S5PC100_CLKGATE_D01_ONENAND (1<<2)
#define S5PC100_CLKGATE_D01_NFCON (1<<3)
#define S5PC100_CLKGATE_D01_INTMEM (1<<4)
#define S5PC100_CLKGATE_D01_EBI (1<<5)
/* PCLKD0 Clock Gate 2 Registers */
#define S5PC100_CLKGATE_D02_SECKEY (1<<1)
#define S5PC100_CLKGATE_D02_SDM (1<<2)
/* HCLKD1/PCLKD1 Clock Gate 0 Registers */
#define S5PC100_CLKGATE_D10_PDMA0 (1<<0)
#define S5PC100_CLKGATE_D10_PDMA1 (1<<1)
#define S5PC100_CLKGATE_D10_USBHOST (1<<2)
#define S5PC100_CLKGATE_D10_USBOTG (1<<3)
#define S5PC100_CLKGATE_D10_MODEMIF (1<<4)
#define S5PC100_CLKGATE_D10_HSMMC0 (1<<5)
#define S5PC100_CLKGATE_D10_HSMMC1 (1<<6)
#define S5PC100_CLKGATE_D10_HSMMC2 (1<<7)
/* HCLKD1/PCLKD1 Clock Gate 1 Registers */
#define S5PC100_CLKGATE_D11_LCD (1<<0)
#define S5PC100_CLKGATE_D11_ROTATOR (1<<1)
#define S5PC100_CLKGATE_D11_FIMC0 (1<<2)
#define S5PC100_CLKGATE_D11_FIMC1 (1<<3)
#define S5PC100_CLKGATE_D11_FIMC2 (1<<4)
#define S5PC100_CLKGATE_D11_JPEG (1<<5)
#define S5PC100_CLKGATE_D11_DSI (1<<6)
#define S5PC100_CLKGATE_D11_CSI (1<<7)
#define S5PC100_CLKGATE_D11_G3D (1<<8)
/* HCLKD1/PCLKD1 Clock Gate 2 Registers */
#define S5PC100_CLKGATE_D12_TV (1<<0)
#define S5PC100_CLKGATE_D12_VP (1<<1)
#define S5PC100_CLKGATE_D12_MIXER (1<<2)
#define S5PC100_CLKGATE_D12_HDMI (1<<3)
#define S5PC100_CLKGATE_D12_MFC (1<<4)
/* HCLKD1/PCLKD1 Clock Gate 3 Registers */
#define S5PC100_CLKGATE_D13_CHIPID (1<<0)
#define S5PC100_CLKGATE_D13_GPIO (1<<1)
#define S5PC100_CLKGATE_D13_APC (1<<2)
#define S5PC100_CLKGATE_D13_IEC (1<<3)
#define S5PC100_CLKGATE_D13_PWM (1<<6)
#define S5PC100_CLKGATE_D13_SYSTIMER (1<<7)
#define S5PC100_CLKGATE_D13_WDT (1<<8)
#define S5PC100_CLKGATE_D13_RTC (1<<9)
/* HCLKD1/PCLKD1 Clock Gate 4 Registers */
#define S5PC100_CLKGATE_D14_UART0 (1<<0)
#define S5PC100_CLKGATE_D14_UART1 (1<<1)
#define S5PC100_CLKGATE_D14_UART2 (1<<2)
#define S5PC100_CLKGATE_D14_UART3 (1<<3)
#define S5PC100_CLKGATE_D14_IIC (1<<4)
#define S5PC100_CLKGATE_D14_HDMI_IIC (1<<5)
#define S5PC100_CLKGATE_D14_SPI0 (1<<6)
#define S5PC100_CLKGATE_D14_SPI1 (1<<7)
#define S5PC100_CLKGATE_D14_SPI2 (1<<8)
#define S5PC100_CLKGATE_D14_IRDA (1<<9)
#define S5PC100_CLKGATE_D14_CCAN0 (1<<10)
#define S5PC100_CLKGATE_D14_CCAN1 (1<<11)
#define S5PC100_CLKGATE_D14_HSITX (1<<12)
#define S5PC100_CLKGATE_D14_HSIRX (1<<13)
/* HCLKD1/PCLKD1 Clock Gate 5 Registers */
#define S5PC100_CLKGATE_D15_IIS0 (1<<0)
#define S5PC100_CLKGATE_D15_IIS1 (1<<1)
#define S5PC100_CLKGATE_D15_IIS2 (1<<2)
#define S5PC100_CLKGATE_D15_AC97 (1<<3)
#define S5PC100_CLKGATE_D15_PCM0 (1<<4)
#define S5PC100_CLKGATE_D15_PCM1 (1<<5)
#define S5PC100_CLKGATE_D15_SPDIF (1<<6)
#define S5PC100_CLKGATE_D15_TSADC (1<<7)
#define S5PC100_CLKGATE_D15_KEYIF (1<<8)
#define S5PC100_CLKGATE_D15_CG (1<<9)
/* HCLKD2 Clock Gate 0 Registers */
#define S5PC100_CLKGATE_D20_HCLKD2 (1<<0)
#define S5PC100_CLKGATE_D20_I2SD2 (1<<1)
/* Special Clock Gate 0 Registers */
#define S5PC1XX_CLKGATE_SCLK0_HPM (1<<0)
#define S5PC1XX_CLKGATE_SCLK0_PWI (1<<1)
#define S5PC100_CLKGATE_SCLK0_ONENAND (1<<2)
#define S5PC100_CLKGATE_SCLK0_UART (1<<3)
#define S5PC100_CLKGATE_SCLK0_SPI0 (1<<4)
#define S5PC100_CLKGATE_SCLK0_SPI1 (1<<5)
#define S5PC100_CLKGATE_SCLK0_SPI2 (1<<6)
#define S5PC100_CLKGATE_SCLK0_SPI0_48 (1<<7)
#define S5PC100_CLKGATE_SCLK0_SPI1_48 (1<<8)
#define S5PC100_CLKGATE_SCLK0_SPI2_48 (1<<9)
#define S5PC100_CLKGATE_SCLK0_IRDA (1<<10)
#define S5PC100_CLKGATE_SCLK0_USBHOST (1<<11)
#define S5PC100_CLKGATE_SCLK0_MMC0 (1<<12)
#define S5PC100_CLKGATE_SCLK0_MMC1 (1<<13)
#define S5PC100_CLKGATE_SCLK0_MMC2 (1<<14)
#define S5PC100_CLKGATE_SCLK0_MMC0_48 (1<<15)
#define S5PC100_CLKGATE_SCLK0_MMC1_48 (1<<16)
#define S5PC100_CLKGATE_SCLK0_MMC2_48 (1<<17)
/* Special Clock Gate 1 Registers */
#define S5PC100_CLKGATE_SCLK1_LCD (1<<0)
#define S5PC100_CLKGATE_SCLK1_FIMC0 (1<<1)
#define S5PC100_CLKGATE_SCLK1_FIMC1 (1<<2)
#define S5PC100_CLKGATE_SCLK1_FIMC2 (1<<3)
#define S5PC100_CLKGATE_SCLK1_TV54 (1<<4)
#define S5PC100_CLKGATE_SCLK1_VDAC54 (1<<5)
#define S5PC100_CLKGATE_SCLK1_MIXER (1<<6)
#define S5PC100_CLKGATE_SCLK1_HDMI (1<<7)
#define S5PC100_CLKGATE_SCLK1_AUDIO0 (1<<8)
#define S5PC100_CLKGATE_SCLK1_AUDIO1 (1<<9)
#define S5PC100_CLKGATE_SCLK1_AUDIO2 (1<<10)
#define S5PC100_CLKGATE_SCLK1_SPDIF (1<<11)
#define S5PC100_CLKGATE_SCLK1_CAM (1<<12)
/* register for power management */
#define S5PC100_PWR_CFG S5PC1XX_CLKREG(0x8000)
#define S5PC100_EINT_WAKEUP_MASK S5PC1XX_CLKREG(0x8004)
#define S5PC100_NORMAL_CFG S5PC1XX_CLKREG(0x8010)
#define S5PC100_STOP_CFG S5PC1XX_CLKREG(0x8014)
#define S5PC100_SLEEP_CFG S5PC1XX_CLKREG(0x8018)
#define S5PC100_STOP_MEM_CFG S5PC1XX_CLKREG(0x801C)
#define S5PC100_OSC_FREQ S5PC1XX_CLKREG(0x8100)
#define S5PC100_OSC_STABLE S5PC1XX_CLKREG(0x8104)
#define S5PC100_PWR_STABLE S5PC1XX_CLKREG(0x8108)
#define S5PC100_MTC_STABLE S5PC1XX_CLKREG(0x8110)
#define S5PC100_CLAMP_STABLE S5PC1XX_CLKREG(0x8114)
#define S5PC100_OTHERS S5PC1XX_CLKREG(0x8200)
#define S5PC100_RST_STAT S5PC1XX_CLKREG(0x8300)
#define S5PC100_WAKEUP_STAT S5PC1XX_CLKREG(0x8304)
#define S5PC100_BLK_PWR_STAT S5PC1XX_CLKREG(0x8308)
#define S5PC100_INFORM0 S5PC1XX_CLKREG(0x8400)
#define S5PC100_INFORM1 S5PC1XX_CLKREG(0x8404)
#define S5PC100_INFORM2 S5PC1XX_CLKREG(0x8408)
#define S5PC100_INFORM3 S5PC1XX_CLKREG(0x840C)
#define S5PC100_INFORM4 S5PC1XX_CLKREG(0x8410)
#define S5PC100_INFORM5 S5PC1XX_CLKREG(0x8414)
#define S5PC100_INFORM6 S5PC1XX_CLKREG(0x8418)
#define S5PC100_INFORM7 S5PC1XX_CLKREG(0x841C)
#define S5PC100_DCGIDX_MAP0 S5PC1XX_CLKREG(0x8500)
#define S5PC100_DCGIDX_MAP1 S5PC1XX_CLKREG(0x8504)
#define S5PC100_DCGIDX_MAP2 S5PC1XX_CLKREG(0x8508)
#define S5PC100_DCGPERF_MAP0 S5PC1XX_CLKREG(0x850C)
#define S5PC100_DCGPERF_MAP1 S5PC1XX_CLKREG(0x8510)
#define S5PC100_DVCIDX_MAP S5PC1XX_CLKREG(0x8514)
#define S5PC100_FREQ_CPU S5PC1XX_CLKREG(0x8518)
#define S5PC100_FREQ_DPM S5PC1XX_CLKREG(0x851C)
#define S5PC100_DVSEMCLK_EN S5PC1XX_CLKREG(0x8520)
#define S5PC100_APLL_CON_L8 S5PC1XX_CLKREG(0x8600)
#define S5PC100_APLL_CON_L7 S5PC1XX_CLKREG(0x8604)
#define S5PC100_APLL_CON_L6 S5PC1XX_CLKREG(0x8608)
#define S5PC100_APLL_CON_L5 S5PC1XX_CLKREG(0x860C)
#define S5PC100_APLL_CON_L4 S5PC1XX_CLKREG(0x8610)
#define S5PC100_APLL_CON_L3 S5PC1XX_CLKREG(0x8614)
#define S5PC100_APLL_CON_L2 S5PC1XX_CLKREG(0x8618)
#define S5PC100_APLL_CON_L1 S5PC1XX_CLKREG(0x861C)
#define S5PC100_IEM_CONTROL S5PC1XX_CLKREG(0x8620)
#define S5PC100_CLKDIV_IEM_L8 S5PC1XX_CLKREG(0x8700)
#define S5PC100_CLKDIV_IEM_L7 S5PC1XX_CLKREG(0x8704)
#define S5PC100_CLKDIV_IEM_L6 S5PC1XX_CLKREG(0x8708)
#define S5PC100_CLKDIV_IEM_L5 S5PC1XX_CLKREG(0x870C)
#define S5PC100_CLKDIV_IEM_L4 S5PC1XX_CLKREG(0x8710)
#define S5PC100_CLKDIV_IEM_L3 S5PC1XX_CLKREG(0x8714)
#define S5PC100_CLKDIV_IEM_L2 S5PC1XX_CLKREG(0x8718)
#define S5PC100_CLKDIV_IEM_L1 S5PC1XX_CLKREG(0x871C)
#define S5PC100_IEM_HPMCLK_DIV S5PC1XX_CLKREG(0x8724)
#define S5PC100_SWRESET S5PC1XX_CLKREG(0x100000)
#define S5PC100_OND_SWRESET S5PC1XX_CLKREG(0x100008)
#define S5PC100_GEN_CTRL S5PC1XX_CLKREG(0x100100)
#define S5PC100_GEN_STATUS S5PC1XX_CLKREG(0x100104)
#define S5PC100_MEM_SYS_CFG S5PC1XX_CLKREG(0x100200)
#define S5PC100_CAM_MUX_SEL S5PC1XX_CLKREG(0x100300)
#define S5PC100_MIXER_OUT_SEL S5PC1XX_CLKREG(0x100304)
#define S5PC100_LPMP_MODE_SEL S5PC1XX_CLKREG(0x100308)
#define S5PC100_MIPI_PHY_CON0 S5PC1XX_CLKREG(0x100400)
#define S5PC100_MIPI_PHY_CON1 S5PC1XX_CLKREG(0x100414)
#define S5PC100_HDMI_PHY_CON0 S5PC1XX_CLKREG(0x100420)
#define S5PC100_CFG_WFI_CLEAN (~(3<<5))
#define S5PC100_CFG_WFI_IDLE (1<<5)
#define S5PC100_CFG_WFI_STOP (2<<5)
#define S5PC100_CFG_WFI_SLEEP (3<<5)
#define S5PC100_OTHER_SYS_INT 24
#define S5PC100_OTHER_STA_TYPE 23
#define STA_TYPE_EXPON 0
#define STA_TYPE_SFR 1
#define S5PC100_PWR_STA_EXP_SCALE 0
#define S5PC100_PWR_STA_CNT 4
#define S5PC100_PWR_STABLE_COUNT 85500
#define S5PC100_SLEEP_CFG_OSC_EN 0
/* OTHERS Resgister */
#define S5PC100_OTHERS_USB_SIG_MASK (1 << 16)
#define S5PC100_OTHERS_MIPI_DPHY_EN (1 << 28)
/* MIPI D-PHY Control Register 0 */
#define S5PC100_MIPI_PHY_CON0_M_RESETN (1 << 1)
#define S5PC100_MIPI_PHY_CON0_S_RESETN (1 << 0)
#endif /* _PLAT_REGS_CLOCK_H */
/* linux/arch/arm/plat-s5pc1xx/s5pc100-clock.c
*
* Copyright 2009 Samsung Electronics, Co.
* Byungho Min <bhmin@samsung.com>
*
* S5PC100 based common clock support
*
* Based on plat-s3c64xx/s3c6400-clock.c
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/errno.h>
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/sysdev.h>
#include <linux/io.h>
#include <mach/hardware.h>
#include <mach/map.h>
#include <plat/cpu-freq.h>
#include <plat/regs-clock.h>
#include <plat/clock.h>
#include <plat/cpu.h>
#include <plat/pll.h>
#include <plat/devs.h>
#include <plat/s5pc100.h>
/* fin_apll, fin_mpll and fin_epll are all the same clock, which we call
* ext_xtal_mux for want of an actual name from the manual.
*/
static struct clk clk_ext_xtal_mux = {
.name = "ext_xtal",
.id = -1,
};
#define clk_fin_apll clk_ext_xtal_mux
#define clk_fin_mpll clk_ext_xtal_mux
#define clk_fin_epll clk_ext_xtal_mux
#define clk_fin_hpll clk_ext_xtal_mux
#define clk_fout_mpll clk_mpll
struct clk_sources {
unsigned int nr_sources;
struct clk **sources;
};
struct clksrc_clk {
struct clk clk;
unsigned int mask;
unsigned int shift;
struct clk_sources *sources;
unsigned int divider_shift;
void __iomem *reg_divider;
void __iomem *reg_source;
};
static int clk_default_setrate(struct clk *clk, unsigned long rate)
{
clk->rate = rate;
return 1;
}
struct clk clk_27m = {
.name = "clk_27m",
.id = -1,
.rate = 27000000,
};
static int clk_48m_ctrl(struct clk *clk, int enable)
{
unsigned long flags;
u32 val;
/* can't rely on clock lock, this register has other usages */
local_irq_save(flags);
val = __raw_readl(S5PC1XX_CLK_SRC1);
if (enable)
val |= S5PC100_CLKSRC1_CLK48M_MASK;
else
val &= ~S5PC100_CLKSRC1_CLK48M_MASK;
__raw_writel(val, S5PC1XX_CLK_SRC1);
local_irq_restore(flags);
return 0;
}
struct clk clk_48m = {
.name = "clk_48m",
.id = -1,
.rate = 48000000,
.enable = clk_48m_ctrl,
};
struct clk clk_54m = {
.name = "clk_54m",
.id = -1,
.rate = 54000000,
};
struct clk clk_hpll = {
.name = "hpll",
.id = -1,
};
struct clk clk_hd0 = {
.name = "hclkd0",
.id = -1,
.rate = 0,
.parent = NULL,
.ctrlbit = 0,
.set_rate = clk_default_setrate,
};
struct clk clk_pd0 = {
.name = "pclkd0",
.id = -1,
.rate = 0,
.parent = NULL,
.ctrlbit = 0,
.set_rate = clk_default_setrate,
};
static int s5pc1xx_clk_gate(void __iomem *reg,
struct clk *clk,
int enable)
{
unsigned int ctrlbit = clk->ctrlbit;
u32 con;
con = __raw_readl(reg);
if (enable)
con |= ctrlbit;
else
con &= ~ctrlbit;
__raw_writel(con, reg);
return 0;
}
static int s5pc1xx_clk_d00_ctrl(struct clk *clk, int enable)
{
return s5pc1xx_clk_gate(S5PC100_CLKGATE_D00, clk, enable);
}
static int s5pc1xx_clk_d01_ctrl(struct clk *clk, int enable)
{
return s5pc1xx_clk_gate(S5PC100_CLKGATE_D01, clk, enable);
}
static int s5pc1xx_clk_d02_ctrl(struct clk *clk, int enable)
{
return s5pc1xx_clk_gate(S5PC100_CLKGATE_D02, clk, enable);
}
static int s5pc1xx_clk_d10_ctrl(struct clk *clk, int enable)
{
return s5pc1xx_clk_gate(S5PC100_CLKGATE_D10, clk, enable);
}
static int s5pc1xx_clk_d11_ctrl(struct clk *clk, int enable)
{
return s5pc1xx_clk_gate(S5PC100_CLKGATE_D11, clk, enable);
}
static int s5pc1xx_clk_d12_ctrl(struct clk *clk, int enable)
{
return s5pc1xx_clk_gate(S5PC100_CLKGATE_D12, clk, enable);
}
static int s5pc1xx_clk_d13_ctrl(struct clk *clk, int enable)
{
return s5pc1xx_clk_gate(S5PC100_CLKGATE_D13, clk, enable);
}
static int s5pc1xx_clk_d14_ctrl(struct clk *clk, int enable)
{
return s5pc1xx_clk_gate(S5PC100_CLKGATE_D14, clk, enable);
}
static int s5pc1xx_clk_d15_ctrl(struct clk *clk, int enable)
{
return s5pc1xx_clk_gate(S5PC100_CLKGATE_D15, clk, enable);
}
static int s5pc1xx_clk_d20_ctrl(struct clk *clk, int enable)
{
return s5pc1xx_clk_gate(S5PC100_CLKGATE_D20, clk, enable);
}
int s5pc1xx_sclk0_ctrl(struct clk *clk, int enable)
{
return s5pc1xx_clk_gate(S5PC100_SCLKGATE0, clk, enable);
}
int s5pc1xx_sclk1_ctrl(struct clk *clk, int enable)
{
return s5pc1xx_clk_gate(S5PC100_SCLKGATE1, clk, enable);
}
static struct clk init_clocks_disable[] = {
{
.name = "dsi",
.id = -1,
.parent = &clk_p,
.enable = s5pc1xx_clk_d11_ctrl,
.ctrlbit = S5PC100_CLKGATE_D11_DSI,
}, {
.name = "csi",
.id = -1,
.parent = &clk_h,
.enable = s5pc1xx_clk_d11_ctrl,
.ctrlbit = S5PC100_CLKGATE_D11_CSI,
}, {
.name = "ccan0",
.id = 0,
.parent = &clk_p,
.enable = s5pc1xx_clk_d14_ctrl,
.ctrlbit = S5PC100_CLKGATE_D14_CCAN0,
}, {
.name = "ccan1",
.id = 1,
.parent = &clk_p,
.enable = s5pc1xx_clk_d14_ctrl,
.ctrlbit = S5PC100_CLKGATE_D14_CCAN1,
}, {
.name = "keypad",
.id = -1,
.parent = &clk_p,
.enable = s5pc1xx_clk_d15_ctrl,
.ctrlbit = S5PC100_CLKGATE_D15_KEYIF,
}, {
.name = "hclkd2",
.id = -1,
.parent = NULL,
.enable = s5pc1xx_clk_d20_ctrl,
.ctrlbit = S5PC100_CLKGATE_D20_HCLKD2,
}, {
.name = "iis-d2",
.id = -1,
.parent = NULL,
.enable = s5pc1xx_clk_d20_ctrl,
.ctrlbit = S5PC100_CLKGATE_D20_I2SD2,
}, {
.name = "otg",
.id = -1,
.parent = &clk_h,
.enable = s5pc1xx_clk_d10_ctrl,
.ctrlbit = S5PC100_CLKGATE_D10_USBOTG,
},
};
static struct clk init_clocks[] = {
/* System1 (D0_0) devices */
{
.name = "intc",
.id = -1,
.parent = &clk_hd0,
.enable = s5pc1xx_clk_d00_ctrl,
.ctrlbit = S5PC100_CLKGATE_D00_INTC,
}, {
.name = "tzic",
.id = -1,
.parent = &clk_hd0,
.enable = s5pc1xx_clk_d00_ctrl,
.ctrlbit = S5PC100_CLKGATE_D00_TZIC,
}, {
.name = "cf-ata",
.id = -1,
.parent = &clk_hd0,
.enable = s5pc1xx_clk_d00_ctrl,
.ctrlbit = S5PC100_CLKGATE_D00_CFCON,
}, {
.name = "mdma",
.id = -1,
.parent = &clk_hd0,
.enable = s5pc1xx_clk_d00_ctrl,
.ctrlbit = S5PC100_CLKGATE_D00_MDMA,
}, {
.name = "g2d",
.id = -1,
.parent = &clk_hd0,
.enable = s5pc1xx_clk_d00_ctrl,
.ctrlbit = S5PC100_CLKGATE_D00_G2D,
}, {
.name = "secss",
.id = -1,
.parent = &clk_hd0,
.enable = s5pc1xx_clk_d00_ctrl,
.ctrlbit = S5PC100_CLKGATE_D00_SECSS,
}, {
.name = "cssys",
.id = -1,
.parent = &clk_hd0,
.enable = s5pc1xx_clk_d00_ctrl,
.ctrlbit = S5PC100_CLKGATE_D00_CSSYS,
},
/* Memory (D0_1) devices */
{
.name = "dmc",
.id = -1,
.parent = &clk_hd0,
.enable = s5pc1xx_clk_d01_ctrl,
.ctrlbit = S5PC100_CLKGATE_D01_DMC,
}, {
.name = "sromc",
.id = -1,
.parent = &clk_hd0,
.enable = s5pc1xx_clk_d01_ctrl,
.ctrlbit = S5PC100_CLKGATE_D01_SROMC,
}, {
.name = "onenand",
.id = -1,
.parent = &clk_hd0,
.enable = s5pc1xx_clk_d01_ctrl,
.ctrlbit = S5PC100_CLKGATE_D01_ONENAND,
}, {
.name = "nand",
.id = -1,
.parent = &clk_hd0,
.enable = s5pc1xx_clk_d01_ctrl,
.ctrlbit = S5PC100_CLKGATE_D01_NFCON,
}, {
.name = "intmem",
.id = -1,
.parent = &clk_hd0,
.enable = s5pc1xx_clk_d01_ctrl,
.ctrlbit = S5PC100_CLKGATE_D01_INTMEM,
}, {
.name = "ebi",
.id = -1,
.parent = &clk_hd0,
.enable = s5pc1xx_clk_d01_ctrl,
.ctrlbit = S5PC100_CLKGATE_D01_EBI,
},
/* System2 (D0_2) devices */
{
.name = "seckey",
.id = -1,
.parent = &clk_pd0,
.enable = s5pc1xx_clk_d02_ctrl,
.ctrlbit = S5PC100_CLKGATE_D02_SECKEY,
}, {
.name = "sdm",
.id = -1,
.parent = &clk_hd0,
.enable = s5pc1xx_clk_d02_ctrl,
.ctrlbit = S5PC100_CLKGATE_D02_SDM,
},
/* File (D1_0) devices */
{
.name = "pdma0",
.id = -1,
.parent = &clk_h,
.enable = s5pc1xx_clk_d10_ctrl,
.ctrlbit = S5PC100_CLKGATE_D10_PDMA0,
}, {
.name = "pdma1",
.id = -1,
.parent = &clk_h,
.enable = s5pc1xx_clk_d10_ctrl,
.ctrlbit = S5PC100_CLKGATE_D10_PDMA1,
}, {
.name = "usb-host",
.id = -1,
.parent = &clk_h,
.enable = s5pc1xx_clk_d10_ctrl,
.ctrlbit = S5PC100_CLKGATE_D10_USBHOST,
}, {
.name = "modem",
.id = -1,
.parent = &clk_h,
.enable = s5pc1xx_clk_d10_ctrl,
.ctrlbit = S5PC100_CLKGATE_D10_MODEMIF,
}, {
.name = "hsmmc",
.id = 0,
.parent = &clk_h,
.enable = s5pc1xx_clk_d10_ctrl,
.ctrlbit = S5PC100_CLKGATE_D10_HSMMC0,
}, {
.name = "hsmmc",
.id = 1,
.parent = &clk_h,
.enable = s5pc1xx_clk_d10_ctrl,
.ctrlbit = S5PC100_CLKGATE_D10_HSMMC1,
}, {
.name = "hsmmc",
.id = 2,
.parent = &clk_h,
.enable = s5pc1xx_clk_d10_ctrl,
.ctrlbit = S5PC100_CLKGATE_D10_HSMMC2,
},
/* Multimedia1 (D1_1) devices */
{
.name = "lcd",
.id = -1,
.parent = &clk_h,
.enable = s5pc1xx_clk_d11_ctrl,
.ctrlbit = S5PC100_CLKGATE_D11_LCD,
}, {
.name = "rotator",
.id = -1,
.parent = &clk_h,
.enable = s5pc1xx_clk_d11_ctrl,
.ctrlbit = S5PC100_CLKGATE_D11_ROTATOR,
}, {
.name = "fimc",
.id = 0,
.parent = &clk_h,
.enable = s5pc1xx_clk_d11_ctrl,
.ctrlbit = S5PC100_CLKGATE_D11_FIMC0,
}, {
.name = "fimc",
.id = 1,
.parent = &clk_h,
.enable = s5pc1xx_clk_d11_ctrl,
.ctrlbit = S5PC100_CLKGATE_D11_FIMC1,
}, {
.name = "fimc",
.id = 2,
.parent = &clk_h,
.enable = s5pc1xx_clk_d11_ctrl,
.ctrlbit = S5PC100_CLKGATE_D11_FIMC2,
}, {
.name = "jpeg",
.id = -1,
.parent = &clk_h,
.enable = s5pc1xx_clk_d11_ctrl,
.ctrlbit = S5PC100_CLKGATE_D11_JPEG,
}, {
.name = "g3d",
.id = -1,
.parent = &clk_h,
.enable = s5pc1xx_clk_d11_ctrl,
.ctrlbit = S5PC100_CLKGATE_D11_G3D,
},
/* Multimedia2 (D1_2) devices */
{
.name = "tv",
.id = -1,
.parent = &clk_h,
.enable = s5pc1xx_clk_d12_ctrl,
.ctrlbit = S5PC100_CLKGATE_D12_TV,
}, {
.name = "vp",
.id = -1,
.parent = &clk_h,
.enable = s5pc1xx_clk_d12_ctrl,
.ctrlbit = S5PC100_CLKGATE_D12_VP,
}, {
.name = "mixer",
.id = -1,
.parent = &clk_h,
.enable = s5pc1xx_clk_d12_ctrl,
.ctrlbit = S5PC100_CLKGATE_D12_MIXER,
}, {
.name = "hdmi",
.id = -1,
.parent = &clk_h,
.enable = s5pc1xx_clk_d12_ctrl,
.ctrlbit = S5PC100_CLKGATE_D12_HDMI,
}, {
.name = "mfc",
.id = -1,
.parent = &clk_h,
.enable = s5pc1xx_clk_d12_ctrl,
.ctrlbit = S5PC100_CLKGATE_D12_MFC,
},
/* System (D1_3) devices */
{
.name = "chipid",
.id = -1,
.parent = &clk_p,
.enable = s5pc1xx_clk_d13_ctrl,
.ctrlbit = S5PC100_CLKGATE_D13_CHIPID,
}, {
.name = "gpio",
.id = -1,
.parent = &clk_p,
.enable = s5pc1xx_clk_d13_ctrl,
.ctrlbit = S5PC100_CLKGATE_D13_GPIO,
}, {
.name = "apc",
.id = -1,
.parent = &clk_p,
.enable = s5pc1xx_clk_d13_ctrl,
.ctrlbit = S5PC100_CLKGATE_D13_APC,
}, {
.name = "iec",
.id = -1,
.parent = &clk_p,
.enable = s5pc1xx_clk_d13_ctrl,
.ctrlbit = S5PC100_CLKGATE_D13_IEC,
}, {
.name = "timers",
.id = -1,
.parent = &clk_p,
.enable = s5pc1xx_clk_d13_ctrl,
.ctrlbit = S5PC100_CLKGATE_D13_PWM,
}, {
.name = "systimer",
.id = -1,
.parent = &clk_p,
.enable = s5pc1xx_clk_d13_ctrl,
.ctrlbit = S5PC100_CLKGATE_D13_SYSTIMER,
}, {
.name = "watchdog",
.id = -1,
.parent = &clk_p,
.enable = s5pc1xx_clk_d13_ctrl,
.ctrlbit = S5PC100_CLKGATE_D13_WDT,
}, {
.name = "rtc",
.id = -1,
.parent = &clk_p,
.enable = s5pc1xx_clk_d13_ctrl,
.ctrlbit = S5PC100_CLKGATE_D13_RTC,
},
/* Connectivity (D1_4) devices */
{
.name = "uart",
.id = 0,
.parent = &clk_p,
.enable = s5pc1xx_clk_d14_ctrl,
.ctrlbit = S5PC100_CLKGATE_D14_UART0,
}, {
.name = "uart",
.id = 1,
.parent = &clk_p,
.enable = s5pc1xx_clk_d14_ctrl,
.ctrlbit = S5PC100_CLKGATE_D14_UART1,
}, {
.name = "uart",
.id = 2,
.parent = &clk_p,
.enable = s5pc1xx_clk_d14_ctrl,
.ctrlbit = S5PC100_CLKGATE_D14_UART2,
}, {
.name = "uart",
.id = 3,
.parent = &clk_p,
.enable = s5pc1xx_clk_d14_ctrl,
.ctrlbit = S5PC100_CLKGATE_D14_UART3,
}, {
.name = "i2c",
.id = -1,
.parent = &clk_p,
.enable = s5pc1xx_clk_d14_ctrl,
.ctrlbit = S5PC100_CLKGATE_D14_IIC,
}, {
.name = "hdmi-i2c",
.id = -1,
.parent = &clk_p,
.enable = s5pc1xx_clk_d14_ctrl,
.ctrlbit = S5PC100_CLKGATE_D14_HDMI_IIC,
}, {
.name = "spi",
.id = 0,
.parent = &clk_p,
.enable = s5pc1xx_clk_d14_ctrl,
.ctrlbit = S5PC100_CLKGATE_D14_SPI0,
}, {
.name = "spi",
.id = 1,
.parent = &clk_p,
.enable = s5pc1xx_clk_d14_ctrl,
.ctrlbit = S5PC100_CLKGATE_D14_SPI1,
}, {
.name = "spi",
.id = 2,
.parent = &clk_p,
.enable = s5pc1xx_clk_d14_ctrl,
.ctrlbit = S5PC100_CLKGATE_D14_SPI2,
}, {
.name = "irda",
.id = -1,
.parent = &clk_p,
.enable = s5pc1xx_clk_d14_ctrl,
.ctrlbit = S5PC100_CLKGATE_D14_IRDA,
}, {
.name = "hsitx",
.id = -1,
.parent = &clk_p,
.enable = s5pc1xx_clk_d14_ctrl,
.ctrlbit = S5PC100_CLKGATE_D14_HSITX,
}, {
.name = "hsirx",
.id = -1,
.parent = &clk_p,
.enable = s5pc1xx_clk_d14_ctrl,
.ctrlbit = S5PC100_CLKGATE_D14_HSIRX,
},
/* Audio (D1_5) devices */
{
.name = "iis",
.id = 0,
.parent = &clk_p,
.enable = s5pc1xx_clk_d15_ctrl,
.ctrlbit = S5PC100_CLKGATE_D15_IIS0,
}, {
.name = "iis",
.id = 1,
.parent = &clk_p,
.enable = s5pc1xx_clk_d15_ctrl,
.ctrlbit = S5PC100_CLKGATE_D15_IIS1,
}, {
.name = "iis",
.id = 2,
.parent = &clk_p,
.enable = s5pc1xx_clk_d15_ctrl,
.ctrlbit = S5PC100_CLKGATE_D15_IIS2,
}, {
.name = "ac97",
.id = -1,
.parent = &clk_p,
.enable = s5pc1xx_clk_d15_ctrl,
.ctrlbit = S5PC100_CLKGATE_D15_AC97,
}, {
.name = "pcm",
.id = 0,
.parent = &clk_p,
.enable = s5pc1xx_clk_d15_ctrl,
.ctrlbit = S5PC100_CLKGATE_D15_PCM0,
}, {
.name = "pcm",
.id = 1,
.parent = &clk_p,
.enable = s5pc1xx_clk_d15_ctrl,
.ctrlbit = S5PC100_CLKGATE_D15_PCM1,
}, {
.name = "spdif",
.id = -1,
.parent = &clk_p,
.enable = s5pc1xx_clk_d15_ctrl,
.ctrlbit = S5PC100_CLKGATE_D15_SPDIF,
}, {
.name = "adc",
.id = -1,
.parent = &clk_p,
.enable = s5pc1xx_clk_d15_ctrl,
.ctrlbit = S5PC100_CLKGATE_D15_TSADC,
}, {
.name = "keyif",
.id = -1,
.parent = &clk_p,
.enable = s5pc1xx_clk_d15_ctrl,
.ctrlbit = S5PC100_CLKGATE_D15_KEYIF,
}, {
.name = "cg",
.id = -1,
.parent = &clk_p,
.enable = s5pc1xx_clk_d15_ctrl,
.ctrlbit = S5PC100_CLKGATE_D15_CG,
},
/* Audio (D2_0) devices: all disabled */
/* Special Clocks 1 */
{
.name = "sclk_hpm",
.id = -1,
.parent = NULL,
.enable = s5pc1xx_sclk0_ctrl,
.ctrlbit = S5PC1XX_CLKGATE_SCLK0_HPM,
}, {
.name = "sclk_onenand",
.id = -1,
.parent = NULL,
.enable = s5pc1xx_sclk0_ctrl,
.ctrlbit = S5PC100_CLKGATE_SCLK0_ONENAND,
}, {
.name = "sclk_spi_48",
.id = 0,
.parent = &clk_48m,
.enable = s5pc1xx_sclk0_ctrl,
.ctrlbit = S5PC100_CLKGATE_SCLK0_SPI0_48,
}, {
.name = "sclk_spi_48",
.id = 1,
.parent = &clk_48m,
.enable = s5pc1xx_sclk0_ctrl,
.ctrlbit = S5PC100_CLKGATE_SCLK0_SPI1_48,
}, {
.name = "sclk_spi_48",
.id = 2,
.parent = &clk_48m,
.enable = s5pc1xx_sclk0_ctrl,
.ctrlbit = S5PC100_CLKGATE_SCLK0_SPI2_48,
}, {
.name = "sclk_mmc_48",
.id = 0,
.parent = &clk_48m,
.enable = s5pc1xx_sclk0_ctrl,
.ctrlbit = S5PC100_CLKGATE_SCLK0_MMC0_48,
}, {
.name = "sclk_mmc_48",
.id = 1,
.parent = &clk_48m,
.enable = s5pc1xx_sclk0_ctrl,
.ctrlbit = S5PC100_CLKGATE_SCLK0_MMC1_48,
}, {
.name = "sclk_mmc_48",
.id = 2,
.parent = &clk_48m,
.enable = s5pc1xx_sclk0_ctrl,
.ctrlbit = S5PC100_CLKGATE_SCLK0_MMC2_48,
},
/* Special Clocks 2 */
{
.name = "sclk_tv_54",
.id = -1,
.parent = &clk_54m,
.enable = s5pc1xx_sclk1_ctrl,
.ctrlbit = S5PC100_CLKGATE_SCLK1_TV54,
}, {
.name = "sclk_vdac_54",
.id = -1,
.parent = &clk_54m,
.enable = s5pc1xx_sclk1_ctrl,
.ctrlbit = S5PC100_CLKGATE_SCLK1_VDAC54,
}, {
.name = "sclk_spdif",
.id = -1,
.parent = NULL,
.enable = s5pc1xx_sclk1_ctrl,
.ctrlbit = S5PC100_CLKGATE_SCLK1_SPDIF,
},
};
void __init s5pc1xx_register_clocks(void)
{
struct clk *clkp;
int ret;
int ptr;
clkp = init_clocks;
for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
ret = s3c24xx_register_clock(clkp);
if (ret < 0) {
printk(KERN_ERR "Failed to register clock %s (%d)\n",
clkp->name, ret);
}
}
clkp = init_clocks_disable;
for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
ret = s3c24xx_register_clock(clkp);
if (ret < 0) {
printk(KERN_ERR "Failed to register clock %s (%d)\n",
clkp->name, ret);
}
(clkp->enable)(clkp, 0);
}
s3c_pwmclk_init();
}
static struct clk clk_fout_apll = {
.name = "fout_apll",
.id = -1,
};
static struct clk *clk_src_apll_list[] = {
[0] = &clk_fin_apll,
[1] = &clk_fout_apll,
};
static struct clk_sources clk_src_apll = {
.sources = clk_src_apll_list,
.nr_sources = ARRAY_SIZE(clk_src_apll_list),
};
static struct clksrc_clk clk_mout_apll = {
.clk = {
.name = "mout_apll",
.id = -1,
},
.shift = S5PC1XX_CLKSRC0_APLL_SHIFT,
.mask = S5PC1XX_CLKSRC0_APLL_MASK,
.sources = &clk_src_apll,
.reg_source = S5PC1XX_CLK_SRC0,
};
static struct clk clk_fout_epll = {
.name = "fout_epll",
.id = -1,
};
static struct clk *clk_src_epll_list[] = {
[0] = &clk_fin_epll,
[1] = &clk_fout_epll,
};
static struct clk_sources clk_src_epll = {
.sources = clk_src_epll_list,
.nr_sources = ARRAY_SIZE(clk_src_epll_list),
};
static struct clksrc_clk clk_mout_epll = {
.clk = {
.name = "mout_epll",
.id = -1,
},
.shift = S5PC1XX_CLKSRC0_EPLL_SHIFT,
.mask = S5PC1XX_CLKSRC0_EPLL_MASK,
.sources = &clk_src_epll,
.reg_source = S5PC1XX_CLK_SRC0,
};
static struct clk *clk_src_mpll_list[] = {
[0] = &clk_fin_mpll,
[1] = &clk_fout_mpll,
};
static struct clk_sources clk_src_mpll = {
.sources = clk_src_mpll_list,
.nr_sources = ARRAY_SIZE(clk_src_mpll_list),
};
static struct clksrc_clk clk_mout_mpll = {
.clk = {
.name = "mout_mpll",
.id = -1,
},
.shift = S5PC1XX_CLKSRC0_MPLL_SHIFT,
.mask = S5PC1XX_CLKSRC0_MPLL_MASK,
.sources = &clk_src_mpll,
.reg_source = S5PC1XX_CLK_SRC0,
};
static unsigned long s5pc1xx_clk_doutmpll_get_rate(struct clk *clk)
{
unsigned long rate = clk_get_rate(clk->parent);
unsigned long clkdiv;
printk(KERN_DEBUG "%s: parent is %ld\n", __func__, rate);
clkdiv = __raw_readl(S5PC1XX_CLK_DIV1) & S5PC100_CLKDIV1_MPLL_MASK;
rate /= (clkdiv >> S5PC100_CLKDIV1_MPLL_SHIFT) + 1;
return rate;
}
static struct clk clk_dout_mpll = {
.name = "dout_mpll",
.id = -1,
.parent = &clk_mout_mpll.clk,
.get_rate = s5pc1xx_clk_doutmpll_get_rate,
};
static unsigned long s5pc1xx_clk_doutmpll2_get_rate(struct clk *clk)
{
unsigned long rate = clk_get_rate(clk->parent);
unsigned long clkdiv;
printk(KERN_DEBUG "%s: parent is %ld\n", __func__, rate);
clkdiv = __raw_readl(S5PC1XX_CLK_DIV1) & S5PC100_CLKDIV1_MPLL2_MASK;
rate /= (clkdiv >> S5PC100_CLKDIV1_MPLL2_SHIFT) + 1;
return rate;
}
struct clk clk_dout_mpll2 = {
.name = "dout_mpll2",
.id = -1,
.parent = &clk_mout_mpll.clk,
.get_rate = s5pc1xx_clk_doutmpll2_get_rate,
};
static struct clk *clkset_uart_list[] = {
&clk_mout_epll.clk,
&clk_dout_mpll,
NULL,
NULL
};
static struct clk_sources clkset_uart = {
.sources = clkset_uart_list,
.nr_sources = ARRAY_SIZE(clkset_uart_list),
};
static inline struct clksrc_clk *to_clksrc(struct clk *clk)
{
return container_of(clk, struct clksrc_clk, clk);
}
static unsigned long s5pc1xx_getrate_clksrc(struct clk *clk)
{
struct clksrc_clk *sclk = to_clksrc(clk);
unsigned long rate = clk_get_rate(clk->parent);
u32 clkdiv = __raw_readl(sclk->reg_divider);
clkdiv >>= sclk->divider_shift;
clkdiv &= 0xf;
clkdiv++;
rate /= clkdiv;
return rate;
}
static int s5pc1xx_setrate_clksrc(struct clk *clk, unsigned long rate)
{
struct clksrc_clk *sclk = to_clksrc(clk);
void __iomem *reg = sclk->reg_divider;
unsigned int div;
u32 val;
rate = clk_round_rate(clk, rate);
div = clk_get_rate(clk->parent) / rate;
if (div > 16)
return -EINVAL;
val = __raw_readl(reg);
val &= ~(0xf << sclk->shift);
val |= (div - 1) << sclk->shift;
__raw_writel(val, reg);
return 0;
}
static int s5pc1xx_setparent_clksrc(struct clk *clk, struct clk *parent)
{
struct clksrc_clk *sclk = to_clksrc(clk);
struct clk_sources *srcs = sclk->sources;
u32 clksrc = __raw_readl(sclk->reg_source);
int src_nr = -1;
int ptr;
for (ptr = 0; ptr < srcs->nr_sources; ptr++)
if (srcs->sources[ptr] == parent) {
src_nr = ptr;
break;
}
if (src_nr >= 0) {
clksrc &= ~sclk->mask;
clksrc |= src_nr << sclk->shift;
__raw_writel(clksrc, sclk->reg_source);
return 0;
}
return -EINVAL;
}
static unsigned long s5pc1xx_roundrate_clksrc(struct clk *clk,
unsigned long rate)
{
unsigned long parent_rate = clk_get_rate(clk->parent);
int div;
if (rate > parent_rate)
rate = parent_rate;
else {
div = rate / parent_rate;
if (div == 0)
div = 1;
if (div > 16)
div = 16;
rate = parent_rate / div;
}
return rate;
}
static struct clksrc_clk clk_uart_uclk1 = {
.clk = {
.name = "uclk1",
.id = -1,
.ctrlbit = S5PC100_CLKGATE_SCLK0_UART,
.enable = s5pc1xx_sclk0_ctrl,
.set_parent = s5pc1xx_setparent_clksrc,
.get_rate = s5pc1xx_getrate_clksrc,
.set_rate = s5pc1xx_setrate_clksrc,
.round_rate = s5pc1xx_roundrate_clksrc,
},
.shift = S5PC100_CLKSRC1_UART_SHIFT,
.mask = S5PC100_CLKSRC1_UART_MASK,
.sources = &clkset_uart,
.divider_shift = S5PC100_CLKDIV2_UART_SHIFT,
.reg_divider = S5PC1XX_CLK_DIV2,
.reg_source = S5PC1XX_CLK_SRC1,
};
/* Clock initialisation code */
static struct clksrc_clk *init_parents[] = {
&clk_mout_apll,
&clk_mout_epll,
&clk_mout_mpll,
&clk_uart_uclk1,
};
static void __init_or_cpufreq s5pc1xx_set_clksrc(struct clksrc_clk *clk)
{
struct clk_sources *srcs = clk->sources;
u32 clksrc = __raw_readl(clk->reg_source);
clksrc &= clk->mask;
clksrc >>= clk->shift;
if (clksrc > srcs->nr_sources || !srcs->sources[clksrc]) {
printk(KERN_ERR "%s: bad source %d\n",
clk->clk.name, clksrc);
return;
}
clk->clk.parent = srcs->sources[clksrc];
printk(KERN_INFO "%s: source is %s (%d), rate is %ld\n",
clk->clk.name, clk->clk.parent->name, clksrc,
clk_get_rate(&clk->clk));
}
#define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1)
void __init_or_cpufreq s5pc100_setup_clocks(void)
{
struct clk *xtal_clk;
unsigned long xtal;
unsigned long armclk;
unsigned long hclkd0;
unsigned long hclk;
unsigned long pclkd0;
unsigned long pclk;
unsigned long apll;
unsigned long mpll;
unsigned long hpll;
unsigned long epll;
unsigned int ptr;
u32 clkdiv0, clkdiv1;
printk(KERN_DEBUG "%s: registering clocks\n", __func__);
clkdiv0 = __raw_readl(S5PC1XX_CLK_DIV0);
clkdiv1 = __raw_readl(S5PC1XX_CLK_DIV1);
printk(KERN_DEBUG "%s: clkdiv0 = %08x, clkdiv1 = %08x\n",
__func__, clkdiv0, clkdiv1);
xtal_clk = clk_get(NULL, "xtal");
BUG_ON(IS_ERR(xtal_clk));
xtal = clk_get_rate(xtal_clk);
clk_put(xtal_clk);
printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal);
apll = s5pc1xx_get_pll(xtal, __raw_readl(S5PC1XX_APLL_CON));
mpll = s5pc1xx_get_pll(xtal, __raw_readl(S5PC1XX_MPLL_CON));
epll = s5pc1xx_get_pll(xtal, __raw_readl(S5PC1XX_EPLL_CON));
hpll = s5pc1xx_get_pll(xtal, __raw_readl(S5PC100_HPLL_CON));
printk(KERN_INFO "S5PC100: PLL settings, A=%ld, M=%ld, E=%ld, H=%ld\n",
apll, mpll, epll, hpll);
armclk = apll / GET_DIV(clkdiv0, S5PC1XX_CLKDIV0_APLL);
armclk = armclk / GET_DIV(clkdiv0, S5PC100_CLKDIV0_ARM);
hclkd0 = armclk / GET_DIV(clkdiv0, S5PC100_CLKDIV0_D0);
pclkd0 = hclkd0 / GET_DIV(clkdiv0, S5PC100_CLKDIV0_PCLKD0);
hclk = mpll / GET_DIV(clkdiv1, S5PC100_CLKDIV1_D1);
pclk = hclk / GET_DIV(clkdiv1, S5PC100_CLKDIV1_PCLKD1);
printk(KERN_INFO "S5PC100: ARMCLK=%ld, HCLKD0=%ld, PCLKD0=%ld, HCLK=%ld, PCLK=%ld\n",
armclk, hclkd0, pclkd0, hclk, pclk);
clk_fout_apll.rate = apll;
clk_fout_mpll.rate = mpll;
clk_fout_epll.rate = epll;
clk_fout_apll.rate = apll;
clk_h.rate = hclk;
clk_p.rate = pclk;
for (ptr = 0; ptr < ARRAY_SIZE(init_parents); ptr++)
s5pc1xx_set_clksrc(init_parents[ptr]);
}
static struct clk *clks[] __initdata = {
&clk_ext_xtal_mux,
&clk_mout_epll.clk,
&clk_fout_epll,
&clk_mout_mpll.clk,
&clk_dout_mpll,
&clk_uart_uclk1.clk,
&clk_ext,
&clk_epll,
&clk_27m,
&clk_48m,
&clk_54m,
};
void __init s5pc100_register_clocks(void)
{
struct clk *clkp;
int ret;
int ptr;
for (ptr = 0; ptr < ARRAY_SIZE(clks); ptr++) {
clkp = clks[ptr];
ret = s3c24xx_register_clock(clkp);
if (ret < 0) {
printk(KERN_ERR "Failed to register clock %s (%d)\n",
clkp->name, ret);
}
}
clk_mpll.parent = &clk_mout_mpll.clk;
clk_epll.parent = &clk_mout_epll.clk;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment