From 9d0412680e6c7b685ee466842047bcfb924d6dc5 Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Mon, 5 Feb 2007 11:42:07 +0100 Subject: [ARM] 4124/1: Rename mach-at91rm9200 and arch-at91rm9200 directories Now that Linux includes support for the Atmel AT91SAM9260 and AT91SAM9261 processors in addition to the original Atmel AT91RM9200 (with support for more AT91 processors pending), the "mach-at91rm9200" and "arch-at91rm9200" directories should be renamed to indicate their more generic nature. The following git commands should be run BEFORE applying this patch: git-mv arch/arm/mach-at91rm9200 arch/arm/mach-at91 git-mv include/asm-arm/arch-at91rm9200 include/asm-arm/arch-at91 Signed-off-by: Andrew Victor Signed-off-by: Russell King --- arch/arm/mach-at91/clock.c | 644 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 644 insertions(+) create mode 100644 arch/arm/mach-at91/clock.c (limited to 'arch/arm/mach-at91/clock.c') diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c new file mode 100644 index 000000000000..baab095f6e32 --- /dev/null +++ b/arch/arm/mach-at91/clock.c @@ -0,0 +1,644 @@ +/* + * linux/arch/arm/mach-at91/clock.c + * + * Copyright (C) 2005 David Brownell + * Copyright (C) 2005 Ivan Kokshaysky + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include "clock.h" + + +/* + * There's a lot more which can be done with clocks, including cpufreq + * integration, slow clock mode support (for system suspend), letting + * PLLB be used at other rates (on boards that don't need USB), etc. + */ + +#define clk_is_primary(x) ((x)->type & CLK_TYPE_PRIMARY) +#define clk_is_programmable(x) ((x)->type & CLK_TYPE_PROGRAMMABLE) +#define clk_is_peripheral(x) ((x)->type & CLK_TYPE_PERIPHERAL) +#define clk_is_sys(x) ((x)->type & CLK_TYPE_SYSTEM) + + +static LIST_HEAD(clocks); +static DEFINE_SPINLOCK(clk_lock); + +static u32 at91_pllb_usb_init; + +/* + * Four primary clock sources: two crystal oscillators (32K, main), and + * two PLLs. PLLA usually runs the master clock; and PLLB must run at + * 48 MHz (unless no USB function clocks are needed). The main clock and + * both PLLs are turned off to run in "slow clock mode" (system suspend). + */ +static struct clk clk32k = { + .name = "clk32k", + .rate_hz = AT91_SLOW_CLOCK, + .users = 1, /* always on */ + .id = 0, + .type = CLK_TYPE_PRIMARY, +}; +static struct clk main_clk = { + .name = "main", + .pmc_mask = AT91_PMC_MOSCS, /* in PMC_SR */ + .id = 1, + .type = CLK_TYPE_PRIMARY, +}; +static struct clk plla = { + .name = "plla", + .parent = &main_clk, + .pmc_mask = AT91_PMC_LOCKA, /* in PMC_SR */ + .id = 2, + .type = CLK_TYPE_PRIMARY | CLK_TYPE_PLL, +}; + +static void pllb_mode(struct clk *clk, int is_on) +{ + u32 value; + + if (is_on) { + is_on = AT91_PMC_LOCKB; + value = at91_pllb_usb_init; + } else + value = 0; + + // REVISIT: Add work-around for AT91RM9200 Errata #26 ? + at91_sys_write(AT91_CKGR_PLLBR, value); + + do { + cpu_relax(); + } while ((at91_sys_read(AT91_PMC_SR) & AT91_PMC_LOCKB) != is_on); +} + +static struct clk pllb = { + .name = "pllb", + .parent = &main_clk, + .pmc_mask = AT91_PMC_LOCKB, /* in PMC_SR */ + .mode = pllb_mode, + .id = 3, + .type = CLK_TYPE_PRIMARY | CLK_TYPE_PLL, +}; + +static void pmc_sys_mode(struct clk *clk, int is_on) +{ + if (is_on) + at91_sys_write(AT91_PMC_SCER, clk->pmc_mask); + else + at91_sys_write(AT91_PMC_SCDR, clk->pmc_mask); +} + +/* USB function clocks (PLLB must be 48 MHz) */ +static struct clk udpck = { + .name = "udpck", + .parent = &pllb, + .mode = pmc_sys_mode, +}; +static struct clk uhpck = { + .name = "uhpck", + .parent = &pllb, + .mode = pmc_sys_mode, +}; + + +/* + * The master clock is divided from the CPU clock (by 1-4). It's used for + * memory, interfaces to on-chip peripherals, the AIC, and sometimes more + * (e.g baud rate generation). It's sourced from one of the primary clocks. + */ +static struct clk mck = { + .name = "mck", + .pmc_mask = AT91_PMC_MCKRDY, /* in PMC_SR */ +}; + +static void pmc_periph_mode(struct clk *clk, int is_on) +{ + if (is_on) + at91_sys_write(AT91_PMC_PCER, clk->pmc_mask); + else + at91_sys_write(AT91_PMC_PCDR, clk->pmc_mask); +} + +static struct clk __init *at91_css_to_clk(unsigned long css) +{ + switch (css) { + case AT91_PMC_CSS_SLOW: + return &clk32k; + case AT91_PMC_CSS_MAIN: + return &main_clk; + case AT91_PMC_CSS_PLLA: + return &plla; + case AT91_PMC_CSS_PLLB: + return &pllb; + } + + return NULL; +} + +/* + * Associate a particular clock with a function (eg, "uart") and device. + * The drivers can then request the same 'function' with several different + * devices and not care about which clock name to use. + */ +void __init at91_clock_associate(const char *id, struct device *dev, const char *func) +{ + struct clk *clk = clk_get(NULL, id); + + if (!dev || !clk || !IS_ERR(clk_get(dev, func))) + return; + + clk->function = func; + clk->dev = dev; +} + +/* clocks cannot be de-registered no refcounting necessary */ +struct clk *clk_get(struct device *dev, const char *id) +{ + struct clk *clk; + + list_for_each_entry(clk, &clocks, node) { + if (strcmp(id, clk->name) == 0) + return clk; + if (clk->function && (dev == clk->dev) && strcmp(id, clk->function) == 0) + return clk; + } + + return ERR_PTR(-ENOENT); +} +EXPORT_SYMBOL(clk_get); + +void clk_put(struct clk *clk) +{ +} +EXPORT_SYMBOL(clk_put); + +static void __clk_enable(struct clk *clk) +{ + if (clk->parent) + __clk_enable(clk->parent); + if (clk->users++ == 0 && clk->mode) + clk->mode(clk, 1); +} + +int clk_enable(struct clk *clk) +{ + unsigned long flags; + + spin_lock_irqsave(&clk_lock, flags); + __clk_enable(clk); + spin_unlock_irqrestore(&clk_lock, flags); + return 0; +} +EXPORT_SYMBOL(clk_enable); + +static void __clk_disable(struct clk *clk) +{ + BUG_ON(clk->users == 0); + if (--clk->users == 0 && clk->mode) + clk->mode(clk, 0); + if (clk->parent) + __clk_disable(clk->parent); +} + +void clk_disable(struct clk *clk) +{ + unsigned long flags; + + spin_lock_irqsave(&clk_lock, flags); + __clk_disable(clk); + spin_unlock_irqrestore(&clk_lock, flags); +} +EXPORT_SYMBOL(clk_disable); + +unsigned long clk_get_rate(struct clk *clk) +{ + unsigned long flags; + unsigned long rate; + + spin_lock_irqsave(&clk_lock, flags); + for (;;) { + rate = clk->rate_hz; + if (rate || !clk->parent) + break; + clk = clk->parent; + } + spin_unlock_irqrestore(&clk_lock, flags); + return rate; +} +EXPORT_SYMBOL(clk_get_rate); + +/*------------------------------------------------------------------------*/ + +#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS + +/* + * For now, only the programmable clocks support reparenting (MCK could + * do this too, with care) or rate changing (the PLLs could do this too, + * ditto MCK but that's more for cpufreq). Drivers may reparent to get + * a better rate match; we don't. + */ + +long clk_round_rate(struct clk *clk, unsigned long rate) +{ + unsigned long flags; + unsigned prescale; + unsigned long actual; + + if (!clk_is_programmable(clk)) + return -EINVAL; + spin_lock_irqsave(&clk_lock, flags); + + actual = clk->parent->rate_hz; + for (prescale = 0; prescale < 7; prescale++) { + if (actual && actual <= rate) + break; + actual >>= 1; + } + + spin_unlock_irqrestore(&clk_lock, flags); + return (prescale < 7) ? actual : -ENOENT; +} +EXPORT_SYMBOL(clk_round_rate); + +int clk_set_rate(struct clk *clk, unsigned long rate) +{ + unsigned long flags; + unsigned prescale; + unsigned long actual; + + if (!clk_is_programmable(clk)) + return -EINVAL; + if (clk->users) + return -EBUSY; + spin_lock_irqsave(&clk_lock, flags); + + actual = clk->parent->rate_hz; + for (prescale = 0; prescale < 7; prescale++) { + if (actual && actual <= rate) { + u32 pckr; + + pckr = at91_sys_read(AT91_PMC_PCKR(clk->id)); + pckr &= AT91_PMC_CSS_PLLB; /* clock selection */ + pckr |= prescale << 2; + at91_sys_write(AT91_PMC_PCKR(clk->id), pckr); + clk->rate_hz = actual; + break; + } + actual >>= 1; + } + + spin_unlock_irqrestore(&clk_lock, flags); + return (prescale < 7) ? actual : -ENOENT; +} +EXPORT_SYMBOL(clk_set_rate); + +struct clk *clk_get_parent(struct clk *clk) +{ + return clk->parent; +} +EXPORT_SYMBOL(clk_get_parent); + +int clk_set_parent(struct clk *clk, struct clk *parent) +{ + unsigned long flags; + + if (clk->users) + return -EBUSY; + if (!clk_is_primary(parent) || !clk_is_programmable(clk)) + return -EINVAL; + spin_lock_irqsave(&clk_lock, flags); + + clk->rate_hz = parent->rate_hz; + clk->parent = parent; + at91_sys_write(AT91_PMC_PCKR(clk->id), parent->id); + + spin_unlock_irqrestore(&clk_lock, flags); + return 0; +} +EXPORT_SYMBOL(clk_set_parent); + +/* establish PCK0..PCK3 parentage and rate */ +static void init_programmable_clock(struct clk *clk) +{ + struct clk *parent; + u32 pckr; + + pckr = at91_sys_read(AT91_PMC_PCKR(clk->id)); + parent = at91_css_to_clk(pckr & AT91_PMC_CSS); + clk->parent = parent; + clk->rate_hz = parent->rate_hz / (1 << ((pckr >> 2) & 3)); +} + +#endif /* CONFIG_AT91_PROGRAMMABLE_CLOCKS */ + +/*------------------------------------------------------------------------*/ + +#ifdef CONFIG_DEBUG_FS + +static int at91_clk_show(struct seq_file *s, void *unused) +{ + u32 scsr, pcsr, sr; + struct clk *clk; + unsigned i; + + seq_printf(s, "SCSR = %8x\n", scsr = at91_sys_read(AT91_PMC_SCSR)); + seq_printf(s, "PCSR = %8x\n", pcsr = at91_sys_read(AT91_PMC_PCSR)); + + seq_printf(s, "MOR = %8x\n", at91_sys_read(AT91_CKGR_MOR)); + seq_printf(s, "MCFR = %8x\n", at91_sys_read(AT91_CKGR_MCFR)); + seq_printf(s, "PLLA = %8x\n", at91_sys_read(AT91_CKGR_PLLAR)); + seq_printf(s, "PLLB = %8x\n", at91_sys_read(AT91_CKGR_PLLBR)); + + seq_printf(s, "MCKR = %8x\n", at91_sys_read(AT91_PMC_MCKR)); + for (i = 0; i < 4; i++) + seq_printf(s, "PCK%d = %8x\n", i, at91_sys_read(AT91_PMC_PCKR(i))); + seq_printf(s, "SR = %8x\n", sr = at91_sys_read(AT91_PMC_SR)); + + seq_printf(s, "\n"); + + list_for_each_entry(clk, &clocks, node) { + char *state; + + if (clk->mode == pmc_sys_mode) + state = (scsr & clk->pmc_mask) ? "on" : "off"; + else if (clk->mode == pmc_periph_mode) + state = (pcsr & clk->pmc_mask) ? "on" : "off"; + else if (clk->pmc_mask) + state = (sr & clk->pmc_mask) ? "on" : "off"; + else if (clk == &clk32k || clk == &main_clk) + state = "on"; + else + state = ""; + + seq_printf(s, "%-10s users=%2d %-3s %9ld Hz %s\n", + clk->name, clk->users, state, clk_get_rate(clk), + clk->parent ? clk->parent->name : ""); + } + return 0; +} + +static int at91_clk_open(struct inode *inode, struct file *file) +{ + return single_open(file, at91_clk_show, NULL); +} + +static struct file_operations at91_clk_operations = { + .open = at91_clk_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int __init at91_clk_debugfs_init(void) +{ + /* /sys/kernel/debug/at91_clk */ + (void) debugfs_create_file("at91_clk", S_IFREG | S_IRUGO, NULL, NULL, &at91_clk_operations); + + return 0; +} +postcore_initcall(at91_clk_debugfs_init); + +#endif + +/*------------------------------------------------------------------------*/ + +/* Register a new clock */ +int __init clk_register(struct clk *clk) +{ + if (clk_is_peripheral(clk)) { + clk->parent = &mck; + clk->mode = pmc_periph_mode; + list_add_tail(&clk->node, &clocks); + } + else if (clk_is_sys(clk)) { + clk->parent = &mck; + clk->mode = pmc_sys_mode; + + list_add_tail(&clk->node, &clocks); + } +#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS + else if (clk_is_programmable(clk)) { + clk->mode = pmc_sys_mode; + init_programmable_clock(clk); + list_add_tail(&clk->node, &clocks); + } +#endif + + return 0; +} + + +/*------------------------------------------------------------------------*/ + +static u32 __init at91_pll_rate(struct clk *pll, u32 freq, u32 reg) +{ + unsigned mul, div; + + div = reg & 0xff; + mul = (reg >> 16) & 0x7ff; + if (div && mul) { + freq /= div; + freq *= mul + 1; + } else + freq = 0; + + return freq; +} + +static u32 __init at91_usb_rate(struct clk *pll, u32 freq, u32 reg) +{ + if (pll == &pllb && (reg & AT91_PMC_USB96M)) + return freq / 2; + else + return freq; +} + +static unsigned __init at91_pll_calc(unsigned main_freq, unsigned out_freq) +{ + unsigned i, div = 0, mul = 0, diff = 1 << 30; + unsigned ret = (out_freq > 155000000) ? 0xbe00 : 0x3e00; + + /* PLL output max 240 MHz (or 180 MHz per errata) */ + if (out_freq > 240000000) + goto fail; + + for (i = 1; i < 256; i++) { + int diff1; + unsigned input, mul1; + + /* + * PLL input between 1MHz and 32MHz per spec, but lower + * frequences seem necessary in some cases so allow 100K. + */ + input = main_freq / i; + if (input < 100000) + continue; + if (input > 32000000) + continue; + + mul1 = out_freq / input; + if (mul1 > 2048) + continue; + if (mul1 < 2) + goto fail; + + diff1 = out_freq - input * mul1; + if (diff1 < 0) + diff1 = -diff1; + if (diff > diff1) { + diff = diff1; + div = i; + mul = mul1; + if (diff == 0) + break; + } + } + if (i == 256 && diff > (out_freq >> 5)) + goto fail; + return ret | ((mul - 1) << 16) | div; +fail: + return 0; +} + +/* + * Several unused clocks may be active. Turn them off. + */ +static void __init at91_periphclk_reset(void) +{ + unsigned long reg; + struct clk *clk; + + reg = at91_sys_read(AT91_PMC_PCSR); + + list_for_each_entry(clk, &clocks, node) { + if (clk->mode != pmc_periph_mode) + continue; + + if (clk->users > 0) + reg &= ~clk->pmc_mask; + } + + at91_sys_write(AT91_PMC_PCDR, reg); +} + +static struct clk *const standard_pmc_clocks[] __initdata = { + /* four primary clocks */ + &clk32k, + &main_clk, + &plla, + &pllb, + + /* PLLB children (USB) */ + &udpck, + &uhpck, + + /* MCK */ + &mck +}; + +int __init at91_clock_init(unsigned long main_clock) +{ + unsigned tmp, freq, mckr; + int i; + + /* + * When the bootloader initialized the main oscillator correctly, + * there's no problem using the cycle counter. But if it didn't, + * or when using oscillator bypass mode, we must be told the speed + * of the main clock. + */ + if (!main_clock) { + do { + tmp = at91_sys_read(AT91_CKGR_MCFR); + } while (!(tmp & AT91_PMC_MAINRDY)); + main_clock = (tmp & AT91_PMC_MAINF) * (AT91_SLOW_CLOCK / 16); + } + main_clk.rate_hz = main_clock; + + /* report if PLLA is more than mildly overclocked */ + plla.rate_hz = at91_pll_rate(&plla, main_clock, at91_sys_read(AT91_CKGR_PLLAR)); + if (plla.rate_hz > 209000000) + pr_info("Clocks: PLLA overclocked, %ld MHz\n", plla.rate_hz / 1000000); + + /* + * USB clock init: choose 48 MHz PLLB value, turn all clocks off, + * disable 48MHz clock during usb peripheral suspend. + * + * REVISIT: assumes MCK doesn't derive from PLLB! + */ + at91_pllb_usb_init = at91_pll_calc(main_clock, 48000000 * 2) | AT91_PMC_USB96M; + pllb.rate_hz = at91_pll_rate(&pllb, main_clock, at91_pllb_usb_init); + if (cpu_is_at91rm9200()) { + uhpck.pmc_mask = AT91RM9200_PMC_UHP; + udpck.pmc_mask = AT91RM9200_PMC_UDP; + at91_sys_write(AT91_PMC_SCDR, AT91RM9200_PMC_UHP | AT91RM9200_PMC_UDP); + at91_sys_write(AT91_PMC_SCER, AT91RM9200_PMC_MCKUDP); + } else if (cpu_is_at91sam9260()) { + uhpck.pmc_mask = AT91SAM926x_PMC_UHP; + udpck.pmc_mask = AT91SAM926x_PMC_UDP; + at91_sys_write(AT91_PMC_SCDR, AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP); + } else if (cpu_is_at91sam9261()) { + uhpck.pmc_mask = (AT91SAM926x_PMC_UHP | AT91_PMC_HCK0); + udpck.pmc_mask = AT91SAM926x_PMC_UDP; + at91_sys_write(AT91_PMC_SCDR, AT91SAM926x_PMC_UHP | AT91_PMC_HCK0 | AT91SAM926x_PMC_UDP); + } + at91_sys_write(AT91_CKGR_PLLBR, 0); + + udpck.rate_hz = at91_usb_rate(&pllb, pllb.rate_hz, at91_pllb_usb_init); + uhpck.rate_hz = at91_usb_rate(&pllb, pllb.rate_hz, at91_pllb_usb_init); + + /* + * MCK and CPU derive from one of those primary clocks. + * For now, assume this parentage won't change. + */ + mckr = at91_sys_read(AT91_PMC_MCKR); + mck.parent = at91_css_to_clk(mckr & AT91_PMC_CSS); + freq = mck.parent->rate_hz; + freq /= (1 << ((mckr >> 2) & 3)); /* prescale */ + mck.rate_hz = freq / (1 + ((mckr >> 8) & 3)); /* mdiv */ + + /* Register the PMC's standard clocks */ + for (i = 0; i < ARRAY_SIZE(standard_pmc_clocks); i++) + list_add_tail(&standard_pmc_clocks[i]->node, &clocks); + + /* MCK and CPU clock are "always on" */ + clk_enable(&mck); + + printk("Clocks: CPU %u MHz, master %u MHz, main %u.%03u MHz\n", + freq / 1000000, (unsigned) mck.rate_hz / 1000000, + (unsigned) main_clock / 1000000, + ((unsigned) main_clock % 1000000) / 1000); + + /* disable all programmable clocks */ + at91_sys_write(AT91_PMC_SCDR, AT91_PMC_PCK0 | AT91_PMC_PCK1 | AT91_PMC_PCK2 | AT91_PMC_PCK3); + + /* disable all other unused peripheral clocks */ + at91_periphclk_reset(); + + return 0; +} -- cgit v1.2.3 From b2c6561605da4802886cafe96432b8e2968e9edc Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Thu, 8 Feb 2007 09:42:40 +0100 Subject: [ARM] 4145/2: AT91: Add support for AT91SAM9263 processor Add support for the Atmel AT91SAM9263 processor. It is similar to the AT91SAM9260 but with more integrated peripherals, 5 GPIO banks, etc. Original patch from Nicolas Ferre. Signed-off-by: Andrew Victor Signed-off-by: Russell King --- arch/arm/mach-at91/Kconfig | 3 + arch/arm/mach-at91/Makefile | 1 + arch/arm/mach-at91/at91sam9263.c | 313 ++++++++++ arch/arm/mach-at91/at91sam9263_devices.c | 818 +++++++++++++++++++++++++ arch/arm/mach-at91/clock.c | 2 +- arch/arm/mach-at91/generic.h | 2 + arch/arm/mach-at91/pm.c | 2 + arch/arm/mm/Kconfig | 4 +- drivers/usb/gadget/at91_udc.c | 4 +- include/asm-arm/arch-at91/at91sam9263.h | 131 ++++ include/asm-arm/arch-at91/at91sam9263_matrix.h | 129 ++++ include/asm-arm/arch-at91/at91sam926x_mc.h | 7 + include/asm-arm/arch-at91/cpu.h | 7 + include/asm-arm/arch-at91/hardware.h | 2 + include/asm-arm/arch-at91/timex.h | 5 + 15 files changed, 1425 insertions(+), 5 deletions(-) create mode 100644 arch/arm/mach-at91/at91sam9263.c create mode 100644 arch/arm/mach-at91/at91sam9263_devices.c create mode 100644 include/asm-arm/arch-at91/at91sam9263.h create mode 100644 include/asm-arm/arch-at91/at91sam9263_matrix.h (limited to 'arch/arm/mach-at91/clock.c') diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index 9f11db8af233..2499385e22da 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -14,6 +14,9 @@ config ARCH_AT91SAM9260 config ARCH_AT91SAM9261 bool "AT91SAM9261" +config ARCH_AT91SAM9263 + bool "AT91SAM9263" + endchoice # ---------------------------------------------------------- diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile index cf777007847a..2fd4cd4a57f8 100644 --- a/arch/arm/mach-at91/Makefile +++ b/arch/arm/mach-at91/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_PM) += pm.o obj-$(CONFIG_ARCH_AT91RM9200) += at91rm9200.o at91rm9200_time.o at91rm9200_devices.o obj-$(CONFIG_ARCH_AT91SAM9260) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o obj-$(CONFIG_ARCH_AT91SAM9261) += at91sam9261.o at91sam926x_time.o at91sam9261_devices.o +obj-$(CONFIG_ARCH_AT91SAM9263) += at91sam9263.o at91sam926x_time.o at91sam9263_devices.o # AT91RM9200 board-specific support obj-$(CONFIG_MACH_ONEARM) += board-1arm.o diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c new file mode 100644 index 000000000000..fae6a821a61b --- /dev/null +++ b/arch/arm/mach-at91/at91sam9263.c @@ -0,0 +1,313 @@ +/* + * arch/arm/mach-at91/at91sam9263.c + * + * Copyright (C) 2007 Atmel Corporation. + * + * 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. + * + */ + +#include + +#include +#include +#include +#include +#include + +#include "generic.h" +#include "clock.h" + +static struct map_desc at91sam9263_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 - AT91SAM9263_SRAM0_SIZE, + .pfn = __phys_to_pfn(AT91SAM9263_SRAM0_BASE), + .length = AT91SAM9263_SRAM0_SIZE, + .type = MT_DEVICE, + }, { + .virtual = AT91_IO_VIRT_BASE - AT91SAM9263_SRAM0_SIZE - AT91SAM9263_SRAM1_SIZE, + .pfn = __phys_to_pfn(AT91SAM9263_SRAM1_BASE), + .length = AT91SAM9263_SRAM1_SIZE, + .type = MT_DEVICE, + }, +}; + +/* -------------------------------------------------------------------- + * Clocks + * -------------------------------------------------------------------- */ + +/* + * The peripheral clocks. + */ +static struct clk pioA_clk = { + .name = "pioA_clk", + .pmc_mask = 1 << AT91SAM9263_ID_PIOA, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk pioB_clk = { + .name = "pioB_clk", + .pmc_mask = 1 << AT91SAM9263_ID_PIOB, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk pioCDE_clk = { + .name = "pioCDE_clk", + .pmc_mask = 1 << AT91SAM9263_ID_PIOCDE, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk usart0_clk = { + .name = "usart0_clk", + .pmc_mask = 1 << AT91SAM9263_ID_US0, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk usart1_clk = { + .name = "usart1_clk", + .pmc_mask = 1 << AT91SAM9263_ID_US1, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk usart2_clk = { + .name = "usart2_clk", + .pmc_mask = 1 << AT91SAM9263_ID_US2, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk mmc0_clk = { + .name = "mci0_clk", + .pmc_mask = 1 << AT91SAM9263_ID_MCI0, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk mmc1_clk = { + .name = "mci1_clk", + .pmc_mask = 1 << AT91SAM9263_ID_MCI1, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk twi_clk = { + .name = "twi_clk", + .pmc_mask = 1 << AT91SAM9263_ID_TWI, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk spi0_clk = { + .name = "spi0_clk", + .pmc_mask = 1 << AT91SAM9263_ID_SPI0, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk spi1_clk = { + .name = "spi1_clk", + .pmc_mask = 1 << AT91SAM9263_ID_SPI1, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk tcb_clk = { + .name = "tcb_clk", + .pmc_mask = 1 << AT91SAM9263_ID_TCB, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk ether_clk = { + .name = "ether_clk", + .pmc_mask = 1 << AT91SAM9263_ID_EMAC, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk udc_clk = { + .name = "udc_clk", + .pmc_mask = 1 << AT91SAM9263_ID_UDP, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk isi_clk = { + .name = "isi_clk", + .pmc_mask = 1 << AT91SAM9263_ID_ISI, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk lcdc_clk = { + .name = "lcdc_clk", + .pmc_mask = 1 << AT91SAM9263_ID_ISI, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk ohci_clk = { + .name = "ohci_clk", + .pmc_mask = 1 << AT91SAM9263_ID_UHP, + .type = CLK_TYPE_PERIPHERAL, +}; + +static struct clk *periph_clocks[] __initdata = { + &pioA_clk, + &pioB_clk, + &pioCDE_clk, + &usart0_clk, + &usart1_clk, + &usart2_clk, + &mmc0_clk, + &mmc1_clk, + // can + &twi_clk, + &spi0_clk, + &spi1_clk, + // ssc0 .. ssc1 + // ac97 + &tcb_clk, + // pwmc + ðer_clk, + // 2dge + &udc_clk, + &isi_clk, + &lcdc_clk, + // dma + &ohci_clk, + // irq0 .. irq1 +}; + +/* + * The four 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 void __init at91sam9263_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); +} + +/* -------------------------------------------------------------------- + * GPIO + * -------------------------------------------------------------------- */ + +static struct at91_gpio_bank at91sam9263_gpio[] = { + { + .id = AT91SAM9263_ID_PIOA, + .offset = AT91_PIOA, + .clock = &pioA_clk, + }, { + .id = AT91SAM9263_ID_PIOB, + .offset = AT91_PIOB, + .clock = &pioB_clk, + }, { + .id = AT91SAM9263_ID_PIOCDE, + .offset = AT91_PIOC, + .clock = &pioCDE_clk, + }, { + .id = AT91SAM9263_ID_PIOCDE, + .offset = AT91_PIOD, + .clock = &pioCDE_clk, + }, { + .id = AT91SAM9263_ID_PIOCDE, + .offset = AT91_PIOE, + .clock = &pioCDE_clk, + } +}; + +static void at91sam9263_reset(void) +{ + at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST); +} + + +/* -------------------------------------------------------------------- + * AT91SAM9263 processor initialization + * -------------------------------------------------------------------- */ + +void __init at91sam9263_initialize(unsigned long main_clock) +{ + /* Map peripherals */ + iotable_init(at91sam9263_io_desc, ARRAY_SIZE(at91sam9263_io_desc)); + + at91_arch_reset = at91sam9263_reset; + at91_extern_irq = (1 << AT91SAM9263_ID_IRQ0) | (1 << AT91SAM9263_ID_IRQ1); + + /* Init clock subsystem */ + at91_clock_init(main_clock); + + /* Register the processor-specific clocks */ + at91sam9263_register_clocks(); + + /* Register GPIO subsystem */ + at91_gpio_init(at91sam9263_gpio, 5); +} + +/* -------------------------------------------------------------------- + * Interrupt initialization + * -------------------------------------------------------------------- */ + +/* + * The default interrupt priority levels (0 = lowest, 7 = highest). + */ +static unsigned int at91sam9263_default_irq_priority[NR_AIC_IRQS] __initdata = { + 7, /* Advanced Interrupt Controller (FIQ) */ + 7, /* System Peripherals */ + 0, /* Parallel IO Controller A */ + 0, /* Parallel IO Controller B */ + 0, /* Parallel IO Controller C, D and E */ + 0, + 0, + 6, /* USART 0 */ + 6, /* USART 1 */ + 6, /* USART 2 */ + 0, /* Multimedia Card Interface 0 */ + 0, /* Multimedia Card Interface 1 */ + 4, /* CAN */ + 0, /* Two-Wire Interface */ + 6, /* Serial Peripheral Interface 0 */ + 6, /* Serial Peripheral Interface 1 */ + 5, /* Serial Synchronous Controller 0 */ + 5, /* Serial Synchronous Controller 1 */ + 6, /* AC97 Controller */ + 0, /* Timer Counter 0, 1 and 2 */ + 0, /* Pulse Width Modulation Controller */ + 3, /* Ethernet */ + 0, + 0, /* 2D Graphic Engine */ + 3, /* USB Device Port */ + 0, /* Image Sensor Interface */ + 3, /* LDC Controller */ + 0, /* DMA Controller */ + 0, + 3, /* USB Host port */ + 0, /* Advanced Interrupt Controller (IRQ0) */ + 0, /* Advanced Interrupt Controller (IRQ1) */ +}; + +void __init at91sam9263_init_interrupts(unsigned int priority[NR_AIC_IRQS]) +{ + if (!priority) + priority = at91sam9263_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/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c new file mode 100644 index 000000000000..d9af7ca58bce --- /dev/null +++ b/arch/arm/mach-at91/at91sam9263_devices.c @@ -0,0 +1,818 @@ +/* + * arch/arm/mach-at91/at91sam9263_devices.c + * + * Copyright (C) 2007 Atmel Corporation. + * + * 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. + * + */ +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include "generic.h" + +#define SZ_512 0x00000200 +#define SZ_256 0x00000100 +#define SZ_16 0x00000010 + +/* -------------------------------------------------------------------- + * USB Host + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) +static u64 ohci_dmamask = 0xffffffffUL; +static struct at91_usbh_data usbh_data; + +static struct resource usbh_resources[] = { + [0] = { + .start = AT91SAM9263_UHP_BASE, + .end = AT91SAM9263_UHP_BASE + SZ_1M - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9263_ID_UHP, + .end = AT91SAM9263_ID_UHP, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91_usbh_device = { + .name = "at91_ohci", + .id = -1, + .dev = { + .dma_mask = &ohci_dmamask, + .coherent_dma_mask = 0xffffffff, + .platform_data = &usbh_data, + }, + .resource = usbh_resources, + .num_resources = ARRAY_SIZE(usbh_resources), +}; + +void __init at91_add_device_usbh(struct at91_usbh_data *data) +{ + int i; + + if (!data) + return; + + /* Enable VBus control for UHP ports */ + for (i = 0; i < data->ports; i++) { + if (data->vbus_pin[i]) + at91_set_gpio_output(data->vbus_pin[i], 0); + } + + usbh_data = *data; + platform_device_register(&at91_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 = AT91SAM9263_BASE_UDP, + .end = AT91SAM9263_BASE_UDP + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9263_ID_UDP, + .end = AT91SAM9263_ID_UDP, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91_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 by USB device peripheral */ + + udc_data = *data; + platform_device_register(&at91_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 = 0xffffffffUL; +static struct at91_eth_data eth_data; + +static struct resource eth_resources[] = { + [0] = { + .start = AT91SAM9263_BASE_EMAC, + .end = AT91SAM9263_BASE_EMAC + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9263_ID_EMAC, + .end = AT91SAM9263_ID_EMAC, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9263_eth_device = { + .name = "macb", + .id = -1, + .dev = { + .dma_mask = ð_dmamask, + .coherent_dma_mask = 0xffffffff, + .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); + } + + /* Pins used for MII and RMII */ + at91_set_A_periph(AT91_PIN_PE21, 0); /* ETXCK_EREFCK */ + at91_set_B_periph(AT91_PIN_PC25, 0); /* ERXDV */ + at91_set_A_periph(AT91_PIN_PE25, 0); /* ERX0 */ + at91_set_A_periph(AT91_PIN_PE26, 0); /* ERX1 */ + at91_set_A_periph(AT91_PIN_PE27, 0); /* ERXER */ + at91_set_A_periph(AT91_PIN_PE28, 0); /* ETXEN */ + at91_set_A_periph(AT91_PIN_PE23, 0); /* ETX0 */ + at91_set_A_periph(AT91_PIN_PE24, 0); /* ETX1 */ + at91_set_A_periph(AT91_PIN_PE30, 0); /* EMDIO */ + at91_set_A_periph(AT91_PIN_PE29, 0); /* EMDC */ + + if (!data->is_rmii) { + at91_set_A_periph(AT91_PIN_PE22, 0); /* ECRS */ + at91_set_B_periph(AT91_PIN_PC26, 0); /* ECOL */ + at91_set_B_periph(AT91_PIN_PC22, 0); /* ERX2 */ + at91_set_B_periph(AT91_PIN_PC23, 0); /* ERX3 */ + at91_set_B_periph(AT91_PIN_PC27, 0); /* ERXCK */ + at91_set_B_periph(AT91_PIN_PC20, 0); /* ETX2 */ + at91_set_B_periph(AT91_PIN_PC21, 0); /* ETX3 */ + at91_set_B_periph(AT91_PIN_PC24, 0); /* ETXER */ + } + + eth_data = *data; + platform_device_register(&at91sam9263_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 = 0xffffffffUL; +static struct at91_mmc_data mmc0_data, mmc1_data; + +static struct resource mmc0_resources[] = { + [0] = { + .start = AT91SAM9263_BASE_MCI0, + .end = AT91SAM9263_BASE_MCI0 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9263_ID_MCI0, + .end = AT91SAM9263_ID_MCI0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9263_mmc0_device = { + .name = "at91_mci", + .id = 0, + .dev = { + .dma_mask = &mmc_dmamask, + .coherent_dma_mask = 0xffffffff, + .platform_data = &mmc0_data, + }, + .resource = mmc0_resources, + .num_resources = ARRAY_SIZE(mmc0_resources), +}; + +static struct resource mmc1_resources[] = { + [0] = { + .start = AT91SAM9263_BASE_MCI1, + .end = AT91SAM9263_BASE_MCI1 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9263_ID_MCI1, + .end = AT91SAM9263_ID_MCI1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9263_mmc1_device = { + .name = "at91_mci", + .id = 1, + .dev = { + .dma_mask = &mmc_dmamask, + .coherent_dma_mask = 0xffffffff, + .platform_data = &mmc1_data, + }, + .resource = mmc1_resources, + .num_resources = ARRAY_SIZE(mmc1_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); + + if (mmc_id == 0) { /* MCI0 */ + /* CLK */ + at91_set_A_periph(AT91_PIN_PA12, 0); + + if (data->slot_b) { + /* CMD */ + at91_set_A_periph(AT91_PIN_PA16, 1); + + /* DAT0, maybe DAT1..DAT3 */ + at91_set_A_periph(AT91_PIN_PA17, 1); + if (data->wire4) { + at91_set_A_periph(AT91_PIN_PA18, 1); + at91_set_A_periph(AT91_PIN_PA19, 1); + at91_set_A_periph(AT91_PIN_PA20, 1); + } + } else { + /* CMD */ + at91_set_A_periph(AT91_PIN_PA1, 1); + + /* DAT0, maybe DAT1..DAT3 */ + at91_set_A_periph(AT91_PIN_PA0, 1); + if (data->wire4) { + at91_set_A_periph(AT91_PIN_PA3, 1); + at91_set_A_periph(AT91_PIN_PA4, 1); + at91_set_A_periph(AT91_PIN_PA5, 1); + } + } + + mmc0_data = *data; + at91_clock_associate("mci0_clk", &at91sam9263_mmc1_device.dev, "mci_clk"); + platform_device_register(&at91sam9263_mmc0_device); + } else { /* MCI1 */ + /* CLK */ + at91_set_A_periph(AT91_PIN_PA6, 0); + + if (data->slot_b) { + /* CMD */ + at91_set_A_periph(AT91_PIN_PA21, 1); + + /* DAT0, maybe DAT1..DAT3 */ + at91_set_A_periph(AT91_PIN_PA22, 1); + if (data->wire4) { + at91_set_A_periph(AT91_PIN_PA23, 1); + at91_set_A_periph(AT91_PIN_PA24, 1); + at91_set_A_periph(AT91_PIN_PA25, 1); + } + } else { + /* CMD */ + at91_set_A_periph(AT91_PIN_PA7, 1); + + /* DAT0, maybe DAT1..DAT3 */ + at91_set_A_periph(AT91_PIN_PA8, 1); + if (data->wire4) { + at91_set_A_periph(AT91_PIN_PA9, 1); + at91_set_A_periph(AT91_PIN_PA10, 1); + at91_set_A_periph(AT91_PIN_PA11, 1); + } + } + + mmc1_data = *data; + at91_clock_associate("mci1_clk", &at91sam9263_mmc1_device.dev, "mci_clk"); + platform_device_register(&at91sam9263_mmc1_device); + } +} +#else +void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + * NAND / SmartMedia + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE) +static struct at91_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 at91sam9263_nand_device = { + .name = "at91_nand", + .id = -1, + .dev = { + .platform_data = &nand_data, + }, + .resource = nand_resources, + .num_resources = ARRAY_SIZE(nand_resources), +}; + +void __init at91_add_device_nand(struct at91_nand_data *data) +{ + unsigned long csa, mode; + + if (!data) + return; + + csa = at91_sys_read(AT91_MATRIX_EBI0CSA); + at91_sys_write(AT91_MATRIX_EBI0CSA, csa | AT91_MATRIX_EBI0_CS3A_SMC); + + /* set the bus interface characteristics */ + at91_sys_write(AT91_SMC_SETUP(3), AT91_SMC_NWESETUP_(0) | AT91_SMC_NCS_WRSETUP_(0) + | AT91_SMC_NRDSETUP_(0) | AT91_SMC_NCS_RDSETUP_(0)); + + at91_sys_write(AT91_SMC_PULSE(3), AT91_SMC_NWEPULSE_(3) | AT91_SMC_NCS_WRPULSE_(3) + | AT91_SMC_NRDPULSE_(3) | AT91_SMC_NCS_RDPULSE_(3)); + + at91_sys_write(AT91_SMC_CYCLE(3), AT91_SMC_NWECYCLE_(5) | AT91_SMC_NRDCYCLE_(5)); + + if (data->bus_width_16) + mode = AT91_SMC_DBW_16; + else + mode = AT91_SMC_DBW_8; + at91_sys_write(AT91_SMC_MODE(3), mode | AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_TDF_(2)); + + /* 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); + + nand_data = *data; + platform_device_register(&at91sam9263_nand_device); +} +#else +void __init at91_add_device_nand(struct at91_nand_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + * TWI (i2c) + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE) + +static struct resource twi_resources[] = { + [0] = { + .start = AT91SAM9263_BASE_TWI, + .end = AT91SAM9263_BASE_TWI + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9263_ID_TWI, + .end = AT91SAM9263_ID_TWI, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9263_twi_device = { + .name = "at91_i2c", + .id = -1, + .resource = twi_resources, + .num_resources = ARRAY_SIZE(twi_resources), +}; + +void __init at91_add_device_i2c(void) +{ + /* pins used for TWI interface */ + at91_set_A_periph(AT91_PIN_PB4, 0); /* TWD */ + at91_set_multi_drive(AT91_PIN_PB4, 1); + + at91_set_A_periph(AT91_PIN_PB5, 0); /* TWCK */ + at91_set_multi_drive(AT91_PIN_PB5, 1); + + platform_device_register(&at91sam9263_twi_device); +} +#else +void __init at91_add_device_i2c(void) {} +#endif + + +/* -------------------------------------------------------------------- + * SPI + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE) +static u64 spi_dmamask = 0xffffffffUL; + +static struct resource spi0_resources[] = { + [0] = { + .start = AT91SAM9263_BASE_SPI0, + .end = AT91SAM9263_BASE_SPI0 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9263_ID_SPI0, + .end = AT91SAM9263_ID_SPI0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9263_spi0_device = { + .name = "atmel_spi", + .id = 0, + .dev = { + .dma_mask = &spi_dmamask, + .coherent_dma_mask = 0xffffffff, + }, + .resource = spi0_resources, + .num_resources = ARRAY_SIZE(spi0_resources), +}; + +static const unsigned spi0_standard_cs[4] = { AT91_PIN_PA5, AT91_PIN_PA3, AT91_PIN_PA4, AT91_PIN_PB11 }; + +static struct resource spi1_resources[] = { + [0] = { + .start = AT91SAM9263_BASE_SPI1, + .end = AT91SAM9263_BASE_SPI1 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9263_ID_SPI1, + .end = AT91SAM9263_ID_SPI1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9263_spi1_device = { + .name = "atmel_spi", + .id = 1, + .dev = { + .dma_mask = &spi_dmamask, + .coherent_dma_mask = 0xffffffff, + }, + .resource = spi1_resources, + .num_resources = ARRAY_SIZE(spi1_resources), +}; + +static const unsigned spi1_standard_cs[4] = { AT91_PIN_PB15, AT91_PIN_PB16, AT91_PIN_PB17, AT91_PIN_PB18 }; + +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_B_periph(AT91_PIN_PA0, 0); /* SPI0_MISO */ + at91_set_B_periph(AT91_PIN_PA1, 0); /* SPI0_MOSI */ + at91_set_B_periph(AT91_PIN_PA2, 0); /* SPI1_SPCK */ + + at91_clock_associate("spi0_clk", &at91sam9263_spi0_device.dev, "spi_clk"); + platform_device_register(&at91sam9263_spi0_device); + } + if (enable_spi1) { + at91_set_A_periph(AT91_PIN_PB12, 0); /* SPI1_MISO */ + at91_set_A_periph(AT91_PIN_PB13, 0); /* SPI1_MOSI */ + at91_set_A_periph(AT91_PIN_PB14, 0); /* SPI1_SPCK */ + + at91_clock_associate("spi1_clk", &at91sam9263_spi1_device.dev, "spi_clk"); + platform_device_register(&at91sam9263_spi1_device); + } +} +#else +void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {} +#endif + + +/* -------------------------------------------------------------------- + * LEDs + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_LEDS) +u8 at91_leds_cpu; +u8 at91_leds_timer; + +void __init at91_init_leds(u8 cpu_led, u8 timer_led) +{ + /* Enable GPIO to access the LEDs */ + at91_set_gpio_output(cpu_led, 1); + at91_set_gpio_output(timer_led, 1); + + at91_leds_cpu = cpu_led; + at91_leds_timer = timer_led; +} +#else +void __init at91_init_leds(u8 cpu_led, u8 timer_led) {} +#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 struct platform_device at91sam9263_dbgu_device = { + .name = "atmel_usart", + .id = 0, + .dev = { + .platform_data = &dbgu_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = dbgu_resources, + .num_resources = ARRAY_SIZE(dbgu_resources), +}; + +static inline void configure_dbgu_pins(void) +{ + at91_set_A_periph(AT91_PIN_PC30, 0); /* DRXD */ + at91_set_A_periph(AT91_PIN_PC31, 1); /* DTXD */ +} + +static struct resource uart0_resources[] = { + [0] = { + .start = AT91SAM9263_BASE_US0, + .end = AT91SAM9263_BASE_US0 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9263_ID_US0, + .end = AT91SAM9263_ID_US0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data uart0_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static struct platform_device at91sam9263_uart0_device = { + .name = "atmel_usart", + .id = 1, + .dev = { + .platform_data = &uart0_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = uart0_resources, + .num_resources = ARRAY_SIZE(uart0_resources), +}; + +static inline void configure_usart0_pins(void) +{ + at91_set_A_periph(AT91_PIN_PA26, 1); /* TXD0 */ + at91_set_A_periph(AT91_PIN_PA27, 0); /* RXD0 */ + at91_set_A_periph(AT91_PIN_PA28, 0); /* RTS0 */ + at91_set_A_periph(AT91_PIN_PA29, 0); /* CTS0 */ +} + +static struct resource uart1_resources[] = { + [0] = { + .start = AT91SAM9263_BASE_US1, + .end = AT91SAM9263_BASE_US1 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9263_ID_US1, + .end = AT91SAM9263_ID_US1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data uart1_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static struct platform_device at91sam9263_uart1_device = { + .name = "atmel_usart", + .id = 2, + .dev = { + .platform_data = &uart1_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = uart1_resources, + .num_resources = ARRAY_SIZE(uart1_resources), +}; + +static inline void configure_usart1_pins(void) +{ + at91_set_A_periph(AT91_PIN_PD0, 1); /* TXD1 */ + at91_set_A_periph(AT91_PIN_PD1, 0); /* RXD1 */ + at91_set_B_periph(AT91_PIN_PD7, 0); /* RTS1 */ + at91_set_B_periph(AT91_PIN_PD8, 0); /* CTS1 */ +} + +static struct resource uart2_resources[] = { + [0] = { + .start = AT91SAM9263_BASE_US2, + .end = AT91SAM9263_BASE_US2 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9263_ID_US2, + .end = AT91SAM9263_ID_US2, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data uart2_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static struct platform_device at91sam9263_uart2_device = { + .name = "atmel_usart", + .id = 3, + .dev = { + .platform_data = &uart2_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = uart2_resources, + .num_resources = ARRAY_SIZE(uart2_resources), +}; + +static inline void configure_usart2_pins(void) +{ + at91_set_A_periph(AT91_PIN_PD2, 1); /* TXD2 */ + at91_set_A_periph(AT91_PIN_PD3, 0); /* RXD2 */ + at91_set_B_periph(AT91_PIN_PD5, 0); /* RTS2 */ + at91_set_B_periph(AT91_PIN_PD6, 0); /* CTS2 */ +} + +struct platform_device *at91_uarts[ATMEL_MAX_UART]; /* the UARTs to use */ +struct platform_device *atmel_default_console_device; /* the serial console device */ + +void __init at91_init_serial(struct at91_uart_config *config) +{ + int i; + + /* Fill in list of supported UARTs */ + for (i = 0; i < config->nr_tty; i++) { + switch (config->tty_map[i]) { + case 0: + configure_usart0_pins(); + at91_uarts[i] = &at91sam9263_uart0_device; + at91_clock_associate("usart0_clk", &at91sam9263_uart0_device.dev, "usart"); + break; + case 1: + configure_usart1_pins(); + at91_uarts[i] = &at91sam9263_uart1_device; + at91_clock_associate("usart1_clk", &at91sam9263_uart1_device.dev, "usart"); + break; + case 2: + configure_usart2_pins(); + at91_uarts[i] = &at91sam9263_uart2_device; + at91_clock_associate("usart2_clk", &at91sam9263_uart2_device.dev, "usart"); + break; + case 3: + configure_dbgu_pins(); + at91_uarts[i] = &at91sam9263_dbgu_device; + at91_clock_associate("mck", &at91sam9263_dbgu_device.dev, "usart"); + break; + default: + continue; + } + at91_uarts[i]->id = i; /* update ID number to mapped ID */ + } + + /* Set serial console device */ + if (config->console_tty < ATMEL_MAX_UART) + atmel_default_console_device = at91_uarts[config->console_tty]; + if (!atmel_default_console_device) + printk(KERN_INFO "AT91: No default serial console defined.\n"); +} + +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]); + } +} +#else +void __init at91_init_serial(struct at91_uart_config *config) {} +void __init at91_add_device_serial(void) {} +#endif + + +/* -------------------------------------------------------------------- */ +/* + * These devices are always present and don't need any board-specific + * setup. + */ +static int __init at91_add_standard_devices(void) +{ + 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 baab095f6e32..27e7279b5b39 100644 --- a/arch/arm/mach-at91/clock.c +++ b/arch/arm/mach-at91/clock.c @@ -598,7 +598,7 @@ int __init at91_clock_init(unsigned long main_clock) udpck.pmc_mask = AT91RM9200_PMC_UDP; at91_sys_write(AT91_PMC_SCDR, AT91RM9200_PMC_UHP | AT91RM9200_PMC_UDP); at91_sys_write(AT91_PMC_SCER, AT91RM9200_PMC_MCKUDP); - } else if (cpu_is_at91sam9260()) { + } else if (cpu_is_at91sam9260() || cpu_is_at91sam9263()) { uhpck.pmc_mask = AT91SAM926x_PMC_UHP; udpck.pmc_mask = AT91SAM926x_PMC_UDP; at91_sys_write(AT91_PMC_SCDR, AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP); diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h index 10ee37bf6d4d..bda26221c522 100644 --- a/arch/arm/mach-at91/generic.h +++ b/arch/arm/mach-at91/generic.h @@ -12,11 +12,13 @@ extern void __init at91rm9200_initialize(unsigned long main_clock, unsigned short banks); extern void __init at91sam9260_initialize(unsigned long main_clock); extern void __init at91sam9261_initialize(unsigned long main_clock); +extern void __init at91sam9263_initialize(unsigned long main_clock); /* Interrupts */ extern void __init at91rm9200_init_interrupts(unsigned int priority[]); extern void __init at91sam9260_init_interrupts(unsigned int priority[]); extern void __init at91sam9261_init_interrupts(unsigned int priority[]); +extern void __init at91sam9263_init_interrupts(unsigned int priority[]); extern void __init at91_aic_init(unsigned int priority[]); /* Timer */ diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index e095b1fe8d8a..b49bfda53d7f 100644 --- a/arch/arm/mach-at91/pm.c +++ b/arch/arm/mach-at91/pm.c @@ -80,6 +80,8 @@ static int at91_pm_verify_clocks(void) #warning "Check SAM9260 USB clocks" } else if (cpu_is_at91sam9261()) { #warning "Check SAM9261 USB clocks" + } else if (cpu_is_at91sam9263()) { +#warning "Check SAM9263 USB clocks" } #ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index aade2f72c920..b305cbda8b87 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -171,8 +171,8 @@ config CPU_ARM925T # ARM926T config CPU_ARM926T bool "Support ARM926T processor" - depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || MACH_REALVIEW_EB || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261 - default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261 + depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || MACH_REALVIEW_EB || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261 || ARCH_AT91SAM9263 + default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261 || ARCH_AT91SAM9263 select CPU_32v5 select CPU_ABRT_EV5TJ select CPU_CACHE_VIVT diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index 812c733ba8ce..8afecb8a98ee 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -913,7 +913,7 @@ static void pullup(struct at91_udc *udc, int is_on) at91_udp_write(udc, AT91_UDP_TXVC, 0); if (cpu_is_at91rm9200()) at91_set_gpio_value(udc->board.pullup_pin, 1); - else if (cpu_is_at91sam9260()) { + else if (cpu_is_at91sam9260() || cpu_is_at91sam9263()) { u32 txvc = at91_udp_read(udc, AT91_UDP_TXVC); txvc |= AT91_UDP_TXVC_PUON; @@ -930,7 +930,7 @@ static void pullup(struct at91_udc *udc, int is_on) at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS); if (cpu_is_at91rm9200()) at91_set_gpio_value(udc->board.pullup_pin, 0); - else if (cpu_is_at91sam9260()) { + else if (cpu_is_at91sam9260() || cpu_is_at91sam9263()) { u32 txvc = at91_udp_read(udc, AT91_UDP_TXVC); txvc &= ~AT91_UDP_TXVC_PUON; diff --git a/include/asm-arm/arch-at91/at91sam9263.h b/include/asm-arm/arch-at91/at91sam9263.h new file mode 100644 index 000000000000..f4af68ae0ea9 --- /dev/null +++ b/include/asm-arm/arch-at91/at91sam9263.h @@ -0,0 +1,131 @@ +/* + * include/asm-arm/arch-at91/at91sam9263.h + * + * (C) 2007 Atmel Corporation. + * + * Common definitions. + * Based on AT91SAM9263 datasheet revision B (Preliminary). + * + * 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. + */ + +#ifndef AT91SAM9263_H +#define AT91SAM9263_H + +/* + * Peripheral identifiers/interrupts. + */ +#define AT91_ID_FIQ 0 /* Advanced Interrupt Controller (FIQ) */ +#define AT91_ID_SYS 1 /* System Peripherals */ +#define AT91SAM9263_ID_PIOA 2 /* Parallel IO Controller A */ +#define AT91SAM9263_ID_PIOB 3 /* Parallel IO Controller B */ +#define AT91SAM9263_ID_PIOCDE 4 /* Parallel IO Controller C, D and E */ +#define AT91SAM9263_ID_US0 7 /* USART 0 */ +#define AT91SAM9263_ID_US1 8 /* USART 1 */ +#define AT91SAM9263_ID_US2 9 /* USART 2 */ +#define AT91SAM9263_ID_MCI0 10 /* Multimedia Card Interface 0 */ +#define AT91SAM9263_ID_MCI1 11 /* Multimedia Card Interface 1 */ +#define AT91SAM9263_ID_CAN 12 /* CAN */ +#define AT91SAM9263_ID_TWI 13 /* Two-Wire Interface */ +#define AT91SAM9263_ID_SPI0 14 /* Serial Peripheral Interface 0 */ +#define AT91SAM9263_ID_SPI1 15 /* Serial Peripheral Interface 1 */ +#define AT91SAM9263_ID_SSC0 16 /* Serial Synchronous Controller 0 */ +#define AT91SAM9263_ID_SSC1 17 /* Serial Synchronous Controller 1 */ +#define AT91SAM9263_ID_AC97C 18 /* AC97 Controller */ +#define AT91SAM9263_ID_TCB 19 /* Timer Counter 0, 1 and 2 */ +#define AT91SAM9263_ID_PWMC 20 /* Pulse Width Modulation Controller */ +#define AT91SAM9263_ID_EMAC 21 /* Ethernet */ +#define AT91SAM9263_ID_2DGE 23 /* 2D Graphic Engine */ +#define AT91SAM9263_ID_UDP 24 /* USB Device Port */ +#define AT91SAM9263_ID_ISI 25 /* Image Sensor Interface */ +#define AT91SAM9263_ID_LCDC 26 /* LCD Controller */ +#define AT91SAM9263_ID_DMA 27 /* DMA Controller */ +#define AT91SAM9263_ID_UHP 29 /* USB Host port */ +#define AT91SAM9263_ID_IRQ0 30 /* Advanced Interrupt Controller (IRQ0) */ +#define AT91SAM9263_ID_IRQ1 31 /* Advanced Interrupt Controller (IRQ1) */ + + +/* + * User Peripheral physical base addresses. + */ +#define AT91SAM9263_BASE_UDP 0xfff78000 +#define AT91SAM9263_BASE_TCB0 0xfff7c000 +#define AT91SAM9263_BASE_TC0 0xfff7c000 +#define AT91SAM9263_BASE_TC1 0xfff7c040 +#define AT91SAM9263_BASE_TC2 0xfff7c080 +#define AT91SAM9263_BASE_MCI0 0xfff80000 +#define AT91SAM9263_BASE_MCI1 0xfff84000 +#define AT91SAM9263_BASE_TWI 0xfff88000 +#define AT91SAM9263_BASE_US0 0xfff8c000 +#define AT91SAM9263_BASE_US1 0xfff90000 +#define AT91SAM9263_BASE_US2 0xfff94000 +#define AT91SAM9263_BASE_SSC0 0xfff98000 +#define AT91SAM9263_BASE_SSC1 0xfff9c000 +#define AT91SAM9263_BASE_AC97C 0xfffa0000 +#define AT91SAM9263_BASE_SPI0 0xfffa4000 +#define AT91SAM9263_BASE_SPI1 0xfffa8000 +#define AT91SAM9263_BASE_CAN 0xfffac000 +#define AT91SAM9263_BASE_PWMC 0xfffb8000 +#define AT91SAM9263_BASE_EMAC 0xfffbc000 +#define AT91SAM9263_BASE_ISI 0xfffc4000 +#define AT91SAM9263_BASE_2DGE 0xfffc8000 +#define AT91_BASE_SYS 0xffffe000 + +/* + * System Peripherals (offset from AT91_BASE_SYS) + */ +#define AT91_ECC0 (0xffffe000 - AT91_BASE_SYS) +#define AT91_SDRAMC0 (0xffffe200 - AT91_BASE_SYS) +#define AT91_SMC0 (0xffffe400 - AT91_BASE_SYS) +#define AT91_ECC1 (0xffffe600 - AT91_BASE_SYS) +#define AT91_SDRAMC1 (0xffffe800 - AT91_BASE_SYS) +#define AT91_SMC1 (0xffffea00 - AT91_BASE_SYS) +#define AT91_MATRIX (0xffffec00 - AT91_BASE_SYS) +#define AT91_CCFG (0xffffed10 - AT91_BASE_SYS) +#define AT91_DBGU (0xffffee00 - AT91_BASE_SYS) +#define AT91_AIC (0xfffff000 - AT91_BASE_SYS) +#define AT91_PIOA (0xfffff200 - AT91_BASE_SYS) +#define AT91_PIOB (0xfffff400 - AT91_BASE_SYS) +#define AT91_PIOC (0xfffff600 - AT91_BASE_SYS) +#define AT91_PIOD (0xfffff800 - AT91_BASE_SYS) +#define AT91_PIOE (0xfffffa00 - AT91_BASE_SYS) +#define AT91_PMC (0xfffffc00 - AT91_BASE_SYS) +#define AT91_RSTC (0xfffffd00 - AT91_BASE_SYS) +#define AT91_SHDWC (0xfffffd10 - AT91_BASE_SYS) +#define AT91_RTT0 (0xfffffd20 - AT91_BASE_SYS) +#define AT91_PIT (0xfffffd30 - AT91_BASE_SYS) +#define AT91_WDT (0xfffffd40 - AT91_BASE_SYS) +#define AT91_RTT1 (0xfffffd50 - AT91_BASE_SYS) +#define AT91_GPBR (0xfffffd60 - AT91_BASE_SYS) + +#define AT91_SMC AT91_SMC0 + +/* + * Internal Memory. + */ +#define AT91SAM9263_SRAM0_BASE 0x00300000 /* Internal SRAM 0 base address */ +#define AT91SAM9263_SRAM0_SIZE (80 * SZ_1K) /* Internal SRAM 0 size (80Kb) */ + +#define AT91SAM9263_ROM_BASE 0x00400000 /* Internal ROM base address */ +#define AT91SAM9263_ROM_SIZE SZ_128K /* Internal ROM size (128Kb) */ + +#define AT91SAM9263_SRAM1_BASE 0x00500000 /* Internal SRAM 1 base address */ +#define AT91SAM9263_SRAM1_SIZE SZ_16K /* Internal SRAM 1 size (16Kb) */ + +#define AT91SAM9263_LCDC_BASE 0x00700000 /* LCD Controller */ +#define AT91SAM9263_DMAC_BASE 0x00800000 /* DMA Controller */ +#define AT91SAM9263_UHP_BASE 0x00a00000 /* USB Host controller */ + +#if 0 +/* + * PIO pin definitions (peripheral A/B multiplexing). + */ + +// TODO: Add + +#endif + +#endif diff --git a/include/asm-arm/arch-at91/at91sam9263_matrix.h b/include/asm-arm/arch-at91/at91sam9263_matrix.h new file mode 100644 index 000000000000..6fc6e4be624e --- /dev/null +++ b/include/asm-arm/arch-at91/at91sam9263_matrix.h @@ -0,0 +1,129 @@ +/* + * include/asm-arm/arch-at91/at91sam9263_matrix.h + * + * Copyright (C) 2006 Atmel Corporation. + * + * Memory Controllers (MATRIX, EBI) - System peripherals registers. + * Based on AT91SAM9263 datasheet revision B (Preliminary). + * + * 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. + */ + +#ifndef AT91SAM9263_MATRIX_H +#define AT91SAM9263_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_MCFG6 (AT91_MATRIX + 0x18) /* Master Configuration Register 6 */ +#define AT91_MATRIX_MCFG7 (AT91_MATRIX + 0x1C) /* Master Configuration Register 7 */ +#define AT91_MATRIX_MCFG8 (AT91_MATRIX + 0x20) /* Master Configuration Register 8 */ +#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_SCFG5 (AT91_MATRIX + 0x54) /* Slave Configuration Register 5 */ +#define AT91_MATRIX_SCFG6 (AT91_MATRIX + 0x58) /* Slave Configuration Register 6 */ +#define AT91_MATRIX_SCFG7 (AT91_MATRIX + 0x5C) /* Slave Configuration Register 7 */ +#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 (7 << 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_PRBS0 (AT91_MATRIX + 0x84) /* Priority Register B for Slave 0 */ +#define AT91_MATRIX_PRAS1 (AT91_MATRIX + 0x88) /* Priority Register A for Slave 1 */ +#define AT91_MATRIX_PRBS1 (AT91_MATRIX + 0x8C) /* Priority Register B for Slave 1 */ +#define AT91_MATRIX_PRAS2 (AT91_MATRIX + 0x90) /* Priority Register A for Slave 2 */ +#define AT91_MATRIX_PRBS2 (AT91_MATRIX + 0x94) /* Priority Register B for Slave 2 */ +#define AT91_MATRIX_PRAS3 (AT91_MATRIX + 0x98) /* Priority Register A for Slave 3 */ +#define AT91_MATRIX_PRBS3 (AT91_MATRIX + 0x9C) /* Priority Register B for Slave 3 */ +#define AT91_MATRIX_PRAS4 (AT91_MATRIX + 0xA0) /* Priority Register A for Slave 4 */ +#define AT91_MATRIX_PRBS4 (AT91_MATRIX + 0xA4) /* Priority Register B for Slave 4 */ +#define AT91_MATRIX_PRAS5 (AT91_MATRIX + 0xA8) /* Priority Register A for Slave 5 */ +#define AT91_MATRIX_PRBS5 (AT91_MATRIX + 0xAC) /* Priority Register B for Slave 5 */ +#define AT91_MATRIX_PRAS6 (AT91_MATRIX + 0xB0) /* Priority Register A for Slave 6 */ +#define AT91_MATRIX_PRBS6 (AT91_MATRIX + 0xB4) /* Priority Register B for Slave 6 */ +#define AT91_MATRIX_PRAS7 (AT91_MATRIX + 0xB8) /* Priority Register A for Slave 7 */ +#define AT91_MATRIX_PRBS7 (AT91_MATRIX + 0xBC) /* Priority Register B for Slave 7 */ +#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_M7PR (3 << 28) /* Master 7 Priority */ +#define AT91_MATRIX_M8PR (3 << 0) /* Master 8 Priority (in Register B) */ + +#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_RCB2 (1 << 2) +#define AT91_MATRIX_RCB3 (1 << 3) +#define AT91_MATRIX_RCB4 (1 << 4) +#define AT91_MATRIX_RCB5 (1 << 5) +#define AT91_MATRIX_RCB6 (1 << 6) +#define AT91_MATRIX_RCB7 (1 << 7) +#define AT91_MATRIX_RCB8 (1 << 8) + +#define AT91_MATRIX_TCMR (AT91_MATRIX + 0x114) /* 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_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_EBI0CSA (AT91_MATRIX + 0x120) /* EBI0 Chip Select Assignment Register */ +#define AT91_MATRIX_EBI0_CS1A (1 << 1) /* Chip Select 1 Assignment */ +#define AT91_MATRIX_EBI0_CS1A_SMC (0 << 1) +#define AT91_MATRIX_EBI0_CS1A_SDRAMC (1 << 1) +#define AT91_MATRIX_EBI0_CS3A (1 << 3) /* Chip Select 3 Assignment */ +#define AT91_MATRIX_EBI0_CS3A_SMC (0 << 3) +#define AT91_MATRIX_EBI0_CS3A_SMC_SMARTMEDIA (1 << 3) +#define AT91_MATRIX_EBI0_CS4A (1 << 4) /* Chip Select 4 Assignment */ +#define AT91_MATRIX_EBI0_CS4A_SMC (0 << 4) +#define AT91_MATRIX_EBI0_CS4A_SMC_CF1 (1 << 4) +#define AT91_MATRIX_EBI0_CS5A (1 << 5) /* Chip Select 5 Assignment */ +#define AT91_MATRIX_EBI0_CS5A_SMC (0 << 5) +#define AT91_MATRIX_EBI0_CS5A_SMC_CF2 (1 << 5) +#define AT91_MATRIX_EBI0_DBPUC (1 << 8) /* Data Bus Pull-up Configuration */ +#define AT91_MATRIX_EBI0_VDDIOMSEL (1 << 16) /* Memory voltage selection */ +#define AT91_MATRIX_EBI0_VDDIOMSEL_1_8V (0 << 16) +#define AT91_MATRIX_EBI0_VDDIOMSEL_3_3V (1 << 16) + +#define AT91_MATRIX_EBI1CSA (AT91_MATRIX + 0x124) /* EBI1 Chip Select Assignment Register */ +#define AT91_MATRIX_EBI1_CS1A (1 << 1) /* Chip Select 1 Assignment */ +#define AT91_MATRIX_EBI1_CS1A_SMC (0 << 1) +#define AT91_MATRIX_EBI1_CS1A_SDRAMC (1 << 1) +#define AT91_MATRIX_EBI1_CS2A (1 << 3) /* Chip Select 3 Assignment */ +#define AT91_MATRIX_EBI1_CS2A_SMC (0 << 3) +#define AT91_MATRIX_EBI1_CS2A_SMC_SMARTMEDIA (1 << 3) +#define AT91_MATRIX_EBI1_DBPUC (1 << 8) /* Data Bus Pull-up Configuration */ +#define AT91_MATRIX_EBI1_VDDIOMSEL (1 << 16) /* Memory voltage selection */ +#define AT91_MATRIX_EBI1_VDDIOMSEL_1_8V (0 << 16) +#define AT91_MATRIX_EBI1_VDDIOMSEL_3_3V (1 << 16) + +#endif diff --git a/include/asm-arm/arch-at91/at91sam926x_mc.h b/include/asm-arm/arch-at91/at91sam926x_mc.h index 355eee67ebca..d82631c251f1 100644 --- a/include/asm-arm/arch-at91/at91sam926x_mc.h +++ b/include/asm-arm/arch-at91/at91sam926x_mc.h @@ -131,4 +131,11 @@ #define AT91_SMC_PS_16 (2 << 28) #define AT91_SMC_PS_32 (3 << 28) +#if defined(AT91_SMC1) /* The AT91SAM9263 has 2 Static Memory contollers */ +#define AT91_SMC1_SETUP(n) (AT91_SMC1 + 0x00 + ((n)*0x10)) /* Setup Register for CS n */ +#define AT91_SMC1_PULSE(n) (AT91_SMC1 + 0x04 + ((n)*0x10)) /* Pulse Register for CS n */ +#define AT91_SMC1_CYCLE(n) (AT91_SMC1 + 0x08 + ((n)*0x10)) /* Cycle Register for CS n */ +#define AT91_SMC1_MODE(n) (AT91_SMC1 + 0x0c + ((n)*0x10)) /* Mode Register for CS n */ +#endif + #endif diff --git a/include/asm-arm/arch-at91/cpu.h b/include/asm-arm/arch-at91/cpu.h index 762eb41aa675..9efde0dad249 100644 --- a/include/asm-arm/arch-at91/cpu.h +++ b/include/asm-arm/arch-at91/cpu.h @@ -20,6 +20,7 @@ #define ARCH_ID_AT91RM9200 0x09290780 #define ARCH_ID_AT91SAM9260 0x019803a0 #define ARCH_ID_AT91SAM9261 0x019703a0 +#define ARCH_ID_AT91SAM9263 0x019607a0 static inline unsigned long at91_cpu_identify(void) @@ -46,4 +47,10 @@ static inline unsigned long at91_cpu_identify(void) #define cpu_is_at91sam9261() (0) #endif +#ifdef CONFIG_ARCH_AT91SAM9263 +#define cpu_is_at91sam9263() (at91_cpu_identify() == ARCH_ID_AT91SAM9263) +#else +#define cpu_is_at91sam9263() (0) +#endif + #endif diff --git a/include/asm-arm/arch-at91/hardware.h b/include/asm-arm/arch-at91/hardware.h index 1637fc4a0d8f..eaaf1c12b753 100644 --- a/include/asm-arm/arch-at91/hardware.h +++ b/include/asm-arm/arch-at91/hardware.h @@ -22,6 +22,8 @@ #include #elif defined(CONFIG_ARCH_AT91SAM9261) #include +#elif defined(CONFIG_ARCH_AT91SAM9263) +#include #else #error "Unsupported AT91 processor" #endif diff --git a/include/asm-arm/arch-at91/timex.h b/include/asm-arm/arch-at91/timex.h index b24e364997e1..f41636d607a2 100644 --- a/include/asm-arm/arch-at91/timex.h +++ b/include/asm-arm/arch-at91/timex.h @@ -32,6 +32,11 @@ #define AT91SAM9_MASTER_CLOCK 99300000 #define CLOCK_TICK_RATE (AT91SAM9_MASTER_CLOCK/16) +#elif defined(CONFIG_ARCH_AT91SAM9263) + +#define AT91SAM9_MASTER_CLOCK 99959500 +#define CLOCK_TICK_RATE (AT91SAM9_MASTER_CLOCK/16) + #endif #endif -- cgit v1.2.3 From c9b75d132261096ac1170354b9e27837af76a512 Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Thu, 8 Feb 2007 17:36:34 +0100 Subject: [ARM] 4154/1: AT91: Clock update Unconditionally disabling the PCKs (Programmable Clocks) is not a good idea as it breaks boards that depend on those clocks being enabled by bootloaders. Therefore only disable unused clocks late in the init process, giving the board init code the chance to claim the clock. Patch from Steven Scholz. Since the HCK clocks on SAM9261 are already being registered as a independent clocks, we don't need the special case for HCK0 on the SAM9261. Platform-init code and drivers should use the clock API to enable/disable the clock. Patch from Nicolas Ferre. Signed-off-by: Andrew Victor Signed-off-by: Russell King --- arch/arm/mach-at91/clock.c | 62 ++++++++++++++++++++++------------------------ 1 file changed, 29 insertions(+), 33 deletions(-) (limited to 'arch/arm/mach-at91/clock.c') diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c index 27e7279b5b39..f6cb74806043 100644 --- a/arch/arm/mach-at91/clock.c +++ b/arch/arm/mach-at91/clock.c @@ -525,27 +525,6 @@ fail: return 0; } -/* - * Several unused clocks may be active. Turn them off. - */ -static void __init at91_periphclk_reset(void) -{ - unsigned long reg; - struct clk *clk; - - reg = at91_sys_read(AT91_PMC_PCSR); - - list_for_each_entry(clk, &clocks, node) { - if (clk->mode != pmc_periph_mode) - continue; - - if (clk->users > 0) - reg &= ~clk->pmc_mask; - } - - at91_sys_write(AT91_PMC_PCDR, reg); -} - static struct clk *const standard_pmc_clocks[] __initdata = { /* four primary clocks */ &clk32k, @@ -586,7 +565,7 @@ int __init at91_clock_init(unsigned long main_clock) pr_info("Clocks: PLLA overclocked, %ld MHz\n", plla.rate_hz / 1000000); /* - * USB clock init: choose 48 MHz PLLB value, turn all clocks off, + * USB clock init: choose 48 MHz PLLB value, * disable 48MHz clock during usb peripheral suspend. * * REVISIT: assumes MCK doesn't derive from PLLB! @@ -596,16 +575,10 @@ int __init at91_clock_init(unsigned long main_clock) if (cpu_is_at91rm9200()) { uhpck.pmc_mask = AT91RM9200_PMC_UHP; udpck.pmc_mask = AT91RM9200_PMC_UDP; - at91_sys_write(AT91_PMC_SCDR, AT91RM9200_PMC_UHP | AT91RM9200_PMC_UDP); at91_sys_write(AT91_PMC_SCER, AT91RM9200_PMC_MCKUDP); - } else if (cpu_is_at91sam9260() || cpu_is_at91sam9263()) { + } else if (cpu_is_at91sam9260() || cpu_is_at91sam9261() || cpu_is_at91sam9263()) { uhpck.pmc_mask = AT91SAM926x_PMC_UHP; udpck.pmc_mask = AT91SAM926x_PMC_UDP; - at91_sys_write(AT91_PMC_SCDR, AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP); - } else if (cpu_is_at91sam9261()) { - uhpck.pmc_mask = (AT91SAM926x_PMC_UHP | AT91_PMC_HCK0); - udpck.pmc_mask = AT91SAM926x_PMC_UDP; - at91_sys_write(AT91_PMC_SCDR, AT91SAM926x_PMC_UHP | AT91_PMC_HCK0 | AT91SAM926x_PMC_UDP); } at91_sys_write(AT91_CKGR_PLLBR, 0); @@ -634,11 +607,34 @@ int __init at91_clock_init(unsigned long main_clock) (unsigned) main_clock / 1000000, ((unsigned) main_clock % 1000000) / 1000); - /* disable all programmable clocks */ - at91_sys_write(AT91_PMC_SCDR, AT91_PMC_PCK0 | AT91_PMC_PCK1 | AT91_PMC_PCK2 | AT91_PMC_PCK3); + return 0; +} + +/* + * Several unused clocks may be active. Turn them off. + */ +static int __init at91_clock_reset(void) +{ + unsigned long pcdr = 0; + unsigned long scdr = 0; + struct clk *clk; + + list_for_each_entry(clk, &clocks, node) { + if (clk->users > 0) + continue; + + if (clk->mode == pmc_periph_mode) + pcdr |= clk->pmc_mask; + + if (clk->mode == pmc_sys_mode) + scdr |= clk->pmc_mask; + + pr_debug("Clocks: disable unused %s\n", clk->name); + } - /* disable all other unused peripheral clocks */ - at91_periphclk_reset(); + at91_sys_write(AT91_PMC_PCDR, pcdr); + at91_sys_write(AT91_PMC_SCDR, scdr); return 0; } +late_initcall(at91_clock_reset); -- cgit v1.2.3