很多硬體的正常運行需要有匯流排時鐘的支援,比如LCD、I2C等裝置。本文分析一下s3c2440的匯流排時鐘,以及在linux中對s3c2440匯流排時鐘頻率的相關操作。首先分析硬體s3c2440的匯流排時鐘。
1. s3c2440的FCLK HCLK PCLK:
時鐘源首先來自外部晶振12MHz。對於必須運行在200MHz以上的ARM920t核心來說,這個頻率實在太低了,不能直接使用,所以首先要通過s3c2440片上的pll硬體電路將12MHz的晶振時鐘訊號升頻,而具體升到多少MHz是通過MPLL控制寄存器來控制的。比如MPLLCON賦值為 0x5c<<12 | 2<<4 | 1就可以將PLL電路的輸出時鐘設定為400MHz,也就是將12MHz的外部時鐘升頻為400MHz供s3c2440使用。另外系統的USB時鐘可以配置UPLL來擷取USB所需的合適時鐘訊號,此處不介紹。
FCLK:當PLL可以穩定輸出時,其輸出訊號直接給FCLK使用,FCLK串連的是s3c2440的ARM核心。相當於ARM核心運行在400MHz了。
那i2c控制器LCD控制器等外設的時鐘怎麼擷取呢?
對上述外設來經過PLL升頻後的400MHz的頻率太高了,需要降頻使用,所以通過分頻器將FCLK的頻率降下來給PCLK、HCLK使用。那麼降低多少怎麼控制呢?可以通過分頻控制寄存器CLKDIVN來控制。
例如將CLKDIVN賦值0x5時 也就是FCLK:HCLK:PCLK = 1:4:8 = 400MHz:100MHz:50MHz。
s3c2440的外設時鐘有兩條,分別是PCLK、HCLK。
使用PCLK的外設有:WDT, IIS, I2C, PWM timer, MMC interface,ADC, UART, GPIO, RTC and SPI(IO型)
使用HCLK的外設有:memory controller,interrupt controller,LCD controller, DMA and USB host block(匯流排型)
2. U-boot、linux中對s3c2440時鐘的設定
s3c2440的匯流排時鐘是在bootload中就設定好的。linux中只是讀取了MPLL以及CLKDIVN寄存器中的值,通過這些數值來算出s3c2440當前啟動並執行頻率,而並不會對其修改!
uboot對時鐘的設定在board_init()函數中完成。linux對時鐘方面的設定是在smdk2440_map_io->s3c24xx_init_clocks()->(cpu->init_clocks)(xtal);此處的cup數值為arch/arm/plat-s3c24xx/cpu.c中的cpu_ids數組。
s3c2440的代碼為0x32440001,時鐘初始話函數為s3c244x_init_clocks。
在此函數中:
調用s3c244x_setup_clocks來計算當前裝置啟動並執行頻率等。調用s3c2410_baseclk_add函數將i2c uart spi rtc等需要使用時鐘的外設通過鏈錶鏈接起來。