diff options
Diffstat (limited to 'arch/arm/mach-vexpress/v2m.c')
| -rw-r--r-- | arch/arm/mach-vexpress/v2m.c | 274 | 
1 files changed, 129 insertions, 145 deletions
diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c index fde26adaef3..37608f22ee3 100644 --- a/arch/arm/mach-vexpress/v2m.c +++ b/arch/arm/mach-vexpress/v2m.c @@ -16,7 +16,10 @@  #include <linux/spinlock.h>  #include <linux/usb/isp1760.h>  #include <linux/clkdev.h> +#include <linux/clk-provider.h>  #include <linux/mtd/physmap.h> +#include <linux/regulator/fixed.h> +#include <linux/regulator/machine.h>  #include <asm/arch_timer.h>  #include <asm/mach-types.h> @@ -81,16 +84,6 @@ static void __init v2m_sp804_init(void __iomem *base, unsigned int irq)  	sp804_clockevents_init(base + TIMER_1_BASE, irq, "v2m-timer0");  } -static void __init v2m_timer_init(void) -{ -	v2m_sysctl_init(ioremap(V2M_SYSCTL, SZ_4K)); -	v2m_sp804_init(ioremap(V2M_TIMER01, SZ_4K), IRQ_V2M_TIMER0); -} - -static struct sys_timer v2m_timer = { -	.init	= v2m_timer_init, -}; -  static DEFINE_SPINLOCK(v2m_cfg_lock); @@ -147,6 +140,13 @@ void __init v2m_flags_set(u32 data)  	writel(data, v2m_sysreg_base + V2M_SYS_FLAGSSET);  } +int v2m_get_master_site(void) +{ +	u32 misc = readl(v2m_sysreg_base + V2M_SYS_MISC); + +	return misc & SYS_MISC_MASTERSITE ? SYS_CFG_SITE_DB2 : SYS_CFG_SITE_DB1; +} +  static struct resource v2m_pcie_i2c_resource = {  	.start	= V2M_SERIAL_BUS_PCI, @@ -201,6 +201,11 @@ static struct platform_device v2m_eth_device = {  	.dev.platform_data = &v2m_eth_config,  }; +static struct regulator_consumer_supply v2m_eth_supplies[] = { +	REGULATOR_SUPPLY("vddvario", "smsc911x"), +	REGULATOR_SUPPLY("vdd33a", "smsc911x"), +}; +  static struct resource v2m_usb_resources[] = {  	{  		.start	= V2M_ISP1761, @@ -319,98 +324,145 @@ static struct amba_device *v2m_amba_devs[] __initdata = {  }; -static long v2m_osc_round(struct clk *clk, unsigned long rate) +static unsigned long v2m_osc_recalc_rate(struct clk_hw *hw, +		unsigned long parent_rate)  { +	struct v2m_osc *osc = to_v2m_osc(hw); + +	return !parent_rate ? osc->rate_default : parent_rate; +} + +static long v2m_osc_round_rate(struct clk_hw *hw, unsigned long rate, +		unsigned long *parent_rate) +{ +	struct v2m_osc *osc = to_v2m_osc(hw); + +	if (WARN_ON(rate < osc->rate_min)) +		rate = osc->rate_min; + +	if (WARN_ON(rate > osc->rate_max)) +		rate = osc->rate_max; +  	return rate;  } -static int v2m_osc1_set(struct clk *clk, unsigned long rate) +static int v2m_osc_set_rate(struct clk_hw *hw, unsigned long rate, +		unsigned long parent_rate)  { -	return v2m_cfg_write(SYS_CFG_OSC | SYS_CFG_SITE_MB | 1, rate); +	struct v2m_osc *osc = to_v2m_osc(hw); + +	v2m_cfg_write(SYS_CFG_OSC | SYS_CFG_SITE(osc->site) | +			SYS_CFG_STACK(osc->stack) | osc->osc, rate); + +	return 0;  } -static const struct clk_ops osc1_clk_ops = { -	.round	= v2m_osc_round, -	.set	= v2m_osc1_set, +static struct clk_ops v2m_osc_ops = { +	.recalc_rate = v2m_osc_recalc_rate, +	.round_rate = v2m_osc_round_rate, +	.set_rate = v2m_osc_set_rate,  }; -static struct clk osc1_clk = { -	.ops	= &osc1_clk_ops, -	.rate	= 24000000, +struct clk * __init v2m_osc_register(const char *name, struct v2m_osc *osc) +{ +	struct clk_init_data init; + +	WARN_ON(osc->site > 2); +	WARN_ON(osc->stack > 15); +	WARN_ON(osc->osc > 4095); + +	init.name = name; +	init.ops = &v2m_osc_ops; +	init.flags = CLK_IS_ROOT; +	init.num_parents = 0; + +	osc->hw.init = &init; + +	return clk_register(NULL, &osc->hw); +} + +static struct v2m_osc v2m_mb_osc1 = { +	.site = SYS_CFG_SITE_MB, +	.osc = 1, +	.rate_min = 23750000, +	.rate_max = 63500000, +	.rate_default = 23750000,  }; -static struct clk osc2_clk = { -	.rate	= 24000000, +static const char *v2m_ref_clk_periphs[] __initconst = { +	"mb:wdt",   "1000f000.wdt",  "1c0f0000.wdt",	/* SP805 WDT */  }; -static struct clk v2m_sp804_clk = { -	.rate	= 1000000, +static const char *v2m_osc1_periphs[] __initconst = { +	"mb:clcd",  "1001f000.clcd", "1c1f0000.clcd",	/* PL111 CLCD */  }; -static struct clk v2m_ref_clk = { -	.rate   = 32768, +static const char *v2m_osc2_periphs[] __initconst = { +	"mb:mmci",  "10005000.mmci", "1c050000.mmci",	/* PL180 MMCI */ +	"mb:kmi0",  "10006000.kmi",  "1c060000.kmi",	/* PL050 KMI0 */ +	"mb:kmi1",  "10007000.kmi",  "1c070000.kmi",	/* PL050 KMI1 */ +	"mb:uart0", "10009000.uart", "1c090000.uart",	/* PL011 UART0 */ +	"mb:uart1", "1000a000.uart", "1c0a0000.uart",	/* PL011 UART1 */ +	"mb:uart2", "1000b000.uart", "1c0b0000.uart",	/* PL011 UART2 */ +	"mb:uart3", "1000c000.uart", "1c0c0000.uart",	/* PL011 UART3 */  }; -static struct clk dummy_apb_pclk; +static void __init v2m_clk_init(void) +{ +	struct clk *clk; +	int i; -static struct clk_lookup v2m_lookups[] = { -	{	/* AMBA bus clock */ -		.con_id		= "apb_pclk", -		.clk		= &dummy_apb_pclk, -	}, {	/* UART0 */ -		.dev_id		= "mb:uart0", -		.clk		= &osc2_clk, -	}, {	/* UART1 */ -		.dev_id		= "mb:uart1", -		.clk		= &osc2_clk, -	}, {	/* UART2 */ -		.dev_id		= "mb:uart2", -		.clk		= &osc2_clk, -	}, {	/* UART3 */ -		.dev_id		= "mb:uart3", -		.clk		= &osc2_clk, -	}, {	/* KMI0 */ -		.dev_id		= "mb:kmi0", -		.clk		= &osc2_clk, -	}, {	/* KMI1 */ -		.dev_id		= "mb:kmi1", -		.clk		= &osc2_clk, -	}, {	/* MMC0 */ -		.dev_id		= "mb:mmci", -		.clk		= &osc2_clk, -	}, {	/* CLCD */ -		.dev_id		= "mb:clcd", -		.clk		= &osc1_clk, -	}, {	/* SP805 WDT */ -		.dev_id		= "mb:wdt", -		.clk		= &v2m_ref_clk, -	}, {	/* SP804 timers */ -		.dev_id		= "sp804", -		.con_id		= "v2m-timer0", -		.clk		= &v2m_sp804_clk, -	}, {	/* SP804 timers */ -		.dev_id		= "sp804", -		.con_id		= "v2m-timer1", -		.clk		= &v2m_sp804_clk, -	}, +	clk = clk_register_fixed_rate(NULL, "dummy_apb_pclk", NULL, +			CLK_IS_ROOT, 0); +	WARN_ON(clk_register_clkdev(clk, "apb_pclk", NULL)); + +	clk = clk_register_fixed_rate(NULL, "mb:ref_clk", NULL, +			CLK_IS_ROOT, 32768); +	for (i = 0; i < ARRAY_SIZE(v2m_ref_clk_periphs); i++) +		WARN_ON(clk_register_clkdev(clk, NULL, v2m_ref_clk_periphs[i])); + +	clk = clk_register_fixed_rate(NULL, "mb:sp804_clk", NULL, +			CLK_IS_ROOT, 1000000); +	WARN_ON(clk_register_clkdev(clk, "v2m-timer0", "sp804")); +	WARN_ON(clk_register_clkdev(clk, "v2m-timer1", "sp804")); + +	clk = v2m_osc_register("mb:osc1", &v2m_mb_osc1); +	for (i = 0; i < ARRAY_SIZE(v2m_osc1_periphs); i++) +		WARN_ON(clk_register_clkdev(clk, NULL, v2m_osc1_periphs[i])); + +	clk = clk_register_fixed_rate(NULL, "mb:osc2", NULL, +			CLK_IS_ROOT, 24000000); +	for (i = 0; i < ARRAY_SIZE(v2m_osc2_periphs); i++) +		WARN_ON(clk_register_clkdev(clk, NULL, v2m_osc2_periphs[i])); +} + +static void __init v2m_timer_init(void) +{ +	v2m_sysctl_init(ioremap(V2M_SYSCTL, SZ_4K)); +	v2m_clk_init(); +	v2m_sp804_init(ioremap(V2M_TIMER01, SZ_4K), IRQ_V2M_TIMER0); +} + +static struct sys_timer v2m_timer = { +	.init	= v2m_timer_init,  };  static void __init v2m_init_early(void)  { -	ct_desc->init_early(); -	clkdev_add_table(v2m_lookups, ARRAY_SIZE(v2m_lookups)); +	if (ct_desc->init_early) +		ct_desc->init_early();  	versatile_sched_clock_init(v2m_sysreg_base + V2M_SYS_24MHZ, 24000000);  }  static void v2m_power_off(void)  { -	if (v2m_cfg_write(SYS_CFG_SHUTDOWN | SYS_CFG_SITE_MB, 0)) +	if (v2m_cfg_write(SYS_CFG_SHUTDOWN | SYS_CFG_SITE(SYS_CFG_SITE_MB), 0))  		printk(KERN_EMERG "Unable to shutdown\n");  }  static void v2m_restart(char str, const char *cmd)  { -	if (v2m_cfg_write(SYS_CFG_REBOOT | SYS_CFG_SITE_MB, 0)) +	if (v2m_cfg_write(SYS_CFG_REBOOT | SYS_CFG_SITE(SYS_CFG_SITE_MB), 0))  		printk(KERN_EMERG "Unable to reboot\n");  } @@ -458,6 +510,9 @@ static void __init v2m_init(void)  {  	int i; +	regulator_register_fixed(0, v2m_eth_supplies, +			ARRAY_SIZE(v2m_eth_supplies)); +  	platform_device_register(&v2m_pcie_i2c_device);  	platform_device_register(&v2m_ddc_i2c_device);  	platform_device_register(&v2m_flash_device); @@ -522,77 +577,6 @@ void __init v2m_dt_map_io(void)  #endif  } -static struct clk_lookup v2m_dt_lookups[] = { -	{	/* AMBA bus clock */ -		.con_id		= "apb_pclk", -		.clk		= &dummy_apb_pclk, -	}, {	/* SP804 timers */ -		.dev_id		= "sp804", -		.con_id		= "v2m-timer0", -		.clk		= &v2m_sp804_clk, -	}, {	/* SP804 timers */ -		.dev_id		= "sp804", -		.con_id		= "v2m-timer1", -		.clk		= &v2m_sp804_clk, -	}, {	/* PL180 MMCI */ -		.dev_id		= "mb:mmci", /* 10005000.mmci */ -		.clk		= &osc2_clk, -	}, {	/* PL050 KMI0 */ -		.dev_id		= "10006000.kmi", -		.clk		= &osc2_clk, -	}, {	/* PL050 KMI1 */ -		.dev_id		= "10007000.kmi", -		.clk		= &osc2_clk, -	}, {	/* PL011 UART0 */ -		.dev_id		= "10009000.uart", -		.clk		= &osc2_clk, -	}, {	/* PL011 UART1 */ -		.dev_id		= "1000a000.uart", -		.clk		= &osc2_clk, -	}, {	/* PL011 UART2 */ -		.dev_id		= "1000b000.uart", -		.clk		= &osc2_clk, -	}, {	/* PL011 UART3 */ -		.dev_id		= "1000c000.uart", -		.clk		= &osc2_clk, -	}, {	/* SP805 WDT */ -		.dev_id		= "1000f000.wdt", -		.clk		= &v2m_ref_clk, -	}, {	/* PL111 CLCD */ -		.dev_id		= "1001f000.clcd", -		.clk		= &osc1_clk, -	}, -	/* RS1 memory map */ -	{	/* PL180 MMCI */ -		.dev_id		= "mb:mmci", /* 1c050000.mmci */ -		.clk		= &osc2_clk, -	}, {	/* PL050 KMI0 */ -		.dev_id		= "1c060000.kmi", -		.clk		= &osc2_clk, -	}, {	/* PL050 KMI1 */ -		.dev_id		= "1c070000.kmi", -		.clk		= &osc2_clk, -	}, {	/* PL011 UART0 */ -		.dev_id		= "1c090000.uart", -		.clk		= &osc2_clk, -	}, {	/* PL011 UART1 */ -		.dev_id		= "1c0a0000.uart", -		.clk		= &osc2_clk, -	}, {	/* PL011 UART2 */ -		.dev_id		= "1c0b0000.uart", -		.clk		= &osc2_clk, -	}, {	/* PL011 UART3 */ -		.dev_id		= "1c0c0000.uart", -		.clk		= &osc2_clk, -	}, {	/* SP805 WDT */ -		.dev_id		= "1c0f0000.wdt", -		.clk		= &v2m_ref_clk, -	}, {	/* PL111 CLCD */ -		.dev_id		= "1c1f0000.clcd", -		.clk		= &osc1_clk, -	}, -}; -  void __init v2m_dt_init_early(void)  {  	struct device_node *node; @@ -605,8 +589,8 @@ void __init v2m_dt_init_early(void)  	/* Confirm board type against DT property, if available */  	if (of_property_read_u32(allnodes, "arm,hbi", &dt_hbi) == 0) { -		u32 misc = readl(v2m_sysreg_base + V2M_SYS_MISC); -		u32 id = readl(v2m_sysreg_base + (misc & SYS_MISC_MASTERSITE ? +		int site = v2m_get_master_site(); +		u32 id = readl(v2m_sysreg_base + (site == SYS_CFG_SITE_DB2 ?  				V2M_SYS_PROCID1 : V2M_SYS_PROCID0));  		u32 hbi = id & SYS_PROCIDx_HBI_MASK; @@ -614,8 +598,6 @@ void __init v2m_dt_init_early(void)  			pr_warning("vexpress: DT HBI (%x) is not matching "  					"hardware (%x)!\n", dt_hbi, hbi);  	} - -	clkdev_add_table(v2m_dt_lookups, ARRAY_SIZE(v2m_dt_lookups));  }  static  struct of_device_id vexpress_irq_match[] __initdata = { @@ -637,6 +619,8 @@ static void __init v2m_dt_timer_init(void)  	node = of_find_compatible_node(NULL, NULL, "arm,sp810");  	v2m_sysctl_init(of_iomap(node, 0)); +	v2m_clk_init(); +  	err = of_property_read_string(of_aliases, "arm,v2m_timer", &path);  	if (WARN_ON(err))  		return;  |