diff options
author | Andrew Victor <linux@maxim.org.za> | 2009-12-15 21:57:27 +0100 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-01-20 12:34:06 +0000 |
commit | 5e38efae9635436efa1e4952cf953085839a7121 (patch) | |
tree | 2e9d8a7b0476c72f8e876929416f940e78efece4 /arch | |
parent | 74d2e4f8d79ae0c4b6ec027958d5b18058662eea (diff) |
ARM: 5850/1: [AT91] AT572D940HF processor support
Add support for the Atmel AT572D940HF processor (DIOPSIS range).
This processor integrates an ARM926 core, a DSP and the SoC
peripherals usually found on an AT91 processor (USART, SSC, SPI, TWI,
CAN, etc)
Signed-off-by: Antonio R. Costa <costa.antonior@gmail.com>
Signed-off-by: Andrew Victor <linux@maxim.org.za>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-at91/Kconfig | 6 | ||||
-rw-r--r-- | arch/arm/mach-at91/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/mach-at91/at572d940hf.c | 377 | ||||
-rw-r--r-- | arch/arm/mach-at91/at572d940hf_devices.c | 970 | ||||
-rw-r--r-- | arch/arm/mach-at91/clock.c | 8 | ||||
-rw-r--r-- | arch/arm/mach-at91/clock.h | 2 | ||||
-rw-r--r-- | arch/arm/mach-at91/generic.h | 2 | ||||
-rw-r--r-- | arch/arm/mach-at91/include/mach/at572d940hf.h | 123 | ||||
-rw-r--r-- | arch/arm/mach-at91/include/mach/at572d940hf_matrix.h | 123 | ||||
-rw-r--r-- | arch/arm/mach-at91/include/mach/at91_pmc.h | 1 | ||||
-rw-r--r-- | arch/arm/mach-at91/include/mach/board.h | 5 | ||||
-rw-r--r-- | arch/arm/mach-at91/include/mach/cpu.h | 8 | ||||
-rw-r--r-- | arch/arm/mach-at91/include/mach/hardware.h | 2 | ||||
-rw-r--r-- | arch/arm/mach-at91/include/mach/timex.h | 5 |
14 files changed, 1628 insertions, 5 deletions
diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index 0b2ee953f16..c67fa3b7eeb 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -89,6 +89,12 @@ config ARCH_AT91CAP9 select GENERIC_CLOCKEVENTS select HAVE_FB_ATMEL +config ARCH_AT572D940HF + bool "AT572D940HF" + select CPU_ARM926T + select GENERIC_TIME + select GENERIC_CLOCKEVENTS + config ARCH_AT91X40 bool "AT91x40" diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile index 709fbad4a3e..8ddce96b6aa 100644 --- a/arch/arm/mach-at91/Makefile +++ b/arch/arm/mach-at91/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_ARCH_AT91SAM9RL) += at91sam9rl.o at91sam926x_time.o at91sam9rl_devi obj-$(CONFIG_ARCH_AT91SAM9G20) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o sam9_smc.o obj-$(CONFIG_ARCH_AT91SAM9G45) += at91sam9g45.o at91sam926x_time.o at91sam9g45_devices.o sam9_smc.o obj-$(CONFIG_ARCH_AT91CAP9) += at91cap9.o at91sam926x_time.o at91cap9_devices.o sam9_smc.o +obj-$(CONFIG_ARCH_AT572D940HF) += at572d940hf.o at91sam926x_time.o at572d940hf_devices.o sam9_smc.o obj-$(CONFIG_ARCH_AT91X40) += at91x40.o at91x40_time.o # AT91RM9200 board-specific support diff --git a/arch/arm/mach-at91/at572d940hf.c b/arch/arm/mach-at91/at572d940hf.c new file mode 100644 index 00000000000..a6b9c68c003 --- /dev/null +++ b/arch/arm/mach-at91/at572d940hf.c @@ -0,0 +1,377 @@ +/* + * arch/arm/mach-at91/at572d940hf.c + * + * Antonio R. Costa <costa.antonior@gmail.com> + * Copyright (C) 2008 Atmel + * + * Copyright (C) 2005 SAN People + * + * 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 <linux/module.h> + +#include <asm/mach/irq.h> +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <mach/at572d940hf.h> +#include <mach/at91_pmc.h> +#include <mach/at91_rstc.h> + +#include "generic.h" +#include "clock.h" + +static struct map_desc at572d940hf_io_desc[] __initdata = { + { + .virtual = AT91_VA_BASE_SYS, + .pfn = __phys_to_pfn(AT91_BASE_SYS), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = AT91_IO_VIRT_BASE - AT572D940HF_SRAM_SIZE, + .pfn = __phys_to_pfn(AT572D940HF_SRAM_BASE), + .length = AT572D940HF_SRAM_SIZE, + .type = MT_DEVICE, + }, +}; + +/* -------------------------------------------------------------------- + * Clocks + * -------------------------------------------------------------------- */ + +/* + * The peripheral clocks. + */ +static struct clk pioA_clk = { + .name = "pioA_clk", + .pmc_mask = 1 << AT572D940HF_ID_PIOA, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk pioB_clk = { + .name = "pioB_clk", + .pmc_mask = 1 << AT572D940HF_ID_PIOB, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk pioC_clk = { + .name = "pioC_clk", + .pmc_mask = 1 << AT572D940HF_ID_PIOC, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk macb_clk = { + .name = "macb_clk", + .pmc_mask = 1 << AT572D940HF_ID_EMAC, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk usart0_clk = { + .name = "usart0_clk", + .pmc_mask = 1 << AT572D940HF_ID_US0, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk usart1_clk = { + .name = "usart1_clk", + .pmc_mask = 1 << AT572D940HF_ID_US1, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk usart2_clk = { + .name = "usart2_clk", + .pmc_mask = 1 << AT572D940HF_ID_US2, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk mmc_clk = { + .name = "mci_clk", + .pmc_mask = 1 << AT572D940HF_ID_MCI, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk udc_clk = { + .name = "udc_clk", + .pmc_mask = 1 << AT572D940HF_ID_UDP, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk twi0_clk = { + .name = "twi0_clk", + .pmc_mask = 1 << AT572D940HF_ID_TWI0, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk spi0_clk = { + .name = "spi0_clk", + .pmc_mask = 1 << AT572D940HF_ID_SPI0, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk spi1_clk = { + .name = "spi1_clk", + .pmc_mask = 1 << AT572D940HF_ID_SPI1, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk ssc0_clk = { + .name = "ssc0_clk", + .pmc_mask = 1 << AT572D940HF_ID_SSC0, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk ssc1_clk = { + .name = "ssc1_clk", + .pmc_mask = 1 << AT572D940HF_ID_SSC1, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk ssc2_clk = { + .name = "ssc2_clk", + .pmc_mask = 1 << AT572D940HF_ID_SSC2, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk tc0_clk = { + .name = "tc0_clk", + .pmc_mask = 1 << AT572D940HF_ID_TC0, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk tc1_clk = { + .name = "tc1_clk", + .pmc_mask = 1 << AT572D940HF_ID_TC1, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk tc2_clk = { + .name = "tc2_clk", + .pmc_mask = 1 << AT572D940HF_ID_TC2, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk ohci_clk = { + .name = "ohci_clk", + .pmc_mask = 1 << AT572D940HF_ID_UHP, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk ssc3_clk = { + .name = "ssc3_clk", + .pmc_mask = 1 << AT572D940HF_ID_SSC3, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk twi1_clk = { + .name = "twi1_clk", + .pmc_mask = 1 << AT572D940HF_ID_TWI1, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk can0_clk = { + .name = "can0_clk", + .pmc_mask = 1 << AT572D940HF_ID_CAN0, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk can1_clk = { + .name = "can1_clk", + .pmc_mask = 1 << AT572D940HF_ID_CAN1, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk mAgicV_clk = { + .name = "mAgicV_clk", + .pmc_mask = 1 << AT572D940HF_ID_MSIRQ0, + .type = CLK_TYPE_PERIPHERAL, +}; + + +static struct clk *periph_clocks[] __initdata = { + &pioA_clk, + &pioB_clk, + &pioC_clk, + &macb_clk, + &usart0_clk, + &usart1_clk, + &usart2_clk, + &mmc_clk, + &udc_clk, + &twi0_clk, + &spi0_clk, + &spi1_clk, + &ssc0_clk, + &ssc1_clk, + &ssc2_clk, + &tc0_clk, + &tc1_clk, + &tc2_clk, + &ohci_clk, + &ssc3_clk, + &twi1_clk, + &can0_clk, + &can1_clk, + &mAgicV_clk, + /* irq0 .. irq2 */ +}; + +/* + * The five programmable clocks. + * You must configure pin multiplexing to bring these signals out. + */ +static struct clk pck0 = { + .name = "pck0", + .pmc_mask = AT91_PMC_PCK0, + .type = CLK_TYPE_PROGRAMMABLE, + .id = 0, +}; +static struct clk pck1 = { + .name = "pck1", + .pmc_mask = AT91_PMC_PCK1, + .type = CLK_TYPE_PROGRAMMABLE, + .id = 1, +}; +static struct clk pck2 = { + .name = "pck2", + .pmc_mask = AT91_PMC_PCK2, + .type = CLK_TYPE_PROGRAMMABLE, + .id = 2, +}; +static struct clk pck3 = { + .name = "pck3", + .pmc_mask = AT91_PMC_PCK3, + .type = CLK_TYPE_PROGRAMMABLE, + .id = 3, +}; + +static struct clk mAgicV_mem_clk = { + .name = "mAgicV_mem_clk", + .pmc_mask = AT91_PMC_PCK4, + .type = CLK_TYPE_PROGRAMMABLE, + .id = 4, +}; + +/* HClocks */ +static struct clk hck0 = { + .name = "hck0", + .pmc_mask = AT91_PMC_HCK0, + .type = CLK_TYPE_SYSTEM, + .id = 0, +}; +static struct clk hck1 = { + .name = "hck1", + .pmc_mask = AT91_PMC_HCK1, + .type = CLK_TYPE_SYSTEM, + .id = 1, +}; + +static void __init at572d940hf_register_clocks(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(periph_clocks); i++) + clk_register(periph_clocks[i]); + + clk_register(&pck0); + clk_register(&pck1); + clk_register(&pck2); + clk_register(&pck3); + clk_register(&mAgicV_mem_clk); + + clk_register(&hck0); + clk_register(&hck1); +} + +/* -------------------------------------------------------------------- + * GPIO + * -------------------------------------------------------------------- */ + +static struct at91_gpio_bank at572d940hf_gpio[] = { + { + .id = AT572D940HF_ID_PIOA, + .offset = AT91_PIOA, + .clock = &pioA_clk, + }, { + .id = AT572D940HF_ID_PIOB, + .offset = AT91_PIOB, + .clock = &pioB_clk, + }, { + .id = AT572D940HF_ID_PIOC, + .offset = AT91_PIOC, + .clock = &pioC_clk, + } +}; + +static void at572d940hf_reset(void) +{ + at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST); +} + + +/* -------------------------------------------------------------------- + * AT572D940HF processor initialization + * -------------------------------------------------------------------- */ + +void __init at572d940hf_initialize(unsigned long main_clock) +{ + /* Map peripherals */ + iotable_init(at572d940hf_io_desc, ARRAY_SIZE(at572d940hf_io_desc)); + + at91_arch_reset = at572d940hf_reset; + at91_extern_irq = (1 << AT572D940HF_ID_IRQ0) | (1 << AT572D940HF_ID_IRQ1) + | (1 << AT572D940HF_ID_IRQ2); + + /* Init clock subsystem */ + at91_clock_init(main_clock); + + /* Register the processor-specific clocks */ + at572d940hf_register_clocks(); + + /* Register GPIO subsystem */ + at91_gpio_init(at572d940hf_gpio, 3); +} + +/* -------------------------------------------------------------------- + * Interrupt initialization + * -------------------------------------------------------------------- */ + +/* + * The default interrupt priority levels (0 = lowest, 7 = highest). + */ +static unsigned int at572d940hf_default_irq_priority[NR_AIC_IRQS] __initdata = { + 7, /* Advanced Interrupt Controller */ + 7, /* System Peripherals */ + 0, /* Parallel IO Controller A */ + 0, /* Parallel IO Controller B */ + 0, /* Parallel IO Controller C */ + 3, /* Ethernet */ + 6, /* USART 0 */ + 6, /* USART 1 */ + 6, /* USART 2 */ + 0, /* Multimedia Card Interface */ + 4, /* USB Device Port */ + 0, /* Two-Wire Interface 0 */ + 6, /* Serial Peripheral Interface 0 */ + 6, /* Serial Peripheral Interface 1 */ + 5, /* Serial Synchronous Controller 0 */ + 5, /* Serial Synchronous Controller 1 */ + 5, /* Serial Synchronous Controller 2 */ + 0, /* Timer Counter 0 */ + 0, /* Timer Counter 1 */ + 0, /* Timer Counter 2 */ + 3, /* USB Host port */ + 3, /* Serial Synchronous Controller 3 */ + 0, /* Two-Wire Interface 1 */ + 0, /* CAN Controller 0 */ + 0, /* CAN Controller 1 */ + 0, /* mAgicV HALT line */ + 0, /* mAgicV SIRQ0 line */ + 0, /* mAgicV exception line */ + 0, /* mAgicV end of DMA line */ + 0, /* Advanced Interrupt Controller */ + 0, /* Advanced Interrupt Controller */ + 0, /* Advanced Interrupt Controller */ +}; + +void __init at572d940hf_init_interrupts(unsigned int priority[NR_AIC_IRQS]) +{ + if (!priority) + priority = at572d940hf_default_irq_priority; + + /* Initialize the AIC interrupt controller */ + at91_aic_init(priority); + + /* Enable GPIO interrupts */ + at91_gpio_irq_setup(); +} + diff --git a/arch/arm/mach-at91/at572d940hf_devices.c b/arch/arm/mach-at91/at572d940hf_devices.c new file mode 100644 index 00000000000..0fc20a24078 --- /dev/null +++ b/arch/arm/mach-at91/at572d940hf_devices.c @@ -0,0 +1,970 @@ +/* + * arch/arm/mach-at91/at572d940hf_devices.c + * + * Copyright (C) 2008 Atmel Antonio R. Costa <costa.antonior@gmail.com> + * Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.org> + * Copyright (C) 2005 David Brownell + * + * 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 <asm/mach/arch.h> +#include <asm/mach/map.h> + +#include <linux/dma-mapping.h> +#include <linux/platform_device.h> + +#include <mach/board.h> +#include <mach/gpio.h> +#include <mach/at572d940hf.h> +#include <mach/at572d940hf_matrix.h> +#include <mach/at91sam9_smc.h> + +#include "generic.h" +#include "sam9_smc.h" + + +/* -------------------------------------------------------------------- + * USB Host + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) +static u64 ohci_dmamask = DMA_BIT_MASK(32); +static struct at91_usbh_data usbh_data; + +static struct resource usbh_resources[] = { + [0] = { + .start = AT572D940HF_UHP_BASE, + .end = AT572D940HF_UHP_BASE + SZ_1M - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT572D940HF_ID_UHP, + .end = AT572D940HF_ID_UHP, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at572d940hf_usbh_device = { + .name = "at91_ohci", + .id = -1, + .dev = { + .dma_mask = &ohci_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = &usbh_data, + }, + .resource = usbh_resources, + .num_resources = ARRAY_SIZE(usbh_resources), +}; + +void __init at91_add_device_usbh(struct at91_usbh_data *data) +{ + if (!data) + return; + + usbh_data = *data; + platform_device_register(&at572d940hf_usbh_device); + +} +#else +void __init at91_add_device_usbh(struct at91_usbh_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + * USB Device (Gadget) + * -------------------------------------------------------------------- */ + +#ifdef CONFIG_USB_GADGET_AT91 +static struct at91_udc_data udc_data; + +static struct resource udc_resources[] = { + [0] = { + .start = AT572D940HF_BASE_UDP, + .end = AT572D940HF_BASE_UDP + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT572D940HF_ID_UDP, + .end = AT572D940HF_ID_UDP, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at572d940hf_udc_device = { + .name = "at91_udc", + .id = -1, + .dev = { + .platform_data = &udc_data, + }, + .resource = udc_resources, + .num_resources = ARRAY_SIZE(udc_resources), +}; + +void __init at91_add_device_udc(struct at91_udc_data *data) +{ + if (!data) + return; + + if (data->vbus_pin) { + at91_set_gpio_input(data->vbus_pin, 0); + at91_set_deglitch(data->vbus_pin, 1); + } + + /* Pullup pin is handled internally */ + + udc_data = *data; + platform_device_register(&at572d940hf_udc_device); +} +#else +void __init at91_add_device_udc(struct at91_udc_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + * Ethernet + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE) +static u64 eth_dmamask = DMA_BIT_MASK(32); +static struct at91_eth_data eth_data; + +static struct resource eth_resources[] = { + [0] = { + .start = AT572D940HF_BASE_EMAC, + .end = AT572D940HF_BASE_EMAC + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT572D940HF_ID_EMAC, + .end = AT572D940HF_ID_EMAC, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at572d940hf_eth_device = { + .name = "macb", + .id = -1, + .dev = { + .dma_mask = ð_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = ð_data, + }, + .resource = eth_resources, + .num_resources = ARRAY_SIZE(eth_resources), +}; + +void __init at91_add_device_eth(struct at91_eth_data *data) +{ + if (!data) + return; + + if (data->phy_irq_pin) { + at91_set_gpio_input(data->phy_irq_pin, 0); + at91_set_deglitch(data->phy_irq_pin, 1); + } + + /* Only RMII is supported */ + data->is_rmii = 1; + + /* Pins used for RMII */ + at91_set_A_periph(AT91_PIN_PA16, 0); /* ETXCK_EREFCK */ + at91_set_A_periph(AT91_PIN_PA17, 0); /* ERXDV */ + at91_set_A_periph(AT91_PIN_PA18, 0); /* ERX0 */ + at91_set_A_periph(AT91_PIN_PA19, 0); /* ERX1 */ + at91_set_A_periph(AT91_PIN_PA20, 0); /* ERXER */ + at91_set_A_periph(AT91_PIN_PA23, 0); /* ETXEN */ + at91_set_A_periph(AT91_PIN_PA21, 0); /* ETX0 */ + at91_set_A_periph(AT91_PIN_PA22, 0); /* ETX1 */ + at91_set_A_periph(AT91_PIN_PA13, 0); /* EMDIO */ + at91_set_A_periph(AT91_PIN_PA14, 0); /* EMDC */ + + eth_data = *data; + platform_device_register(&at572d940hf_eth_device); +} +#else +void __init at91_add_device_eth(struct at91_eth_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + * MMC / SD + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE) +static u64 mmc_dmamask = DMA_BIT_MASK(32); +static struct at91_mmc_data mmc_data; + +static struct resource mmc_resources[] = { + [0] = { + .start = AT572D940HF_BASE_MCI, + .end = AT572D940HF_BASE_MCI + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT572D940HF_ID_MCI, + .end = AT572D940HF_ID_MCI, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at572d940hf_mmc_device = { + .name = "at91_mci", + .id = -1, + .dev = { + .dma_mask = &mmc_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = &mmc_data, + }, + .resource = mmc_resources, + .num_resources = ARRAY_SIZE(mmc_resources), +}; + +void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) +{ + if (!data) + return; + + /* input/irq */ + if (data->det_pin) { + at91_set_gpio_input(data->det_pin, 1); + at91_set_deglitch(data->det_pin, 1); + } + if (data->wp_pin) + at91_set_gpio_input(data->wp_pin, 1); + if (data->vcc_pin) + at91_set_gpio_output(data->vcc_pin, 0); + + /* CLK */ + at91_set_A_periph(AT91_PIN_PC22, 0); + + /* CMD */ + at91_set_A_periph(AT91_PIN_PC23, 1); + + /* DAT0, maybe DAT1..DAT3 */ + at91_set_A_periph(AT91_PIN_PC24, 1); + if (data->wire4) { + at91_set_A_periph(AT91_PIN_PC25, 1); + at91_set_A_periph(AT91_PIN_PC26, 1); + at91_set_A_periph(AT91_PIN_PC27, 1); + } + + mmc_data = *data; + platform_device_register(&at572d940hf_mmc_device); +} +#else +void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + * NAND / SmartMedia + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_MTD_NAND_ATMEL) || defined(CONFIG_MTD_NAND_ATMEL_MODULE) +static struct atmel_nand_data nand_data; + +#define NAND_BASE AT91_CHIPSELECT_3 + +static struct resource nand_resources[] = { + { + .start = NAND_BASE, + .end = NAND_BASE + SZ_256M - 1, + .flags = IORESOURCE_MEM, + } +}; + +static struct platform_device at572d940hf_nand_device = { + .name = "atmel_nand", + .id = -1, + .dev = { + .platform_data = &nand_data, + }, + .resource = nand_resources, + .num_resources = ARRAY_SIZE(nand_resources), +}; + +void __init at91_add_device_nand(struct atmel_nand_data *data) +{ + unsigned long csa; + + if (!data) + return; + + csa = at91_sys_read(AT91_MATRIX_EBICSA); + at91_sys_write(AT91_MATRIX_EBICSA, csa | AT91_MATRIX_CS3A_SMC_SMARTMEDIA); + + /* enable pin */ + if (data->enable_pin) + at91_set_gpio_output(data->enable_pin, 1); + + /* ready/busy pin */ + if (data->rdy_pin) + at91_set_gpio_input(data->rdy_pin, 1); + + /* card detect pin */ + if (data->det_pin) + at91_set_gpio_input(data->det_pin, 1); + + at91_set_A_periph(AT91_PIN_PB28, 0); /* A[22] */ + at91_set_B_periph(AT91_PIN_PA28, 0); /* NANDOE */ + at91_set_B_periph(AT91_PIN_PA29, 0); /* NANDWE */ + + nand_data = *data; + platform_device_register(&at572d940hf_nand_device); +} + +#else +void __init at91_add_device_nand(struct atmel_nand_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + * TWI (i2c) + * -------------------------------------------------------------------- */ + +/* + * Prefer the GPIO code since the TWI controller isn't robust + * (gets overruns and underruns under load) and can only issue + * repeated STARTs in one scenario (the driver doesn't yet handle them). + */ + +#if defined(CONFIG_I2C_GPIO) || defined(CONFIG_I2C_GPIO_MODULE) + +static struct i2c_gpio_platform_data pdata = { + .sda_pin = AT91_PIN_PC7, + .sda_is_open_drain = 1, + .scl_pin = AT91_PIN_PC8, + .scl_is_open_drain = 1, + .udelay = 2, /* ~100 kHz */ +}; + +static struct platform_device at572d940hf_twi_device { + .name = "i2c-gpio", + .id = -1, + .dev.platform_data = &pdata, +}; + +void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices) +{ + at91_set_GPIO_periph(AT91_PIN_PC7, 1); /* TWD (SDA) */ + at91_set_multi_drive(AT91_PIN_PC7, 1); + + at91_set_GPIO_periph(AT91_PIN_PA8, 1); /* TWCK (SCL) */ + at91_set_multi_drive(AT91_PIN_PC8, 1); + + i2c_register_board_info(0, devices, nr_devices); + platform_device_register(&at572d940hf_twi_device); +} + +#elif defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE) + +static struct resource twi0_resources[] = { + [0] = { + .start = AT572D940HF_BASE_TWI0, + .end = AT572D940HF_BASE_TWI0 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT572D940HF_ID_TWI0, + .end = AT572D940HF_ID_TWI0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at572d940hf_twi0_device = { + .name = "at91_i2c", + .id = 0, + .resource = twi0_resources, + .num_resources = ARRAY_SIZE(twi0_resources), +}; + +static struct resource twi1_resources[] = { + [0] = { + .start = AT572D940HF_BASE_TWI1, + .end = AT572D940HF_BASE_TWI1 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT572D940HF_ID_TWI1, + .end = AT572D940HF_ID_TWI1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at572d940hf_twi1_device = { + .name = "at91_i2c", + .id = 1, + .resource = twi1_resources, + .num_resources = ARRAY_SIZE(twi1_resources), +}; + +void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices) +{ + /* pins used for TWI0 interface */ + at91_set_A_periph(AT91_PIN_PC7, 0); /* TWD */ + at91_set_multi_drive(AT91_PIN_PC7, 1); + + at91_set_A_periph(AT91_PIN_PC8, 0); /* TWCK */ + at91_set_multi_drive(AT91_PIN_PC8, 1); + + /* pins used for TWI1 interface */ + at91_set_A_periph(AT91_PIN_PC20, 0); /* TWD */ + at91_set_multi_drive(AT91_PIN_PC20, 1); + + at91_set_A_periph(AT91_PIN_PC21, 0); /* TWCK */ + at91_set_multi_drive(AT91_PIN_PC21, 1); + + i2c_register_board_info(0, devices, nr_devices); + platform_device_register(&at572d940hf_twi0_device); + platform_device_register(&at572d940hf_twi1_device); +} +#else +void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices) {} +#endif + + +/* -------------------------------------------------------------------- + * SPI + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE) +static u64 spi_dmamask = DMA_BIT_MASK(32); + +static struct resource spi0_resources[] = { + [0] = { + .start = AT572D940HF_BASE_SPI0, + .end = AT572D940HF_BASE_SPI0 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT572D940HF_ID_SPI0, + .end = AT572D940HF_ID_SPI0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at572d940hf_spi0_device = { + .name = "atmel_spi", + .id = 0, + .dev = { + .dma_mask = &spi_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + .resource = spi0_resources, + .num_resources = ARRAY_SIZE(spi0_resources), +}; + +static const unsigned spi0_standard_cs[4] = { AT91_PIN_PA3, AT91_PIN_PA4, AT91_PIN_PA5, AT91_PIN_PA6 }; + +static struct resource spi1_resources[] = { + [0] = { + .start = AT572D940HF_BASE_SPI1, + .end = AT572D940HF_BASE_SPI1 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT572D940HF_ID_SPI1, + .end = AT572D940HF_ID_SPI1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at572d940hf_spi1_device = { + .name = "atmel_spi", + .id = 1, + .dev = { + .dma_mask = &spi_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + .resource = spi1_resources, + .num_resources = ARRAY_SIZE(spi1_resources), +}; + +static const unsigned spi1_standard_cs[4] = { AT91_PIN_PC3, AT91_PIN_PC4, AT91_PIN_PC5, AT91_PIN_PC6 }; + +void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) +{ + int i; + unsigned long cs_pin; + short enable_spi0 = 0; + short enable_spi1 = 0; + + /* Choose SPI chip-selects */ + for (i = 0; i < nr_devices; i++) { + if (devices[i].controller_data) + cs_pin = (unsigned long) devices[i].controller_data; + else if (devices[i].bus_num == 0) + cs_pin = spi0_standard_cs[devices[i].chip_select]; + else + cs_pin = spi1_standard_cs[devices[i].chip_select]; + + if (devices[i].bus_num == 0) + enable_spi0 = 1; + else + enable_spi1 = 1; + + /* enable chip-select pin */ + at91_set_gpio_output(cs_pin, 1); + + /* pass chip-select pin to driver */ + devices[i].controller_data = (void *) cs_pin; + } + + spi_register_board_info(devices, nr_devices); + + /* Configure SPI bus(es) */ + if (enable_spi0) { + at91_set_A_periph(AT91_PIN_PA0, 0); /* SPI0_MISO */ + at91_set_A_periph(AT91_PIN_PA1, 0); /* SPI0_MOSI */ + at91_set_A_periph(AT91_PIN_PA2, 0); /* SPI0_SPCK */ + + at91_clock_associate("spi0_clk", &at572d940hf_spi0_device.dev, "spi_clk"); + platform_device_register(&at572d940hf_spi0_device); + } + if (enable_spi1) { + at91_set_A_periph(AT91_PIN_PC0, 0); /* SPI1_MISO */ + at91_set_A_periph(AT91_PIN_PC1, 0); /* SPI1_MOSI */ + at91_set_A_periph(AT91_PIN_PC2, 0); /* SPI1_SPCK */ + + at91_clock_associate("spi1_clk", &at572d940hf_spi1_device.dev, "spi_clk"); + platform_device_register(&at572d940hf_spi1_device); + } +} +#else +void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {} +#endif + + +/* -------------------------------------------------------------------- + * Timer/Counter blocks + * -------------------------------------------------------------------- */ + +#ifdef CONFIG_ATMEL_TCLIB + +static struct resource tcb_resources[] = { + [0] = { + .start = AT572D940HF_BASE_TCB, + .end = AT572D940HF_BASE_TCB + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT572D940HF_ID_TC0, + .end = AT572D940HF_ID_TC0, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = AT572D940HF_ID_TC1, + .end = AT572D940HF_ID_TC1, + .flags = IORESOURCE_IRQ, + }, + [3] = { + .start = AT572D940HF_ID_TC2, + .end = AT572D940HF_ID_TC2, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at572d940hf_tcb_device = { + .name = "atmel_tcb", + .id = 0, + .resource = tcb_resources, + .num_resources = ARRAY_SIZE(tcb_resources), +}; + +static void __init at91_add_device_tc(void) +{ + /* this chip has a separate clock and irq for each TC channel */ + at91_clock_associate("tc0_clk", &at572d940hf_tcb_device.dev, "t0_clk"); + at91_clock_associate("tc1_clk", &at572d940hf_tcb_device.dev, "t1_clk"); + at91_clock_associate("tc2_clk", &at572d940hf_tcb_device.dev, "t2_clk"); + platform_device_register(&at572d940hf_tcb_device); +} +#else +static void __init at91_add_device_tc(void) { } +#endif + + +/* -------------------------------------------------------------------- + * RTT + * -------------------------------------------------------------------- */ + +static struct resource rtt_resources[] = { + { + .start = AT91_BASE_SYS + AT91_RTT, + .end = AT91_BASE_SYS + AT91_RTT + SZ_16 - 1, + .flags = IORESOURCE_MEM, + } +}; + +static struct platform_device at572d940hf_rtt_device = { + .name = "at91_rtt", + .id = 0, + .resource = rtt_resources, + .num_resources = ARRAY_SIZE(rtt_resources), +}; + +static void __init at91_add_device_rtt(void) +{ + platform_device_register(&at572d940hf_rtt_device); +} + + +/* -------------------------------------------------------------------- + * Watchdog + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_AT91SAM9X_WATCHDOG) || defined(CONFIG_AT91SAM9X_WATCHDOG_MODULE) +static struct platform_device at572d940hf_wdt_device = { + .name = "at91_wdt", + .id = -1, + .num_resources = 0, +}; + +static void __init at91_add_device_watchdog(void) +{ + platform_device_register(&at572d940hf_wdt_device); +} +#else +static void __init at91_add_device_watchdog(void) {} +#endif + + +/* -------------------------------------------------------------------- + * UART + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_SERIAL_ATMEL) +static struct resource dbgu_resources[] = { + [0] = { + .start = AT91_VA_BASE_SYS + AT91_DBGU, + .end = AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91_ID_SYS, + .end = AT91_ID_SYS, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data dbgu_data = { + .use_dma_tx = 0, + .use_dma_rx = 0, /* DBGU not capable of receive DMA */ + .regs = (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU), +}; + +static u64 dbgu_dmamask = DMA_BIT_MASK(32); + +static struct platform_device at572d940hf_dbgu_device = { + .name = "atmel_usart", + .id = 0, + .dev = { + .dma_mask = &dbgu_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = &dbgu_data, + }, + .resource = dbgu_resources, + .num_resources = ARRAY_SIZE(dbgu_resources), +}; + +static inline void configure_dbgu_pins(void) +{ + at91_set_A_periph(AT91_PIN_PC31, 1); /* DTXD */ + at91_set_A_periph(AT91_PIN_PC30, 0); /* DRXD */ +} + +static struct resource uart0_resources[] = { + [0] = { + .start = AT572D940HF_BASE_US0, + .end = AT572D940HF_BASE_US0 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT572D940HF_ID_US0, + .end = AT572D940HF_ID_US0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data uart0_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static u64 uart0_dmamask = DMA_BIT_MASK(32); + +static struct platform_device at572d940hf_uart0_device = { + .name = "atmel_usart", + .id = 1, + .dev = { + .dma_mask = &uart0_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = &uart0_data, + }, + .resource = uart0_resources, + .num_resources = ARRAY_SIZE(uart0_resources), +}; + +static inline void configure_usart0_pins(unsigned pins) +{ + at91_set_A_periph(AT91_PIN_PA8, 1); /* TXD0 */ + at91_set_A_periph(AT91_PIN_PA7, 0); /* RXD0 */ + + if (pins & ATMEL_UART_RTS) + at91_set_A_periph(AT91_PIN_PA10, 0); /* RTS0 */ + if (pins & ATMEL_UART_CTS) + at91_set_A_periph(AT91_PIN_PA9, 0); /* CTS0 */ +} + +static struct resource uart1_resources[] = { + [0] = { + .start = AT572D940HF_BASE_US1, + .end = AT572D940HF_BASE_US1 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT572D940HF_ID_US1, + .end = AT572D940HF_ID_US1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data uart1_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static u64 uart1_dmamask = DMA_BIT_MASK(32); + +static struct platform_device at572d940hf_uart1_device = { + .name = "atmel_usart", + .id = 2, + .dev = { + .dma_mask = &uart1_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = &uart1_data, + }, + .resource = uart1_resources, + .num_resources = ARRAY_SIZE(uart1_resources), +}; + +static inline void configure_usart1_pins(unsigned pins) +{ + at91_set_A_periph(AT91_PIN_PC10, 1); /* TXD1 */ + at91_set_A_periph(AT91_PIN_PC9 , 0); /* RXD1 */ + + if (pins & ATMEL_UART_RTS) + at91_set_A_periph(AT91_PIN_PC12, 0); /* RTS1 */ + if (pins & ATMEL_UART_CTS) + at91_set_A_periph(AT91_PIN_PC11, 0); /* CTS1 */ +} + +static struct resource uart2_resources[] = { + [0] = { + .start = AT572D940HF_BASE_US2, + .end = AT572D940HF_BASE_US2 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT572D940HF_ID_US2, + .end = AT572D940HF_ID_US2, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data uart2_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static u64 uart2_dmamask = DMA_BIT_MASK(32); + +static struct platform_device at572d940hf_uart2_device = { + .name = "atmel_usart", + .id = 3, + .dev = { + .dma_mask = &uart2_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = &uart2_data, + }, + .resource = uart2_resources, + .num_resources = ARRAY_SIZE(uart2_resources), +}; + +static inline void configure_usart2_pins(unsigned pins) +{ + at91_set_A_periph(AT91_PIN_PC15, 1); /* TXD2 */ + at91_set_A_periph(AT91_PIN_PC14, 0); /* RXD2 */ + + if (pins & ATMEL_UART_RTS) + at91_set_A_periph(AT91_PIN_PC17, 0); /* RTS2 */ + if (pins & ATMEL_UART_CTS) + at91_set_A_periph(AT91_PIN_PC16, 0); /* CTS2 */ +} + +static struct platform_device *__initdata at91_uarts[ATMEL_MAX_UART]; /* the UARTs to use */ +struct platform_device *atmel_default_console_device; /* the serial console device */ + +void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) +{ + struct platform_device *pdev; + + switch (id) { + case 0: /* DBGU */ + pdev = &at572d940hf_dbgu_device; + configure_dbgu_pins(); + at91_clock_associate("mck", &pdev->dev, "usart"); + break; + case AT572D940HF_ID_US0: + pdev = &at572d940hf_uart0_device; + configure_usart0_pins(pins); + at91_clock_associate("usart0_clk", &pdev->dev, "usart"); + break; + case AT572D940HF_ID_US1: + pdev = &at572d940hf_uart1_device; + configure_usart1_pins(pins); + at91_clock_associate("usart1_clk", &pdev->dev, "usart"); + break; + case AT572D940HF_ID_US2: + pdev = &at572d940hf_uart2_device; + configure_usart2_pins(pins); + at91_clock_associate("usart2_clk", &pdev->dev, "usart"); + break; + default: + return; + } + pdev->id = portnr; /* update to mapped ID */ + + if (portnr < ATMEL_MAX_UART) + at91_uarts[portnr] = pdev; +} + +void __init at91_set_serial_console(unsigned portnr) +{ + if (portnr < ATMEL_MAX_UART) + atmel_default_console_device = at91_uarts[portnr]; +} + +void __init at91_add_device_serial(void) +{ + int i; + + for (i = 0; i < ATMEL_MAX_UART; i++) { + if (at91_uarts[i]) + platform_device_register(at91_uarts[i]); + } + + if (!atmel_default_console_device) + printk(KERN_INFO "AT91: No default serial console defined.\n"); +} + +#else +void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {} +void __init at91_set_serial_console(unsigned portnr) {} +void __init at91_add_device_serial(void) {} +#endif + + +/* -------------------------------------------------------------------- + * mAgic + * -------------------------------------------------------------------- */ + +#ifdef CONFIG_MAGICV +static struct resource mAgic_resources[] = { + { + .start = AT91_MAGIC_PM_BASE, + .end = AT91_MAGIC_PM_BASE + AT91_MAGIC_PM_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = AT91_MAGIC_DM_I_BASE, + .end = AT91_MAGIC_DM_I_BASE + AT91_MAGIC_DM_I_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = AT91_MAGIC_DM_F_BASE, + .end = AT91_MAGIC_DM_F_BASE + AT91_MAGIC_DM_F_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = AT91_MAGIC_DM_DB_BASE, + .end = AT91_MAGIC_DM_DB_BASE + AT91_MAGIC_DM_DB_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = AT91_MAGIC_REGS_BASE, + .end = AT91_MAGIC_REGS_BASE + AT91_MAGIC_REGS_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = AT91_MAGIC_EXTPAGE_BASE, + .end = AT91_MAGIC_EXTPAGE_BASE + AT91_MAGIC_EXTPAGE_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = AT572D940HF_ID_MSIRQ0, + .end = AT572D940HF_ID_MSIRQ0, + .flags = IORESOURCE_IRQ, + }, + { + .start = AT572D940HF_ID_MHALT, + .end = AT572D940HF_ID_MHALT, + .flags = IORESOURCE_IRQ, + }, + { + .start = AT572D940HF_ID_MEXC, + .end = AT572D940HF_ID_MEXC, + .flags = IORESOURCE_IRQ, + }, + { + .start = AT572D940HF_ID_MEDMA, + .end = AT572D940HF_ID_MEDMA, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device mAgic_device = { + .name = "mAgic", + .id = -1, + .num_resources = ARRAY_SIZE(mAgic_resources), + .resource = mAgic_resources, +}; + +void __init at91_add_device_mAgic(void) +{ + platform_device_register(&mAgic_device); +} +#else +void __init at91_add_device_mAgic(void) {} +#endif + + +/* -------------------------------------------------------------------- */ + +/* + * These devices are always present and don't need any board-specific + * setup. + */ +static int __init at91_add_standard_devices(void) +{ + at91_add_device_rtt(); + at91_add_device_watchdog(); + at91_add_device_tc(); + return 0; +} + +arch_initcall(at91_add_standard_devices); diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c index c042dcf4725..7f7da439341 100644 --- a/arch/arm/mach-at91/clock.c +++ b/arch/arm/mach-at91/clock.c @@ -29,6 +29,7 @@ #include <mach/cpu.h> #include "clock.h" +#include "generic.h" /* @@ -628,7 +629,7 @@ static void __init at91_pllb_usbfs_clock_init(unsigned long main_clock) at91_sys_write(AT91_PMC_SCER, AT91RM9200_PMC_MCKUDP); } else if (cpu_is_at91sam9260() || cpu_is_at91sam9261() || cpu_is_at91sam9263() || cpu_is_at91sam9g20() || - cpu_is_at91sam9g10()) { + cpu_is_at91sam9g10() || cpu_is_at572d940hf()) { uhpck.pmc_mask = AT91SAM926x_PMC_UHP; udpck.pmc_mask = AT91SAM926x_PMC_UDP; } else if (cpu_is_at91cap9()) { @@ -711,12 +712,13 @@ int __init at91_clock_init(unsigned long main_clock) /* * USB HS clock init */ - if (cpu_has_utmi()) + if (cpu_has_utmi()) { /* * multiplier is hard-wired to 40 * (obtain the USB High Speed 480 MHz when input is 12 MHz) */ utmi_clk.rate_hz = 40 * utmi_clk.parent->rate_hz; + } /* * USB FS clock init @@ -746,7 +748,7 @@ int __init at91_clock_init(unsigned long main_clock) mck.rate_hz = (mckr & AT91_PMC_MDIV) == AT91SAM9_PMC_MDIV_3 ? freq / 3 : freq / (1 << ((mckr & AT91_PMC_MDIV) >> 8)); /* mdiv */ } else { - mck.rate_hz = freq / (1 << ((mckr & AT91_PMC_MDIV) >> 8)); /* mdiv */ + mck.rate_hz = freq / (1 << ((mckr & AT91_PMC_MDIV) >> 8)); /* mdiv */ } /* Register the PMC's standard clocks */ diff --git a/arch/arm/mach-at91/clock.h b/arch/arm/mach-at91/clock.h index 1ba3b95ff35..6cf4b78e175 100644 --- a/arch/arm/mach-at91/clock.h +++ b/arch/arm/mach-at91/clock.h @@ -22,7 +22,7 @@ struct clk { struct clk *parent; u32 pmc_mask; void (*mode)(struct clk *, int); - unsigned id:2; /* PCK0..3, or 32k/main/a/b */ + unsigned id:3; /* PCK0..4, or 32k/main/a/b */ unsigned type; /* clock type */ u16 users; }; diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h index 88e413b3848..65c3dc5ba0d 100644 --- a/arch/arm/mach-at91/generic.h +++ b/arch/arm/mach-at91/generic.h @@ -17,6 +17,7 @@ extern void __init at91sam9rl_initialize(unsigned long main_clock); extern void __init at91sam9g45_initialize(unsigned long main_clock); extern void __init at91x40_initialize(unsigned long main_clock); extern void __init at91cap9_initialize(unsigned long main_clock); +extern void __init at572d940hf_initialize(unsigned long main_clock); /* Interrupts */ extern void __init at91rm9200_init_interrupts(unsigned int priority[]); @@ -27,6 +28,7 @@ extern void __init at91sam9rl_init_interrupts(unsigned int priority[]); extern void __init at91sam9g45_init_interrupts(unsigned int priority[]); extern void __init at91x40_init_interrupts(unsigned int priority[]); extern void __init at91cap9_init_interrupts(unsigned int priority[]); +extern void __init at572d940hf_init_interrupts(unsigned int priority[]); extern void __init at91_aic_init(unsigned int priority[]); /* Timer */ diff --git a/arch/arm/mach-at91/include/mach/at572d940hf.h b/arch/arm/mach-at91/include/mach/at572d940hf.h new file mode 100644 index 00000000000..2d9b0af9c4d --- /dev/null +++ b/arch/arm/mach-at91/include/mach/at572d940hf.h @@ -0,0 +1,123 @@ +/* + * include/mach/at572d940hf.h + * + * Antonio R. Costa <costa.antonior@gmail.com> + * Copyright (C) 2008 Atmel + * + * 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 AT572D940HF_H +#define AT572D940HF_H + +/* + * Peripheral identifiers/interrupts. + */ +#define AT91_ID_FIQ 0 /* Advanced Interrupt Controller (FIQ) */ +#define AT91_ID_SYS 1 /* System Peripherals */ +#define AT572D940HF_ID_PIOA 2 /* Parallel IO Controller A */ +#define AT572D940HF_ID_PIOB 3 /* Parallel IO Controller B */ +#define AT572D940HF_ID_PIOC 4 /* Parallel IO Controller C */ +#define AT572D940HF_ID_EMAC 5 /* MACB ethernet controller */ +#define AT572D940HF_ID_US0 6 /* USART 0 */ +#define AT572D940HF_ID_US1 7 /* USART 1 */ +#define AT572D940HF_ID_US2 8 /* USART 2 */ +#define AT572D940HF_ID_MCI 9 /* Multimedia Card Interface */ +#define AT572D940HF_ID_UDP 10 /* USB Device Port */ +#define AT572D940HF_ID_TWI0 11 /* Two-Wire Interface 0 */ +#define AT572D940HF_ID_SPI0 12 /* Serial Peripheral Interface 0 */ +#define AT572D940HF_ID_SPI1 13 /* Serial Peripheral Interface 1 */ +#define AT572D940HF_ID_SSC0 14 /* Serial Synchronous Controller 0 */ +#define AT572D940HF_ID_SSC1 15 /* Serial Synchronous Controller 1 */ +#define AT572D940HF_ID_SSC2 16 /* Serial Synchronous Controller 2 */ +#define AT572D940HF_ID_TC0 17 /* Timer Counter 0 */ +#define AT572D940HF_ID_TC1 18 /* Timer Counter 1 */ +#define AT572D940HF_ID_TC2 19 /* Timer Counter 2 */ +#define AT572D940HF_ID_UHP 20 /* USB Host port */ +#define AT572D940HF_ID_SSC3 21 /* Serial Synchronous Controller 3 */ +#define AT572D940HF_ID_TWI1 22 /* Two-Wire Interface 1 */ +#define AT572D940HF_ID_CAN0 23 /* CAN Controller 0 */ +#define AT572D940HF_ID_CAN1 24 /* CAN Controller 1 */ +#define AT572D940HF_ID_MHALT 25 /* mAgicV HALT line */ +#define AT572D940HF_ID_MSIRQ0 26 /* mAgicV SIRQ0 line */ +#define AT572D940HF_ID_MEXC 27 /* mAgicV exception line */ +#define AT572D940HF_ID_MEDMA 28 /* mAgicV end of DMA line */ +#define AT572D940HF_ID_IRQ0 29 /* External Interrupt Source (IRQ0) */ +#define AT572D940HF_ID_IRQ1 30 /* External Interrupt Source (IRQ1) */ +#define AT572D940HF_ID_IRQ2 31 /* External Interrupt Source (IRQ2) */ + + +/* + * User Peripheral physical base addresses. + */ +#define AT572D940HF_BASE_TCB 0xfffa0000 +#define AT572D940HF_BASE_TC0 0xfffa0000 +#define AT572D940HF_BASE_TC1 0xfffa0040 +#define AT572D940HF_BASE_TC2 0xfffa0080 +#define AT572D940HF_BASE_UDP 0xfffa4000 +#define AT572D940HF_BASE_MCI 0xfffa8000 +#define AT572D940HF_BASE_TWI0 0xfffac000 +#define AT572D940HF_BASE_US0 0xfffb0000 +#define AT572D940HF_BASE_US1 0xfffb4000 +#define AT572D940HF_BASE_US2 0xfffb8000 +#define AT572D940HF_BASE_SSC0 0xfffbc000 +#define AT572D940HF_BASE_SSC1 0xfffc0000 +#define AT572D940HF_BASE_SSC2 0xfffc4000 +#define AT572D940HF_BASE_SPI0 0xfffc8000 +#define AT572D940HF_BASE_SPI1 0xfffcc000 +#define AT572D940HF_BASE_SSC3 0xfffd0000 +#define AT572D940HF_BASE_TWI1 0xfffd4000 +#define AT572D940HF_BASE_EMAC 0xfffd8000 +#define AT572D940HF_BASE_CAN0 0xfffdc000 +#define AT572D940HF_BASE_CAN1 0xfffe0000 +#define AT91_BASE_SYS 0xffffea00 + + +/* + * System Peripherals (offset from AT91_BASE_SYS) + */ +#define AT91_SDRAMC (0xffffea00 - AT91_BASE_SYS) +#define AT91_SMC (0xffffec00 - AT91_BASE_SYS) +#define AT91_MATRIX (0xffffee00 - AT91_BASE_SYS) +#define AT91_AIC (0xfffff000 - AT91_BASE_SYS) +#define AT91_DBGU (0xfffff200 - AT91_BASE_SYS) +#define AT91_PIOA (0xfffff400 - AT91_BASE_SYS) +#define AT91_PIOB (0xfffff600 - AT91_BASE_SYS) +#define AT91_PIOC (0xfffff800 - AT91_BASE_SYS) +#define AT91_PMC (0xfffffc00 - AT91_BASE_SYS) +#define AT91_RSTC (0xfffffd00 - AT91_BASE_SYS) +#define AT91_RTT (0xfffffd20 - AT91_BASE_SYS) +#define AT91_PIT (0xfffffd30 - AT91_BASE_SYS) +#define AT91_WDT (0xfffffd40 - AT91_BASE_SYS) + +#define AT91_USART0 AT572D940HF_ID_US0 +#define AT91_USART1 AT572D940HF_ID_US1 +#define AT91_USART2 AT572D940HF_ID_US2 + + +/* + * Internal Memory. + */ +#define AT572D940HF_SRAM_BASE 0x00300000 /* Internal SRAM base address */ +#define AT572D940HF_SRAM_SIZE (48 * SZ_1K) /* Internal SRAM size (48Kb) */ + +#define AT572D940HF_ROM_BASE 0x00400000 /* Internal ROM base address */ +#define AT572D940HF_ROM_SIZE SZ_32K /* Internal ROM size (32Kb) */ + +#define AT572D940HF_UHP_BASE 0x00500000 /* USB Host controller */ + + +#endif diff --git a/arch/arm/mach-at91/include/mach/at572d940hf_matrix.h b/arch/arm/mach-at91/include/mach/at572d940hf_matrix.h new file mode 100644 index 00000000000..b6751df0948 --- /dev/null +++ b/arch/arm/mach-at91/include/mach/at572d940hf_matrix.h @@ -0,0 +1,123 @@ +/* + * include/mach//at572d940hf_matrix.h + * + * Antonio R. Costa <costa.antonior@gmail.com> + * Copyright (C) 2008 Atmel + * + * Copyright (C) 2005 SAN People + * + * 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 AT572D940HF_MATRIX_H +#define AT572D940HF_MATRIX_H + +#define AT91_MATRIX_MCFG0 (AT91_MATRIX + 0x00) /* Master Configuration Register 0 */ +#define AT91_MATRIX_MCFG1 (AT91_MATRIX + 0x04) /* Master Configuration Register 1 */ +#define AT91_MATRIX_MCFG2 (AT91_MATRIX + 0x08) /* Master Configuration Register 2 */ +#define AT91_MATRIX_MCFG3 (AT91_MATRIX + 0x0C) /* Master Configuration Register 3 */ +#define AT91_MATRIX_MCFG4 (AT91_MATRIX + 0x10) /* Master Configuration Register 4 */ +#define AT91_MATRIX_MCFG5 (AT91_MATRIX + 0x14) /* Master Configuration Register 5 */ + +#define AT91_MATRIX_ULBT (7 << 0) /* Undefined Length Burst Type */ +#define AT91_MATRIX_ULBT_INFINITE (0 << 0) +#define AT91_MATRIX_ULBT_SINGLE (1 << 0) +#define AT91_MATRIX_ULBT_FOUR (2 << 0) +#define AT91_MATRIX_ULBT_EIGHT (3 << 0) +#define AT91_MATRIX_ULBT_SIXTEEN (4 << 0) + +#define AT91_MATRIX_SCFG0 (AT91_MATRIX + 0x40) /* Slave Configuration Register 0 */ +#define AT91_MATRIX_SCFG1 (AT91_MATRIX + 0x44) /* Slave Configuration Register 1 */ +#define AT91_MATRIX_SCFG2 (AT91_MATRIX + 0x48) /* Slave Configuration Register 2 */ +#define AT91_MATRIX_SCFG3 (AT91_MATRIX + 0x4C) /* Slave Configuration Register 3 */ +#define AT91_MATRIX_SCFG4 (AT91_MATRIX + 0x50) /* Slave Configuration Register 4 */ +#define AT91_MATRIX_SLOT_CYCLE (0xff << 0) /* Maximum Number of Allowed Cycles for a Burst */ +#define AT91_MATRIX_DEFMSTR_TYPE (3 << 16) /* Default Master Type */ +#define AT91_MATRIX_DEFMSTR_TYPE_NONE (0 << 16) +#define AT91_MATRIX_DEFMSTR_TYPE_LAST (1 << 16) +#define AT91_MATRIX_DEFMSTR_TYPE_FIXED (2 << 16) +#define AT91_MATRIX_FIXED_DEFMSTR (0x7 << 18) /* Fixed Index of Default Master */ +#define AT91_MATRIX_ARBT (3 << 24) /* Arbitration Type */ +#define AT91_MATRIX_ARBT_ROUND_ROBIN (0 << 24) +#define AT91_MATRIX_ARBT_FIXED_PRIORITY (1 << 24) + +#define AT91_MATRIX_PRAS0 (AT91_MATRIX + 0x80) /* Priority Register A for Slave 0 */ +#define AT91_MATRIX_PRAS1 (AT91_MATRIX + 0x88) /* Priority Register A for Slave 1 */ +#define AT91_MATRIX_PRAS2 (AT91_MATRIX + 0x90) /* Priority Register A for Slave 2 */ +#define AT91_MATRIX_PRAS3 (AT91_MATRIX + 0x98) /* Priority Register A for Slave 3 */ +#define AT91_MATRIX_PRAS4 (AT91_MATRIX + 0xA0) /* Priority Register A for Slave 4 */ + +#define AT91_MATRIX_M0PR (3 << 0) /* Master 0 Priority */ +#define AT91_MATRIX_M1PR (3 << 4) /* Master 1 Priority */ +#define AT91_MATRIX_M2PR (3 << 8) /* Master 2 Priority */ +#define AT91_MATRIX_M3PR (3 << 12) /* Master 3 Priority */ +#define AT91_MATRIX_M4PR (3 << 16) /* Master 4 Priority */ +#define AT91_MATRIX_M5PR (3 << 20) /* Master 5 Priority */ +#define AT91_MATRIX_M6PR (3 << 24) /* Master 6 Priority */ + +#define AT91_MATRIX_MRCR (AT91_MATRIX + 0x100) /* Master Remap Control Register */ +#define AT91_MATRIX_RCB0 (1 << 0) /* Remap Command for AHB Master 0 (ARM926EJ-S Instruction Master) */ +#define AT91_MATRIX_RCB1 (1 << 1) /* Remap Command for AHB Master 1 (ARM926EJ-S Data Master) */ + +#define AT91_MATRIX_SFR0 (AT91_MATRIX + 0x110) /* Special Function Register 0 */ +#define AT91_MATRIX_SFR1 (AT91_MATRIX + 0x114) /* Special Function Register 1 */ +#define AT91_MATRIX_SFR2 (AT91_MATRIX + 0x118) /* Special Function Register 2 */ +#define AT91_MATRIX_SFR3 (AT91_MATRIX + 0x11C) /* Special Function Register 3 */ +#define AT91_MATRIX_SFR4 (AT91_MATRIX + 0x120) /* Special Function Register 4 */ +#define AT91_MATRIX_SFR5 (AT91_MATRIX + 0x124) /* Special Function Register 5 */ +#define AT91_MATRIX_SFR6 (AT91_MATRIX + 0x128) /* Special Function Register 6 */ +#define AT91_MATRIX_SFR7 (AT91_MATRIX + 0x12C) /* Special Function Register 7 */ +#define AT91_MATRIX_SFR8 (AT91_MATRIX + 0x130) /* Special Function Register 8 */ +#define AT91_MATRIX_SFR9 (AT91_MATRIX + 0x134) /* Special Function Register 9 */ +#define AT91_MATRIX_SFR10 (AT91_MATRIX + 0x138) /* Special Function Register 10 */ +#define AT91_MATRIX_SFR11 (AT91_MATRIX + 0x13C) /* Special Function Register 11 */ +#define AT91_MATRIX_SFR12 (AT91_MATRIX + 0x140) /* Special Function Register 12 */ +#define AT91_MATRIX_SFR13 (AT91_MATRIX + 0x144) /* Special Function Register 13 */ +#define AT91_MATRIX_SFR14 (AT91_MATRIX + 0x148) /* Special Function Register 14 */ +#define AT91_MATRIX_SFR15 (AT91_MATRIX + 0x14C) /* Special Function Register 15 */ + + +/* + * The following registers / bits are not defined in the Datasheet (Revision A) + */ + +#define AT91_MATRIX_TCR (AT91_MATRIX + 0x100) /* TCM Configuration Register */ +#define AT91_MATRIX_ITCM_SIZE (0xf << 0) /* Size of ITCM enabled memory block */ +#define AT91_MATRIX_ITCM_0 (0 << 0) +#define AT91_MATRIX_ITCM_16 (5 << 0) +#define AT91_MATRIX_ITCM_32 (6 << 0) +#define AT91_MATRIX_ITCM_64 (7 << 0) +#define AT91_MATRIX_DTCM_SIZE (0xf << 4) /* Size of DTCM enabled memory block */ +#define AT91_MATRIX_DTCM_0 (0 << 4) +#define AT91_MATRIX_DTCM_16 (5 << 4) +#define AT91_MATRIX_DTCM_32 (6 << 4) +#define AT91_MATRIX_DTCM_64 (7 << 4) + +#define AT91_MATRIX_EBICSA (AT91_MATRIX + 0x11C) /* EBI Chip Select Assignment Register */ +#define AT91_MATRIX_CS1A (1 << 1) /* Chip Select 1 Assignment */ +#define AT91_MATRIX_CS1A_SMC (0 << 1) +#define AT91_MATRIX_CS1A_SDRAMC (1 << 1) +#define AT91_MATRIX_CS3A (1 << 3) /* Chip Select 3 Assignment */ +#define AT91_MATRIX_CS3A_SMC (0 << 3) +#define AT91_MATRIX_CS3A_SMC_SMARTMEDIA (1 << 3) +#define AT91_MATRIX_CS4A (1 << 4) /* Chip Select 4 Assignment */ +#define AT91_MATRIX_CS4A_SMC (0 << 4) +#define AT91_MATRIX_CS4A_SMC_CF1 (1 << 4) +#define AT91_MATRIX_CS5A (1 << 5) /* Chip Select 5 Assignment */ +#define AT91_MATRIX_CS5A_SMC (0 << 5) +#define AT91_MATRIX_CS5A_SMC_CF2 (1 << 5) +#define AT91_MATRIX_DBPUC (1 << 8) /* Data Bus Pull-up Configuration */ + +#endif diff --git a/arch/arm/mach-at91/include/mach/at91_pmc.h b/arch/arm/mach-at91/include/mach/at91_pmc.h index 64589eaaaee..e46f93e34aa 100644 --- a/arch/arm/mach-at91/include/mach/at91_pmc.h +++ b/arch/arm/mach-at91/include/mach/at91_pmc.h @@ -32,6 +32,7 @@ #define AT91_PMC_PCK1 (1 << 9) /* Programmable Clock 1 */ #define AT91_PMC_PCK2 (1 << 10) /* Programmable Clock 2 */ #define AT91_PMC_PCK3 (1 << 11) /* Programmable Clock 3 */ +#define AT91_PMC_PCK4 (1 << 12) /* Programmable Clock 4 [AT572D940HF only] */ #define AT91_PMC_HCK0 (1 << 16) /* AHB Clock (USB host) [AT91SAM9261 only] */ #define AT91_PMC_HCK1 (1 << 17) /* AHB Clock (LCD) [AT91SAM9261 only] */ diff --git a/arch/arm/mach-at91/include/mach/board.h b/arch/arm/mach-at91/include/mach/board.h index bb6f6a7ba5e..ceaec6c16eb 100644 --- a/arch/arm/mach-at91/include/mach/board.h +++ b/arch/arm/mach-at91/include/mach/board.h @@ -87,7 +87,7 @@ struct at91_eth_data { extern void __init at91_add_device_eth(struct at91_eth_data *data); #if defined(CONFIG_ARCH_AT91SAM9260) || defined(CONFIG_ARCH_AT91SAM9263) || defined(CONFIG_ARCH_AT91SAM9G20) || defined(CONFIG_ARCH_AT91CAP9) \ - || defined(CONFIG_ARCH_AT91SAM9G45) + || defined(CONFIG_ARCH_AT91SAM9G45) || defined(CONFIG_ARCH_AT572D940HF) #define eth_platform_data at91_eth_data #endif @@ -205,6 +205,9 @@ extern void __init at91_init_leds(u8 cpu_led, u8 timer_led); extern void __init at91_gpio_leds(struct gpio_led *leds, int nr); extern void __init at91_pwm_leds(struct gpio_led *leds, int nr); + /* AT572D940HF DSP */ +extern void __init at91_add_device_mAgic(void); + /* FIXME: this needs a better location, but gets stuff building again */ extern int at91_suspend_entering_slow_clock(void); diff --git a/arch/arm/mach-at91/include/mach/cpu.h b/arch/arm/mach-at91/include/mach/cpu.h index c22df30ed5e..5a0650101d4 100644 --- a/arch/arm/mach-at91/include/mach/cpu.h +++ b/arch/arm/mach-at91/include/mach/cpu.h @@ -33,6 +33,8 @@ #define ARCH_ID_AT91SAM9XE256 0x329a93a0 #define ARCH_ID_AT91SAM9XE512 0x329aa3a0 +#define ARCH_ID_AT572D940HF 0x0e0303e0 + #define ARCH_ID_AT91M40800 0x14080044 #define ARCH_ID_AT91R40807 0x44080746 #define ARCH_ID_AT91M40807 0x14080745 @@ -141,6 +143,12 @@ static inline unsigned long at91cap9_rev_identify(void) #define cpu_is_at91cap9_revC() (0) #endif +#ifdef CONFIG_ARCH_AT572D940HF +#define cpu_is_at572d940hf() (at91_cpu_identify() == ARCH_ID_AT572D940HF) +#else +#define cpu_is_at572d940hf() (0) +#endif + /* * Since this is ARM, we will never run on any AVR32 CPU. But these * definitions may reduce clutter in common drivers. diff --git a/arch/arm/mach-at91/include/mach/hardware.h b/arch/arm/mach-at91/include/mach/hardware.h index a0df8b022df..3d64a75e3ed 100644 --- a/arch/arm/mach-at91/include/mach/hardware.h +++ b/arch/arm/mach-at91/include/mach/hardware.h @@ -32,6 +32,8 @@ #include <mach/at91cap9.h> #elif defined(CONFIG_ARCH_AT91X40) #include <mach/at91x40.h> +#elif defined(CONFIG_ARCH_AT572D940HF) +#include <mach/at572d940hf.h> #else #error "Unsupported AT91 processor" #endif diff --git a/arch/arm/mach-at91/include/mach/timex.h b/arch/arm/mach-at91/include/mach/timex.h index 31ac2d97f14..05a6e8af80c 100644 --- a/arch/arm/mach-at91/include/mach/timex.h +++ b/arch/arm/mach-at91/include/mach/timex.h @@ -82,6 +82,11 @@ #define AT91X40_MASTER_CLOCK 40000000 #define CLOCK_TICK_RATE (AT91X40_MASTER_CLOCK) +#elif defined(CONFIG_ARCH_AT572D940HF) + +#define AT572D940HF_MASTER_CLOCK 80000000 +#define CLOCK_TICK_RATE (AT572D940HF_MASTER_CLOCK/16) + #endif #endif |