Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hskinnemoen/avr32-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hskinnemoen/avr32-2.6: [AVR32] Initialize phy_mask for both macb devices [AVR32] Fix atomic_add_unless() and atomic_sub_unless() [AVR32] Correct misspelled CONFIG_BLK_DEV_INITRD variable. [AVR32] Fix build error in parse_tag_rdimg() [AVR32] Don't wire up macb0 unless SW6 is in default position [AVR32] Wire up SSC platform device 0 as TX on ATSTK1000 board [AVR32] Add Atmel SSC driver platform device to AT32AP architecture [AVR32] Remove optimization of unaligned word loads [AVR32] Make STK1000 mux settings configurable [AVR32] CPU frequency scaling for AT32AP [AVR32] Split SM device into PM, RTC, WDT and EIC [AVR32] faster avr32 unaligned access
This commit is contained in:
Коммит
5bae7ac9fe
|
@ -113,6 +113,10 @@ config BOARD_ATNGW100
|
|||
bool "ATNGW100 Network Gateway"
|
||||
endchoice
|
||||
|
||||
if BOARD_ATSTK1000
|
||||
source "arch/avr32/boards/atstk1000/Kconfig"
|
||||
endif
|
||||
|
||||
choice
|
||||
prompt "Boot loader type"
|
||||
default LOADER_U_BOOT
|
||||
|
@ -185,6 +189,27 @@ config CMDLINE
|
|||
|
||||
endmenu
|
||||
|
||||
menu "Power managment options"
|
||||
|
||||
menu "CPU Frequency scaling"
|
||||
|
||||
source "drivers/cpufreq/Kconfig"
|
||||
|
||||
config CPU_FREQ_AT32AP
|
||||
bool "CPU frequency driver for AT32AP"
|
||||
depends on CPU_FREQ && PLATFORM_AT32AP
|
||||
default n
|
||||
help
|
||||
This enables the CPU frequency driver for AT32AP processors.
|
||||
|
||||
For details, take a look in <file:Documentation/cpu-freq>.
|
||||
|
||||
If in doubt, say N.
|
||||
|
||||
endmenu
|
||||
|
||||
endmenu
|
||||
|
||||
menu "Bus options"
|
||||
|
||||
config PCI
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
# STK1000 customization
|
||||
|
||||
if BOARD_ATSTK1002
|
||||
|
||||
config BOARD_ATSTK1002_CUSTOM
|
||||
bool "Non-default STK-1002 jumper settings"
|
||||
help
|
||||
You will normally leave the jumpers on the CPU card at their
|
||||
default settings. If you need to use certain peripherals,
|
||||
you will need to change some of those jumpers.
|
||||
|
||||
if BOARD_ATSTK1002_CUSTOM
|
||||
|
||||
config BOARD_ATSTK1002_SW1_CUSTOM
|
||||
bool "SW1: use SSC1 (not SPI0)"
|
||||
help
|
||||
This also prevents using the external DAC as an audio interface,
|
||||
and means you can't initialize the on-board QVGA display.
|
||||
|
||||
config BOARD_ATSTK1002_SW2_CUSTOM
|
||||
bool "SW2: use IRDA or TIMER0 (not UART-A, MMC/SD, and PS2-A)"
|
||||
help
|
||||
If you change this you'll want an updated boot loader putting
|
||||
the console on UART-C not UART-A.
|
||||
|
||||
config BOARD_ATSTK1002_SW3_CUSTOM
|
||||
bool "SW3: use TIMER1 (not SSC0 and GCLK)"
|
||||
help
|
||||
This also prevents using the external DAC as an audio interface.
|
||||
|
||||
config BOARD_ATSTK1002_SW4_CUSTOM
|
||||
bool "SW4: use ISI/Camera (not GPIOs, SPI1, and PS2-B)"
|
||||
help
|
||||
To use the camera interface you'll need a custom card (on the
|
||||
PCI-format connector) connect a video sensor.
|
||||
|
||||
config BOARD_ATSTK1002_SW5_CUSTOM
|
||||
bool "SW5: use MACB1 (not LCDC)"
|
||||
|
||||
config BOARD_ATSTK1002_SW6_CUSTOM
|
||||
bool "SW6: more GPIOs (not MACB0)"
|
||||
|
||||
endif # custom
|
||||
|
||||
config BOARD_ATSTK1002_SPI1
|
||||
bool "Configure SPI1 controller"
|
||||
depends on !BOARD_ATSTK1002_SW4_CUSTOM
|
||||
help
|
||||
All the signals for the second SPI controller are available on
|
||||
GPIO lines and accessed through the J1 jumper block. Say "y"
|
||||
here to configure that SPI controller.
|
||||
|
||||
endif # stk 1002
|
|
@ -27,15 +27,27 @@
|
|||
|
||||
#include "atstk1000.h"
|
||||
|
||||
#define SW2_DEFAULT /* MMCI and UART_A available */
|
||||
|
||||
struct eth_addr {
|
||||
u8 addr[6];
|
||||
};
|
||||
|
||||
static struct eth_addr __initdata hw_addr[2];
|
||||
static struct eth_platform_data __initdata eth_data[2];
|
||||
static struct eth_platform_data __initdata eth_data[2] = {
|
||||
{
|
||||
/*
|
||||
* The MDIO pullups on STK1000 are a bit too weak for
|
||||
* the autodetection to work properly, so we have to
|
||||
* mask out everything but the correct address.
|
||||
*/
|
||||
.phy_mask = ~(1U << 16),
|
||||
},
|
||||
{
|
||||
.phy_mask = ~(1U << 17),
|
||||
},
|
||||
};
|
||||
|
||||
#ifndef CONFIG_BOARD_ATSTK1002_SW1_CUSTOM
|
||||
static struct spi_board_info spi0_board_info[] __initdata = {
|
||||
{
|
||||
/* QVGA display */
|
||||
|
@ -45,6 +57,13 @@ static struct spi_board_info spi0_board_info[] __initdata = {
|
|||
.mode = SPI_MODE_3,
|
||||
},
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BOARD_ATSTK1002_SPI1
|
||||
static struct spi_board_info spi1_board_info[] __initdata = { {
|
||||
/* patch in custom entries here */
|
||||
} };
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The next two functions should go away as the boot loader is
|
||||
|
@ -103,10 +122,10 @@ static void __init set_hw_addr(struct platform_device *pdev)
|
|||
|
||||
void __init setup_board(void)
|
||||
{
|
||||
#ifdef SW2_DEFAULT
|
||||
at32_map_usart(1, 0); /* USART 1/A: /dev/ttyS0, DB9 */
|
||||
#else
|
||||
#ifdef CONFIG_BOARD_ATSTK1002_SW2_CUSTOM
|
||||
at32_map_usart(0, 1); /* USART 0/B: /dev/ttyS1, IRDA */
|
||||
#else
|
||||
at32_map_usart(1, 0); /* USART 1/A: /dev/ttyS0, DB9 */
|
||||
#endif
|
||||
/* USART 2/unused: expansion connector */
|
||||
at32_map_usart(3, 2); /* USART 3/C: /dev/ttyS2, DB9 */
|
||||
|
@ -140,18 +159,31 @@ static int __init atstk1002_init(void)
|
|||
|
||||
at32_add_system_devices();
|
||||
|
||||
#ifdef SW2_DEFAULT
|
||||
at32_add_device_usart(0);
|
||||
#else
|
||||
#ifdef CONFIG_BOARD_ATSTK1002_SW2_CUSTOM
|
||||
at32_add_device_usart(1);
|
||||
#else
|
||||
at32_add_device_usart(0);
|
||||
#endif
|
||||
at32_add_device_usart(2);
|
||||
|
||||
#ifndef CONFIG_BOARD_ATSTK1002_SW6_CUSTOM
|
||||
set_hw_addr(at32_add_device_eth(0, ð_data[0]));
|
||||
|
||||
#endif
|
||||
#ifndef CONFIG_BOARD_ATSTK1002_SW1_CUSTOM
|
||||
at32_add_device_spi(0, spi0_board_info, ARRAY_SIZE(spi0_board_info));
|
||||
#endif
|
||||
#ifdef CONFIG_BOARD_ATSTK1002_SPI1
|
||||
at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info));
|
||||
#endif
|
||||
#ifdef CONFIG_BOARD_ATSTK1002_SW5_CUSTOM
|
||||
set_hw_addr(at32_add_device_eth(1, ð_data[1]));
|
||||
#else
|
||||
at32_add_device_lcdc(0, &atstk1000_lcdc_data,
|
||||
fbmem_start, fbmem_size);
|
||||
#endif
|
||||
#ifndef CONFIG_BOARD_ATSTK1002_SW3_CUSTOM
|
||||
at32_add_device_ssc(0, ATMEL_SSC_TX);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -313,7 +313,7 @@ __tagtable(ATAG_MEM, parse_tag_mem);
|
|||
|
||||
static int __init parse_tag_rdimg(struct tag *tag)
|
||||
{
|
||||
#ifdef CONFIG_INITRD
|
||||
#ifdef CONFIG_BLK_DEV_INITRD
|
||||
struct tag_mem_range *mem = &tag->u.mem_range;
|
||||
int ret;
|
||||
|
||||
|
@ -323,7 +323,7 @@ static int __init parse_tag_rdimg(struct tag *tag)
|
|||
return 0;
|
||||
}
|
||||
|
||||
ret = add_reserved_region(mem->start, mem->start + mem->size - 1,
|
||||
ret = add_reserved_region(mem->addr, mem->addr + mem->size - 1,
|
||||
"initrd");
|
||||
if (ret) {
|
||||
printk(KERN_WARNING
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
obj-y += at32ap.o clock.o intc.o extint.o pio.o hsmc.o
|
||||
obj-$(CONFIG_CPU_AT32AP7000) += at32ap7000.o
|
||||
obj-$(CONFIG_CPU_AT32AP7000) += time-tc.o
|
||||
obj-$(CONFIG_CPU_FREQ_AT32AP) += cpufreq.o
|
||||
|
|
|
@ -11,41 +11,10 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
|
||||
#include <asm/arch/init.h>
|
||||
#include <asm/arch/sm.h>
|
||||
|
||||
struct at32_sm system_manager;
|
||||
|
||||
static int __init at32_sm_init(void)
|
||||
{
|
||||
struct resource *regs;
|
||||
struct at32_sm *sm = &system_manager;
|
||||
int ret = -ENXIO;
|
||||
|
||||
regs = platform_get_resource(&at32_sm_device, IORESOURCE_MEM, 0);
|
||||
if (!regs)
|
||||
goto fail;
|
||||
|
||||
spin_lock_init(&sm->lock);
|
||||
sm->pdev = &at32_sm_device;
|
||||
|
||||
ret = -ENOMEM;
|
||||
sm->regs = ioremap(regs->start, regs->end - regs->start + 1);
|
||||
if (!sm->regs)
|
||||
goto fail;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
printk(KERN_ERR "Failed to initialize System Manager: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void __init setup_platform(void)
|
||||
{
|
||||
at32_sm_init();
|
||||
at32_clock_init();
|
||||
at32_portmux_init();
|
||||
}
|
||||
|
|
|
@ -17,14 +17,20 @@
|
|||
#include <asm/arch/at32ap7000.h>
|
||||
#include <asm/arch/board.h>
|
||||
#include <asm/arch/portmux.h>
|
||||
#include <asm/arch/sm.h>
|
||||
|
||||
#include <video/atmel_lcdc.h>
|
||||
|
||||
#include "clock.h"
|
||||
#include "hmatrix.h"
|
||||
#include "pio.h"
|
||||
#include "sm.h"
|
||||
#include "pm.h"
|
||||
|
||||
/*
|
||||
* We can reduce the code size a bit by using a constant here. Since
|
||||
* this file is completely chip-specific, it's safe to not use
|
||||
* ioremap. Generic drivers should of course never do this.
|
||||
*/
|
||||
#define AT32_PM_BASE 0xfff00000
|
||||
|
||||
#define PBMEM(base) \
|
||||
{ \
|
||||
|
@ -88,6 +94,8 @@ static struct clk devname##_##_name = { \
|
|||
.index = _index, \
|
||||
}
|
||||
|
||||
static DEFINE_SPINLOCK(pm_lock);
|
||||
|
||||
unsigned long at32ap7000_osc_rates[3] = {
|
||||
[0] = 32768,
|
||||
/* FIXME: these are ATSTK1002-specific */
|
||||
|
@ -104,11 +112,11 @@ static unsigned long pll_get_rate(struct clk *clk, unsigned long control)
|
|||
{
|
||||
unsigned long div, mul, rate;
|
||||
|
||||
if (!(control & SM_BIT(PLLEN)))
|
||||
if (!(control & PM_BIT(PLLEN)))
|
||||
return 0;
|
||||
|
||||
div = SM_BFEXT(PLLDIV, control) + 1;
|
||||
mul = SM_BFEXT(PLLMUL, control) + 1;
|
||||
div = PM_BFEXT(PLLDIV, control) + 1;
|
||||
mul = PM_BFEXT(PLLMUL, control) + 1;
|
||||
|
||||
rate = clk->parent->get_rate(clk->parent);
|
||||
rate = (rate + div / 2) / div;
|
||||
|
@ -121,7 +129,7 @@ static unsigned long pll0_get_rate(struct clk *clk)
|
|||
{
|
||||
u32 control;
|
||||
|
||||
control = sm_readl(&system_manager, PM_PLL0);
|
||||
control = pm_readl(PLL0);
|
||||
|
||||
return pll_get_rate(clk, control);
|
||||
}
|
||||
|
@ -130,7 +138,7 @@ static unsigned long pll1_get_rate(struct clk *clk)
|
|||
{
|
||||
u32 control;
|
||||
|
||||
control = sm_readl(&system_manager, PM_PLL1);
|
||||
control = pm_readl(PLL1);
|
||||
|
||||
return pll_get_rate(clk, control);
|
||||
}
|
||||
|
@ -187,108 +195,139 @@ static unsigned long bus_clk_get_rate(struct clk *clk, unsigned int shift)
|
|||
|
||||
static void cpu_clk_mode(struct clk *clk, int enabled)
|
||||
{
|
||||
struct at32_sm *sm = &system_manager;
|
||||
unsigned long flags;
|
||||
u32 mask;
|
||||
|
||||
spin_lock_irqsave(&sm->lock, flags);
|
||||
mask = sm_readl(sm, PM_CPU_MASK);
|
||||
spin_lock_irqsave(&pm_lock, flags);
|
||||
mask = pm_readl(CPU_MASK);
|
||||
if (enabled)
|
||||
mask |= 1 << clk->index;
|
||||
else
|
||||
mask &= ~(1 << clk->index);
|
||||
sm_writel(sm, PM_CPU_MASK, mask);
|
||||
spin_unlock_irqrestore(&sm->lock, flags);
|
||||
pm_writel(CPU_MASK, mask);
|
||||
spin_unlock_irqrestore(&pm_lock, flags);
|
||||
}
|
||||
|
||||
static unsigned long cpu_clk_get_rate(struct clk *clk)
|
||||
{
|
||||
unsigned long cksel, shift = 0;
|
||||
|
||||
cksel = sm_readl(&system_manager, PM_CKSEL);
|
||||
if (cksel & SM_BIT(CPUDIV))
|
||||
shift = SM_BFEXT(CPUSEL, cksel) + 1;
|
||||
cksel = pm_readl(CKSEL);
|
||||
if (cksel & PM_BIT(CPUDIV))
|
||||
shift = PM_BFEXT(CPUSEL, cksel) + 1;
|
||||
|
||||
return bus_clk_get_rate(clk, shift);
|
||||
}
|
||||
|
||||
static long cpu_clk_set_rate(struct clk *clk, unsigned long rate, int apply)
|
||||
{
|
||||
u32 control;
|
||||
unsigned long parent_rate, child_div, actual_rate, div;
|
||||
|
||||
parent_rate = clk->parent->get_rate(clk->parent);
|
||||
control = pm_readl(CKSEL);
|
||||
|
||||
if (control & PM_BIT(HSBDIV))
|
||||
child_div = 1 << (PM_BFEXT(HSBSEL, control) + 1);
|
||||
else
|
||||
child_div = 1;
|
||||
|
||||
if (rate > 3 * (parent_rate / 4) || child_div == 1) {
|
||||
actual_rate = parent_rate;
|
||||
control &= ~PM_BIT(CPUDIV);
|
||||
} else {
|
||||
unsigned int cpusel;
|
||||
div = (parent_rate + rate / 2) / rate;
|
||||
if (div > child_div)
|
||||
div = child_div;
|
||||
cpusel = (div > 1) ? (fls(div) - 2) : 0;
|
||||
control = PM_BIT(CPUDIV) | PM_BFINS(CPUSEL, cpusel, control);
|
||||
actual_rate = parent_rate / (1 << (cpusel + 1));
|
||||
}
|
||||
|
||||
pr_debug("clk %s: new rate %lu (actual rate %lu)\n",
|
||||
clk->name, rate, actual_rate);
|
||||
|
||||
if (apply)
|
||||
pm_writel(CKSEL, control);
|
||||
|
||||
return actual_rate;
|
||||
}
|
||||
|
||||
static void hsb_clk_mode(struct clk *clk, int enabled)
|
||||
{
|
||||
struct at32_sm *sm = &system_manager;
|
||||
unsigned long flags;
|
||||
u32 mask;
|
||||
|
||||
spin_lock_irqsave(&sm->lock, flags);
|
||||
mask = sm_readl(sm, PM_HSB_MASK);
|
||||
spin_lock_irqsave(&pm_lock, flags);
|
||||
mask = pm_readl(HSB_MASK);
|
||||
if (enabled)
|
||||
mask |= 1 << clk->index;
|
||||
else
|
||||
mask &= ~(1 << clk->index);
|
||||
sm_writel(sm, PM_HSB_MASK, mask);
|
||||
spin_unlock_irqrestore(&sm->lock, flags);
|
||||
pm_writel(HSB_MASK, mask);
|
||||
spin_unlock_irqrestore(&pm_lock, flags);
|
||||
}
|
||||
|
||||
static unsigned long hsb_clk_get_rate(struct clk *clk)
|
||||
{
|
||||
unsigned long cksel, shift = 0;
|
||||
|
||||
cksel = sm_readl(&system_manager, PM_CKSEL);
|
||||
if (cksel & SM_BIT(HSBDIV))
|
||||
shift = SM_BFEXT(HSBSEL, cksel) + 1;
|
||||
cksel = pm_readl(CKSEL);
|
||||
if (cksel & PM_BIT(HSBDIV))
|
||||
shift = PM_BFEXT(HSBSEL, cksel) + 1;
|
||||
|
||||
return bus_clk_get_rate(clk, shift);
|
||||
}
|
||||
|
||||
static void pba_clk_mode(struct clk *clk, int enabled)
|
||||
{
|
||||
struct at32_sm *sm = &system_manager;
|
||||
unsigned long flags;
|
||||
u32 mask;
|
||||
|
||||
spin_lock_irqsave(&sm->lock, flags);
|
||||
mask = sm_readl(sm, PM_PBA_MASK);
|
||||
spin_lock_irqsave(&pm_lock, flags);
|
||||
mask = pm_readl(PBA_MASK);
|
||||
if (enabled)
|
||||
mask |= 1 << clk->index;
|
||||
else
|
||||
mask &= ~(1 << clk->index);
|
||||
sm_writel(sm, PM_PBA_MASK, mask);
|
||||
spin_unlock_irqrestore(&sm->lock, flags);
|
||||
pm_writel(PBA_MASK, mask);
|
||||
spin_unlock_irqrestore(&pm_lock, flags);
|
||||
}
|
||||
|
||||
static unsigned long pba_clk_get_rate(struct clk *clk)
|
||||
{
|
||||
unsigned long cksel, shift = 0;
|
||||
|
||||
cksel = sm_readl(&system_manager, PM_CKSEL);
|
||||
if (cksel & SM_BIT(PBADIV))
|
||||
shift = SM_BFEXT(PBASEL, cksel) + 1;
|
||||
cksel = pm_readl(CKSEL);
|
||||
if (cksel & PM_BIT(PBADIV))
|
||||
shift = PM_BFEXT(PBASEL, cksel) + 1;
|
||||
|
||||
return bus_clk_get_rate(clk, shift);
|
||||
}
|
||||
|
||||
static void pbb_clk_mode(struct clk *clk, int enabled)
|
||||
{
|
||||
struct at32_sm *sm = &system_manager;
|
||||
unsigned long flags;
|
||||
u32 mask;
|
||||
|
||||
spin_lock_irqsave(&sm->lock, flags);
|
||||
mask = sm_readl(sm, PM_PBB_MASK);
|
||||
spin_lock_irqsave(&pm_lock, flags);
|
||||
mask = pm_readl(PBB_MASK);
|
||||
if (enabled)
|
||||
mask |= 1 << clk->index;
|
||||
else
|
||||
mask &= ~(1 << clk->index);
|
||||
sm_writel(sm, PM_PBB_MASK, mask);
|
||||
spin_unlock_irqrestore(&sm->lock, flags);
|
||||
pm_writel(PBB_MASK, mask);
|
||||
spin_unlock_irqrestore(&pm_lock, flags);
|
||||
}
|
||||
|
||||
static unsigned long pbb_clk_get_rate(struct clk *clk)
|
||||
{
|
||||
unsigned long cksel, shift = 0;
|
||||
|
||||
cksel = sm_readl(&system_manager, PM_CKSEL);
|
||||
if (cksel & SM_BIT(PBBDIV))
|
||||
shift = SM_BFEXT(PBBSEL, cksel) + 1;
|
||||
cksel = pm_readl(CKSEL);
|
||||
if (cksel & PM_BIT(PBBDIV))
|
||||
shift = PM_BFEXT(PBBSEL, cksel) + 1;
|
||||
|
||||
return bus_clk_get_rate(clk, shift);
|
||||
}
|
||||
|
@ -296,6 +335,7 @@ static unsigned long pbb_clk_get_rate(struct clk *clk)
|
|||
static struct clk cpu_clk = {
|
||||
.name = "cpu",
|
||||
.get_rate = cpu_clk_get_rate,
|
||||
.set_rate = cpu_clk_set_rate,
|
||||
.users = 1,
|
||||
};
|
||||
static struct clk hsb_clk = {
|
||||
|
@ -327,12 +367,12 @@ static void genclk_mode(struct clk *clk, int enabled)
|
|||
{
|
||||
u32 control;
|
||||
|
||||
control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index);
|
||||
control = pm_readl(GCCTRL(clk->index));
|
||||
if (enabled)
|
||||
control |= SM_BIT(CEN);
|
||||
control |= PM_BIT(CEN);
|
||||
else
|
||||
control &= ~SM_BIT(CEN);
|
||||
sm_writel(&system_manager, PM_GCCTRL + 4 * clk->index, control);
|
||||
control &= ~PM_BIT(CEN);
|
||||
pm_writel(GCCTRL(clk->index), control);
|
||||
}
|
||||
|
||||
static unsigned long genclk_get_rate(struct clk *clk)
|
||||
|
@ -340,9 +380,9 @@ static unsigned long genclk_get_rate(struct clk *clk)
|
|||
u32 control;
|
||||
unsigned long div = 1;
|
||||
|
||||
control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index);
|
||||
if (control & SM_BIT(DIVEN))
|
||||
div = 2 * (SM_BFEXT(DIV, control) + 1);
|
||||
control = pm_readl(GCCTRL(clk->index));
|
||||
if (control & PM_BIT(DIVEN))
|
||||
div = 2 * (PM_BFEXT(DIV, control) + 1);
|
||||
|
||||
return clk->parent->get_rate(clk->parent) / div;
|
||||
}
|
||||
|
@ -353,23 +393,22 @@ static long genclk_set_rate(struct clk *clk, unsigned long rate, int apply)
|
|||
unsigned long parent_rate, actual_rate, div;
|
||||
|
||||
parent_rate = clk->parent->get_rate(clk->parent);
|
||||
control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index);
|
||||
control = pm_readl(GCCTRL(clk->index));
|
||||
|
||||
if (rate > 3 * parent_rate / 4) {
|
||||
actual_rate = parent_rate;
|
||||
control &= ~SM_BIT(DIVEN);
|
||||
control &= ~PM_BIT(DIVEN);
|
||||
} else {
|
||||
div = (parent_rate + rate) / (2 * rate) - 1;
|
||||
control = SM_BFINS(DIV, div, control) | SM_BIT(DIVEN);
|
||||
control = PM_BFINS(DIV, div, control) | PM_BIT(DIVEN);
|
||||
actual_rate = parent_rate / (2 * (div + 1));
|
||||
}
|
||||
|
||||
printk("clk %s: new rate %lu (actual rate %lu)\n",
|
||||
clk->name, rate, actual_rate);
|
||||
dev_dbg(clk->dev, "clk %s: new rate %lu (actual rate %lu)\n",
|
||||
clk->name, rate, actual_rate);
|
||||
|
||||
if (apply)
|
||||
sm_writel(&system_manager, PM_GCCTRL + 4 * clk->index,
|
||||
control);
|
||||
pm_writel(GCCTRL(clk->index), control);
|
||||
|
||||
return actual_rate;
|
||||
}
|
||||
|
@ -378,24 +417,24 @@ int genclk_set_parent(struct clk *clk, struct clk *parent)
|
|||
{
|
||||
u32 control;
|
||||
|
||||
printk("clk %s: new parent %s (was %s)\n",
|
||||
clk->name, parent->name, clk->parent->name);
|
||||
dev_dbg(clk->dev, "clk %s: new parent %s (was %s)\n",
|
||||
clk->name, parent->name, clk->parent->name);
|
||||
|
||||
control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index);
|
||||
control = pm_readl(GCCTRL(clk->index));
|
||||
|
||||
if (parent == &osc1 || parent == &pll1)
|
||||
control |= SM_BIT(OSCSEL);
|
||||
control |= PM_BIT(OSCSEL);
|
||||
else if (parent == &osc0 || parent == &pll0)
|
||||
control &= ~SM_BIT(OSCSEL);
|
||||
control &= ~PM_BIT(OSCSEL);
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
if (parent == &pll0 || parent == &pll1)
|
||||
control |= SM_BIT(PLLSEL);
|
||||
control |= PM_BIT(PLLSEL);
|
||||
else
|
||||
control &= ~SM_BIT(PLLSEL);
|
||||
control &= ~PM_BIT(PLLSEL);
|
||||
|
||||
sm_writel(&system_manager, PM_GCCTRL + 4 * clk->index, control);
|
||||
pm_writel(GCCTRL(clk->index), control);
|
||||
clk->parent = parent;
|
||||
|
||||
return 0;
|
||||
|
@ -408,11 +447,11 @@ static void __init genclk_init_parent(struct clk *clk)
|
|||
|
||||
BUG_ON(clk->index > 7);
|
||||
|
||||
control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index);
|
||||
if (control & SM_BIT(OSCSEL))
|
||||
parent = (control & SM_BIT(PLLSEL)) ? &pll1 : &osc1;
|
||||
control = pm_readl(GCCTRL(clk->index));
|
||||
if (control & PM_BIT(OSCSEL))
|
||||
parent = (control & PM_BIT(PLLSEL)) ? &pll1 : &osc1;
|
||||
else
|
||||
parent = (control & SM_BIT(PLLSEL)) ? &pll0 : &osc0;
|
||||
parent = (control & PM_BIT(PLLSEL)) ? &pll0 : &osc0;
|
||||
|
||||
clk->parent = parent;
|
||||
}
|
||||
|
@ -420,21 +459,53 @@ static void __init genclk_init_parent(struct clk *clk)
|
|||
/* --------------------------------------------------------------------
|
||||
* System peripherals
|
||||
* -------------------------------------------------------------------- */
|
||||
static struct resource sm_resource[] = {
|
||||
PBMEM(0xfff00000),
|
||||
NAMED_IRQ(19, "eim"),
|
||||
NAMED_IRQ(20, "pm"),
|
||||
NAMED_IRQ(21, "rtc"),
|
||||
static struct resource at32_pm0_resource[] = {
|
||||
{
|
||||
.start = 0xfff00000,
|
||||
.end = 0xfff0007f,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
IRQ(20),
|
||||
};
|
||||
struct platform_device at32_sm_device = {
|
||||
.name = "sm",
|
||||
.id = 0,
|
||||
.resource = sm_resource,
|
||||
.num_resources = ARRAY_SIZE(sm_resource),
|
||||
|
||||
static struct resource at32ap700x_rtc0_resource[] = {
|
||||
{
|
||||
.start = 0xfff00080,
|
||||
.end = 0xfff000af,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
IRQ(21),
|
||||
};
|
||||
static struct clk at32_sm_pclk = {
|
||||
|
||||
static struct resource at32_wdt0_resource[] = {
|
||||
{
|
||||
.start = 0xfff000b0,
|
||||
.end = 0xfff000bf,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource at32_eic0_resource[] = {
|
||||
{
|
||||
.start = 0xfff00100,
|
||||
.end = 0xfff0013f,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
IRQ(19),
|
||||
};
|
||||
|
||||
DEFINE_DEV(at32_pm, 0);
|
||||
DEFINE_DEV(at32ap700x_rtc, 0);
|
||||
DEFINE_DEV(at32_wdt, 0);
|
||||
DEFINE_DEV(at32_eic, 0);
|
||||
|
||||
/*
|
||||
* Peripheral clock for PM, RTC, WDT and EIC. PM will ensure that this
|
||||
* is always running.
|
||||
*/
|
||||
static struct clk at32_pm_pclk = {
|
||||
.name = "pclk",
|
||||
.dev = &at32_sm_device.dev,
|
||||
.dev = &at32_pm0_device.dev,
|
||||
.parent = &pbb_clk,
|
||||
.mode = pbb_clk_mode,
|
||||
.get_rate = pbb_clk_get_rate,
|
||||
|
@ -583,10 +654,11 @@ DEV_CLK(mck, pio4, pba, 14);
|
|||
|
||||
void __init at32_add_system_devices(void)
|
||||
{
|
||||
system_manager.eim_first_irq = EIM_IRQ_BASE;
|
||||
|
||||
platform_device_register(&at32_sm_device);
|
||||
platform_device_register(&at32_pm0_device);
|
||||
platform_device_register(&at32_intc0_device);
|
||||
platform_device_register(&at32ap700x_rtc0_device);
|
||||
platform_device_register(&at32_wdt0_device);
|
||||
platform_device_register(&at32_eic0_device);
|
||||
platform_device_register(&smc0_device);
|
||||
platform_device_register(&pdc_device);
|
||||
|
||||
|
@ -1012,6 +1084,89 @@ err_dup_modedb:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* SSC
|
||||
* -------------------------------------------------------------------- */
|
||||
static struct resource ssc0_resource[] = {
|
||||
PBMEM(0xffe01c00),
|
||||
IRQ(10),
|
||||
};
|
||||
DEFINE_DEV(ssc, 0);
|
||||
DEV_CLK(pclk, ssc0, pba, 7);
|
||||
|
||||
static struct resource ssc1_resource[] = {
|
||||
PBMEM(0xffe02000),
|
||||
IRQ(11),
|
||||
};
|
||||
DEFINE_DEV(ssc, 1);
|
||||
DEV_CLK(pclk, ssc1, pba, 8);
|
||||
|
||||
static struct resource ssc2_resource[] = {
|
||||
PBMEM(0xffe02400),
|
||||
IRQ(12),
|
||||
};
|
||||
DEFINE_DEV(ssc, 2);
|
||||
DEV_CLK(pclk, ssc2, pba, 9);
|
||||
|
||||
struct platform_device *__init
|
||||
at32_add_device_ssc(unsigned int id, unsigned int flags)
|
||||
{
|
||||
struct platform_device *pdev;
|
||||
|
||||
switch (id) {
|
||||
case 0:
|
||||
pdev = &ssc0_device;
|
||||
if (flags & ATMEL_SSC_RF)
|
||||
select_peripheral(PA(21), PERIPH_A, 0); /* RF */
|
||||
if (flags & ATMEL_SSC_RK)
|
||||
select_peripheral(PA(22), PERIPH_A, 0); /* RK */
|
||||
if (flags & ATMEL_SSC_TK)
|
||||
select_peripheral(PA(23), PERIPH_A, 0); /* TK */
|
||||
if (flags & ATMEL_SSC_TF)
|
||||
select_peripheral(PA(24), PERIPH_A, 0); /* TF */
|
||||
if (flags & ATMEL_SSC_TD)
|
||||
select_peripheral(PA(25), PERIPH_A, 0); /* TD */
|
||||
if (flags & ATMEL_SSC_RD)
|
||||
select_peripheral(PA(26), PERIPH_A, 0); /* RD */
|
||||
break;
|
||||
case 1:
|
||||
pdev = &ssc1_device;
|
||||
if (flags & ATMEL_SSC_RF)
|
||||
select_peripheral(PA(0), PERIPH_B, 0); /* RF */
|
||||
if (flags & ATMEL_SSC_RK)
|
||||
select_peripheral(PA(1), PERIPH_B, 0); /* RK */
|
||||
if (flags & ATMEL_SSC_TK)
|
||||
select_peripheral(PA(2), PERIPH_B, 0); /* TK */
|
||||
if (flags & ATMEL_SSC_TF)
|
||||
select_peripheral(PA(3), PERIPH_B, 0); /* TF */
|
||||
if (flags & ATMEL_SSC_TD)
|
||||
select_peripheral(PA(4), PERIPH_B, 0); /* TD */
|
||||
if (flags & ATMEL_SSC_RD)
|
||||
select_peripheral(PA(5), PERIPH_B, 0); /* RD */
|
||||
break;
|
||||
case 2:
|
||||
pdev = &ssc2_device;
|
||||
if (flags & ATMEL_SSC_TD)
|
||||
select_peripheral(PB(13), PERIPH_A, 0); /* TD */
|
||||
if (flags & ATMEL_SSC_RD)
|
||||
select_peripheral(PB(14), PERIPH_A, 0); /* RD */
|
||||
if (flags & ATMEL_SSC_TK)
|
||||
select_peripheral(PB(15), PERIPH_A, 0); /* TK */
|
||||
if (flags & ATMEL_SSC_TF)
|
||||
select_peripheral(PB(16), PERIPH_A, 0); /* TF */
|
||||
if (flags & ATMEL_SSC_RF)
|
||||
select_peripheral(PB(17), PERIPH_A, 0); /* RF */
|
||||
if (flags & ATMEL_SSC_RK)
|
||||
select_peripheral(PB(18), PERIPH_A, 0); /* RK */
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
platform_device_register(pdev);
|
||||
return pdev;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* GCLK
|
||||
* -------------------------------------------------------------------- */
|
||||
|
@ -1066,7 +1221,7 @@ struct clk *at32_clock_list[] = {
|
|||
&hsb_clk,
|
||||
&pba_clk,
|
||||
&pbb_clk,
|
||||
&at32_sm_pclk,
|
||||
&at32_pm_pclk,
|
||||
&at32_intc0_pclk,
|
||||
&hmatrix_clk,
|
||||
&ebi_clk,
|
||||
|
@ -1094,6 +1249,9 @@ struct clk *at32_clock_list[] = {
|
|||
&atmel_spi1_spi_clk,
|
||||
&atmel_lcdfb0_hck1,
|
||||
&atmel_lcdfb0_pixclk,
|
||||
&ssc0_pclk,
|
||||
&ssc1_pclk,
|
||||
&ssc2_pclk,
|
||||
&gclk0,
|
||||
&gclk1,
|
||||
&gclk2,
|
||||
|
@ -1113,18 +1271,20 @@ void __init at32_portmux_init(void)
|
|||
|
||||
void __init at32_clock_init(void)
|
||||
{
|
||||
struct at32_sm *sm = &system_manager;
|
||||
u32 cpu_mask = 0, hsb_mask = 0, pba_mask = 0, pbb_mask = 0;
|
||||
int i;
|
||||
|
||||
if (sm_readl(sm, PM_MCCTRL) & SM_BIT(PLLSEL))
|
||||
if (pm_readl(MCCTRL) & PM_BIT(PLLSEL)) {
|
||||
main_clock = &pll0;
|
||||
else
|
||||
cpu_clk.parent = &pll0;
|
||||
} else {
|
||||
main_clock = &osc0;
|
||||
cpu_clk.parent = &osc0;
|
||||
}
|
||||
|
||||
if (sm_readl(sm, PM_PLL0) & SM_BIT(PLLOSC))
|
||||
if (pm_readl(PLL0) & PM_BIT(PLLOSC))
|
||||
pll0.parent = &osc1;
|
||||
if (sm_readl(sm, PM_PLL1) & SM_BIT(PLLOSC))
|
||||
if (pm_readl(PLL1) & PM_BIT(PLLOSC))
|
||||
pll1.parent = &osc1;
|
||||
|
||||
genclk_init_parent(&gclk0);
|
||||
|
@ -1157,8 +1317,8 @@ void __init at32_clock_init(void)
|
|||
pbb_mask |= 1 << clk->index;
|
||||
}
|
||||
|
||||
sm_writel(sm, PM_CPU_MASK, cpu_mask);
|
||||
sm_writel(sm, PM_HSB_MASK, hsb_mask);
|
||||
sm_writel(sm, PM_PBA_MASK, pba_mask);
|
||||
sm_writel(sm, PM_PBB_MASK, pbb_mask);
|
||||
pm_writel(CPU_MASK, cpu_mask);
|
||||
pm_writel(HSB_MASK, hsb_mask);
|
||||
pm_writel(PBA_MASK, pba_mask);
|
||||
pm_writel(PBB_MASK, pbb_mask);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* Copyright (C) 2004-2007 Atmel Corporation
|
||||
*
|
||||
* Based on MIPS implementation arch/mips/kernel/time.c
|
||||
* Copyright 2001 MontaVista Software Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/*#define DEBUG*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/cpufreq.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/err.h>
|
||||
#include <asm/system.h>
|
||||
|
||||
static struct clk *cpuclk;
|
||||
|
||||
static int at32_verify_speed(struct cpufreq_policy *policy)
|
||||
{
|
||||
if (policy->cpu != 0)
|
||||
return -EINVAL;
|
||||
|
||||
cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
|
||||
policy->cpuinfo.max_freq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int at32_get_speed(unsigned int cpu)
|
||||
{
|
||||
/* No SMP support */
|
||||
if (cpu)
|
||||
return 0;
|
||||
return (unsigned int)((clk_get_rate(cpuclk) + 500) / 1000);
|
||||
}
|
||||
|
||||
static int at32_set_target(struct cpufreq_policy *policy,
|
||||
unsigned int target_freq,
|
||||
unsigned int relation)
|
||||
{
|
||||
struct cpufreq_freqs freqs;
|
||||
long freq;
|
||||
|
||||
/* Convert target_freq from kHz to Hz */
|
||||
freq = clk_round_rate(cpuclk, target_freq * 1000);
|
||||
|
||||
/* Check if policy->min <= new_freq <= policy->max */
|
||||
if(freq < (policy->min * 1000) || freq > (policy->max * 1000))
|
||||
return -EINVAL;
|
||||
|
||||
pr_debug("cpufreq: requested frequency %u Hz\n", target_freq * 1000);
|
||||
|
||||
freqs.old = at32_get_speed(0);
|
||||
freqs.new = (freq + 500) / 1000;
|
||||
freqs.cpu = 0;
|
||||
freqs.flags = 0;
|
||||
|
||||
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
|
||||
clk_set_rate(cpuclk, freq);
|
||||
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
|
||||
|
||||
pr_debug("cpufreq: set frequency %lu Hz\n", freq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init at32_cpufreq_driver_init(struct cpufreq_policy *policy)
|
||||
{
|
||||
if (policy->cpu != 0)
|
||||
return -EINVAL;
|
||||
|
||||
cpuclk = clk_get(NULL, "cpu");
|
||||
if (IS_ERR(cpuclk)) {
|
||||
pr_debug("cpufreq: could not get CPU clk\n");
|
||||
return PTR_ERR(cpuclk);
|
||||
}
|
||||
|
||||
policy->cpuinfo.min_freq = (clk_round_rate(cpuclk, 1) + 500) / 1000;
|
||||
policy->cpuinfo.max_freq = (clk_round_rate(cpuclk, ~0UL) + 500) / 1000;
|
||||
policy->cpuinfo.transition_latency = 0;
|
||||
policy->cur = at32_get_speed(0);
|
||||
policy->min = policy->cpuinfo.min_freq;
|
||||
policy->max = policy->cpuinfo.max_freq;
|
||||
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
|
||||
|
||||
printk("cpufreq: AT32AP CPU frequency driver\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct cpufreq_driver at32_driver = {
|
||||
.name = "at32ap",
|
||||
.owner = THIS_MODULE,
|
||||
.init = at32_cpufreq_driver_init,
|
||||
.verify = at32_verify_speed,
|
||||
.target = at32_set_target,
|
||||
.get = at32_get_speed,
|
||||
.flags = CPUFREQ_STICKY,
|
||||
};
|
||||
|
||||
static int __init at32_cpufreq_init(void)
|
||||
{
|
||||
return cpufreq_register_driver(&at32_driver);
|
||||
}
|
||||
|
||||
arch_initcall(at32_cpufreq_init);
|
|
@ -17,42 +17,83 @@
|
|||
|
||||
#include <asm/io.h>
|
||||
|
||||
#include <asm/arch/sm.h>
|
||||
/* EIC register offsets */
|
||||
#define EIC_IER 0x0000
|
||||
#define EIC_IDR 0x0004
|
||||
#define EIC_IMR 0x0008
|
||||
#define EIC_ISR 0x000c
|
||||
#define EIC_ICR 0x0010
|
||||
#define EIC_MODE 0x0014
|
||||
#define EIC_EDGE 0x0018
|
||||
#define EIC_LEVEL 0x001c
|
||||
#define EIC_TEST 0x0020
|
||||
#define EIC_NMIC 0x0024
|
||||
|
||||
#include "sm.h"
|
||||
/* Bitfields in TEST */
|
||||
#define EIC_TESTEN_OFFSET 31
|
||||
#define EIC_TESTEN_SIZE 1
|
||||
|
||||
static void eim_ack_irq(unsigned int irq)
|
||||
/* Bitfields in NMIC */
|
||||
#define EIC_EN_OFFSET 0
|
||||
#define EIC_EN_SIZE 1
|
||||
|
||||
/* Bit manipulation macros */
|
||||
#define EIC_BIT(name) \
|
||||
(1 << EIC_##name##_OFFSET)
|
||||
#define EIC_BF(name,value) \
|
||||
(((value) & ((1 << EIC_##name##_SIZE) - 1)) \
|
||||
<< EIC_##name##_OFFSET)
|
||||
#define EIC_BFEXT(name,value) \
|
||||
(((value) >> EIC_##name##_OFFSET) \
|
||||
& ((1 << EIC_##name##_SIZE) - 1))
|
||||
#define EIC_BFINS(name,value,old) \
|
||||
(((old) & ~(((1 << EIC_##name##_SIZE) - 1) \
|
||||
<< EIC_##name##_OFFSET)) \
|
||||
| EIC_BF(name,value))
|
||||
|
||||
/* Register access macros */
|
||||
#define eic_readl(port,reg) \
|
||||
__raw_readl((port)->regs + EIC_##reg)
|
||||
#define eic_writel(port,reg,value) \
|
||||
__raw_writel((value), (port)->regs + EIC_##reg)
|
||||
|
||||
struct eic {
|
||||
void __iomem *regs;
|
||||
struct irq_chip *chip;
|
||||
unsigned int first_irq;
|
||||
};
|
||||
|
||||
static void eic_ack_irq(unsigned int irq)
|
||||
{
|
||||
struct at32_sm *sm = get_irq_chip_data(irq);
|
||||
sm_writel(sm, EIM_ICR, 1 << (irq - sm->eim_first_irq));
|
||||
struct eic *eic = get_irq_chip_data(irq);
|
||||
eic_writel(eic, ICR, 1 << (irq - eic->first_irq));
|
||||
}
|
||||
|
||||
static void eim_mask_irq(unsigned int irq)
|
||||
static void eic_mask_irq(unsigned int irq)
|
||||
{
|
||||
struct at32_sm *sm = get_irq_chip_data(irq);
|
||||
sm_writel(sm, EIM_IDR, 1 << (irq - sm->eim_first_irq));
|
||||
struct eic *eic = get_irq_chip_data(irq);
|
||||
eic_writel(eic, IDR, 1 << (irq - eic->first_irq));
|
||||
}
|
||||
|
||||
static void eim_mask_ack_irq(unsigned int irq)
|
||||
static void eic_mask_ack_irq(unsigned int irq)
|
||||
{
|
||||
struct at32_sm *sm = get_irq_chip_data(irq);
|
||||
sm_writel(sm, EIM_ICR, 1 << (irq - sm->eim_first_irq));
|
||||
sm_writel(sm, EIM_IDR, 1 << (irq - sm->eim_first_irq));
|
||||
struct eic *eic = get_irq_chip_data(irq);
|
||||
eic_writel(eic, ICR, 1 << (irq - eic->first_irq));
|
||||
eic_writel(eic, IDR, 1 << (irq - eic->first_irq));
|
||||
}
|
||||
|
||||
static void eim_unmask_irq(unsigned int irq)
|
||||
static void eic_unmask_irq(unsigned int irq)
|
||||
{
|
||||
struct at32_sm *sm = get_irq_chip_data(irq);
|
||||
sm_writel(sm, EIM_IER, 1 << (irq - sm->eim_first_irq));
|
||||
struct eic *eic = get_irq_chip_data(irq);
|
||||
eic_writel(eic, IER, 1 << (irq - eic->first_irq));
|
||||
}
|
||||
|
||||
static int eim_set_irq_type(unsigned int irq, unsigned int flow_type)
|
||||
static int eic_set_irq_type(unsigned int irq, unsigned int flow_type)
|
||||
{
|
||||
struct at32_sm *sm = get_irq_chip_data(irq);
|
||||
struct eic *eic = get_irq_chip_data(irq);
|
||||
struct irq_desc *desc;
|
||||
unsigned int i = irq - sm->eim_first_irq;
|
||||
unsigned int i = irq - eic->first_irq;
|
||||
u32 mode, edge, level;
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
|
||||
flow_type &= IRQ_TYPE_SENSE_MASK;
|
||||
|
@ -60,11 +101,10 @@ static int eim_set_irq_type(unsigned int irq, unsigned int flow_type)
|
|||
flow_type = IRQ_TYPE_LEVEL_LOW;
|
||||
|
||||
desc = &irq_desc[irq];
|
||||
spin_lock_irqsave(&sm->lock, flags);
|
||||
|
||||
mode = sm_readl(sm, EIM_MODE);
|
||||
edge = sm_readl(sm, EIM_EDGE);
|
||||
level = sm_readl(sm, EIM_LEVEL);
|
||||
mode = eic_readl(eic, MODE);
|
||||
edge = eic_readl(eic, EDGE);
|
||||
level = eic_readl(eic, LEVEL);
|
||||
|
||||
switch (flow_type) {
|
||||
case IRQ_TYPE_LEVEL_LOW:
|
||||
|
@ -89,9 +129,9 @@ static int eim_set_irq_type(unsigned int irq, unsigned int flow_type)
|
|||
}
|
||||
|
||||
if (ret == 0) {
|
||||
sm_writel(sm, EIM_MODE, mode);
|
||||
sm_writel(sm, EIM_EDGE, edge);
|
||||
sm_writel(sm, EIM_LEVEL, level);
|
||||
eic_writel(eic, MODE, mode);
|
||||
eic_writel(eic, EDGE, edge);
|
||||
eic_writel(eic, LEVEL, level);
|
||||
|
||||
if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
|
||||
flow_type |= IRQ_LEVEL;
|
||||
|
@ -99,35 +139,33 @@ static int eim_set_irq_type(unsigned int irq, unsigned int flow_type)
|
|||
desc->status |= flow_type;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&sm->lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct irq_chip eim_chip = {
|
||||
.name = "eim",
|
||||
.ack = eim_ack_irq,
|
||||
.mask = eim_mask_irq,
|
||||
.mask_ack = eim_mask_ack_irq,
|
||||
.unmask = eim_unmask_irq,
|
||||
.set_type = eim_set_irq_type,
|
||||
struct irq_chip eic_chip = {
|
||||
.name = "eic",
|
||||
.ack = eic_ack_irq,
|
||||
.mask = eic_mask_irq,
|
||||
.mask_ack = eic_mask_ack_irq,
|
||||
.unmask = eic_unmask_irq,
|
||||
.set_type = eic_set_irq_type,
|
||||
};
|
||||
|
||||
static void demux_eim_irq(unsigned int irq, struct irq_desc *desc)
|
||||
static void demux_eic_irq(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
struct at32_sm *sm = desc->handler_data;
|
||||
struct eic *eic = desc->handler_data;
|
||||
struct irq_desc *ext_desc;
|
||||
unsigned long status, pending;
|
||||
unsigned int i, ext_irq;
|
||||
|
||||
status = sm_readl(sm, EIM_ISR);
|
||||
pending = status & sm_readl(sm, EIM_IMR);
|
||||
status = eic_readl(eic, ISR);
|
||||
pending = status & eic_readl(eic, IMR);
|
||||
|
||||
while (pending) {
|
||||
i = fls(pending) - 1;
|
||||
pending &= ~(1 << i);
|
||||
|
||||
ext_irq = i + sm->eim_first_irq;
|
||||
ext_irq = i + eic->first_irq;
|
||||
ext_desc = irq_desc + ext_irq;
|
||||
if (ext_desc->status & IRQ_LEVEL)
|
||||
handle_level_irq(ext_irq, ext_desc);
|
||||
|
@ -136,51 +174,85 @@ static void demux_eim_irq(unsigned int irq, struct irq_desc *desc)
|
|||
}
|
||||
}
|
||||
|
||||
static int __init eim_init(void)
|
||||
static int __init eic_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct at32_sm *sm = &system_manager;
|
||||
struct eic *eic;
|
||||
struct resource *regs;
|
||||
unsigned int i;
|
||||
unsigned int nr_irqs;
|
||||
unsigned int int_irq;
|
||||
int ret;
|
||||
u32 pattern;
|
||||
|
||||
/*
|
||||
* The EIM is really the same module as SM, so register
|
||||
* mapping, etc. has been taken care of already.
|
||||
*/
|
||||
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
int_irq = platform_get_irq(pdev, 0);
|
||||
if (!regs || !int_irq) {
|
||||
dev_dbg(&pdev->dev, "missing regs and/or irq resource\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
ret = -ENOMEM;
|
||||
eic = kzalloc(sizeof(struct eic), GFP_KERNEL);
|
||||
if (!eic) {
|
||||
dev_dbg(&pdev->dev, "no memory for eic structure\n");
|
||||
goto err_kzalloc;
|
||||
}
|
||||
|
||||
eic->first_irq = EIM_IRQ_BASE + 32 * pdev->id;
|
||||
eic->regs = ioremap(regs->start, regs->end - regs->start + 1);
|
||||
if (!eic->regs) {
|
||||
dev_dbg(&pdev->dev, "failed to map regs\n");
|
||||
goto err_ioremap;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find out how many interrupt lines that are actually
|
||||
* implemented in hardware.
|
||||
*/
|
||||
sm_writel(sm, EIM_IDR, ~0UL);
|
||||
sm_writel(sm, EIM_MODE, ~0UL);
|
||||
pattern = sm_readl(sm, EIM_MODE);
|
||||
eic_writel(eic, IDR, ~0UL);
|
||||
eic_writel(eic, MODE, ~0UL);
|
||||
pattern = eic_readl(eic, MODE);
|
||||
nr_irqs = fls(pattern);
|
||||
|
||||
/* Trigger on falling edge unless overridden by driver */
|
||||
sm_writel(sm, EIM_MODE, 0UL);
|
||||
sm_writel(sm, EIM_EDGE, 0UL);
|
||||
eic_writel(eic, MODE, 0UL);
|
||||
eic_writel(eic, EDGE, 0UL);
|
||||
|
||||
sm->eim_chip = &eim_chip;
|
||||
eic->chip = &eic_chip;
|
||||
|
||||
for (i = 0; i < nr_irqs; i++) {
|
||||
/* NOTE the handler we set here is ignored by the demux */
|
||||
set_irq_chip_and_handler(sm->eim_first_irq + i, &eim_chip,
|
||||
set_irq_chip_and_handler(eic->first_irq + i, &eic_chip,
|
||||
handle_level_irq);
|
||||
set_irq_chip_data(sm->eim_first_irq + i, sm);
|
||||
set_irq_chip_data(eic->first_irq + i, eic);
|
||||
}
|
||||
|
||||
int_irq = platform_get_irq_byname(sm->pdev, "eim");
|
||||
set_irq_chained_handler(int_irq, demux_eic_irq);
|
||||
set_irq_data(int_irq, eic);
|
||||
|
||||
set_irq_chained_handler(int_irq, demux_eim_irq);
|
||||
set_irq_data(int_irq, sm);
|
||||
|
||||
printk("EIM: External Interrupt Module at 0x%p, IRQ %u\n",
|
||||
sm->regs, int_irq);
|
||||
printk("EIM: Handling %u external IRQs, starting with IRQ %u\n",
|
||||
nr_irqs, sm->eim_first_irq);
|
||||
dev_info(&pdev->dev,
|
||||
"External Interrupt Controller at 0x%p, IRQ %u\n",
|
||||
eic->regs, int_irq);
|
||||
dev_info(&pdev->dev,
|
||||
"Handling %u external IRQs, starting with IRQ %u\n",
|
||||
nr_irqs, eic->first_irq);
|
||||
|
||||
return 0;
|
||||
|
||||
err_ioremap:
|
||||
kfree(eic);
|
||||
err_kzalloc:
|
||||
return ret;
|
||||
}
|
||||
arch_initcall(eim_init);
|
||||
|
||||
static struct platform_driver eic_driver = {
|
||||
.driver = {
|
||||
.name = "at32_eic",
|
||||
},
|
||||
};
|
||||
|
||||
static int __init eic_init(void)
|
||||
{
|
||||
return platform_driver_probe(&eic_driver, eic_probe);
|
||||
}
|
||||
arch_initcall(eic_init);
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* Register definitions for the Power Manager (PM)
|
||||
*/
|
||||
#ifndef __ARCH_AVR32_MACH_AT32AP_PM_H__
|
||||
#define __ARCH_AVR32_MACH_AT32AP_PM_H__
|
||||
|
||||
/* PM register offsets */
|
||||
#define PM_MCCTRL 0x0000
|
||||
#define PM_CKSEL 0x0004
|
||||
#define PM_CPU_MASK 0x0008
|
||||
#define PM_HSB_MASK 0x000c
|
||||
#define PM_PBA_MASK 0x0010
|
||||
#define PM_PBB_MASK 0x0014
|
||||
#define PM_PLL0 0x0020
|
||||
#define PM_PLL1 0x0024
|
||||
#define PM_IER 0x0040
|
||||
#define PM_IDR 0x0044
|
||||
#define PM_IMR 0x0048
|
||||
#define PM_ISR 0x004c
|
||||
#define PM_ICR 0x0050
|
||||
#define PM_GCCTRL(x) (0x0060 + 4 * (x))
|
||||
#define PM_RCAUSE 0x00c0
|
||||
|
||||
/* Bitfields in CKSEL */
|
||||
#define PM_CPUSEL_OFFSET 0
|
||||
#define PM_CPUSEL_SIZE 3
|
||||
#define PM_CPUDIV_OFFSET 7
|
||||
#define PM_CPUDIV_SIZE 1
|
||||
#define PM_HSBSEL_OFFSET 8
|
||||
#define PM_HSBSEL_SIZE 3
|
||||
#define PM_HSBDIV_OFFSET 15
|
||||
#define PM_HSBDIV_SIZE 1
|
||||
#define PM_PBASEL_OFFSET 16
|
||||
#define PM_PBASEL_SIZE 3
|
||||
#define PM_PBADIV_OFFSET 23
|
||||
#define PM_PBADIV_SIZE 1
|
||||
#define PM_PBBSEL_OFFSET 24
|
||||
#define PM_PBBSEL_SIZE 3
|
||||
#define PM_PBBDIV_OFFSET 31
|
||||
#define PM_PBBDIV_SIZE 1
|
||||
|
||||
/* Bitfields in PLL0 */
|
||||
#define PM_PLLEN_OFFSET 0
|
||||
#define PM_PLLEN_SIZE 1
|
||||
#define PM_PLLOSC_OFFSET 1
|
||||
#define PM_PLLOSC_SIZE 1
|
||||
#define PM_PLLOPT_OFFSET 2
|
||||
#define PM_PLLOPT_SIZE 3
|
||||
#define PM_PLLDIV_OFFSET 8
|
||||
#define PM_PLLDIV_SIZE 8
|
||||
#define PM_PLLMUL_OFFSET 16
|
||||
#define PM_PLLMUL_SIZE 8
|
||||
#define PM_PLLCOUNT_OFFSET 24
|
||||
#define PM_PLLCOUNT_SIZE 6
|
||||
#define PM_PLLTEST_OFFSET 31
|
||||
#define PM_PLLTEST_SIZE 1
|
||||
|
||||
/* Bitfields in ICR */
|
||||
#define PM_LOCK0_OFFSET 0
|
||||
#define PM_LOCK0_SIZE 1
|
||||
#define PM_LOCK1_OFFSET 1
|
||||
#define PM_LOCK1_SIZE 1
|
||||
#define PM_WAKE_OFFSET 2
|
||||
#define PM_WAKE_SIZE 1
|
||||
#define PM_CKRDY_OFFSET 5
|
||||
#define PM_CKRDY_SIZE 1
|
||||
#define PM_MSKRDY_OFFSET 6
|
||||
#define PM_MSKRDY_SIZE 1
|
||||
|
||||
/* Bitfields in GCCTRL0 */
|
||||
#define PM_OSCSEL_OFFSET 0
|
||||
#define PM_OSCSEL_SIZE 1
|
||||
#define PM_PLLSEL_OFFSET 1
|
||||
#define PM_PLLSEL_SIZE 1
|
||||
#define PM_CEN_OFFSET 2
|
||||
#define PM_CEN_SIZE 1
|
||||
#define PM_DIVEN_OFFSET 4
|
||||
#define PM_DIVEN_SIZE 1
|
||||
#define PM_DIV_OFFSET 8
|
||||
#define PM_DIV_SIZE 8
|
||||
|
||||
/* Bitfields in RCAUSE */
|
||||
#define PM_POR_OFFSET 0
|
||||
#define PM_POR_SIZE 1
|
||||
#define PM_EXT_OFFSET 2
|
||||
#define PM_EXT_SIZE 1
|
||||
#define PM_WDT_OFFSET 3
|
||||
#define PM_WDT_SIZE 1
|
||||
#define PM_NTAE_OFFSET 4
|
||||
#define PM_NTAE_SIZE 1
|
||||
|
||||
/* Bit manipulation macros */
|
||||
#define PM_BIT(name) \
|
||||
(1 << PM_##name##_OFFSET)
|
||||
#define PM_BF(name,value) \
|
||||
(((value) & ((1 << PM_##name##_SIZE) - 1)) \
|
||||
<< PM_##name##_OFFSET)
|
||||
#define PM_BFEXT(name,value) \
|
||||
(((value) >> PM_##name##_OFFSET) \
|
||||
& ((1 << PM_##name##_SIZE) - 1))
|
||||
#define PM_BFINS(name,value,old)\
|
||||
(((old) & ~(((1 << PM_##name##_SIZE) - 1) \
|
||||
<< PM_##name##_OFFSET)) \
|
||||
| PM_BF(name,value))
|
||||
|
||||
/* Register access macros */
|
||||
#define pm_readl(reg) \
|
||||
__raw_readl((void __iomem *)AT32_PM_BASE + PM_##reg)
|
||||
#define pm_writel(reg,value) \
|
||||
__raw_writel((value), (void __iomem *)AT32_PM_BASE + PM_##reg)
|
||||
|
||||
#endif /* __ARCH_AVR32_MACH_AT32AP_PM_H__ */
|
|
@ -1,242 +0,0 @@
|
|||
/*
|
||||
* Register definitions for SM
|
||||
*
|
||||
* System Manager
|
||||
*/
|
||||
#ifndef __ASM_AVR32_SM_H__
|
||||
#define __ASM_AVR32_SM_H__
|
||||
|
||||
/* SM register offsets */
|
||||
#define SM_PM_MCCTRL 0x0000
|
||||
#define SM_PM_CKSEL 0x0004
|
||||
#define SM_PM_CPU_MASK 0x0008
|
||||
#define SM_PM_HSB_MASK 0x000c
|
||||
#define SM_PM_PBA_MASK 0x0010
|
||||
#define SM_PM_PBB_MASK 0x0014
|
||||
#define SM_PM_PLL0 0x0020
|
||||
#define SM_PM_PLL1 0x0024
|
||||
#define SM_PM_VCTRL 0x0030
|
||||
#define SM_PM_VMREF 0x0034
|
||||
#define SM_PM_VMV 0x0038
|
||||
#define SM_PM_IER 0x0040
|
||||
#define SM_PM_IDR 0x0044
|
||||
#define SM_PM_IMR 0x0048
|
||||
#define SM_PM_ISR 0x004c
|
||||
#define SM_PM_ICR 0x0050
|
||||
#define SM_PM_GCCTRL 0x0060
|
||||
#define SM_RTC_CTRL 0x0080
|
||||
#define SM_RTC_VAL 0x0084
|
||||
#define SM_RTC_TOP 0x0088
|
||||
#define SM_RTC_IER 0x0090
|
||||
#define SM_RTC_IDR 0x0094
|
||||
#define SM_RTC_IMR 0x0098
|
||||
#define SM_RTC_ISR 0x009c
|
||||
#define SM_RTC_ICR 0x00a0
|
||||
#define SM_WDT_CTRL 0x00b0
|
||||
#define SM_WDT_CLR 0x00b4
|
||||
#define SM_WDT_EXT 0x00b8
|
||||
#define SM_RC_RCAUSE 0x00c0
|
||||
#define SM_EIM_IER 0x0100
|
||||
#define SM_EIM_IDR 0x0104
|
||||
#define SM_EIM_IMR 0x0108
|
||||
#define SM_EIM_ISR 0x010c
|
||||
#define SM_EIM_ICR 0x0110
|
||||
#define SM_EIM_MODE 0x0114
|
||||
#define SM_EIM_EDGE 0x0118
|
||||
#define SM_EIM_LEVEL 0x011c
|
||||
#define SM_EIM_TEST 0x0120
|
||||
#define SM_EIM_NMIC 0x0124
|
||||
|
||||
/* Bitfields in PM_MCCTRL */
|
||||
|
||||
/* Bitfields in PM_CKSEL */
|
||||
#define SM_CPUSEL_OFFSET 0
|
||||
#define SM_CPUSEL_SIZE 3
|
||||
#define SM_CPUDIV_OFFSET 7
|
||||
#define SM_CPUDIV_SIZE 1
|
||||
#define SM_HSBSEL_OFFSET 8
|
||||
#define SM_HSBSEL_SIZE 3
|
||||
#define SM_HSBDIV_OFFSET 15
|
||||
#define SM_HSBDIV_SIZE 1
|
||||
#define SM_PBASEL_OFFSET 16
|
||||
#define SM_PBASEL_SIZE 3
|
||||
#define SM_PBADIV_OFFSET 23
|
||||
#define SM_PBADIV_SIZE 1
|
||||
#define SM_PBBSEL_OFFSET 24
|
||||
#define SM_PBBSEL_SIZE 3
|
||||
#define SM_PBBDIV_OFFSET 31
|
||||
#define SM_PBBDIV_SIZE 1
|
||||
|
||||
/* Bitfields in PM_CPU_MASK */
|
||||
|
||||
/* Bitfields in PM_HSB_MASK */
|
||||
|
||||
/* Bitfields in PM_PBA_MASK */
|
||||
|
||||
/* Bitfields in PM_PBB_MASK */
|
||||
|
||||
/* Bitfields in PM_PLL0 */
|
||||
#define SM_PLLEN_OFFSET 0
|
||||
#define SM_PLLEN_SIZE 1
|
||||
#define SM_PLLOSC_OFFSET 1
|
||||
#define SM_PLLOSC_SIZE 1
|
||||
#define SM_PLLOPT_OFFSET 2
|
||||
#define SM_PLLOPT_SIZE 3
|
||||
#define SM_PLLDIV_OFFSET 8
|
||||
#define SM_PLLDIV_SIZE 8
|
||||
#define SM_PLLMUL_OFFSET 16
|
||||
#define SM_PLLMUL_SIZE 8
|
||||
#define SM_PLLCOUNT_OFFSET 24
|
||||
#define SM_PLLCOUNT_SIZE 6
|
||||
#define SM_PLLTEST_OFFSET 31
|
||||
#define SM_PLLTEST_SIZE 1
|
||||
|
||||
/* Bitfields in PM_PLL1 */
|
||||
|
||||
/* Bitfields in PM_VCTRL */
|
||||
#define SM_VAUTO_OFFSET 0
|
||||
#define SM_VAUTO_SIZE 1
|
||||
#define SM_PM_VCTRL_VAL_OFFSET 8
|
||||
#define SM_PM_VCTRL_VAL_SIZE 7
|
||||
|
||||
/* Bitfields in PM_VMREF */
|
||||
#define SM_REFSEL_OFFSET 0
|
||||
#define SM_REFSEL_SIZE 4
|
||||
|
||||
/* Bitfields in PM_VMV */
|
||||
#define SM_PM_VMV_VAL_OFFSET 0
|
||||
#define SM_PM_VMV_VAL_SIZE 8
|
||||
|
||||
/* Bitfields in PM_IER */
|
||||
|
||||
/* Bitfields in PM_IDR */
|
||||
|
||||
/* Bitfields in PM_IMR */
|
||||
|
||||
/* Bitfields in PM_ISR */
|
||||
|
||||
/* Bitfields in PM_ICR */
|
||||
#define SM_LOCK0_OFFSET 0
|
||||
#define SM_LOCK0_SIZE 1
|
||||
#define SM_LOCK1_OFFSET 1
|
||||
#define SM_LOCK1_SIZE 1
|
||||
#define SM_WAKE_OFFSET 2
|
||||
#define SM_WAKE_SIZE 1
|
||||
#define SM_VOK_OFFSET 3
|
||||
#define SM_VOK_SIZE 1
|
||||
#define SM_VMRDY_OFFSET 4
|
||||
#define SM_VMRDY_SIZE 1
|
||||
#define SM_CKRDY_OFFSET 5
|
||||
#define SM_CKRDY_SIZE 1
|
||||
|
||||
/* Bitfields in PM_GCCTRL */
|
||||
#define SM_OSCSEL_OFFSET 0
|
||||
#define SM_OSCSEL_SIZE 1
|
||||
#define SM_PLLSEL_OFFSET 1
|
||||
#define SM_PLLSEL_SIZE 1
|
||||
#define SM_CEN_OFFSET 2
|
||||
#define SM_CEN_SIZE 1
|
||||
#define SM_CPC_OFFSET 3
|
||||
#define SM_CPC_SIZE 1
|
||||
#define SM_DIVEN_OFFSET 4
|
||||
#define SM_DIVEN_SIZE 1
|
||||
#define SM_DIV_OFFSET 8
|
||||
#define SM_DIV_SIZE 8
|
||||
|
||||
/* Bitfields in RTC_CTRL */
|
||||
#define SM_PCLR_OFFSET 1
|
||||
#define SM_PCLR_SIZE 1
|
||||
#define SM_TOPEN_OFFSET 2
|
||||
#define SM_TOPEN_SIZE 1
|
||||
#define SM_CLKEN_OFFSET 3
|
||||
#define SM_CLKEN_SIZE 1
|
||||
#define SM_PSEL_OFFSET 8
|
||||
#define SM_PSEL_SIZE 16
|
||||
|
||||
/* Bitfields in RTC_VAL */
|
||||
#define SM_RTC_VAL_VAL_OFFSET 0
|
||||
#define SM_RTC_VAL_VAL_SIZE 31
|
||||
|
||||
/* Bitfields in RTC_TOP */
|
||||
#define SM_RTC_TOP_VAL_OFFSET 0
|
||||
#define SM_RTC_TOP_VAL_SIZE 32
|
||||
|
||||
/* Bitfields in RTC_IER */
|
||||
|
||||
/* Bitfields in RTC_IDR */
|
||||
|
||||
/* Bitfields in RTC_IMR */
|
||||
|
||||
/* Bitfields in RTC_ISR */
|
||||
|
||||
/* Bitfields in RTC_ICR */
|
||||
#define SM_TOPI_OFFSET 0
|
||||
#define SM_TOPI_SIZE 1
|
||||
|
||||
/* Bitfields in WDT_CTRL */
|
||||
#define SM_KEY_OFFSET 24
|
||||
#define SM_KEY_SIZE 8
|
||||
|
||||
/* Bitfields in WDT_CLR */
|
||||
|
||||
/* Bitfields in WDT_EXT */
|
||||
|
||||
/* Bitfields in RC_RCAUSE */
|
||||
#define SM_POR_OFFSET 0
|
||||
#define SM_POR_SIZE 1
|
||||
#define SM_BOD_OFFSET 1
|
||||
#define SM_BOD_SIZE 1
|
||||
#define SM_EXT_OFFSET 2
|
||||
#define SM_EXT_SIZE 1
|
||||
#define SM_WDT_OFFSET 3
|
||||
#define SM_WDT_SIZE 1
|
||||
#define SM_NTAE_OFFSET 4
|
||||
#define SM_NTAE_SIZE 1
|
||||
#define SM_SERP_OFFSET 5
|
||||
#define SM_SERP_SIZE 1
|
||||
|
||||
/* Bitfields in EIM_IER */
|
||||
|
||||
/* Bitfields in EIM_IDR */
|
||||
|
||||
/* Bitfields in EIM_IMR */
|
||||
|
||||
/* Bitfields in EIM_ISR */
|
||||
|
||||
/* Bitfields in EIM_ICR */
|
||||
|
||||
/* Bitfields in EIM_MODE */
|
||||
|
||||
/* Bitfields in EIM_EDGE */
|
||||
#define SM_INT0_OFFSET 0
|
||||
#define SM_INT0_SIZE 1
|
||||
#define SM_INT1_OFFSET 1
|
||||
#define SM_INT1_SIZE 1
|
||||
#define SM_INT2_OFFSET 2
|
||||
#define SM_INT2_SIZE 1
|
||||
#define SM_INT3_OFFSET 3
|
||||
#define SM_INT3_SIZE 1
|
||||
|
||||
/* Bitfields in EIM_LEVEL */
|
||||
|
||||
/* Bitfields in EIM_TEST */
|
||||
#define SM_TESTEN_OFFSET 31
|
||||
#define SM_TESTEN_SIZE 1
|
||||
|
||||
/* Bitfields in EIM_NMIC */
|
||||
#define SM_EN_OFFSET 0
|
||||
#define SM_EN_SIZE 1
|
||||
|
||||
/* Bit manipulation macros */
|
||||
#define SM_BIT(name) (1 << SM_##name##_OFFSET)
|
||||
#define SM_BF(name,value) (((value) & ((1 << SM_##name##_SIZE) - 1)) << SM_##name##_OFFSET)
|
||||
#define SM_BFEXT(name,value) (((value) >> SM_##name##_OFFSET) & ((1 << SM_##name##_SIZE) - 1))
|
||||
#define SM_BFINS(name,value,old) (((old) & ~(((1 << SM_##name##_SIZE) - 1) << SM_##name##_OFFSET)) | SM_BF(name,value))
|
||||
|
||||
/* Register access macros */
|
||||
#define sm_readl(port,reg) \
|
||||
__raw_readl((port)->regs + SM_##reg)
|
||||
#define sm_writel(port,reg,value) \
|
||||
__raw_writel((value), (port)->regs + SM_##reg)
|
||||
|
||||
#endif /* __ASM_AVR32_SM_H__ */
|
|
@ -36,4 +36,18 @@ struct platform_device *
|
|||
at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data,
|
||||
unsigned long fbmem_start, unsigned long fbmem_len);
|
||||
|
||||
/* depending on what's hooked up, not all SSC pins will be used */
|
||||
#define ATMEL_SSC_TK 0x01
|
||||
#define ATMEL_SSC_TF 0x02
|
||||
#define ATMEL_SSC_TD 0x04
|
||||
#define ATMEL_SSC_TX (ATMEL_SSC_TK | ATMEL_SSC_TF | ATMEL_SSC_TD)
|
||||
|
||||
#define ATMEL_SSC_RK 0x10
|
||||
#define ATMEL_SSC_RF 0x20
|
||||
#define ATMEL_SSC_RD 0x40
|
||||
#define ATMEL_SSC_RX (ATMEL_SSC_RK | ATMEL_SSC_RF | ATMEL_SSC_RD)
|
||||
|
||||
struct platform_device *
|
||||
at32_add_device_ssc(unsigned int id, unsigned int flags);
|
||||
|
||||
#endif /* __ASM_ARCH_BOARD_H */
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
/*
|
||||
* AT32 System Manager interface.
|
||||
*
|
||||
* Copyright (C) 2006 Atmel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef __ASM_AVR32_AT32_SM_H__
|
||||
#define __ASM_AVR32_AT32_SM_H__
|
||||
|
||||
struct irq_chip;
|
||||
struct platform_device;
|
||||
|
||||
struct at32_sm {
|
||||
spinlock_t lock;
|
||||
void __iomem *regs;
|
||||
struct irq_chip *eim_chip;
|
||||
unsigned int eim_first_irq;
|
||||
struct platform_device *pdev;
|
||||
};
|
||||
|
||||
extern struct platform_device at32_sm_device;
|
||||
extern struct at32_sm system_manager;
|
||||
|
||||
#endif /* __ASM_AVR32_AT32_SM_H__ */
|
|
@ -101,7 +101,7 @@ static inline int atomic_sub_unless(atomic_t *v, int a, int u)
|
|||
" mov %1, 1\n"
|
||||
"1:"
|
||||
: "=&r"(tmp), "=&r"(result), "=o"(v->counter)
|
||||
: "m"(v->counter), "rKs21"(a), "rKs21"(u)
|
||||
: "m"(v->counter), "rKs21"(a), "rKs21"(u), "1"(result)
|
||||
: "cc", "memory");
|
||||
|
||||
return result;
|
||||
|
@ -137,7 +137,7 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
|
|||
" mov %1, 1\n"
|
||||
"1:"
|
||||
: "=&r"(tmp), "=&r"(result), "=o"(v->counter)
|
||||
: "m"(v->counter), "r"(a), "ir"(u)
|
||||
: "m"(v->counter), "r"(a), "ir"(u), "1"(result)
|
||||
: "cc", "memory");
|
||||
}
|
||||
|
||||
|
|
|
@ -7,19 +7,10 @@
|
|||
* words, but halfwords must be halfword-aligned, and doublewords must
|
||||
* be word-aligned.
|
||||
*
|
||||
* TODO: Make all this CPU-specific and optimize.
|
||||
* However, swapped word loads must be word-aligned so we can't
|
||||
* optimize word loads in general.
|
||||
*/
|
||||
|
||||
#include <linux/string.h>
|
||||
|
||||
/* Use memmove here, so gcc does not insert a __builtin_memcpy. */
|
||||
|
||||
#define get_unaligned(ptr) \
|
||||
({ __typeof__(*(ptr)) __tmp; memmove(&__tmp, (ptr), sizeof(*(ptr))); __tmp; })
|
||||
|
||||
#define put_unaligned(val, ptr) \
|
||||
({ __typeof__(*(ptr)) __tmp = (val); \
|
||||
memmove((ptr), &__tmp, sizeof(*(ptr))); \
|
||||
(void)0; })
|
||||
#include <asm-generic/unaligned.h>
|
||||
|
||||
#endif /* __ASM_AVR32_UNALIGNED_H */
|
||||
|
|
Загрузка…
Ссылка в новой задаче