/* linux/arch/arm/plat-s3c64xx/clock.c * * Copyright 2008 Openmoko, Inc. * Copyright 2008 Simtec Electronics * Ben Dooks * http://armlinux.simtec.co.uk/ * * S3C64XX Base clock support * * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* 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", }; #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_fout_mpll clk_mpll #define clk_fout_epll clk_epll struct clk clk_h2 = { .name = "hclk2", .rate = 0, }; struct clk clk_27m = { .name = "clk_27m", .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(S3C64XX_OTHERS); if (enable) val |= S3C64XX_OTHERS_USBMASK; else val &= ~S3C64XX_OTHERS_USBMASK; __raw_writel(val, S3C64XX_OTHERS); local_irq_restore(flags); return 0; } struct clk clk_48m = { .name = "clk_48m", .rate = 48000000, .enable = clk_48m_ctrl, }; struct clk clk_xusbxti = { .name = "xusbxti", .rate = 48000000, }; static int inline s3c64xx_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 s3c64xx_pclk_ctrl(struct clk *clk, int enable) { return s3c64xx_gate(S3C_PCLK_GATE, clk, enable); } static int s3c64xx_hclk_ctrl(struct clk *clk, int enable) { return s3c64xx_gate(S3C_HCLK_GATE, clk, enable); } int s3c64xx_sclk_ctrl(struct clk *clk, int enable) { return s3c64xx_gate(S3C_SCLK_GATE, clk, enable); } static struct clk init_clocks_off[] = { { .name = "nand", .parent = &clk_h, }, { .name = "rtc", .parent = &clk_p, .enable = s3c64xx_pclk_ctrl, .ctrlbit = S3C_CLKCON_PCLK_RTC, }, { .name = "adc", .parent = &clk_p, .enable = s3c64xx_pclk_ctrl, .ctrlbit = S3C_CLKCON_PCLK_TSADC, }, { .name = "i2c", .devname = "s3c2440-i2c.0", .parent = &clk_p, .enable = s3c64xx_pclk_ctrl, .ctrlbit = S3C_CLKCON_PCLK_IIC, }, { .name = "i2c", .devname = "s3c2440-i2c.1", .parent = &clk_p, .enable = s3c64xx_pclk_ctrl, .ctrlbit = S3C6410_CLKCON_PCLK_I2C1, }, { .name = "keypad", .parent = &clk_p, .enable = s3c64xx_pclk_ctrl, .ctrlbit = S3C_CLKCON_PCLK_KEYPAD, }, { .name = "spi", .devname = "s3c6410-spi.0", .parent = &clk_p, .enable = s3c64xx_pclk_ctrl, .ctrlbit = S3C_CLKCON_PCLK_SPI0, }, { .name = "spi", .devname = "s3c6410-spi.1", .parent = &clk_p, .enable = s3c64xx_pclk_ctrl, .ctrlbit = S3C_CLKCON_PCLK_SPI1, }, { .name = "48m", .devname = "s3c-sdhci.0", .parent = &clk_48m, .enable = s3c64xx_sclk_ctrl, .ctrlbit = S3C_CLKCON_SCLK_MMC0_48, }, { .name = "48m", .devname = "s3c-sdhci.1", .parent = &clk_48m, .enable = s3c64xx_sclk_ctrl, .ctrlbit = S3C_CLKCON_SCLK_MMC1_48, }, {