diff options
Diffstat (limited to 'cpu/at32ap')
| -rw-r--r-- | cpu/at32ap/Makefile | 2 | ||||
| -rw-r--r-- | cpu/at32ap/at32ap7000/Makefile | 2 | ||||
| -rw-r--r-- | cpu/at32ap/at32ap7000/devices.c | 448 | ||||
| -rw-r--r-- | cpu/at32ap/at32ap7000/gpio.c | 137 | ||||
| -rw-r--r-- | cpu/at32ap/at32ap7000/hebi.c | 38 | ||||
| -rw-r--r-- | cpu/at32ap/atmel_mci.c | 477 | ||||
| -rw-r--r-- | cpu/at32ap/atmel_mci.h | 197 | ||||
| -rw-r--r-- | cpu/at32ap/cpu.c | 64 | ||||
| -rw-r--r-- | cpu/at32ap/device.c | 126 | ||||
| -rw-r--r-- | cpu/at32ap/entry.S | 3 | ||||
| -rw-r--r-- | cpu/at32ap/exception.c | 7 | ||||
| -rw-r--r-- | cpu/at32ap/hsdramc.c | 43 | ||||
| -rw-r--r-- | cpu/at32ap/hsdramc1.h | 8 | ||||
| -rw-r--r-- | cpu/at32ap/hsmc3.h | 8 | ||||
| -rw-r--r-- | cpu/at32ap/interrupts.c | 14 | ||||
| -rw-r--r-- | cpu/at32ap/pio.c | 82 | ||||
| -rw-r--r-- | cpu/at32ap/pio2.h | 8 | ||||
| -rw-r--r-- | cpu/at32ap/pm.c | 127 | ||||
| -rw-r--r-- | cpu/at32ap/sm.h | 8 | ||||
| -rw-r--r-- | cpu/at32ap/start.S | 113 | 
20 files changed, 1018 insertions, 894 deletions
diff --git a/cpu/at32ap/Makefile b/cpu/at32ap/Makefile index f62ec8bc9..f69b1f385 100644 --- a/cpu/at32ap/Makefile +++ b/cpu/at32ap/Makefile @@ -30,7 +30,7 @@ LIB	:= $(obj)lib$(CPU).a  START	:= start.o  SOBJS	:= entry.o  COBJS	:= cpu.o hsdramc.o exception.o cache.o -COBJS	+= interrupts.o device.o pm.o pio.o +COBJS	+= interrupts.o pio.o atmel_mci.o  SRCS	:= $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)  OBJS	:= $(addprefix $(obj),$(SOBJS) $(COBJS))  START	:= $(addprefix $(obj),$(START)) diff --git a/cpu/at32ap/at32ap7000/Makefile b/cpu/at32ap/at32ap7000/Makefile index 2ed74d250..d27671211 100644 --- a/cpu/at32ap/at32ap7000/Makefile +++ b/cpu/at32ap/at32ap7000/Makefile @@ -24,7 +24,7 @@ include $(TOPDIR)/config.mk  LIB	:= $(obj)lib$(SOC).a -COBJS	:= hebi.o devices.o +COBJS	:= gpio.o  SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)  OBJS	:= $(addprefix $(obj),$(SOBJS) $(COBJS)) diff --git a/cpu/at32ap/at32ap7000/devices.c b/cpu/at32ap/at32ap7000/devices.c deleted file mode 100644 index 8b216e906..000000000 --- a/cpu/at32ap/at32ap7000/devices.c +++ /dev/null @@ -1,448 +0,0 @@ -/* - * Copyright (C) 2006 Atmel Corporation - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ -#include <common.h> - -#include <asm/arch/memory-map.h> -#include <asm/arch/platform.h> - -#include "../sm.h" - -#define ARRAY_SIZE(x)	(sizeof(x) / sizeof((x)[0])) - -const struct clock_domain chip_clock[] = { -	[CLOCK_CPU] = { -		.reg	= SM_PM_CPU_MASK, -		.id	= CLOCK_CPU, -		.bridge	= NO_DEVICE, -	}, -	[CLOCK_HSB] = { -		.reg	= SM_PM_HSB_MASK, -		.id	= CLOCK_HSB, -		.bridge	= NO_DEVICE, -	}, -	[CLOCK_PBA] = { -		.reg	= SM_PM_PBA_MASK, -		.id	= CLOCK_PBA, -		.bridge	= DEVICE_PBA_BRIDGE, -	}, -	[CLOCK_PBB] = { -		.reg	= SM_PM_PBB_MASK, -		.id	= CLOCK_PBB, -		.bridge	= DEVICE_PBB_BRIDGE, -	}, -}; - -static const struct resource hebi_resource[] = { -	{ -		.type	= RESOURCE_CLOCK, -		.u	= { -			.clock	= { CLOCK_HSB, 0 }, -		}, -	}, { -		.type	= RESOURCE_CLOCK, -		.u	= { -			.clock	= { CLOCK_PBB, 13 }, -		}, -	}, { -		.type	= RESOURCE_CLOCK, -		.u	= { -			.clock	= { CLOCK_PBB, 14 }, -		}, -	}, { -		.type	= RESOURCE_GPIO, -		.u	= { -			.gpio	= { 27, DEVICE_PIOE, GPIO_FUNC_A, 0 }, -		}, -	}, -}; -static const struct resource pba_bridge_resource[] = { -	{ -		.type	= RESOURCE_CLOCK, -		.u	= { -			.clock	= { CLOCK_HSB, 1 }, -		} -	}, { -		.type	= RESOURCE_CLOCK, -		.u	= { -			/* HSB-HSB Bridge */ -			.clock	= { CLOCK_HSB, 4 }, -		}, -	}, -}; -static const struct resource pbb_bridge_resource[] = { -	{ -		.type	= RESOURCE_CLOCK, -		.u	= { -			.clock	= { CLOCK_HSB, 2 }, -		}, -	}, -}; -static const struct resource hramc_resource[] = { -	{ -		.type	= RESOURCE_CLOCK, -		.u	= { -			.clock	= { CLOCK_HSB, 3 }, -		}, -	}, -}; -static const struct resource pioa_resource[] = { -	{ -		.type	= RESOURCE_CLOCK, -		.u	= { -			.clock	= { CLOCK_PBA, 10 }, -		}, -	}, -}; -static const struct resource piob_resource[] = { -	{ -		.type	= RESOURCE_CLOCK, -		.u	= { -			.clock	= { CLOCK_PBA, 11 }, -		}, -	}, -}; -static const struct resource pioc_resource[] = { -	{ -		.type	= RESOURCE_CLOCK, -		.u	= { -			.clock	= { CLOCK_PBA, 12 }, -		}, -	}, -}; -static const struct resource piod_resource[] = { -	{ -		.type	= RESOURCE_CLOCK, -		.u	= { -			.clock	= { CLOCK_PBA, 13 }, -		}, -	}, -}; -static const struct resource pioe_resource[] = { -	{ -		.type	= RESOURCE_CLOCK, -		.u	= { -			.clock	= { CLOCK_PBA, 14 }, -		}, -	}, -}; -static const struct resource sm_resource[] = { -	{ -		.type	= RESOURCE_CLOCK, -		.u	= { -			.clock	= { CLOCK_PBB, 0 }, -		}, -	}, -}; -static const struct resource intc_resource[] = { -	{ -		.type	= RESOURCE_CLOCK, -		.u	= { -			.clock = { CLOCK_PBB, 1 }, -		}, -	}, -}; -static const struct resource hmatrix_resource[] = { -	{ -		.type	= RESOURCE_CLOCK, -		.u	= { -			.clock = { CLOCK_PBB, 2 }, -		}, -	}, -}; -#if defined(CFG_HPDC) -static const struct resource hpdc_resource[] = { -	{ -		.type	= RESOURCE_CLOCK, -		.u	= { -			.clock	= { CLOCK_PBA, 16 }, -		}, -	}, -}; -#endif -#if defined(CFG_MACB0) -static const struct resource macb0_resource[] = { -	{ -		.type	= RESOURCE_CLOCK, -		.u	= { -			.clock	= { CLOCK_HSB, 8 }, -		}, -	}, { -		.type	= RESOURCE_CLOCK, -		.u	= { -			.clock	= { CLOCK_PBB, 6 }, -		}, -	}, { -		.type	= RESOURCE_GPIO, -		.u	= { -			.gpio	= { 19, DEVICE_PIOC, GPIO_FUNC_A, 0 }, -		}, -	}, -}; -#endif -#if defined(CFG_MACB1) -static const struct resource macb1_resource[] = { -	{ -		.type	= RESOURCE_CLOCK, -		.u	= { -			.clock	= { CLOCK_HSB, 9 }, -		}, -	}, { -		.type	= RESOURCE_CLOCK, -		.u	= { -			.clock	= { CLOCK_PBB, 7 }, -		}, -	}, { -		.type	= RESOURCE_GPIO, -		.u	= { -			.gpio	= { 12, DEVICE_PIOC, GPIO_FUNC_B, 19 }, -		}, -	}, { -		.type	= RESOURCE_GPIO, -		.u	= { -			.gpio	= { 14, DEVICE_PIOD, GPIO_FUNC_B, 2 }, -		}, -	}, -}; -#endif -#if defined(CFG_LCDC) -static const struct resource lcdc_resource[] = { -	{ -		.type	= RESOURCE_CLOCK, -		.u	= { -			.clock	= { CLOCK_HSB, 7 }, -		}, -	}, -}; -#endif -#if defined(CFG_USART0) -static const struct resource usart0_resource[] = { -	{ -		.type	= RESOURCE_CLOCK, -		.u	= { -			.clock	= { CLOCK_PBA, 3 }, -		}, -	}, { -		.type	= RESOURCE_GPIO, -		.u	= { -			.gpio = { 2, DEVICE_PIOA, GPIO_FUNC_B, 8 }, -		}, -	}, -}; -#endif -#if defined(CFG_USART1) -static const struct resource usart1_resource[] = { -	{ -		.type	= RESOURCE_CLOCK, -		.u	= { -			.clock	= { CLOCK_PBA, 4 }, -		}, -	}, { -		.type	= RESOURCE_GPIO, -		.u	= { -			.gpio = { 2, DEVICE_PIOA, GPIO_FUNC_A, 17 }, -		}, -	}, -}; -#endif -#if defined(CFG_USART2) -static const struct resource usart2_resource[] = { -	{ -		.type	= RESOURCE_CLOCK, -		.u	= { -			.clock	= { CLOCK_PBA, 5 }, -		}, -	}, { -		.type	= RESOURCE_GPIO, -		.u	= { -			.gpio = { 2, DEVICE_PIOB, GPIO_FUNC_B, 26 }, -		}, -	}, -}; -#endif -#if defined(CFG_USART3) -static const struct resource usart3_resource[] = { -	{ -		.type	= RESOURCE_CLOCK, -		.u	= { -			.clock	= { CLOCK_PBA, 6 }, -		}, -	}, { -		.type	= RESOURCE_GPIO, -		.u	= { -			.gpio = { 2, DEVICE_PIOB, GPIO_FUNC_B, 17 }, -		}, -	}, -}; -#endif -#if defined(CFG_MMCI) -static const struct resource mmci_resource[] = { -	{ -		.type	= RESOURCE_CLOCK, -		.u	= { -			.clock	= { CLOCK_PBB, 9 }, -		}, -	}, { -		.type	= RESOURCE_GPIO, -		.u	= { -			.gpio = { 6, DEVICE_PIOA, GPIO_FUNC_A, 10 }, -		}, -	}, -}; -#endif -#if defined(CFG_DMAC) -static const struct resource dmac_resource[] = { -	{ -		.type	= RESOURCE_CLOCK, -		.u	= { -			.clock	= { CLOCK_HSB, 10 }, -		}, -	}, -}; -#endif - -const struct device chip_device[] = { -	[DEVICE_HEBI] = { -		.regs		= (void *)HSMC_BASE, -		.nr_resources	= ARRAY_SIZE(hebi_resource), -		.resource	= hebi_resource, -	}, -	[DEVICE_PBA_BRIDGE] = { -		.nr_resources	= ARRAY_SIZE(pba_bridge_resource), -		.resource	= pba_bridge_resource, -	}, -	[DEVICE_PBB_BRIDGE] = { -		.nr_resources	= ARRAY_SIZE(pbb_bridge_resource), -		.resource	= pbb_bridge_resource, -	}, -	[DEVICE_HRAMC] = { -		.nr_resources	= ARRAY_SIZE(hramc_resource), -		.resource	= hramc_resource, -	}, -	[DEVICE_PIOA] = { -		.regs		= (void *)PIOA_BASE, -		.nr_resources	= ARRAY_SIZE(pioa_resource), -		.resource	= pioa_resource, -	}, -	[DEVICE_PIOB] = { -		.regs		= (void *)PIOB_BASE, -		.nr_resources	= ARRAY_SIZE(piob_resource), -		.resource	= piob_resource, -	}, -	[DEVICE_PIOC] = { -		.regs		= (void *)PIOC_BASE, -		.nr_resources	= ARRAY_SIZE(pioc_resource), -		.resource	= pioc_resource, -	}, -	[DEVICE_PIOD] = { -		.regs		= (void *)PIOD_BASE, -		.nr_resources	= ARRAY_SIZE(piod_resource), -		.resource	= piod_resource, -	}, -	[DEVICE_PIOE] = { -		.regs		= (void *)PIOE_BASE, -		.nr_resources	= ARRAY_SIZE(pioe_resource), -		.resource	= pioe_resource, -	}, -	[DEVICE_SM] = { -		.regs		= (void *)SM_BASE, -		.nr_resources	= ARRAY_SIZE(sm_resource), -		.resource	= sm_resource, -	}, -	[DEVICE_INTC] = { -		.regs		= (void *)INTC_BASE, -		.nr_resources	= ARRAY_SIZE(intc_resource), -		.resource	= intc_resource, -	}, -	[DEVICE_HMATRIX] = { -		.regs		= (void *)HMATRIX_BASE, -		.nr_resources	= ARRAY_SIZE(hmatrix_resource), -		.resource	= hmatrix_resource, -	}, -#if defined(CFG_HPDC) -	[DEVICE_HPDC] = { -		.nr_resources	= ARRAY_SIZE(hpdc_resource), -		.resource	= hpdc_resource, -	}, -#endif -#if defined(CFG_MACB0) -	[DEVICE_MACB0] = { -		.regs		= (void *)MACB0_BASE, -		.nr_resources	= ARRAY_SIZE(macb0_resource), -		.resource	= macb0_resource, -	}, -#endif -#if defined(CFG_MACB1) -	[DEVICE_MACB1] = { -		.regs		= (void *)MACB1_BASE, -		.nr_resources	= ARRAY_SIZE(macb1_resource), -		.resource	= macb1_resource, -	}, -#endif -#if defined(CFG_LCDC) -	[DEVICE_LCDC] = { -		.nr_resources	= ARRAY_SIZE(lcdc_resource), -		.resource	= lcdc_resource, -	}, -#endif -#if defined(CFG_USART0) -	[DEVICE_USART0] = { -		.regs		= (void *)USART0_BASE, -		.nr_resources	= ARRAY_SIZE(usart0_resource), -		.resource	= usart0_resource, -	}, -#endif -#if defined(CFG_USART1) -	[DEVICE_USART1] = { -		.regs		= (void *)USART1_BASE, -		.nr_resources	= ARRAY_SIZE(usart1_resource), -		.resource	= usart1_resource, -	}, -#endif -#if defined(CFG_USART2) -	[DEVICE_USART2] = { -		.regs		= (void *)USART2_BASE, -		.nr_resources	= ARRAY_SIZE(usart2_resource), -		.resource	= usart2_resource, -	}, -#endif -#if defined(CFG_USART3) -	[DEVICE_USART3] = { -		.regs		= (void *)USART3_BASE, -		.nr_resources	= ARRAY_SIZE(usart3_resource), -		.resource	= usart3_resource, -	}, -#endif -#if defined(CFG_MMCI) -	[DEVICE_MMCI] = { -		.regs		= (void *)MMCI_BASE, -		.nr_resources	= ARRAY_SIZE(mmci_resource), -		.resource	= mmci_resource, -	}, -#endif -#if defined(CFG_DMAC) -	[DEVICE_DMAC] = { -		.regs		= (void *)DMAC_BASE, -		.nr_resources	= ARRAY_SIZE(dmac_resource), -		.resource	= dmac_resource, -	}, -#endif -}; diff --git a/cpu/at32ap/at32ap7000/gpio.c b/cpu/at32ap/at32ap7000/gpio.c new file mode 100644 index 000000000..52f5372a6 --- /dev/null +++ b/cpu/at32ap/at32ap7000/gpio.c @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2006 Atmel Corporation + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +#include <common.h> + +#include <asm/arch/gpio.h> + +/* + * Lots of small functions here. We depend on --gc-sections getting + * rid of the ones we don't need. + */ +void gpio_enable_ebi(void) +{ +#ifdef CFG_HSDRAMC +#ifndef CFG_SDRAM_16BIT +	gpio_select_periph_A(GPIO_PIN_PE0, 0); +	gpio_select_periph_A(GPIO_PIN_PE1, 0); +	gpio_select_periph_A(GPIO_PIN_PE2, 0); +	gpio_select_periph_A(GPIO_PIN_PE3, 0); +	gpio_select_periph_A(GPIO_PIN_PE4, 0); +	gpio_select_periph_A(GPIO_PIN_PE5, 0); +	gpio_select_periph_A(GPIO_PIN_PE6, 0); +	gpio_select_periph_A(GPIO_PIN_PE7, 0); +	gpio_select_periph_A(GPIO_PIN_PE8, 0); +	gpio_select_periph_A(GPIO_PIN_PE9, 0); +	gpio_select_periph_A(GPIO_PIN_PE10, 0); +	gpio_select_periph_A(GPIO_PIN_PE11, 0); +	gpio_select_periph_A(GPIO_PIN_PE12, 0); +	gpio_select_periph_A(GPIO_PIN_PE13, 0); +	gpio_select_periph_A(GPIO_PIN_PE14, 0); +	gpio_select_periph_A(GPIO_PIN_PE15, 0); +#endif +	gpio_select_periph_A(GPIO_PIN_PE26, 0); +#endif +} + +void gpio_enable_usart0(void) +{ +	gpio_select_periph_B(GPIO_PIN_PA8, 0); +	gpio_select_periph_B(GPIO_PIN_PA9, 0); +} + +void gpio_enable_usart1(void) +{ +	gpio_select_periph_A(GPIO_PIN_PA17, 0); +	gpio_select_periph_A(GPIO_PIN_PA18, 0); +} + +void gpio_enable_usart2(void) +{ +	gpio_select_periph_B(GPIO_PIN_PB26, 0); +	gpio_select_periph_B(GPIO_PIN_PB27, 0); +} + +void gpio_enable_usart3(void) +{ +	gpio_select_periph_B(GPIO_PIN_PB18, 0); +	gpio_select_periph_B(GPIO_PIN_PB19, 0); +} + +void gpio_enable_macb0(void) +{ +	gpio_select_periph_A(GPIO_PIN_PC3,  0);	/* TXD0	*/ +	gpio_select_periph_A(GPIO_PIN_PC4,  0);	/* TXD1	*/ +	gpio_select_periph_A(GPIO_PIN_PC7,  0);	/* TXEN	*/ +	gpio_select_periph_A(GPIO_PIN_PC8,  0);	/* TXCK */ +	gpio_select_periph_A(GPIO_PIN_PC9,  0);	/* RXD0	*/ +	gpio_select_periph_A(GPIO_PIN_PC10, 0);	/* RXD1	*/ +	gpio_select_periph_A(GPIO_PIN_PC13, 0);	/* RXER	*/ +	gpio_select_periph_A(GPIO_PIN_PC15, 0);	/* RXDV	*/ +	gpio_select_periph_A(GPIO_PIN_PC16, 0);	/* MDC	*/ +	gpio_select_periph_A(GPIO_PIN_PC17, 0);	/* MDIO	*/ +#if !defined(CONFIG_RMII) +	gpio_select_periph_A(GPIO_PIN_PC0,  0);	/* COL	*/ +	gpio_select_periph_A(GPIO_PIN_PC1,  0);	/* CRS	*/ +	gpio_select_periph_A(GPIO_PIN_PC2,  0);	/* TXER	*/ +	gpio_select_periph_A(GPIO_PIN_PC5,  0);	/* TXD2	*/ +	gpio_select_periph_A(GPIO_PIN_PC6,  0);	/* TXD3 */ +	gpio_select_periph_A(GPIO_PIN_PC11, 0);	/* RXD2	*/ +	gpio_select_periph_A(GPIO_PIN_PC12, 0);	/* RXD3	*/ +	gpio_select_periph_A(GPIO_PIN_PC14, 0);	/* RXCK	*/ +	gpio_select_periph_A(GPIO_PIN_PC18, 0);	/* SPD	*/ +#endif +} + +void gpio_enable_macb1(void) +{ +	gpio_select_periph_B(GPIO_PIN_PD13, 0);	/* TXD0	*/ +	gpio_select_periph_B(GPIO_PIN_PD14, 0);	/* TXD1	*/ +	gpio_select_periph_B(GPIO_PIN_PD11, 0);	/* TXEN	*/ +	gpio_select_periph_B(GPIO_PIN_PD12, 0);	/* TXCK */ +	gpio_select_periph_B(GPIO_PIN_PD10, 0);	/* RXD0	*/ +	gpio_select_periph_B(GPIO_PIN_PD6,  0);	/* RXD1	*/ +	gpio_select_periph_B(GPIO_PIN_PD5,  0);	/* RXER	*/ +	gpio_select_periph_B(GPIO_PIN_PD4,  0);	/* RXDV	*/ +	gpio_select_periph_B(GPIO_PIN_PD3,  0);	/* MDC	*/ +	gpio_select_periph_B(GPIO_PIN_PD2,  0);	/* MDIO	*/ +#if !defined(CONFIG_RMII) +	gpio_select_periph_B(GPIO_PIN_PC19, 0);	/* COL	*/ +	gpio_select_periph_B(GPIO_PIN_PC23, 0);	/* CRS	*/ +	gpio_select_periph_B(GPIO_PIN_PC26, 0);	/* TXER	*/ +	gpio_select_periph_B(GPIO_PIN_PC27, 0);	/* TXD2	*/ +	gpio_select_periph_B(GPIO_PIN_PC28, 0);	/* TXD3 */ +	gpio_select_periph_B(GPIO_PIN_PC29, 0);	/* RXD2	*/ +	gpio_select_periph_B(GPIO_PIN_PC30, 0);	/* RXD3	*/ +	gpio_select_periph_B(GPIO_PIN_PC24, 0);	/* RXCK	*/ +	gpio_select_periph_B(GPIO_PIN_PD15, 0);	/* SPD	*/ +#endif +} + +void gpio_enable_mmci(void) +{ +	gpio_select_periph_A(GPIO_PIN_PA10, 0);	/* CLK	 */ +	gpio_select_periph_A(GPIO_PIN_PA11, 0);	/* CMD	 */ +	gpio_select_periph_A(GPIO_PIN_PA12, 0);	/* DATA0 */ +	gpio_select_periph_A(GPIO_PIN_PA13, 0);	/* DATA1 */ +	gpio_select_periph_A(GPIO_PIN_PA14, 0);	/* DATA2 */ +	gpio_select_periph_A(GPIO_PIN_PA15, 0);	/* DATA3 */ +} diff --git a/cpu/at32ap/at32ap7000/hebi.c b/cpu/at32ap/at32ap7000/hebi.c deleted file mode 100644 index 3b32adf1e..000000000 --- a/cpu/at32ap/at32ap7000/hebi.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2006 Atmel Corporation - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ -#include <common.h> - -#include <asm/io.h> - -#include <asm/arch/hmatrix2.h> -#include <asm/arch/memory-map.h> -#include <asm/arch/platform.h> - -void cpu_enable_sdram(void) -{ -	const struct device *hmatrix; - -	hmatrix = get_device(DEVICE_HMATRIX); - -	/* Set the SDRAM_ENABLE bit in the HEBI SFR */ -	hmatrix2_writel(hmatrix, SFR4, 1 << 1); -} diff --git a/cpu/at32ap/atmel_mci.c b/cpu/at32ap/atmel_mci.c new file mode 100644 index 000000000..9f62c0f14 --- /dev/null +++ b/cpu/at32ap/atmel_mci.c @@ -0,0 +1,477 @@ +/* + * Copyright (C) 2004-2006 Atmel Corporation + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +#include <common.h> + +#ifdef CONFIG_MMC + +#include <part.h> +#include <mmc.h> + +#include <asm/io.h> +#include <asm/errno.h> +#include <asm/byteorder.h> +#include <asm/arch/clk.h> +#include <asm/arch/memory-map.h> + +#include "atmel_mci.h" + +#ifdef DEBUG +#define pr_debug(fmt, args...) printf(fmt, ##args) +#else +#define pr_debug(...) do { } while(0) +#endif + +#ifndef CFG_MMC_CLK_OD +#define CFG_MMC_CLK_OD		150000 +#endif + +#ifndef CFG_MMC_CLK_PP +#define CFG_MMC_CLK_PP		5000000 +#endif + +#ifndef CFG_MMC_OP_COND +#define CFG_MMC_OP_COND		0x00100000 +#endif + +#define MMC_DEFAULT_BLKLEN	512 +#define MMC_DEFAULT_RCA		1 + +static unsigned int mmc_rca; +static block_dev_desc_t mmc_blkdev; + +block_dev_desc_t *mmc_get_dev(int dev) +{ +	return &mmc_blkdev; +} + +static void mci_set_mode(unsigned long hz, unsigned long blklen) +{ +	unsigned long bus_hz; +	unsigned long clkdiv; + +	bus_hz = get_mci_clk_rate(); +	clkdiv = (bus_hz / hz) / 2 - 1; + +	pr_debug("mmc: setting clock %lu Hz, block size %lu\n", +		 hz, blklen); + +	if (clkdiv & ~255UL) { +		clkdiv = 255; +		printf("mmc: clock %lu too low; setting CLKDIV to 255\n", +			hz); +	} + +	blklen &= 0xfffc; +	mmci_writel(MR, (MMCI_BF(CLKDIV, clkdiv) +			 | MMCI_BF(BLKLEN, blklen))); +} + +#define RESP_NO_CRC	1 +#define R1		MMCI_BF(RSPTYP, 1) +#define R2		MMCI_BF(RSPTYP, 2) +#define R3		(R1 | RESP_NO_CRC) +#define R6		R1 +#define NID		MMCI_BF(MAXLAT, 0) +#define NCR		MMCI_BF(MAXLAT, 1) +#define TRCMD_START	MMCI_BF(TRCMD, 1) +#define TRDIR_READ	MMCI_BF(TRDIR, 1) +#define TRTYP_BLOCK	MMCI_BF(TRTYP, 0) +#define INIT_CMD	MMCI_BF(SPCMD, 1) +#define OPEN_DRAIN	MMCI_BF(OPDCMD, 1) + +#define ERROR_FLAGS	(MMCI_BIT(DTOE)			\ +			 | MMCI_BIT(RDIRE)		\ +			 | MMCI_BIT(RENDE)		\ +			 | MMCI_BIT(RINDE)		\ +			 | MMCI_BIT(RTOE)) + +static int +mmc_cmd(unsigned long cmd, unsigned long arg, +	void *resp, unsigned long flags) +{ +	unsigned long *response = resp; +	int i, response_words = 0; +	unsigned long error_flags; +	u32 status; + +	pr_debug("mmc: CMD%lu 0x%lx (flags 0x%lx)\n", +		 cmd, arg, flags); + +	error_flags = ERROR_FLAGS; +	if (!(flags & RESP_NO_CRC)) +		error_flags |= MMCI_BIT(RCRCE); + +	flags &= ~MMCI_BF(CMDNB, ~0UL); + +	if (MMCI_BFEXT(RSPTYP, flags) == MMCI_RSPTYP_48_BIT_RESP) +		response_words = 1; +	else if (MMCI_BFEXT(RSPTYP, flags) == MMCI_RSPTYP_136_BIT_RESP) +		response_words = 4; + +	mmci_writel(ARGR, arg); +	mmci_writel(CMDR, cmd | flags); +	do { +		udelay(40); +		status = mmci_readl(SR); +	} while (!(status & MMCI_BIT(CMDRDY))); + +	pr_debug("mmc: status 0x%08lx\n", status); + +	if (status & ERROR_FLAGS) { +		printf("mmc: command %lu failed (status: 0x%08lx)\n", +		       cmd, status); +		return -EIO; +	} + +	if (response_words) +		pr_debug("mmc: response:"); + +	for (i = 0; i < response_words; i++) { +		response[i] = mmci_readl(RSPR); +		pr_debug(" %08lx", response[i]); +	} +	pr_debug("\n"); + +	return 0; +} + +static int mmc_acmd(unsigned long cmd, unsigned long arg, +		    void *resp, unsigned long flags) +{ +	unsigned long aresp[4]; +	int ret; + +	/* +	 * Seems like the APP_CMD part of an ACMD has 64 cycles max +	 * latency even though the ACMD part doesn't. This isn't +	 * entirely clear in the SD Card spec, but some cards refuse +	 * to work if we attempt to use 5 cycles max latency here... +	 */ +	ret = mmc_cmd(MMC_CMD_APP_CMD, 0, aresp, +		      R1 | NCR | (flags & OPEN_DRAIN)); +	if (ret) +		return ret; +	if ((aresp[0] & (R1_ILLEGAL_COMMAND | R1_APP_CMD)) != R1_APP_CMD) +		return -ENODEV; + +	ret = mmc_cmd(cmd, arg, resp, flags); +	return ret; +} + +static unsigned long +mmc_bread(int dev, unsigned long start, lbaint_t blkcnt, +	  unsigned long *buffer) +{ +	int ret, i = 0; +	unsigned long resp[4]; +	unsigned long card_status, data; +	unsigned long wordcount; +	u32 status; + +	if (blkcnt == 0) +		return 0; + +	pr_debug("mmc_bread: dev %d, start %lx, blkcnt %lx\n", +		 dev, start, blkcnt); + +	/* Put the device into Transfer state */ +	ret = mmc_cmd(MMC_CMD_SELECT_CARD, mmc_rca << 16, resp, R1 | NCR); +	if (ret) goto fail; + +	/* Set block length */ +	ret = mmc_cmd(MMC_CMD_SET_BLOCKLEN, mmc_blkdev.blksz, resp, R1 | NCR); +	if (ret) goto fail; + +	pr_debug("MCI_DTOR = %08lx\n", mmci_readl(DTOR)); + +	for (i = 0; i < blkcnt; i++, start++) { +		ret = mmc_cmd(MMC_CMD_READ_SINGLE_BLOCK, +			      start * mmc_blkdev.blksz, resp, +			      (R1 | NCR | TRCMD_START | TRDIR_READ +			       | TRTYP_BLOCK)); +		if (ret) goto fail; + +		ret = -EIO; +		wordcount = 0; +		do { +			do { +				status = mmci_readl(SR); +				if (status & (ERROR_FLAGS | MMCI_BIT(OVRE))) +					goto fail; +			} while (!(status & MMCI_BIT(RXRDY))); + +			if (status & MMCI_BIT(RXRDY)) { +				data = mmci_readl(RDR); +				/* pr_debug("%x\n", data); */ +				*buffer++ = data; +				wordcount++; +			} +		} while(wordcount < (512 / 4)); + +		pr_debug("mmc: read %u words, waiting for BLKE\n", wordcount); + +		do { +			status = mmci_readl(SR); +		} while (!(status & MMCI_BIT(BLKE))); + +		putc('.'); +	} + +out: +	/* Put the device back into Standby state */ +	mmc_cmd(MMC_CMD_SELECT_CARD, 0, resp, NCR); +	return i; + +fail: +	mmc_cmd(MMC_CMD_SEND_STATUS, mmc_rca << 16, &card_status, R1 | NCR); +	printf("mmc: bread failed, card status = ", card_status); +	goto out; +} + +static void mmc_parse_cid(struct mmc_cid *cid, unsigned long *resp) +{ +	cid->mid = resp[0] >> 24; +	cid->oid = (resp[0] >> 8) & 0xffff; +	cid->pnm[0] = resp[0]; +	cid->pnm[1] = resp[1] >> 24; +	cid->pnm[2] = resp[1] >> 16; +	cid->pnm[3] = resp[1] >> 8; +	cid->pnm[4] = resp[1]; +	cid->pnm[5] = resp[2] >> 24; +	cid->pnm[6] = 0; +	cid->prv = resp[2] >> 16; +	cid->psn = (resp[2] << 16) | (resp[3] >> 16); +	cid->mdt = resp[3] >> 8; +} + +static void sd_parse_cid(struct mmc_cid *cid, unsigned long *resp) +{ +	cid->mid = resp[0] >> 24; +	cid->oid = (resp[0] >> 8) & 0xffff; +	cid->pnm[0] = resp[0]; +	cid->pnm[1] = resp[1] >> 24; +	cid->pnm[2] = resp[1] >> 16; +	cid->pnm[3] = resp[1] >> 8; +	cid->pnm[4] = resp[1]; +	cid->pnm[5] = 0; +	cid->pnm[6] = 0; +	cid->prv = resp[2] >> 24; +	cid->psn = (resp[2] << 8) | (resp[3] >> 24); +	cid->mdt = (resp[3] >> 8) & 0x0fff; +} + +static void mmc_dump_cid(const struct mmc_cid *cid) +{ +	printf("Manufacturer ID:       %02lX\n", cid->mid); +	printf("OEM/Application ID:    %04lX\n", cid->oid); +	printf("Product name:          %s\n", cid->pnm); +	printf("Product Revision:      %lu.%lu\n", +	       cid->prv >> 4, cid->prv & 0x0f); +	printf("Product Serial Number: %lu\n", cid->psn); +	printf("Manufacturing Date:    %02lu/%02lu\n", +	       cid->mdt >> 4, cid->mdt & 0x0f); +} + +static void mmc_dump_csd(const struct mmc_csd *csd) +{ +	unsigned long *csd_raw = (unsigned long *)csd; +	printf("CSD data: %08lx %08lx %08lx %08lx\n", +	       csd_raw[0], csd_raw[1], csd_raw[2], csd_raw[3]); +	printf("CSD structure version:   1.%u\n", csd->csd_structure); +	printf("MMC System Spec version: %u\n", csd->spec_vers); +	printf("Card command classes:    %03x\n", csd->ccc); +	printf("Read block length:       %u\n", 1 << csd->read_bl_len); +	if (csd->read_bl_partial) +		puts("Supports partial reads\n"); +	else +		puts("Does not support partial reads\n"); +	printf("Write block length:      %u\n", 1 << csd->write_bl_len); +	if (csd->write_bl_partial) +		puts("Supports partial writes\n"); +	else +		puts("Does not support partial writes\n"); +	if (csd->wp_grp_enable) +		printf("Supports group WP:      %u\n", csd->wp_grp_size + 1); +	else +		puts("Does not support group WP\n"); +	printf("Card capacity:		%u bytes\n", +	       (csd->c_size + 1) * (1 << (csd->c_size_mult + 2)) * +	       (1 << csd->read_bl_len)); +	printf("File format:            %u/%u\n", +	       csd->file_format_grp, csd->file_format); +	puts("Write protection:        "); +	if (csd->perm_write_protect) +		puts(" permanent"); +	if (csd->tmp_write_protect) +		puts(" temporary"); +	putc('\n'); +} + +static int mmc_idle_cards(void) +{ +	int ret; + +	/* Reset and initialize all cards */ +	ret = mmc_cmd(MMC_CMD_GO_IDLE_STATE, 0, NULL, 0); +	if (ret) +		return ret; + +	/* Keep the bus idle for 74 clock cycles */ +	return mmc_cmd(0, 0, NULL, INIT_CMD); +} + +static int sd_init_card(struct mmc_cid *cid, int verbose) +{ +	unsigned long resp[4]; +	int i, ret = 0; + +	mmc_idle_cards(); +	for (i = 0; i < 1000; i++) { +		ret = mmc_acmd(MMC_ACMD_SD_SEND_OP_COND, CFG_MMC_OP_COND, +			       resp, R3 | NID); +		if (ret || (resp[0] & 0x80000000)) +			break; +		ret = -ETIMEDOUT; +	} + +	if (ret) +		return ret; + +	ret = mmc_cmd(MMC_CMD_ALL_SEND_CID, 0, resp, R2 | NID); +	if (ret) +		return ret; +	sd_parse_cid(cid, resp); +	if (verbose) +		mmc_dump_cid(cid); + +	/* Get RCA of the card that responded */ +	ret = mmc_cmd(MMC_CMD_SD_SEND_RELATIVE_ADDR, 0, resp, R6 | NCR); +	if (ret) +		return ret; + +	mmc_rca = resp[0] >> 16; +	if (verbose) +		printf("SD Card detected (RCA %u)\n", mmc_rca); +	return 0; +} + +static int mmc_init_card(struct mmc_cid *cid, int verbose) +{ +	unsigned long resp[4]; +	int i, ret = 0; + +	mmc_idle_cards(); +	for (i = 0; i < 1000; i++) { +		ret = mmc_cmd(MMC_CMD_SEND_OP_COND, CFG_MMC_OP_COND, resp, +			      R3 | NID | OPEN_DRAIN); +		if (ret || (resp[0] & 0x80000000)) +			break; +		ret = -ETIMEDOUT; +	} + +	if (ret) +		return ret; + +	/* Get CID of all cards. FIXME: Support more than one card */ +	ret = mmc_cmd(MMC_CMD_ALL_SEND_CID, 0, resp, R2 | NID | OPEN_DRAIN); +	if (ret) +		return ret; +	mmc_parse_cid(cid, resp); +	if (verbose) +		mmc_dump_cid(cid); + +	/* Set Relative Address of the card that responded */ +	ret = mmc_cmd(MMC_CMD_SET_RELATIVE_ADDR, mmc_rca << 16, resp, +		      R1 | NCR | OPEN_DRAIN); +	return ret; +} + +int mmc_init(int verbose) +{ +	struct mmc_cid cid; +	struct mmc_csd csd; +	int ret; + +	/* Initialize controller */ +	mmci_writel(CR, MMCI_BIT(SWRST)); +	mmci_writel(CR, MMCI_BIT(MCIEN)); +	mmci_writel(DTOR, 0x5f); +	mmci_writel(IDR, ~0UL); +	mci_set_mode(CFG_MMC_CLK_OD, MMC_DEFAULT_BLKLEN); + +	ret = sd_init_card(&cid, verbose); +	if (ret) { +		mmc_rca = MMC_DEFAULT_RCA; +		ret = mmc_init_card(&cid, verbose); +	} +	if (ret) +		return ret; + +	/* Get CSD from the card */ +	ret = mmc_cmd(MMC_CMD_SEND_CSD, mmc_rca << 16, &csd, R2 | NCR); +	if (ret) +		return ret; +	if (verbose) +		mmc_dump_csd(&csd); + +	/* Initialize the blockdev structure */ +	mmc_blkdev.if_type = IF_TYPE_MMC; +	mmc_blkdev.part_type = PART_TYPE_DOS; +	mmc_blkdev.block_read = mmc_bread; +	sprintf((char *)mmc_blkdev.vendor, +		"Man %02x%04x Snr %08x", +		cid.mid, cid.oid, cid.psn); +	strncpy((char *)mmc_blkdev.product, cid.pnm, +		sizeof(mmc_blkdev.product)); +	sprintf((char *)mmc_blkdev.revision, "%x %x", +		cid.prv >> 4, cid.prv & 0x0f); +	mmc_blkdev.blksz = 1 << csd.read_bl_len; +	mmc_blkdev.lba = (csd.c_size + 1) * (1 << (csd.c_size_mult + 2)); + +	mci_set_mode(CFG_MMC_CLK_PP, mmc_blkdev.blksz); + +#if 0 +	if (fat_register_device(&mmc_blkdev, 1)) +		printf("Could not register MMC fat device\n"); +#else +	init_part(&mmc_blkdev); +#endif + +	return 0; +} + +int mmc_read(ulong src, uchar *dst, int size) +{ +	return -ENOSYS; +} + +int mmc_write(uchar *src, ulong dst, int size) +{ +	return -ENOSYS; +} + +int mmc2info(ulong addr) +{ +	return 0; +} + +#endif /* CONFIG_MMC */ diff --git a/cpu/at32ap/atmel_mci.h b/cpu/at32ap/atmel_mci.h new file mode 100644 index 000000000..0ffbc4fd0 --- /dev/null +++ b/cpu/at32ap/atmel_mci.h @@ -0,0 +1,197 @@ +/* + * Copyright (C) 2005-2006 Atmel Corporation + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +#ifndef __CPU_AT32AP_ATMEL_MCI_H__ +#define __CPU_AT32AP_ATMEL_MCI_H__ + +/* Atmel MultiMedia Card Interface (MCI) registers */ +#define MMCI_CR					0x0000 +#define MMCI_MR					0x0004 +#define MMCI_DTOR				0x0008 +#define MMCI_SDCR				0x000c +#define MMCI_ARGR				0x0010 +#define MMCI_CMDR				0x0014 +#define MMCI_RSPR				0x0020 +#define MMCI_RSPR1				0x0024 +#define MMCI_RSPR2				0x0028 +#define MMCI_RSPR3				0x002c +#define MMCI_RDR				0x0030 +#define MMCI_TDR				0x0034 +#define MMCI_SR					0x0040 +#define MMCI_IER				0x0044 +#define MMCI_IDR				0x0048 +#define MMCI_IMR				0x004c + +/* Bitfields in CR */ +#define MMCI_MCIEN_OFFSET			0 +#define MMCI_MCIEN_SIZE				1 +#define MMCI_MCIDIS_OFFSET			1 +#define MMCI_MCIDIS_SIZE			1 +#define MMCI_PWSEN_OFFSET			2 +#define MMCI_PWSEN_SIZE				1 +#define MMCI_PWSDIS_OFFSET			3 +#define MMCI_PWSDIS_SIZE			1 +#define MMCI_SWRST_OFFSET			7 +#define MMCI_SWRST_SIZE				1 + +/* Bitfields in MR */ +#define MMCI_CLKDIV_OFFSET			0 +#define MMCI_CLKDIV_SIZE			8 +#define MMCI_PWSDIV_OFFSET			8 +#define MMCI_PWSDIV_SIZE			3 +#define MMCI_PDCPADV_OFFSET			14 +#define MMCI_PDCPADV_SIZE			1 +#define MMCI_PDCMODE_OFFSET			15 +#define MMCI_PDCMODE_SIZE			1 +#define MMCI_BLKLEN_OFFSET			16 +#define MMCI_BLKLEN_SIZE			16 + +/* Bitfields in DTOR */ +#define MMCI_DTOCYC_OFFSET			0 +#define MMCI_DTOCYC_SIZE			4 +#define MMCI_DTOMUL_OFFSET			4 +#define MMCI_DTOMUL_SIZE			3 + +/* Bitfields in SDCR */ +#define MMCI_SCDSEL_OFFSET			0 +#define MMCI_SCDSEL_SIZE			4 +#define MMCI_SCDBUS_OFFSET			7 +#define MMCI_SCDBUS_SIZE			1 + +/* Bitfields in ARGR */ +#define MMCI_ARG_OFFSET				0 +#define MMCI_ARG_SIZE				32 + +/* Bitfields in CMDR */ +#define MMCI_CMDNB_OFFSET			0 +#define MMCI_CMDNB_SIZE				6 +#define MMCI_RSPTYP_OFFSET			6 +#define MMCI_RSPTYP_SIZE			2 +#define MMCI_SPCMD_OFFSET			8 +#define MMCI_SPCMD_SIZE				3 +#define MMCI_OPDCMD_OFFSET			11 +#define MMCI_OPDCMD_SIZE			1 +#define MMCI_MAXLAT_OFFSET			12 +#define MMCI_MAXLAT_SIZE			1 +#define MMCI_TRCMD_OFFSET			16 +#define MMCI_TRCMD_SIZE				2 +#define MMCI_TRDIR_OFFSET			18 +#define MMCI_TRDIR_SIZE				1 +#define MMCI_TRTYP_OFFSET			19 +#define MMCI_TRTYP_SIZE				2 + +/* Bitfields in RSPRx */ +#define MMCI_RSP_OFFSET				0 +#define MMCI_RSP_SIZE				32 + +/* Bitfields in SR/IER/IDR/IMR */ +#define MMCI_CMDRDY_OFFSET			0 +#define MMCI_CMDRDY_SIZE			1 +#define MMCI_RXRDY_OFFSET			1 +#define MMCI_RXRDY_SIZE				1 +#define MMCI_TXRDY_OFFSET			2 +#define MMCI_TXRDY_SIZE				1 +#define MMCI_BLKE_OFFSET			3 +#define MMCI_BLKE_SIZE				1 +#define MMCI_DTIP_OFFSET			4 +#define MMCI_DTIP_SIZE				1 +#define MMCI_NOTBUSY_OFFSET			5 +#define MMCI_NOTBUSY_SIZE			1 +#define MMCI_ENDRX_OFFSET			6 +#define MMCI_ENDRX_SIZE				1 +#define MMCI_ENDTX_OFFSET			7 +#define MMCI_ENDTX_SIZE				1 +#define MMCI_RXBUFF_OFFSET			14 +#define MMCI_RXBUFF_SIZE			1 +#define MMCI_TXBUFE_OFFSET			15 +#define MMCI_TXBUFE_SIZE			1 +#define MMCI_RINDE_OFFSET			16 +#define MMCI_RINDE_SIZE				1 +#define MMCI_RDIRE_OFFSET			17 +#define MMCI_RDIRE_SIZE				1 +#define MMCI_RCRCE_OFFSET			18 +#define MMCI_RCRCE_SIZE				1 +#define MMCI_RENDE_OFFSET			19 +#define MMCI_RENDE_SIZE				1 +#define MMCI_RTOE_OFFSET			20 +#define MMCI_RTOE_SIZE				1 +#define MMCI_DCRCE_OFFSET			21 +#define MMCI_DCRCE_SIZE				1 +#define MMCI_DTOE_OFFSET			22 +#define MMCI_DTOE_SIZE				1 +#define MMCI_OVRE_OFFSET			30 +#define MMCI_OVRE_SIZE				1 +#define MMCI_UNRE_OFFSET			31 +#define MMCI_UNRE_SIZE				1 + +/* Constants for DTOMUL */ +#define MMCI_DTOMUL_1_CYCLE			0 +#define MMCI_DTOMUL_16_CYCLES			1 +#define MMCI_DTOMUL_128_CYCLES			2 +#define MMCI_DTOMUL_256_CYCLES			3 +#define MMCI_DTOMUL_1024_CYCLES			4 +#define MMCI_DTOMUL_4096_CYCLES			5 +#define MMCI_DTOMUL_65536_CYCLES		6 +#define MMCI_DTOMUL_1048576_CYCLES		7 + +/* Constants for RSPTYP */ +#define MMCI_RSPTYP_NO_RESP			0 +#define MMCI_RSPTYP_48_BIT_RESP			1 +#define MMCI_RSPTYP_136_BIT_RESP		2 + +/* Constants for SPCMD */ +#define MMCI_SPCMD_NO_SPEC_CMD			0 +#define MMCI_SPCMD_INIT_CMD			1 +#define MMCI_SPCMD_SYNC_CMD			2 +#define MMCI_SPCMD_INT_CMD			4 +#define MMCI_SPCMD_INT_RESP			5 + +/* Constants for TRCMD */ +#define MMCI_TRCMD_NO_TRANS			0 +#define MMCI_TRCMD_START_TRANS			1 +#define MMCI_TRCMD_STOP_TRANS			2 + +/* Constants for TRTYP */ +#define MMCI_TRTYP_BLOCK			0 +#define MMCI_TRTYP_MULTI_BLOCK			1 +#define MMCI_TRTYP_STREAM			2 + +/* Bit manipulation macros */ +#define MMCI_BIT(name)					\ +	(1 << MMCI_##name##_OFFSET) +#define MMCI_BF(name,value)				\ +	(((value) & ((1 << MMCI_##name##_SIZE) - 1))	\ +	 << MMCI_##name##_OFFSET) +#define MMCI_BFEXT(name,value)				\ +	(((value) >> MMCI_##name##_OFFSET)\ +	 & ((1 << MMCI_##name##_SIZE) - 1)) +#define MMCI_BFINS(name,value,old)			\ +	(((old) & ~(((1 << MMCI_##name##_SIZE) - 1)	\ +		    << MMCI_##name##_OFFSET))		\ +	 | MMCI_BF(name,value)) + +/* Register access macros */ +#define mmci_readl(reg)					\ +	readl((void *)MMCI_BASE + MMCI_##reg) +#define mmci_writel(reg,value)				\ +	writel((value), (void *)MMCI_BASE + MMCI_##reg) + +#endif /* __CPU_AT32AP_ATMEL_MCI_H__ */ diff --git a/cpu/at32ap/cpu.c b/cpu/at32ap/cpu.c index 37e3ea040..311466b78 100644 --- a/cpu/at32ap/cpu.c +++ b/cpu/at32ap/cpu.c @@ -26,33 +26,79 @@  #include <asm/sections.h>  #include <asm/sysreg.h> +#include <asm/arch/clk.h>  #include <asm/arch/memory-map.h> -#include <asm/arch/platform.h>  #include "hsmc3.h" +#include "sm.h" + +/* Sanity checks */ +#if (CFG_CLKDIV_CPU > CFG_CLKDIV_HSB)		\ +	|| (CFG_CLKDIV_HSB > CFG_CLKDIV_PBA)	\ +	|| (CFG_CLKDIV_HSB > CFG_CLKDIV_PBB) +# error Constraint fCPU >= fHSB >= fPB{A,B} violated +#endif +#if defined(CONFIG_PLL) && ((CFG_PLL0_MUL < 1) || (CFG_PLL0_DIV < 1)) +# error Invalid PLL multiplier and/or divider +#endif  DECLARE_GLOBAL_DATA_PTR; +static void pm_init(void) +{ +	uint32_t cksel; + +#ifdef CONFIG_PLL +	/* Initialize the PLL */ +	sm_writel(PM_PLL0, (SM_BF(PLLCOUNT, CFG_PLL0_SUPPRESS_CYCLES) +			    | SM_BF(PLLMUL, CFG_PLL0_MUL - 1) +			    | SM_BF(PLLDIV, CFG_PLL0_DIV - 1) +			    | SM_BF(PLLOPT, CFG_PLL0_OPT) +			    | SM_BF(PLLOSC, 0) +			    | SM_BIT(PLLEN))); + +	/* Wait for lock */ +	while (!(sm_readl(PM_ISR) & SM_BIT(LOCK0))) ; +#endif + +	/* Set up clocks for the CPU and all peripheral buses */ +	cksel = 0; +	if (CFG_CLKDIV_CPU) +		cksel |= SM_BIT(CPUDIV) | SM_BF(CPUSEL, CFG_CLKDIV_CPU - 1); +	if (CFG_CLKDIV_HSB) +		cksel |= SM_BIT(HSBDIV) | SM_BF(HSBSEL, CFG_CLKDIV_HSB - 1); +	if (CFG_CLKDIV_PBA) +		cksel |= SM_BIT(PBADIV) | SM_BF(PBASEL, CFG_CLKDIV_PBA - 1); +	if (CFG_CLKDIV_PBB) +		cksel |= SM_BIT(PBBDIV) | SM_BF(PBBSEL, CFG_CLKDIV_PBB - 1); +	sm_writel(PM_CKSEL, cksel); + +	gd->cpu_hz = get_cpu_clk_rate(); + +#ifdef CONFIG_PLL +	/* Use PLL0 as main clock */ +	sm_writel(PM_MCCTRL, SM_BIT(PLLSEL)); +#endif +} +  int cpu_init(void)  { -	const struct device *hebi;  	extern void _evba(void);  	char *p;  	gd->cpu_hz = CFG_OSC0_HZ; -	/* fff03400: 00010001 04030402 00050005 10011103 */ -	hebi = get_device(DEVICE_HEBI); -	hsmc3_writel(hebi, MODE0, 0x00031103); -	hsmc3_writel(hebi, CYCLE0, 0x000c000d); -	hsmc3_writel(hebi, PULSE0, 0x0b0a0906); -	hsmc3_writel(hebi, SETUP0, 0x00010002); +	/* TODO: Move somewhere else, but needs to be run before we +	 * increase the clock frequency. */ +	hsmc3_writel(MODE0, 0x00031103); +	hsmc3_writel(CYCLE0, 0x000c000d); +	hsmc3_writel(PULSE0, 0x0b0a0906); +	hsmc3_writel(SETUP0, 0x00010002);  	pm_init();  	sysreg_write(EVBA, (unsigned long)&_evba);  	asm volatile("csrf	%0" : : "i"(SYSREG_EM_OFFSET)); -	gd->console_uart = get_device(CFG_CONSOLE_UART_DEV);  	/* Lock everything that mess with the flash in the icache */  	for (p = __flashprog_start; p <= (__flashprog_end + CFG_ICACHE_LINESZ); diff --git a/cpu/at32ap/device.c b/cpu/at32ap/device.c deleted file mode 100644 index 89914b6b5..000000000 --- a/cpu/at32ap/device.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (C) 2006 Atmel Corporation - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ -#include <common.h> - -#include <asm/arch/platform.h> - -#include "sm.h" - -struct device_state { -	int refcount; -}; - -static struct device_state device_state[NR_DEVICES]; - -static int claim_resource(const struct resource *res) -{ -	int ret = 0; - -	switch (res->type) { -	case RESOURCE_GPIO: -		ret = gpio_set_func(res->u.gpio.gpio_dev, -				    res->u.gpio.start, -				    res->u.gpio.nr_pins, -				    res->u.gpio.func); -		break; -	case RESOURCE_CLOCK: -		ret = pm_enable_clock(res->u.clock.id, res->u.clock.index); -		break; -	} - -	return ret; -} - -static void free_resource(const struct resource *res) -{ -	switch (res->type) { -	case RESOURCE_GPIO: -		gpio_free(res->u.gpio.gpio_dev, res->u.gpio.start, -			  res->u.gpio.nr_pins); -		break; -	case RESOURCE_CLOCK: -		pm_disable_clock(res->u.clock.id, res->u.clock.index); -		break; -	} -} - -static int init_dev(const struct device *dev) -{ -	unsigned int i; -	int ret = 0; - -	for (i = 0; i < dev->nr_resources; i++) { -		ret = claim_resource(&dev->resource[i]); -		if (ret) -			goto cleanup; -	} - -	return 0; - -cleanup: -	while (i--) -		free_resource(&dev->resource[i]); - -	return ret; -} - -const struct device *get_device(enum device_id devid) -{ -	struct device_state *devstate; -	const struct device *dev; -	unsigned long flags; -	int initialized = 0; -	int ret = 0; - -	devstate = &device_state[devid]; -	dev = &chip_device[devid]; - -	flags = disable_interrupts(); -	if (devstate->refcount++) -		initialized = 1; -	if (flags) -		enable_interrupts(); - -	if (!initialized) -		ret = init_dev(dev); - -	return ret ? NULL : dev; -} - -void put_device(const struct device *dev) -{ -	struct device_state *devstate; -	unsigned long devid, flags; - -	devid = (unsigned long)(dev - chip_device) / sizeof(struct device); -	devstate = &device_state[devid]; - -	flags = disable_interrupts(); -	devstate--; -	if (!devstate) { -		unsigned int i; -		for (i = 0; i < dev->nr_resources; i++) -			free_resource(&dev->resource[i]); -	} -	if (flags) -		enable_interrupts(); -} diff --git a/cpu/at32ap/entry.S b/cpu/at32ap/entry.S index b52d798be..a6fc68867 100644 --- a/cpu/at32ap/entry.S +++ b/cpu/at32ap/entry.S @@ -42,8 +42,7 @@ timer_interrupt_handler:  	 * We're running at interrupt level 3, so we don't need to save  	 * r8-r12 or lr to the stack.  	 */ -	mov	r8, lo(timer_overflow) -	orh	r8, hi(timer_overflow) +	lda.w	r8, timer_overflow  	ld.w	r9, r8[0]  	mov	r10, -1  	mtsr	SYSREG_COMPARE, r10 diff --git a/cpu/at32ap/exception.c b/cpu/at32ap/exception.c index 4123c4461..0672685cd 100644 --- a/cpu/at32ap/exception.c +++ b/cpu/at32ap/exception.c @@ -24,6 +24,8 @@  #include <asm/sysreg.h>  #include <asm/ptrace.h> +DECLARE_GLOBAL_DATA_PTR; +  static const char * const cpu_modes[8] = {  	"Application", "Supervisor", "Interrupt level 0", "Interrupt level 1",  	"Interrupt level 2", "Interrupt level 3", "Exception", "NMI" @@ -109,11 +111,10 @@ void do_unknown_exception(unsigned int ecr, struct pt_regs *regs)  	printf("CPU Mode: %s\n", cpu_modes[mode]);  	/* Avoid exception loops */ -	if (regs->sp >= CFG_INIT_SP_ADDR -	    || regs->sp < (CFG_INIT_SP_ADDR - CONFIG_STACKSIZE)) +	if (regs->sp < CFG_SDRAM_BASE || regs->sp >= gd->stack_end)  		printf("\nStack pointer seems bogus, won't do stack dump\n");  	else -		dump_mem("\nStack: ", regs->sp, CFG_INIT_SP_ADDR); +		dump_mem("\nStack: ", regs->sp, gd->stack_end);  	panic("Unhandled exception\n");  } diff --git a/cpu/at32ap/hsdramc.c b/cpu/at32ap/hsdramc.c index f36da3545..a936e0316 100644 --- a/cpu/at32ap/hsdramc.c +++ b/cpu/at32ap/hsdramc.c @@ -25,17 +25,11 @@  #include <asm/io.h>  #include <asm/sdram.h> -#include <asm/arch/platform.h> +#include <asm/arch/clk.h> +#include <asm/arch/memory-map.h>  #include "hsdramc1.h" -struct hsdramc { -	const struct device *hebi; -	void *regs; -}; - -static struct hsdramc hsdramc; -  unsigned long sdram_init(const struct sdram_info *info)  {  	unsigned long *sdram = (unsigned long *)uncached(info->phys_addr); @@ -44,16 +38,6 @@ unsigned long sdram_init(const struct sdram_info *info)  	unsigned long bus_hz;  	unsigned int i; -	hsdramc.hebi = get_device(DEVICE_HEBI); -	if (!hsdramc.hebi) -		return 0; - -	/* FIXME: Both of these lines are complete hacks */ -	hsdramc.regs = hsdramc.hebi->regs + 0x400; -	bus_hz = pm_get_clock_freq(hsdramc.hebi->resource[0].u.clock.id); - -	cpu_enable_sdram(); -  	tmp = (HSDRAMC1_BF(NC, info->col_bits - 8)  	       | HSDRAMC1_BF(NR, info->row_bits - 11)  	       | HSDRAMC1_BF(NB, info->bank_bits - 1) @@ -74,7 +58,7 @@ unsigned long sdram_init(const struct sdram_info *info)  			   + info->bank_bits + 2);  #endif -	hsdramc1_writel(&hsdramc, CR, tmp); +	hsdramc1_writel(CR, tmp);  	/*  	 * Initialization sequence for SDRAM, from the data sheet: @@ -87,15 +71,15 @@ unsigned long sdram_init(const struct sdram_info *info)  	/*  	 * 2. A Precharge All command is issued to the SDRAM  	 */ -	hsdramc1_writel(&hsdramc, MR, HSDRAMC1_MODE_BANKS_PRECHARGE); -	hsdramc1_readl(&hsdramc, MR); +	hsdramc1_writel(MR, HSDRAMC1_MODE_BANKS_PRECHARGE); +	hsdramc1_readl(MR);  	writel(0, sdram);  	/*  	 * 3. Eight auto-refresh (CBR) cycles are provided  	 */ -	hsdramc1_writel(&hsdramc, MR, HSDRAMC1_MODE_AUTO_REFRESH); -	hsdramc1_readl(&hsdramc, MR); +	hsdramc1_writel(MR, HSDRAMC1_MODE_AUTO_REFRESH); +	hsdramc1_readl(MR);  	for (i = 0; i < 8; i++)  		writel(0, sdram); @@ -106,8 +90,8 @@ unsigned long sdram_init(const struct sdram_info *info)  	 *  	 * CAS from info struct, burst length 1, serial burst type  	 */ -	hsdramc1_writel(&hsdramc, MR, HSDRAMC1_MODE_LOAD_MODE); -	hsdramc1_readl(&hsdramc, MR); +	hsdramc1_writel(MR, HSDRAMC1_MODE_LOAD_MODE); +	hsdramc1_readl(MR);  	writel(0, sdram + (info->cas << 4));  	/* @@ -117,9 +101,9 @@ unsigned long sdram_init(const struct sdram_info *info)  	 * From the timing diagram, it looks like tMRD is 3  	 * cycles...try a dummy read from the peripheral bus.  	 */ -	hsdramc1_readl(&hsdramc, MR); -	hsdramc1_writel(&hsdramc, MR, HSDRAMC1_MODE_NORMAL); -	hsdramc1_readl(&hsdramc, MR); +	hsdramc1_readl(MR); +	hsdramc1_writel(MR, HSDRAMC1_MODE_NORMAL); +	hsdramc1_readl(MR);  	writel(0, sdram);  	/* @@ -128,7 +112,8 @@ unsigned long sdram_init(const struct sdram_info *info)  	 *  	 * 15.6 us is a typical value for a burst of length one  	 */ -	hsdramc1_writel(&hsdramc, TR, (156 * (bus_hz / 1000)) / 10000); +	bus_hz = get_sdram_clk_rate(); +	hsdramc1_writel(TR, (156 * (bus_hz / 1000)) / 10000);  	printf("SDRAM: %u MB at address 0x%08lx\n",  	       sdram_size >> 20, info->phys_addr); diff --git a/cpu/at32ap/hsdramc1.h b/cpu/at32ap/hsdramc1.h index ce229bca1..305d2cb5d 100644 --- a/cpu/at32ap/hsdramc1.h +++ b/cpu/at32ap/hsdramc1.h @@ -135,9 +135,9 @@  	 | HSDRAMC1_BF(name,value))  /* Register access macros */ -#define hsdramc1_readl(port,reg)				\ -	readl((port)->regs + HSDRAMC1_##reg) -#define hsdramc1_writel(port,reg,value)				\ -	writel((value), (port)->regs + HSDRAMC1_##reg) +#define hsdramc1_readl(reg)					\ +	readl((void *)HSDRAMC_BASE + HSDRAMC1_##reg) +#define hsdramc1_writel(reg,value)				\ +	writel((value), (void *)HSDRAMC_BASE + HSDRAMC1_##reg)  #endif /* __ASM_AVR32_HSDRAMC1_H__ */ diff --git a/cpu/at32ap/hsmc3.h b/cpu/at32ap/hsmc3.h index ec78cee71..ca533b922 100644 --- a/cpu/at32ap/hsmc3.h +++ b/cpu/at32ap/hsmc3.h @@ -118,9 +118,9 @@  	 | HSMC3_BF(name,value))  /* Register access macros */ -#define hsmc3_readl(port,reg)					\ -	readl((port)->regs + HSMC3_##reg) -#define hsmc3_writel(port,reg,value)				\ -	writel((value), (port)->regs + HSMC3_##reg) +#define hsmc3_readl(reg)					\ +	readl((void *)HSMC_BASE + HSMC3_##reg) +#define hsmc3_writel(reg,value)					\ +	writel((value), (void *)HSMC_BASE + HSMC3_##reg)  #endif /* __CPU_AT32AP_HSMC3_H__ */ diff --git a/cpu/at32ap/interrupts.c b/cpu/at32ap/interrupts.c index d720cfa94..c9e04993c 100644 --- a/cpu/at32ap/interrupts.c +++ b/cpu/at32ap/interrupts.c @@ -27,7 +27,7 @@  #include <asm/processor.h>  #include <asm/sysreg.h> -#include <asm/arch/platform.h> +#include <asm/arch/memory-map.h>  #define HANDLER_MASK	0x00ffffff  #define INTLEV_SHIFT	30 @@ -44,8 +44,6 @@ volatile unsigned long timer_overflow;   */  static unsigned long tb_factor; -static const struct device *intc_dev; -  unsigned long get_tbclk(void)  {  	return gd->cpu_hz; @@ -117,16 +115,19 @@ void udelay(unsigned long usec)  static int set_interrupt_handler(unsigned int nr, void (*handler)(void),  				 unsigned int priority)  { +	extern void _evba(void);  	unsigned long intpr;  	unsigned long handler_addr = (unsigned long)handler; +	handler_addr -= (unsigned long)&_evba; +  	if ((handler_addr & HANDLER_MASK) != handler_addr  	    || (priority & INTLEV_MASK) != priority)  		return -EINVAL;  	intpr = (handler_addr & HANDLER_MASK);  	intpr |= (priority & INTLEV_MASK) << INTLEV_SHIFT; -	writel(intpr, intc_dev->regs + 4 * nr); +	writel(intpr, (void *)INTC_BASE + 4 * nr);  	return 0;  } @@ -143,10 +144,7 @@ void timer_init(void)  	do_div(tmp, gd->cpu_hz);  	tb_factor = (u32)tmp; -	intc_dev = get_device(DEVICE_INTC); - -	if (!intc_dev -	    || set_interrupt_handler(0, &timer_interrupt_handler, 3)) +	if (set_interrupt_handler(0, &timer_interrupt_handler, 3))  		return;  	/* For all practical purposes, this gives us an overflow interrupt */ diff --git a/cpu/at32ap/pio.c b/cpu/at32ap/pio.c index 8b6c3a35d..9ba0b8ea8 100644 --- a/cpu/at32ap/pio.c +++ b/cpu/at32ap/pio.c @@ -21,74 +21,40 @@   */  #include <common.h> -#include <asm/errno.h>  #include <asm/io.h> -#include <asm/arch/platform.h> +#include <asm/arch/gpio.h> +#include <asm/arch/memory-map.h>  #include "pio2.h" -struct pio_state { -	const struct device *dev; -	u32 alloc_mask; -}; - -static struct pio_state pio_state[CFG_NR_PIOS]; - -int gpio_set_func(enum device_id gpio_devid, unsigned int start, -		  unsigned int nr_pins, enum gpio_func func) +void gpio_select_periph_A(unsigned int pin, int use_pullup)  { -	const struct device *gpio; -	struct pio_state *state; -	u32 mask; - -	state = &pio_state[gpio_devid - DEVICE_PIOA]; - -	gpio = get_device(gpio_devid); -	if (!gpio) -		return -EBUSY; +	void *base = gpio_pin_to_addr(pin); +	uint32_t mask = 1 << (pin & 0x1f); -	state->dev = gpio; -	mask = ((1 << nr_pins) - 1) << start; +	if (!base) +		panic("Invalid GPIO pin %u\n", pin); -	if (mask & state->alloc_mask) { -		put_device(gpio); -		return -EBUSY; -	} -	state->alloc_mask |= mask; - -	switch (func) { -	case GPIO_FUNC_GPIO: -		/* TODO */ -		return -EINVAL; -	case GPIO_FUNC_A: -		pio2_writel(gpio, ASR, mask); -		pio2_writel(gpio, PDR, mask); -		pio2_writel(gpio, PUDR, mask); -		break; -	case GPIO_FUNC_B: -		pio2_writel(gpio, BSR, mask); -		pio2_writel(gpio, PDR, mask); -		pio2_writel(gpio, PUDR, mask); -		break; -	} - -	return 0; +	pio2_writel(base, ASR, mask); +	pio2_writel(base, PDR, mask); +	if (use_pullup) +		pio2_writel(base, PUER, mask); +	else +		pio2_writel(base, PUDR, mask);  } -void gpio_free(enum device_id gpio_devid, unsigned int start, -	       unsigned int nr_pins) +void gpio_select_periph_B(unsigned int pin, int use_pullup)  { -	const struct device *gpio; -	struct pio_state *state; -	u32 mask; - -	state = &pio_state[gpio_devid - DEVICE_PIOA]; -	gpio = state->dev; -	mask = ((1 << nr_pins) - 1) << start; +	void *base = gpio_pin_to_addr(pin); +	uint32_t mask = 1 << (pin & 0x1f); -	pio2_writel(gpio, ODR, mask); -	pio2_writel(gpio, PER, mask); +	if (!base) +		panic("Invalid GPIO pin %u\n", pin); -	state->alloc_mask &= ~mask; -	put_device(gpio); +	pio2_writel(base, BSR, mask); +	pio2_writel(base, PDR, mask); +	if (use_pullup) +		pio2_writel(base, PUER, mask); +	else +		pio2_writel(base, PUDR, mask);  } diff --git a/cpu/at32ap/pio2.h b/cpu/at32ap/pio2.h index 6b79de3c7..9719ea8c4 100644 --- a/cpu/at32ap/pio2.h +++ b/cpu/at32ap/pio2.h @@ -36,9 +36,9 @@  #define PIO2_OWSR				0x00a8  /* Register access macros */ -#define pio2_readl(port,reg)				\ -	readl((port)->regs + PIO2_##reg) -#define pio2_writel(port,reg,value)			\ -	writel((value), (port)->regs + PIO2_##reg) +#define pio2_readl(base,reg)				\ +	readl((void *)base + PIO2_##reg) +#define pio2_writel(base,reg,value)			\ +	writel((value), (void *)base + PIO2_##reg)  #endif /* __CPU_AT32AP_PIO2_H__ */ diff --git a/cpu/at32ap/pm.c b/cpu/at32ap/pm.c index 01ac325ee..c78d547f8 100644 --- a/cpu/at32ap/pm.c +++ b/cpu/at32ap/pm.c @@ -26,138 +26,17 @@  #include <asm/io.h>  #include <asm/arch/memory-map.h> -#include <asm/arch/platform.h>  #include "sm.h" -/* Sanity checks */ -#if (CFG_CLKDIV_CPU > CFG_CLKDIV_HSB)		\ -	|| (CFG_CLKDIV_HSB > CFG_CLKDIV_PBA)	\ -	|| (CFG_CLKDIV_HSB > CFG_CLKDIV_PBB) -# error Constraint fCPU >= fHSB >= fPB{A,B} violated -#endif -#if defined(CONFIG_PLL) && ((CFG_PLL0_MUL < 1) || (CFG_PLL0_DIV < 1)) -# error Invalid PLL multiplier and/or divider -#endif - -DECLARE_GLOBAL_DATA_PTR; - -struct clock_domain_state { -	const struct device *bridge; -	unsigned long freq; -	u32 mask; -}; -static struct clock_domain_state ckd_state[NR_CLOCK_DOMAINS]; - -int pm_enable_clock(enum clock_domain_id id, unsigned int index) -{ -	const struct clock_domain *ckd = &chip_clock[id]; -	struct clock_domain_state *state = &ckd_state[id]; - -	if (ckd->bridge != NO_DEVICE) { -		state->bridge = get_device(ckd->bridge); -		if (!state->bridge) -			return -EBUSY; -	} - -	state->mask |= 1 << index; -	if (gd->sm) -		writel(state->mask, gd->sm->regs + ckd->reg); - -	return 0; -} - -void pm_disable_clock(enum clock_domain_id id, unsigned int index) -{ -	const struct clock_domain *ckd = &chip_clock[id]; -	struct clock_domain_state *state = &ckd_state[id]; - -	state->mask &= ~(1 << index); -	if (gd->sm) -		writel(state->mask, gd->sm->regs + ckd->reg); - -	if (ckd->bridge) -		put_device(state->bridge); -} - -unsigned long pm_get_clock_freq(enum clock_domain_id domain) -{ -	return ckd_state[domain].freq; -} - -void pm_init(void) -{ -	uint32_t cksel = 0; -	unsigned long main_clock; - -	/* Make sure we don't disable any device we're already using */ -	get_device(DEVICE_HRAMC); -	get_device(DEVICE_HEBI); - -	/* Enable the PICO as well */ -	ckd_state[CLOCK_CPU].mask |= 1; - -	gd->sm = get_device(DEVICE_SM); -	if (!gd->sm) -		panic("Unable to claim system manager device!\n"); - -	/* Disable any devices that haven't been explicitly claimed */ -	sm_writel(gd->sm, PM_PBB_MASK, ckd_state[CLOCK_PBB].mask); -	sm_writel(gd->sm, PM_PBA_MASK, ckd_state[CLOCK_PBA].mask); -	sm_writel(gd->sm, PM_HSB_MASK, ckd_state[CLOCK_HSB].mask); -	sm_writel(gd->sm, PM_CPU_MASK, ckd_state[CLOCK_CPU].mask);  #ifdef CONFIG_PLL -	/* Initialize the PLL */ -	main_clock = (CFG_OSC0_HZ / CFG_PLL0_DIV) * CFG_PLL0_MUL; - -	sm_writel(gd->sm, PM_PLL0, (SM_BF(PLLCOUNT, CFG_PLL0_SUPPRESS_CYCLES) -				    | SM_BF(PLLMUL, CFG_PLL0_MUL - 1) -				    | SM_BF(PLLDIV, CFG_PLL0_DIV - 1) -				    | SM_BF(PLLOPT, CFG_PLL0_OPT) -				    | SM_BF(PLLOSC, 0) -				    | SM_BIT(PLLEN))); - -	/* Wait for lock */ -	while (!(sm_readl(gd->sm, PM_ISR) & SM_BIT(LOCK0))) ; +#define MAIN_CLK_RATE ((CFG_OSC0_HZ / CFG_PLL0_DIV) * CFG_PLL0_MUL)  #else -	main_clock = CFG_OSC0_HZ; +#define MAIN_CLK_RATE (CFG_OSC0_HZ)  #endif -	/* Set up clocks for the CPU and all peripheral buses */ -	if (CFG_CLKDIV_CPU) { -		cksel |= SM_BIT(CPUDIV) | SM_BF(CPUSEL, CFG_CLKDIV_CPU - 1); -		ckd_state[CLOCK_CPU].freq = main_clock / (1 << CFG_CLKDIV_CPU); -	} else { -		ckd_state[CLOCK_CPU].freq = main_clock; -	} -	if (CFG_CLKDIV_HSB) { -		cksel |= SM_BIT(HSBDIV) | SM_BF(HSBSEL, CFG_CLKDIV_HSB - 1); -		ckd_state[CLOCK_HSB].freq = main_clock / (1 << CFG_CLKDIV_HSB); -	} else { -		ckd_state[CLOCK_HSB].freq = main_clock; -	} -	if (CFG_CLKDIV_PBA) { -		cksel |= SM_BIT(PBADIV) | SM_BF(PBASEL, CFG_CLKDIV_PBA - 1); -		ckd_state[CLOCK_PBA].freq = main_clock / (1 << CFG_CLKDIV_PBA); -	} else { -		ckd_state[CLOCK_PBA].freq = main_clock; -	} -	if (CFG_CLKDIV_PBB) { -		cksel |= SM_BIT(PBBDIV) | SM_BF(PBBSEL, CFG_CLKDIV_PBB - 1); -		ckd_state[CLOCK_PBB].freq = main_clock / (1 << CFG_CLKDIV_PBB); -	} else { -		ckd_state[CLOCK_PBB].freq = main_clock; -	} -	sm_writel(gd->sm, PM_CKSEL, cksel); - -	/* CFG_HZ currently depends on cpu_hz */ -	gd->cpu_hz = ckd_state[CLOCK_CPU].freq; +DECLARE_GLOBAL_DATA_PTR; -#ifdef CONFIG_PLL -	/* Use PLL0 as main clock */ -	sm_writel(gd->sm, PM_MCCTRL, SM_BIT(PLLSEL)); -#endif -}  #endif /* CFG_POWER_MANAGER */ diff --git a/cpu/at32ap/sm.h b/cpu/at32ap/sm.h index ce81ef0a4..6492c8e81 100644 --- a/cpu/at32ap/sm.h +++ b/cpu/at32ap/sm.h @@ -196,9 +196,9 @@  	 | SM_BF(name,value))  /* Register access macros */ -#define sm_readl(port,reg)				\ -	readl((port)->regs + SM_##reg) -#define sm_writel(port,reg,value)			\ -	writel((value), (port)->regs + SM_##reg) +#define sm_readl(reg)					\ +	readl((void *)SM_BASE + SM_##reg) +#define sm_writel(reg,value)				\ +	writel((value), (void *)SM_BASE + SM_##reg)  #endif /* __CPU_AT32AP_SM_H__ */ diff --git a/cpu/at32ap/start.S b/cpu/at32ap/start.S index 79ee33b1f..ab8c2b73d 100644 --- a/cpu/at32ap/start.S +++ b/cpu/at32ap/start.S @@ -70,32 +70,12 @@ _start:  2:	lddpc	sp, sp_init -	/* -	 * Relocate the data section and initialize .bss.  Everything -	 * is guaranteed to be at least doubleword aligned by the -	 * linker script. -	 */ -	lddpc	r12, .Ldata_vma -	lddpc	r11, .Ldata_lma -	lddpc	r10, .Ldata_end -	sub	r10, r12 -4:	ld.d	r8, r11++ -	sub	r10, 8 -	st.d	r12++, r8 -	brne	4b - -	mov	r8, 0 -	mov	r9, 0 -	lddpc	r10, .Lbss_end -	sub	r10, r12 -4:	sub	r10, 8 -	st.d	r12++, r8 -	brne	4b -  	/* Initialize the GOT pointer */  	lddpc	r6, got_init  3:	rsub	r6, pc -	ld.w	pc, r6[start_u_boot@got] + +	/* Let's go */ +	rjmp	board_init_f  	.align	2  	.type	sp_init,@object @@ -103,11 +83,82 @@ sp_init:  	.long	CFG_INIT_SP_ADDR  got_init:  	.long	3b - _GLOBAL_OFFSET_TABLE_ -.Ldata_lma: -	.long	__data_lma -.Ldata_vma: -	.long	_data -.Ldata_end: -	.long	_edata -.Lbss_end: -	.long	_end + +	/* +	 * void	relocate_code(new_sp, new_gd, monitor_addr) +	 * +	 * Relocate the u-boot image into RAM and continue from there. +	 * Does not return. +	 */ +	.global	relocate_code +	.type	relocate_code,@function +relocate_code: +	mov	sp, r12		/* use new stack */ +	mov	r12, r11	/* save new_gd */ +	mov	r11, r10	/* save destination address */ + +	/* copy .text section and flush the cache along the way */ +	lda.w	r8, _text +	lda.w	r9, _etext +	sub	lr, r10, r8	/* relocation offset */ + +1:	ldm	r8++, r0-r3 +	stm	r10, r0-r3 +	sub	r10, -16 +	ldm	r8++, r0-r3 +	stm	r10, r0-r3 +	sub	r10, -16 +	cp.w	r8, r9 +	cache	r10[-4], 0x0d	/* dcache clean/invalidate */ +	cache	r10[-4], 0x01	/* icache invalidate */ +	brlt	1b + +	/* flush write buffer */ +	sync	0 + +	/* copy data sections */ +	lda.w	r9, _edata +1:	ld.d	r0, r8++ +	st.d	r10++, r0 +	cp.w	r8, r9 +	brlt	1b + +	/* zero out .bss */ +	mov	r0, 0 +	mov	r1, 0 +	lda.w	r9, _end +	sub	r9, r8 +1:	st.d	r10++, r0 +	sub	r9, 8 +	brgt	1b + +	/* jump to RAM */ +	sub	r0, pc, . - in_ram +	add	pc, r0, lr + +	.align	2 +in_ram: +	/* find the new GOT and relocate it */ +	lddpc	r6, got_init_reloc +3:	rsub	r6, pc +	mov	r8, r6 +	lda.w	r9, _egot +	lda.w	r10, _got +	sub	r9, r10 +1:	ld.w	r0, r8[0] +	add	r0, lr +	st.w	r8++, r0 +	sub	r9, 4 +	brgt	1b + +	/* Move the exception handlers */ +	mfsr	r2, SYSREG_EVBA +	add	r2, lr +	mtsr	SYSREG_EVBA, r2 + +	/* Do the rest of the initialization sequence */ +	call	board_init_r + +	.align	2 +got_init_reloc: +	.long	3b - _GLOBAL_OFFSET_TABLE_  |