mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-10-30 21:44:27 -04:00 
			
		
		
		
	
		
			
				
	
	
		
			164 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			164 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * arch/arm/mach-mcs814x/common.c
 | |
|  *
 | |
|  * Core functions for Moschip MCS814x SoCs
 | |
|  *
 | |
|  * This file is licensed under the terms of the GNU General Public
 | |
|  * License version 2.  This program is licensed "as is" without any
 | |
|  * warranty of any kind, whether express or implied.
 | |
|  */
 | |
| 
 | |
| #include <linux/kernel.h>
 | |
| #include <linux/init.h>
 | |
| #include <linux/io.h>
 | |
| #include <linux/gpio.h>
 | |
| #include <linux/of.h>
 | |
| #include <linux/of_address.h>
 | |
| 
 | |
| #include <asm/setup.h>
 | |
| #include <asm/mach-types.h>
 | |
| #include <asm/mach/arch.h>
 | |
| #include <mach/mcs814x.h>
 | |
| #include <mach/cpu.h>
 | |
| #include <asm/pgtable.h>
 | |
| #include <asm/mach/map.h>
 | |
| 
 | |
| void __iomem *mcs814x_sysdbg_base;
 | |
| 
 | |
| static struct map_desc mcs814x_io_desc[] __initdata = {
 | |
| 	{
 | |
| 		.virtual	= MCS814X_IO_BASE,
 | |
| 		.pfn		= __phys_to_pfn(MCS814X_IO_START),
 | |
| 		.length		= MCS814X_IO_SIZE,
 | |
| 		.type		= MT_DEVICE
 | |
| 	},
 | |
| };
 | |
| 
 | |
| struct cpu_mode {
 | |
| 	const char *name;
 | |
| 	int gpio_start;
 | |
| 	int gpio_end;
 | |
| };
 | |
| 
 | |
| static const struct cpu_mode cpu_modes[] = {
 | |
| 	{
 | |
| 		.name		= "I2S",
 | |
| 		.gpio_start	= 4,
 | |
| 		.gpio_end	= 8,
 | |
| 	},
 | |
| 	{
 | |
| 		.name		= "UART",
 | |
| 		.gpio_start	= 4,
 | |
| 		.gpio_end	= 9,
 | |
| 	},
 | |
| 	{
 | |
| 		.name		= "External MII",
 | |
| 		.gpio_start	= 0,
 | |
| 		.gpio_end	= 16,
 | |
| 	},
 | |
| 	{
 | |
| 		.name		= "Normal",
 | |
| 		.gpio_start	= -1,
 | |
| 		.gpio_end	= -1,
 | |
| 	},
 | |
| };
 | |
| 
 | |
| static void mcs814x_eth_hardware_filter_set(u8 value)
 | |
| {
 | |
| 	u32 reg;
 | |
| 
 | |
| 	reg = __raw_readl(MCS814X_VIRT_BASE + MCS814X_DBGLED);
 | |
| 	if (value)
 | |
| 		reg |= 0x80;
 | |
| 	else
 | |
| 		reg &= ~0x80;
 | |
| 	__raw_writel(reg, MCS814X_VIRT_BASE + MCS814X_DBGLED);
 | |
| }
 | |
| 
 | |
| static void mcs814x_eth_led_cfg_set(u8 cfg)
 | |
| {
 | |
| 	u32 reg;
 | |
| 
 | |
| 	reg = __raw_readl(mcs814x_sysdbg_base + SYSDBG_BS2);
 | |
| 	reg &= ~LED_CFG_MASK;
 | |
| 	reg |= cfg;
 | |
| 	__raw_writel(reg, mcs814x_sysdbg_base + SYSDBG_BS2);
 | |
| }
 | |
| 
 | |
| static void mcs814x_eth_buffer_shifting_set(u8 value)
 | |
| {
 | |
| 	u8 reg;
 | |
| 
 | |
| 	reg = __raw_readb(mcs814x_sysdbg_base + SYSDBG_SYSCTL_MAC);
 | |
| 	if (value)
 | |
| 		reg |= BUF_SHIFT_BIT;
 | |
| 	else
 | |
| 		reg &= ~BUF_SHIFT_BIT;
 | |
| 	__raw_writeb(reg, mcs814x_sysdbg_base + SYSDBG_SYSCTL_MAC);
 | |
| }
 | |
| 
 | |
| static struct of_device_id mcs814x_eth_ids[] __initdata = {
 | |
| 	{ .compatible = "moschip,nuport-mac", },
 | |
| 	{ /* sentinel */ },
 | |
| };
 | |
| 
 | |
| /* Configure platform specific knobs based on ethernet device node
 | |
|  * properties */
 | |
| static void mcs814x_eth_init(void)
 | |
| {
 | |
| 	struct device_node *np;
 | |
| 	const unsigned int *intspec;
 | |
| 
 | |
| 	np = of_find_matching_node(NULL, mcs814x_eth_ids);
 | |
| 	if (!np)
 | |
| 		return;
 | |
| 
 | |
| 	/* hardware filter must always be enabled */
 | |
| 	mcs814x_eth_hardware_filter_set(1);
 | |
| 
 | |
| 	intspec = of_get_property(np, "nuport-mac,buffer-shifting", NULL);
 | |
| 	if (!intspec)
 | |
| 		mcs814x_eth_buffer_shifting_set(0);
 | |
| 	else
 | |
| 		mcs814x_eth_buffer_shifting_set(1);
 | |
| 
 | |
| 	intspec = of_get_property(np, "nuport-mac,link-activity", NULL);
 | |
| 	if (intspec)
 | |
| 		mcs814x_eth_led_cfg_set(be32_to_cpup(intspec));
 | |
| }
 | |
| 
 | |
| void __init mcs814x_init_machine(void)
 | |
| {
 | |
| 	u32 bs2, cpu_mode;
 | |
| 	int gpio;
 | |
| 
 | |
| 	bs2 = __raw_readl(mcs814x_sysdbg_base + SYSDBG_BS2);
 | |
| 	cpu_mode = (bs2 >> CPU_MODE_SHIFT) & CPU_MODE_MASK;
 | |
| 
 | |
| 	pr_info("CPU mode: %s\n", cpu_modes[cpu_mode].name);
 | |
| 
 | |
| 	/* request the gpios since the pins are muxed for functionnality */
 | |
| 	for (gpio = cpu_modes[cpu_mode].gpio_start;
 | |
| 		gpio == cpu_modes[cpu_mode].gpio_end; gpio++) {
 | |
| 		if (gpio != -1)
 | |
| 			gpio_request(gpio, cpu_modes[cpu_mode].name);
 | |
| 	}
 | |
| 
 | |
| 	mcs814x_eth_init();
 | |
| }
 | |
| 
 | |
| void __init mcs814x_map_io(void)
 | |
| {
 | |
| 	iotable_init(mcs814x_io_desc, ARRAY_SIZE(mcs814x_io_desc));
 | |
| 
 | |
| 	mcs814x_sysdbg_base = ioremap(MCS814X_IO_START + MCS814X_SYSDBG,
 | |
| 					MCS814X_SYSDBG_SIZE);
 | |
| 	if (!mcs814x_sysdbg_base)
 | |
| 		panic("unable to remap sysdbg base");
 | |
| }
 | |
| 
 | |
| void mcs814x_restart(char mode, const char *cmd)
 | |
| {
 | |
| 	__raw_writel(~(1 << 31), mcs814x_sysdbg_base);
 | |
| }
 |