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

📄 at32ap7000.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (C) 2005-2006 Atmel Corporation * * 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/clk.h>#include <linux/fb.h>#include <linux/init.h>#include <linux/platform_device.h>#include <linux/dma-mapping.h>#include <linux/spi/spi.h>#include <asm/io.h>#include <asm/arch/at32ap7000.h>#include <asm/arch/board.h>#include <asm/arch/portmux.h>#include <video/atmel_lcdc.h>#include "clock.h"#include "hmatrix.h"#include "pio.h"#include "pm.h"#define PBMEM(base)					\	{						\		.start		= base,			\		.end		= base + 0x3ff,		\		.flags		= IORESOURCE_MEM,	\	}#define IRQ(num)					\	{						\		.start		= num,			\		.end		= num,			\		.flags		= IORESOURCE_IRQ,	\	}#define NAMED_IRQ(num, _name)				\	{						\		.start		= num,			\		.end		= num,			\		.name		= _name,		\		.flags		= IORESOURCE_IRQ,	\	}/* REVISIT these assume *every* device supports DMA, but several * don't ... tc, smc, pio, rtc, watchdog, pwm, ps2, and more. */#define DEFINE_DEV(_name, _id)					\static u64 _name##_id##_dma_mask = DMA_32BIT_MASK;		\static struct platform_device _name##_id##_device = {		\	.name		= #_name,				\	.id		= _id,					\	.dev		= {					\		.dma_mask = &_name##_id##_dma_mask,		\		.coherent_dma_mask = DMA_32BIT_MASK,		\	},							\	.resource	= _name##_id##_resource,		\	.num_resources	= ARRAY_SIZE(_name##_id##_resource),	\}#define DEFINE_DEV_DATA(_name, _id)				\static u64 _name##_id##_dma_mask = DMA_32BIT_MASK;		\static struct platform_device _name##_id##_device = {		\	.name		= #_name,				\	.id		= _id,					\	.dev		= {					\		.dma_mask = &_name##_id##_dma_mask,		\		.platform_data	= &_name##_id##_data,		\		.coherent_dma_mask = DMA_32BIT_MASK,		\	},							\	.resource	= _name##_id##_resource,		\	.num_resources	= ARRAY_SIZE(_name##_id##_resource),	\}#define select_peripheral(pin, periph, flags)			\	at32_select_periph(GPIO_PIN_##pin, GPIO_##periph, flags)#define DEV_CLK(_name, devname, bus, _index)			\static struct clk devname##_##_name = {				\	.name		= #_name,				\	.dev		= &devname##_device.dev,		\	.parent		= &bus##_clk,				\	.mode		= bus##_clk_mode,			\	.get_rate	= bus##_clk_get_rate,			\	.index		= _index,				\}static DEFINE_SPINLOCK(pm_lock);unsigned long at32ap7000_osc_rates[3] = {	[0] = 32768,	/* FIXME: these are ATSTK1002-specific */	[1] = 20000000,	[2] = 12000000,};static unsigned long osc_get_rate(struct clk *clk){	return at32ap7000_osc_rates[clk->index];}static unsigned long pll_get_rate(struct clk *clk, unsigned long control){	unsigned long div, mul, rate;	if (!(control & PM_BIT(PLLEN)))		return 0;	div = PM_BFEXT(PLLDIV, control) + 1;	mul = PM_BFEXT(PLLMUL, control) + 1;	rate = clk->parent->get_rate(clk->parent);	rate = (rate + div / 2) / div;	rate *= mul;	return rate;}static unsigned long pll0_get_rate(struct clk *clk){	u32 control;	control = pm_readl(PLL0);	return pll_get_rate(clk, control);}static unsigned long pll1_get_rate(struct clk *clk){	u32 control;	control = pm_readl(PLL1);	return pll_get_rate(clk, control);}/* * The AT32AP7000 has five primary clock sources: One 32kHz * oscillator, two crystal oscillators and two PLLs. */static struct clk osc32k = {	.name		= "osc32k",	.get_rate	= osc_get_rate,	.users		= 1,	.index		= 0,};static struct clk osc0 = {	.name		= "osc0",	.get_rate	= osc_get_rate,	.users		= 1,	.index		= 1,};static struct clk osc1 = {	.name		= "osc1",	.get_rate	= osc_get_rate,	.index		= 2,};static struct clk pll0 = {	.name		= "pll0",	.get_rate	= pll0_get_rate,	.parent		= &osc0,};static struct clk pll1 = {	.name		= "pll1",	.get_rate	= pll1_get_rate,	.parent		= &osc0,};/* * The main clock can be either osc0 or pll0.  The boot loader may * have chosen one for us, so we don't really know which one until we * have a look at the SM. */static struct clk *main_clock;/* * Synchronous clocks are generated from the main clock. The clocks * must satisfy the constraint *   fCPU >= fHSB >= fPB * i.e. each clock must not be faster than its parent. */static unsigned long bus_clk_get_rate(struct clk *clk, unsigned int shift){	return main_clock->get_rate(main_clock) >> shift;};static void cpu_clk_mode(struct clk *clk, int enabled){	unsigned long flags;	u32 mask;	spin_lock_irqsave(&pm_lock, flags);	mask = pm_readl(CPU_MASK);	if (enabled)		mask |= 1 << clk->index;	else		mask &= ~(1 << clk->index);	pm_writel(CPU_MASK, mask);	spin_unlock_irqrestore(&pm_lock, flags);}static unsigned long cpu_clk_get_rate(struct clk *clk){	unsigned long cksel, shift = 0;	cksel = pm_readl(CKSEL);	if (cksel & PM_BIT(CPUDIV))		shift = PM_BFEXT(CPUSEL, cksel) + 1;	return bus_clk_get_rate(clk, shift);}static long cpu_clk_set_rate(struct clk *clk, unsigned long rate, int apply){	u32 control;	unsigned long parent_rate, child_div, actual_rate, div;	parent_rate = clk->parent->get_rate(clk->parent);	control = pm_readl(CKSEL);	if (control & PM_BIT(HSBDIV))		child_div = 1 << (PM_BFEXT(HSBSEL, control) + 1);	else		child_div = 1;	if (rate > 3 * (parent_rate / 4) || child_div == 1) {		actual_rate = parent_rate;		control &= ~PM_BIT(CPUDIV);	} else {		unsigned int cpusel;		div = (parent_rate + rate / 2) / rate;		if (div > child_div)			div = child_div;		cpusel = (div > 1) ? (fls(div) - 2) : 0;		control = PM_BIT(CPUDIV) | PM_BFINS(CPUSEL, cpusel, control);		actual_rate = parent_rate / (1 << (cpusel + 1));	}	pr_debug("clk %s: new rate %lu (actual rate %lu)\n",			clk->name, rate, actual_rate);	if (apply)		pm_writel(CKSEL, control);	return actual_rate;}static void hsb_clk_mode(struct clk *clk, int enabled){	unsigned long flags;	u32 mask;	spin_lock_irqsave(&pm_lock, flags);	mask = pm_readl(HSB_MASK);	if (enabled)		mask |= 1 << clk->index;	else		mask &= ~(1 << clk->index);	pm_writel(HSB_MASK, mask);	spin_unlock_irqrestore(&pm_lock, flags);}static unsigned long hsb_clk_get_rate(struct clk *clk){	unsigned long cksel, shift = 0;	cksel = pm_readl(CKSEL);	if (cksel & PM_BIT(HSBDIV))		shift = PM_BFEXT(HSBSEL, cksel) + 1;	return bus_clk_get_rate(clk, shift);}static void pba_clk_mode(struct clk *clk, int enabled){	unsigned long flags;	u32 mask;	spin_lock_irqsave(&pm_lock, flags);	mask = pm_readl(PBA_MASK);	if (enabled)		mask |= 1 << clk->index;	else		mask &= ~(1 << clk->index);	pm_writel(PBA_MASK, mask);	spin_unlock_irqrestore(&pm_lock, flags);}static unsigned long pba_clk_get_rate(struct clk *clk){	unsigned long cksel, shift = 0;	cksel = pm_readl(CKSEL);	if (cksel & PM_BIT(PBADIV))		shift = PM_BFEXT(PBASEL, cksel) + 1;	return bus_clk_get_rate(clk, shift);}static void pbb_clk_mode(struct clk *clk, int enabled){	unsigned long flags;	u32 mask;	spin_lock_irqsave(&pm_lock, flags);	mask = pm_readl(PBB_MASK);	if (enabled)		mask |= 1 << clk->index;	else		mask &= ~(1 << clk->index);	pm_writel(PBB_MASK, mask);	spin_unlock_irqrestore(&pm_lock, flags);}static unsigned long pbb_clk_get_rate(struct clk *clk){	unsigned long cksel, shift = 0;	cksel = pm_readl(CKSEL);	if (cksel & PM_BIT(PBBDIV))		shift = PM_BFEXT(PBBSEL, cksel) + 1;	return bus_clk_get_rate(clk, shift);}static struct clk cpu_clk = {	.name		= "cpu",	.get_rate	= cpu_clk_get_rate,	.set_rate	= cpu_clk_set_rate,	.users		= 1,};static struct clk hsb_clk = {	.name		= "hsb",	.parent		= &cpu_clk,	.get_rate	= hsb_clk_get_rate,};static struct clk pba_clk = {	.name		= "pba",	.parent		= &hsb_clk,	.mode		= hsb_clk_mode,	.get_rate	= pba_clk_get_rate,	.index		= 1,};static struct clk pbb_clk = {	.name		= "pbb",	.parent		= &hsb_clk,	.mode		= hsb_clk_mode,	.get_rate	= pbb_clk_get_rate,	.users		= 1,	.index		= 2,};/* -------------------------------------------------------------------- *  Generic Clock operations * -------------------------------------------------------------------- */static void genclk_mode(struct clk *clk, int enabled){	u32 control;	control = pm_readl(GCCTRL(clk->index));	if (enabled)		control |= PM_BIT(CEN);	else		control &= ~PM_BIT(CEN);	pm_writel(GCCTRL(clk->index), control);}static unsigned long genclk_get_rate(struct clk *clk){	u32 control;	unsigned long div = 1;	control = pm_readl(GCCTRL(clk->index));	if (control & PM_BIT(DIVEN))		div = 2 * (PM_BFEXT(DIV, control) + 1);	return clk->parent->get_rate(clk->parent) / div;}static long genclk_set_rate(struct clk *clk, unsigned long rate, int apply){	u32 control;	unsigned long parent_rate, actual_rate, div;	parent_rate = clk->parent->get_rate(clk->parent);	control = pm_readl(GCCTRL(clk->index));	if (rate > 3 * parent_rate / 4) {		actual_rate = parent_rate;		control &= ~PM_BIT(DIVEN);	} else {		div = (parent_rate + rate) / (2 * rate) - 1;		control = PM_BFINS(DIV, div, control) | PM_BIT(DIVEN);		actual_rate = parent_rate / (2 * (div + 1));	}	dev_dbg(clk->dev, "clk %s: new rate %lu (actual rate %lu)\n",		clk->name, rate, actual_rate);	if (apply)		pm_writel(GCCTRL(clk->index), control);	return actual_rate;}int genclk_set_parent(struct clk *clk, struct clk *parent){	u32 control;	dev_dbg(clk->dev, "clk %s: new parent %s (was %s)\n",		clk->name, parent->name, clk->parent->name);	control = pm_readl(GCCTRL(clk->index));	if (parent == &osc1 || parent == &pll1)		control |= PM_BIT(OSCSEL);	else if (parent == &osc0 || parent == &pll0)		control &= ~PM_BIT(OSCSEL);	else		return -EINVAL;	if (parent == &pll0 || parent == &pll1)		control |= PM_BIT(PLLSEL);	else		control &= ~PM_BIT(PLLSEL);	pm_writel(GCCTRL(clk->index), control);	clk->parent = parent;	return 0;}static void __init genclk_init_parent(struct clk *clk){	u32 control;	struct clk *parent;	BUG_ON(clk->index > 7);	control = pm_readl(GCCTRL(clk->index));	if (control & PM_BIT(OSCSEL))		parent = (control & PM_BIT(PLLSEL)) ? &pll1 : &osc1;	else		parent = (control & PM_BIT(PLLSEL)) ? &pll0 : &osc0;	clk->parent = parent;}/* -------------------------------------------------------------------- *  System peripherals * -------------------------------------------------------------------- */static struct resource at32_pm0_resource[] = {	{		.start	= 0xfff00000,		.end	= 0xfff0007f,		.flags	= IORESOURCE_MEM,	},	IRQ(20),};static struct resource at32ap700x_rtc0_resource[] = {	{		.start	= 0xfff00080,		.end	= 0xfff000af,		.flags	= IORESOURCE_MEM,	},	IRQ(21),};static struct resource at32_wdt0_resource[] = {	{		.start	= 0xfff000b0,		.end	= 0xfff000cf,		.flags	= IORESOURCE_MEM,	},};static struct resource at32_eic0_resource[] = {	{		.start	= 0xfff00100,		.end	= 0xfff0013f,		.flags	= IORESOURCE_MEM,	},	IRQ(19),};DEFINE_DEV(at32_pm, 0);DEFINE_DEV(at32ap700x_rtc, 0);DEFINE_DEV(at32_wdt, 0);DEFINE_DEV(at32_eic, 0);/* * Peripheral clock for PM, RTC, WDT and EIC. PM will ensure that this * is always running. */static struct clk at32_pm_pclk = {	.name		= "pclk",	.dev		= &at32_pm0_device.dev,	.parent		= &pbb_clk,	.mode		= pbb_clk_mode,	.get_rate	= pbb_clk_get_rate,	.users		= 1,	.index		= 0,};static struct resource intc0_resource[] = {	PBMEM(0xfff00400),};struct platform_device at32_intc0_device = {	.name		= "intc",	.id		= 0,	.resource	= intc0_resource,	.num_resources	= ARRAY_SIZE(intc0_resource),};DEV_CLK(pclk, at32_intc0, pbb, 1);static struct clk ebi_clk = {	.name		= "ebi",	.parent		= &hsb_clk,	.mode		= hsb_clk_mode,	.get_rate	= hsb_clk_get_rate,	.users		= 1,};static struct clk hramc_clk = {	.name		= "hramc",	.parent		= &hsb_clk,	.mode		= hsb_clk_mode,	.get_rate	= hsb_clk_get_rate,	.users		= 1,	.index		= 3,};static struct resource smc0_resource[] = {	PBMEM(0xfff03400),};DEFINE_DEV(smc, 0);DEV_CLK(pclk, smc0, pbb, 13);DEV_CLK(mck, smc0, hsb, 0);static struct platform_device pdc_device = {	.name		= "pdc",	.id		= 0,};DEV_CLK(hclk, pdc, hsb, 4);DEV_CLK(pclk, pdc, pba, 16);static struct clk pico_clk = {	.name		= "pico",	.parent		= &cpu_clk,	.mode		= cpu_clk_mode,	.get_rate	= cpu_clk_get_rate,	.users		= 1,};static struct resource dmaca0_resource[] = {	{		.start	= 0xff200000,		.end	= 0xff20ffff,		.flags	= IORESOURCE_MEM,	},	IRQ(2),};DEFINE_DEV(dmaca, 0);DEV_CLK(hclk, dmaca0, hsb, 10);/* -------------------------------------------------------------------- * HMATRIX * -------------------------------------------------------------------- */static struct clk hmatrix_clk = {	.name		= "hmatrix_clk",	.parent		= &pbb_clk,	.mode		= pbb_clk_mode,

⌨️ 快捷键说明

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