⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 clock.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	.name		= "i2s-eplldiv",	.id		= -1,	.parent		= &clk_esysclk,	.get_rate	= s3c2443_getrate_i2s_eplldiv,	.set_rate	= s3c2443_setrate_i2s_eplldiv,	.round_rate	= s3c2443_roundrate_clksrc16,};/* i2s-ref * * i2s bus reference clock, selectable from external, esysclk or epllref*/static int s3c2443_setparent_i2s(struct clk *clk, struct clk *parent){	unsigned long clksrc = __raw_readl(S3C2443_CLKSRC);	clksrc &= ~S3C2443_CLKSRC_I2S_MASK;	if (parent == &clk_epllref)		clksrc |= S3C2443_CLKSRC_I2S_EPLLREF;	else if (parent == &clk_i2s_ext)		clksrc |= S3C2443_CLKSRC_I2S_EXT;	else if (parent != &clk_i2s_eplldiv)		return -EINVAL;	clk->parent = parent;	__raw_writel(clksrc, S3C2443_CLKSRC);	return 0;}static struct clk clk_i2s = {	.name		= "i2s-if",	.id		= -1,	.parent		= &clk_i2s_eplldiv,	.ctrlbit	= S3C2443_SCLKCON_I2SCLK,	.enable		= s3c2443_clkcon_enable_s,	.set_parent	= s3c2443_setparent_i2s,};/* cam-if * * camera interface bus-clock, divided down from esysclk*/static unsigned long s3c2443_getrate_cam(struct clk *clk){	unsigned long parent_rate = clk_get_rate(clk->parent);	unsigned long div = __raw_readl(S3C2443_CLKDIV1);	div  &= S3C2443_CLKDIV1_CAMDIV_MASK;	div >>= S3C2443_CLKDIV1_CAMDIV_SHIFT;	return parent_rate / (div + 1);}static int s3c2443_setrate_cam(struct clk *clk, unsigned long rate){	unsigned long parent_rate = clk_get_rate(clk->parent);	unsigned long clkdiv1 = __raw_readl(S3C2443_CLKDIV1);	rate = s3c2443_roundrate_clksrc16(clk, rate);	rate = parent_rate / rate;	clkdiv1 &= ~S3C2443_CLKDIV1_CAMDIV_MASK;	clkdiv1 |= (rate - 1) << S3C2443_CLKDIV1_CAMDIV_SHIFT;	__raw_writel(clkdiv1, S3C2443_CLKDIV1);	return 0;}static struct clk clk_cam = {	.name		= "camif-upll",		/* same as 2440 name */	.id		= -1,	.parent		= &clk_esysclk,	.ctrlbit	= S3C2443_SCLKCON_CAMCLK,	.enable		= s3c2443_clkcon_enable_s,	.get_rate	= s3c2443_getrate_cam,	.set_rate	= s3c2443_setrate_cam,	.round_rate	= s3c2443_roundrate_clksrc16,};/* display-if * * display interface clock, divided from esysclk*/static unsigned long s3c2443_getrate_display(struct clk *clk){	unsigned long parent_rate = clk_get_rate(clk->parent);	unsigned long div = __raw_readl(S3C2443_CLKDIV1);	div &= S3C2443_CLKDIV1_DISPDIV_MASK;	div >>= S3C2443_CLKDIV1_DISPDIV_SHIFT;	return parent_rate / (div + 1);}static int s3c2443_setrate_display(struct clk *clk, unsigned long rate){	unsigned long parent_rate = clk_get_rate(clk->parent);	unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1);	rate = s3c2443_roundrate_clksrc256(clk, rate);	rate = parent_rate / rate;	clkdivn &= ~S3C2443_CLKDIV1_UARTDIV_MASK;	clkdivn |= (rate - 1) << S3C2443_CLKDIV1_UARTDIV_SHIFT;	__raw_writel(clkdivn, S3C2443_CLKDIV1);	return 0;}static struct clk clk_display = {	.name		= "display-if",	.id		= -1,	.parent		= &clk_esysclk,	.ctrlbit	= S3C2443_SCLKCON_DISPCLK,	.enable		= s3c2443_clkcon_enable_s,	.get_rate	= s3c2443_getrate_display,	.set_rate	= s3c2443_setrate_display,	.round_rate	= s3c2443_roundrate_clksrc256,};/* standard clock definitions */static struct clk init_clocks_disable[] = {	{		.name		= "nand",		.id		= -1,		.parent		= &clk_h,	}, {		.name		= "sdi",		.id		= -1,		.parent		= &clk_p,		.enable		= s3c2443_clkcon_enable_p,		.ctrlbit	= S3C2443_PCLKCON_SDI,	}, {		.name		= "adc",		.id		= -1,		.parent		= &clk_p,		.enable		= s3c2443_clkcon_enable_p,		.ctrlbit	= S3C2443_PCLKCON_ADC,	}, {		.name		= "i2c",		.id		= -1,		.parent		= &clk_p,		.enable		= s3c2443_clkcon_enable_p,		.ctrlbit	= S3C2443_PCLKCON_IIC,	}, {		.name		= "iis",		.id		= -1,		.parent		= &clk_p,		.enable		= s3c2443_clkcon_enable_p,		.ctrlbit	= S3C2443_PCLKCON_IIS,	}, {		.name		= "spi",		.id		= 0,		.parent		= &clk_p,		.enable		= s3c2443_clkcon_enable_p,		.ctrlbit	= S3C2443_PCLKCON_SPI0,	}, {		.name		= "spi",		.id		= 1,		.parent		= &clk_p,		.enable		= s3c2443_clkcon_enable_p,		.ctrlbit	= S3C2443_PCLKCON_SPI1,	}};static struct clk init_clocks[] = {	{		.name		= "dma",		.id		= 0,		.parent		= &clk_h,		.enable		= s3c2443_clkcon_enable_h,		.ctrlbit	= S3C2443_HCLKCON_DMA0,	}, {		.name		= "dma",		.id		= 1,		.parent		= &clk_h,		.enable		= s3c2443_clkcon_enable_h,		.ctrlbit	= S3C2443_HCLKCON_DMA1,	}, {		.name		= "dma",		.id		= 2,		.parent		= &clk_h,		.enable		= s3c2443_clkcon_enable_h,		.ctrlbit	= S3C2443_HCLKCON_DMA2,	}, {		.name		= "dma",		.id		= 3,		.parent		= &clk_h,		.enable		= s3c2443_clkcon_enable_h,		.ctrlbit	= S3C2443_HCLKCON_DMA3,	}, {		.name		= "dma",		.id		= 4,		.parent		= &clk_h,		.enable		= s3c2443_clkcon_enable_h,		.ctrlbit	= S3C2443_HCLKCON_DMA4,	}, {		.name		= "dma",		.id		= 5,		.parent		= &clk_h,		.enable		= s3c2443_clkcon_enable_h,		.ctrlbit	= S3C2443_HCLKCON_DMA5,	}, {		.name		= "lcd",		.id		= -1,		.parent		= &clk_h,		.enable		= s3c2443_clkcon_enable_h,		.ctrlbit	= S3C2443_HCLKCON_LCDC,	}, {		.name		= "gpio",		.id		= -1,		.parent		= &clk_p,		.enable		= s3c2443_clkcon_enable_p,		.ctrlbit	= S3C2443_PCLKCON_GPIO,	}, {		.name		= "usb-host",		.id		= -1,		.parent		= &clk_h,		.enable		= s3c2443_clkcon_enable_h,		.ctrlbit	= S3C2443_HCLKCON_USBH,	}, {		.name		= "usb-device",		.id		= -1,		.parent		= &clk_h,		.enable		= s3c2443_clkcon_enable_h,		.ctrlbit	= S3C2443_HCLKCON_USBD,	}, {		.name		= "hsmmc",		.id		= -1,		.parent		= &clk_h,		.enable		= s3c2443_clkcon_enable_h,		.ctrlbit	= S3C2443_HCLKCON_HSMMC,	}, {		.name		= "cfc",		.id		= -1,		.parent		= &clk_h,		.enable		= s3c2443_clkcon_enable_h,		.ctrlbit	= S3C2443_HCLKCON_CFC,	}, {		.name		= "ssmc",		.id		= -1,		.parent		= &clk_h,		.enable		= s3c2443_clkcon_enable_h,		.ctrlbit	= S3C2443_HCLKCON_SSMC,	}, {		.name		= "timers",		.id		= -1,		.parent		= &clk_p,		.enable		= s3c2443_clkcon_enable_p,		.ctrlbit	= S3C2443_PCLKCON_PWMT,	}, {		.name		= "uart",		.id		= 0,		.parent		= &clk_p,		.enable		= s3c2443_clkcon_enable_p,		.ctrlbit	= S3C2443_PCLKCON_UART0,	}, {		.name		= "uart",		.id		= 1,		.parent		= &clk_p,		.enable		= s3c2443_clkcon_enable_p,		.ctrlbit	= S3C2443_PCLKCON_UART1,	}, {		.name		= "uart",		.id		= 2,		.parent		= &clk_p,		.enable		= s3c2443_clkcon_enable_p,		.ctrlbit	= S3C2443_PCLKCON_UART2,	}, {		.name		= "uart",		.id		= 3,		.parent		= &clk_p,		.enable		= s3c2443_clkcon_enable_p,		.ctrlbit	= S3C2443_PCLKCON_UART3,	}, {		.name		= "rtc",		.id		= -1,		.parent		= &clk_p,		.enable		= s3c2443_clkcon_enable_p,		.ctrlbit	= S3C2443_PCLKCON_RTC,	}, {		.name		= "watchdog",		.id		= -1,		.parent		= &clk_p,		.ctrlbit	= S3C2443_PCLKCON_WDT,	}, {		.name		= "usb-bus-host",		.id		= -1,		.parent		= &clk_usb_bus_host,	}, {		.name		= "ac97",		.id		= -1,		.parent		= &clk_p,		.ctrlbit	= S3C2443_PCLKCON_AC97,	}};/* clocks to add where we need to check their parentage *//* s3c2443_clk_initparents * * Initialise the parents for the clocks that we get at start-time*/static int __init clk_init_set_parent(struct clk *clk, struct clk *parent){	printk(KERN_DEBUG "clock %s: parent %s\n", clk->name, parent->name);	return clk_set_parent(clk, parent);}static void __init s3c2443_clk_initparents(void){	unsigned long clksrc = __raw_readl(S3C2443_CLKSRC);	struct clk *parent;	switch (clksrc & S3C2443_CLKSRC_EPLLREF_MASK) {	case S3C2443_CLKSRC_EPLLREF_EXTCLK:		parent = &clk_ext;		break;	case S3C2443_CLKSRC_EPLLREF_XTAL:	default:		parent = &clk_xtal;		break;	case S3C2443_CLKSRC_EPLLREF_MPLLREF:	case S3C2443_CLKSRC_EPLLREF_MPLLREF2:		parent = &clk_mpllref;		break;	}	clk_init_set_parent(&clk_epllref, parent);	switch (clksrc & S3C2443_CLKSRC_I2S_MASK) {	case S3C2443_CLKSRC_I2S_EXT:		parent = &clk_i2s_ext;		break;	case S3C2443_CLKSRC_I2S_EPLLDIV:	default:		parent = &clk_i2s_eplldiv;		break;	case S3C2443_CLKSRC_I2S_EPLLREF:	case S3C2443_CLKSRC_I2S_EPLLREF3:		parent = &clk_epllref;	}	clk_init_set_parent(&clk_i2s, &clk_epllref);	/* esysclk source */	parent = (clksrc & S3C2443_CLKSRC_ESYSCLK_EPLL) ?		&clk_epll : &clk_epllref;	clk_init_set_parent(&clk_esysclk, parent);	/* msysclk source */	if (clksrc & S3C2443_CLKSRC_MSYSCLK_MPLL) {		parent = &clk_mpll;	} else {		parent = (clksrc & S3C2443_CLKSRC_EXTCLK_DIV) ?			&clk_mdivclk : &clk_mpllref;	}	clk_init_set_parent(&clk_msysclk, parent);}/* armdiv divisor table */static unsigned int armdiv[16] = {	[S3C2443_CLKDIV0_ARMDIV_1 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 1,	[S3C2443_CLKDIV0_ARMDIV_2 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 2,	[S3C2443_CLKDIV0_ARMDIV_3 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 3,	[S3C2443_CLKDIV0_ARMDIV_4 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 4,	[S3C2443_CLKDIV0_ARMDIV_6 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 6,	[S3C2443_CLKDIV0_ARMDIV_8 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 8,	[S3C2443_CLKDIV0_ARMDIV_12 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 12,	[S3C2443_CLKDIV0_ARMDIV_16 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 16,};static inline unsigned int s3c2443_fclk_div(unsigned long clkcon0){	clkcon0 &= S3C2443_CLKDIV0_ARMDIV_MASK;	return armdiv[clkcon0 >> S3C2443_CLKDIV0_ARMDIV_SHIFT];}static inline unsigned long s3c2443_get_prediv(unsigned long clkcon0){	clkcon0 &= S3C2443_CLKDIV0_PREDIV_MASK;	clkcon0 >>= S3C2443_CLKDIV0_PREDIV_SHIFT;	return clkcon0 + 1;}/* clocks to add straight away */static struct clk *clks[] __initdata = {	&clk_ext,	&clk_epll,	&clk_usb_bus_host,	&clk_usb_bus,	&clk_esysclk,	&clk_epllref,	&clk_mpllref,	&clk_msysclk,	&clk_uart,	&clk_display,	&clk_cam,	&clk_i2s_eplldiv,	&clk_i2s,	&clk_hsspi,	&clk_hsmmc_div,	&clk_hsmmc,};void __init s3c2443_init_clocks(int xtal){	unsigned long epllcon = __raw_readl(S3C2443_EPLLCON);	unsigned long mpllcon = __raw_readl(S3C2443_MPLLCON);	unsigned long clkdiv0 = __raw_readl(S3C2443_CLKDIV0);	unsigned long pll;	unsigned long fclk;	unsigned long hclk;	unsigned long pclk;	struct clk *clkp;	int ret;	int ptr;	pll = s3c2443_get_mpll(mpllcon, xtal);	fclk = pll / s3c2443_fclk_div(clkdiv0);	hclk = fclk / s3c2443_get_prediv(clkdiv0);	hclk = hclk / ((clkdiv0 & S3C2443_CLKDIV0_HALF_HCLK) ? 2 : 1); 	pclk = hclk / ((clkdiv0 & S3C2443_CLKDIV0_HALF_PCLK) ? 2 : 1);	s3c24xx_setup_clocks(xtal, fclk, hclk, pclk);	printk("S3C2443: mpll %s %ld.%03ld MHz, cpu %ld.%03ld MHz, mem %ld.%03ld MHz, pclk %ld.%03ld MHz\n",	       (mpllcon & S3C2443_PLLCON_OFF) ? "off":"on",	       print_mhz(pll), print_mhz(fclk),	       print_mhz(hclk), print_mhz(pclk));	s3c2443_clk_initparents();	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_epll.rate = s3c2443_get_epll(epllcon, xtal);	clk_usb_bus.parent = &clk_usb_bus_host;	/* ensure usb bus clock is within correct rate of 48MHz */	if (clk_get_rate(&clk_usb_bus_host) != (48 * 1000 * 1000)) {		printk(KERN_INFO "Warning: USB host bus not at 48MHz\n");		clk_set_rate(&clk_usb_bus_host, 48*1000*1000);	}	printk("S3C2443: epll %s %ld.%03ld MHz, usb-bus %ld.%03ld MHz\n",	       (epllcon & S3C2443_PLLCON_OFF) ? "off":"on",	       print_mhz(clk_get_rate(&clk_epll)),	       print_mhz(clk_get_rate(&clk_usb_bus)));	/* register clocks from clock array */	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);		}	}	/* We must be careful disabling the clocks we are not intending to	 * be using at boot time, as subsystems such as the LCD which do	 * their own DMA requests to the bus can cause the system to lockup	 * if they where in the middle of requesting bus access.	 *	 * Disabling the LCD clock if the LCD is active is very dangerous,	 * and therefore the bootloader should be careful to not enable	 * the LCD clock if it is not needed.	*/	/* install (and disable) the clocks we do not need immediately */	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);	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -