Commit 1a2217a9 authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/hskinnemoen/avr32-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/hskinnemoen/avr32-2.6:
  avr32: Fix build failures in board code
  avr32: Allow selecting multiple pins at once
  avr32: Minor pm_power_off cleanup
  avr32: Implement {read,write}[bwl]_be
  avr32: Replace static clock list with dynamic linked list
  avr32: Use platform_driver_probe for pdc platform driver
  avr32: Use platform_driver_probe for pio platform driver
  avr32: Provide a way to deselect pins in the portmux
  ngw100: export J15 through sysfs
  avr32: Allow fine-grained control over LCDC pins
  avr32: added mem kernel command line option support
  Add kernel support for oprofile callgraphs on AVR32
  avr32: use the new byteorder headers
parents 46b5e340 6eb3ebe0
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
*/ */
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <linux/gpio.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-gpio.h> #include <linux/i2c-gpio.h>
...@@ -193,7 +194,7 @@ static int __init atngw100_init(void) ...@@ -193,7 +194,7 @@ static int __init atngw100_init(void)
* PB28/EXTINT3 doesn't; it should be SMBALERT# (for PMBus), * PB28/EXTINT3 doesn't; it should be SMBALERT# (for PMBus),
* but it's not available off-board. * but it's not available off-board.
*/ */
at32_select_periph(GPIO_PIN_PB(28), 0, AT32_GPIOF_PULLUP); at32_select_periph(GPIO_PIOB_BASE, 1 << 28, 0, AT32_GPIOF_PULLUP);
at32_select_gpio(i2c_gpio_data.sda_pin, at32_select_gpio(i2c_gpio_data.sda_pin,
AT32_GPIOF_MULTIDRV | AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH); AT32_GPIOF_MULTIDRV | AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH);
at32_select_gpio(i2c_gpio_data.scl_pin, at32_select_gpio(i2c_gpio_data.scl_pin,
...@@ -207,6 +208,15 @@ postcore_initcall(atngw100_init); ...@@ -207,6 +208,15 @@ postcore_initcall(atngw100_init);
static int __init atngw100_arch_init(void) static int __init atngw100_arch_init(void)
{ {
/* PB30 is the otherwise unused jumper on the mainboard, with an
* external pullup; the jumper grounds it. Use it however you
* like, including letting U-Boot or Linux tweak boot sequences.
*/
at32_select_gpio(GPIO_PIN_PB(30), 0);
gpio_request(GPIO_PIN_PB(30), "j15");
gpio_direction_input(GPIO_PIN_PB(30));
gpio_export(GPIO_PIN_PB(30), false);
/* set_irq_type() after the arch_initcall for EIC has run, and /* set_irq_type() after the arch_initcall for EIC has run, and
* before the I2C subsystem could try using this IRQ. * before the I2C subsystem could try using this IRQ.
*/ */
......
...@@ -232,7 +232,7 @@ static void __init atstk1002_setup_extdac(void) ...@@ -232,7 +232,7 @@ static void __init atstk1002_setup_extdac(void)
goto err_set_clk; goto err_set_clk;
} }
at32_select_periph(GPIO_PIN_PA(30), GPIO_PERIPH_A, 0); at32_select_periph(GPIO_PIOA_BASE, (1 << 30), GPIO_PERIPH_A, 0);
at73c213_data.dac_clk = gclk; at73c213_data.dac_clk = gclk;
err_set_clk: err_set_clk:
...@@ -330,13 +330,14 @@ static int __init atstk1002_init(void) ...@@ -330,13 +330,14 @@ static int __init atstk1002_init(void)
at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info)); at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info));
#endif #endif
#ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM #ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
at32_add_device_mci(0, &mci0_pdata); at32_add_device_mci(0, &mci0_data);
#endif #endif
#ifdef CONFIG_BOARD_ATSTK1002_SW5_CUSTOM #ifdef CONFIG_BOARD_ATSTK1002_SW5_CUSTOM
set_hw_addr(at32_add_device_eth(1, &eth_data[1])); set_hw_addr(at32_add_device_eth(1, &eth_data[1]));
#else #else
at32_add_device_lcdc(0, &atstk1000_lcdc_data, at32_add_device_lcdc(0, &atstk1000_lcdc_data,
fbmem_start, fbmem_size, 0); fbmem_start, fbmem_size,
ATMEL_LCDC_PRI_24BIT | ATMEL_LCDC_PRI_CONTROL);
#endif #endif
at32_add_device_usba(0, NULL); at32_add_device_usba(0, NULL);
#ifndef CONFIG_BOARD_ATSTK100X_SW3_CUSTOM #ifndef CONFIG_BOARD_ATSTK100X_SW3_CUSTOM
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <asm/setup.h> #include <asm/setup.h>
#include <asm/atmel-mci.h>
#include <mach/at32ap700x.h> #include <mach/at32ap700x.h>
#include <mach/board.h> #include <mach/board.h>
...@@ -94,7 +95,7 @@ static void __init atstk1003_setup_extdac(void) ...@@ -94,7 +95,7 @@ static void __init atstk1003_setup_extdac(void)
goto err_set_clk; goto err_set_clk;
} }
at32_select_periph(GPIO_PIN_PA(30), GPIO_PERIPH_A, 0); at32_select_periph(GPIO_PIOA_BASE, (1 << 30), GPIO_PERIPH_A, 0);
at73c213_data.dac_clk = gclk; at73c213_data.dac_clk = gclk;
err_set_clk: err_set_clk:
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <video/atmel_lcdc.h> #include <video/atmel_lcdc.h>
#include <asm/setup.h> #include <asm/setup.h>
#include <asm/atmel-mci.h>
#include <mach/at32ap700x.h> #include <mach/at32ap700x.h>
#include <mach/board.h> #include <mach/board.h>
...@@ -99,7 +100,7 @@ static void __init atstk1004_setup_extdac(void) ...@@ -99,7 +100,7 @@ static void __init atstk1004_setup_extdac(void)
goto err_set_clk; goto err_set_clk;
} }
at32_select_periph(GPIO_PIN_PA(30), GPIO_PERIPH_A, 0); at32_select_periph(GPIO_PIOA_BASE, (1 << 30), GPIO_PERIPH_A, 0);
at73c213_data.dac_clk = gclk; at73c213_data.dac_clk = gclk;
err_set_clk: err_set_clk:
...@@ -150,7 +151,8 @@ static int __init atstk1004_init(void) ...@@ -150,7 +151,8 @@ static int __init atstk1004_init(void)
at32_add_device_mci(0, &mci0_data); at32_add_device_mci(0, &mci0_data);
#endif #endif
at32_add_device_lcdc(0, &atstk1000_lcdc_data, at32_add_device_lcdc(0, &atstk1000_lcdc_data,
fbmem_start, fbmem_size, 0); fbmem_start, fbmem_size,
ATMEL_LCDC_PRI_24BIT | ATMEL_LCDC_PRI_CONTROL);
at32_add_device_usba(0, NULL); at32_add_device_usba(0, NULL);
#ifndef CONFIG_BOARD_ATSTK100X_SW3_CUSTOM #ifndef CONFIG_BOARD_ATSTK100X_SW3_CUSTOM
at32_add_device_ssc(0, ATMEL_SSC_TX); at32_add_device_ssc(0, ATMEL_SSC_TX);
......
...@@ -7,6 +7,9 @@ ...@@ -7,6 +7,9 @@
#include <asm/types.h> #include <asm/types.h>
#include <linux/compiler.h> #include <linux/compiler.h>
#define __BIG_ENDIAN
#define __SWAB_64_THRU_32__
#ifdef __CHECKER__ #ifdef __CHECKER__
extern unsigned long __builtin_bswap_32(unsigned long x); extern unsigned long __builtin_bswap_32(unsigned long x);
extern unsigned short __builtin_bswap_16(unsigned short x); extern unsigned short __builtin_bswap_16(unsigned short x);
...@@ -17,15 +20,18 @@ extern unsigned short __builtin_bswap_16(unsigned short x); ...@@ -17,15 +20,18 @@ extern unsigned short __builtin_bswap_16(unsigned short x);
* the result. * the result.
*/ */
#if !(__GNUC__ == 4 && __GNUC_MINOR__ < 2) #if !(__GNUC__ == 4 && __GNUC_MINOR__ < 2)
#define __arch__swab32(x) __builtin_bswap_32(x) static inline __attribute_const__ __u16 __arch_swab16(__u16 val)
#define __arch__swab16(x) __builtin_bswap_16(x) {
#endif return __builtin_bswap_16(val);
}
#define __arch_swab16 __arch_swab16
#if !defined(__STRICT_ANSI__) || defined(__KERNEL__) static inline __attribute_const__ __u32 __arch_swab32(__u32 val)
# define __BYTEORDER_HAS_U64__ {
# define __SWAB_64_THRU_32__ return __builtin_bswap_32(val);
}
#define __arch_swab32 __arch_swab32
#endif #endif
#include <linux/byteorder/big_endian.h> #include <linux/byteorder.h>
#endif /* __ASM_AVR32_BYTEORDER_H */ #endif /* __ASM_AVR32_BYTEORDER_H */
...@@ -160,6 +160,14 @@ BUILDIO_IOPORT(l, u32) ...@@ -160,6 +160,14 @@ BUILDIO_IOPORT(l, u32)
#define readw_relaxed readw #define readw_relaxed readw
#define readl_relaxed readl #define readl_relaxed readl
#define readb_be __raw_readb
#define readw_be __raw_readw
#define readl_be __raw_readl
#define writeb_be __raw_writeb
#define writew_be __raw_writew
#define writel_be __raw_writel
#define __BUILD_MEMORY_STRING(bwl, type) \ #define __BUILD_MEMORY_STRING(bwl, type) \
static inline void writes##bwl(volatile void __iomem *addr, \ static inline void writes##bwl(volatile void __iomem *addr, \
const void *data, unsigned int count) \ const void *data, unsigned int count) \
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/kallsyms.h> #include <linux/kallsyms.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/pm.h>
#include <linux/ptrace.h> #include <linux/ptrace.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/tick.h> #include <linux/tick.h>
...@@ -20,7 +21,7 @@ ...@@ -20,7 +21,7 @@
#include <mach/pm.h> #include <mach/pm.h>
void (*pm_power_off)(void) = NULL; void (*pm_power_off)(void);
EXPORT_SYMBOL(pm_power_off); EXPORT_SYMBOL(pm_power_off);
/* /*
......
...@@ -283,6 +283,25 @@ static int __init early_parse_fbmem(char *p) ...@@ -283,6 +283,25 @@ static int __init early_parse_fbmem(char *p)
} }
early_param("fbmem", early_parse_fbmem); early_param("fbmem", early_parse_fbmem);
/*
* Pick out the memory size. We look for mem=size@start,
* where start and size are "size[KkMmGg]"
*/
static int __init early_mem(char *p)
{
resource_size_t size, start;
start = system_ram->start;
size = memparse(p, &p);
if (*p == '@')
start = memparse(p + 1, &p);
system_ram->start = start;
system_ram->end = system_ram->start + size - 1;
return 0;
}
early_param("mem", early_mem);
static int __init parse_tag_core(struct tag *tag) static int __init parse_tag_core(struct tag *tag)
{ {
if (tag->hdr.size > 2) { if (tag->hdr.size > 2) {
......
This diff is collapsed.
...@@ -15,24 +15,40 @@ ...@@ -15,24 +15,40 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/list.h>
#include <mach/chip.h> #include <mach/chip.h>
#include "clock.h" #include "clock.h"
/* at32 clock list */
static LIST_HEAD(at32_clock_list);
static DEFINE_SPINLOCK(clk_lock); static DEFINE_SPINLOCK(clk_lock);
static DEFINE_SPINLOCK(clk_list_lock);
void at32_clk_register(struct clk *clk)
{
spin_lock(&clk_list_lock);
/* add the new item to the end of the list */
list_add_tail(&clk->list, &at32_clock_list);
spin_unlock(&clk_list_lock);
}
struct clk *clk_get(struct device *dev, const char *id) struct clk *clk_get(struct device *dev, const char *id)
{ {
int i; struct clk *clk;
for (i = 0; i < at32_nr_clocks; i++) { spin_lock(&clk_list_lock);
struct clk *clk = at32_clock_list[i];
if (clk->dev == dev && strcmp(id, clk->name) == 0) list_for_each_entry(clk, &at32_clock_list, list) {
if (clk->dev == dev && strcmp(id, clk->name) == 0) {
spin_unlock(&clk_list_lock);
return clk; return clk;
}
} }
spin_unlock(&clk_list_lock);
return ERR_PTR(-ENOENT); return ERR_PTR(-ENOENT);
} }
EXPORT_SYMBOL(clk_get); EXPORT_SYMBOL(clk_get);
...@@ -203,8 +219,8 @@ dump_clock(struct clk *parent, struct clkinf *r) ...@@ -203,8 +219,8 @@ dump_clock(struct clk *parent, struct clkinf *r)
/* cost of this scan is small, but not linear... */ /* cost of this scan is small, but not linear... */
r->nest = nest + NEST_DELTA; r->nest = nest + NEST_DELTA;
for (i = 3; i < at32_nr_clocks; i++) {
clk = at32_clock_list[i]; list_for_each_entry(clk, &at32_clock_list, list) {
if (clk->parent == parent) if (clk->parent == parent)
dump_clock(clk, r); dump_clock(clk, r);
} }
...@@ -215,6 +231,7 @@ static int clk_show(struct seq_file *s, void *unused) ...@@ -215,6 +231,7 @@ static int clk_show(struct seq_file *s, void *unused)
{ {
struct clkinf r; struct clkinf r;
int i; int i;
struct clk *clk;
/* show all the power manager registers */ /* show all the power manager registers */
seq_printf(s, "MCCTRL = %8x\n", pm_readl(MCCTRL)); seq_printf(s, "MCCTRL = %8x\n", pm_readl(MCCTRL));
...@@ -234,14 +251,25 @@ static int clk_show(struct seq_file *s, void *unused) ...@@ -234,14 +251,25 @@ static int clk_show(struct seq_file *s, void *unused)
seq_printf(s, "\n"); seq_printf(s, "\n");
/* show clock tree as derived from the three oscillators
* we "know" are at the head of the list
*/
r.s = s; r.s = s;
r.nest = 0; r.nest = 0;
dump_clock(at32_clock_list[0], &r); /* protected from changes on the list while dumping */
dump_clock(at32_clock_list[1], &r); spin_lock(&clk_list_lock);
dump_clock(at32_clock_list[2], &r);
/* show clock tree as derived from the three oscillators */
clk = clk_get(NULL, "osc32k");
dump_clock(clk, &r);
clk_put(clk);
clk = clk_get(NULL, "osc0");
dump_clock(clk, &r);
clk_put(clk);
clk = clk_get(NULL, "osc1");
dump_clock(clk, &r);
clk_put(clk);
spin_unlock(&clk_list_lock);
return 0; return 0;
} }
......
...@@ -12,8 +12,13 @@ ...@@ -12,8 +12,13 @@
* published by the Free Software Foundation. * published by the Free Software Foundation.
*/ */
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/list.h>
void at32_clk_register(struct clk *clk);
struct clk { struct clk {
struct list_head list; /* linking element */
const char *name; /* Clock name/function */ const char *name; /* Clock name/function */
struct device *dev; /* Device the clock is used by */ struct device *dev; /* Device the clock is used by */
struct clk *parent; /* Parent clock, if any */ struct clk *parent; /* Parent clock, if any */
...@@ -25,6 +30,3 @@ struct clk { ...@@ -25,6 +30,3 @@ struct clk {
u16 users; /* Enabled if non-zero */ u16 users; /* Enabled if non-zero */
u16 index; /* Sibling index */ u16 index; /* Sibling index */
}; };
extern struct clk *at32_clock_list[];
extern unsigned int at32_nr_clocks;
...@@ -83,4 +83,132 @@ ...@@ -83,4 +83,132 @@
#define HMATRIX_BASE 0xfff00800 #define HMATRIX_BASE 0xfff00800
#define SDRAMC_BASE 0xfff03800 #define SDRAMC_BASE 0xfff03800
/* LCDC on port C */
#define ATMEL_LCDC_PC_CC (1ULL << 19)
#define ATMEL_LCDC_PC_HSYNC (1ULL << 20)
#define ATMEL_LCDC_PC_PCLK (1ULL << 21)
#define ATMEL_LCDC_PC_VSYNC (1ULL << 22)
#define ATMEL_LCDC_PC_DVAL (1ULL << 23)
#define ATMEL_LCDC_PC_MODE (1ULL << 24)
#define ATMEL_LCDC_PC_PWR (1ULL << 25)
#define ATMEL_LCDC_PC_DATA0 (1ULL << 26)
#define ATMEL_LCDC_PC_DATA1 (1ULL << 27)
#define ATMEL_LCDC_PC_DATA2 (1ULL << 28)
#define ATMEL_LCDC_PC_DATA3 (1ULL << 29)
#define ATMEL_LCDC_PC_DATA4 (1ULL << 30)
#define ATMEL_LCDC_PC_DATA5 (1ULL << 31)
/* LCDC on port D */
#define ATMEL_LCDC_PD_DATA6 (1ULL << 0)
#define ATMEL_LCDC_PD_DATA7 (1ULL << 1)
#define ATMEL_LCDC_PD_DATA8 (1ULL << 2)
#define ATMEL_LCDC_PD_DATA9 (1ULL << 3)
#define ATMEL_LCDC_PD_DATA10 (1ULL << 4)
#define ATMEL_LCDC_PD_DATA11 (1ULL << 5)
#define ATMEL_LCDC_PD_DATA12 (1ULL << 6)
#define ATMEL_LCDC_PD_DATA13 (1ULL << 7)
#define ATMEL_LCDC_PD_DATA14 (1ULL << 8)
#define ATMEL_LCDC_PD_DATA15 (1ULL << 9)
#define ATMEL_LCDC_PD_DATA16 (1ULL << 10)
#define ATMEL_LCDC_PD_DATA17 (1ULL << 11)
#define ATMEL_LCDC_PD_DATA18 (1ULL << 12)
#define ATMEL_LCDC_PD_DATA19 (1ULL << 13)
#define ATMEL_LCDC_PD_DATA20 (1ULL << 14)
#define ATMEL_LCDC_PD_DATA21 (1ULL << 15)
#define ATMEL_LCDC_PD_DATA22 (1ULL << 16)
#define ATMEL_LCDC_PD_DATA23 (1ULL << 17)
/* LCDC on port E */
#define ATMEL_LCDC_PE_CC (1ULL << (32 + 0))
#define ATMEL_LCDC_PE_DVAL (1ULL << (32 + 1))
#define ATMEL_LCDC_PE_MODE (1ULL << (32 + 2))
#define ATMEL_LCDC_PE_DATA0 (1ULL << (32 + 3))
#define ATMEL_LCDC_PE_DATA1 (1ULL << (32 + 4))
#define ATMEL_LCDC_PE_DATA2 (1ULL << (32 + 5))
#define ATMEL_LCDC_PE_DATA3 (1ULL << (32 + 6))
#define ATMEL_LCDC_PE_DATA4 (1ULL << (32 + 7))
#define ATMEL_LCDC_PE_DATA8 (1ULL << (32 + 8))
#define ATMEL_LCDC_PE_DATA9 (1ULL << (32 + 9))
#define ATMEL_LCDC_PE_DATA10 (1ULL << (32 + 10))
#define ATMEL_LCDC_PE_DATA11 (1ULL << (32 + 11))
#define ATMEL_LCDC_PE_DATA12 (1ULL << (32 + 12))
#define ATMEL_LCDC_PE_DATA16 (1ULL << (32 + 13))
#define ATMEL_LCDC_PE_DATA17 (1ULL << (32 + 14))
#define ATMEL_LCDC_PE_DATA18 (1ULL << (32 + 15))
#define ATMEL_LCDC_PE_DATA19 (1ULL << (32 + 16))
#define ATMEL_LCDC_PE_DATA20 (1ULL << (32 + 17))
#define ATMEL_LCDC_PE_DATA21 (1ULL << (32 + 18))
#define ATMEL_LCDC(PORT, PIN) (ATMEL_LCDC_##PORT##_##PIN)
#define ATMEL_LCDC_PRI_24B_DATA ( \
ATMEL_LCDC(PC, DATA0) | ATMEL_LCDC(PC, DATA1) | \
ATMEL_LCDC(PC, DATA2) | ATMEL_LCDC(PC, DATA3) | \
ATMEL_LCDC(PC, DATA4) | ATMEL_LCDC(PC, DATA5) | \
ATMEL_LCDC(PD, DATA6) | ATMEL_LCDC(PD, DATA7) | \
ATMEL_LCDC(PD, DATA8) | ATMEL_LCDC(PD, DATA9) | \
ATMEL_LCDC(PD, DATA10) | ATMEL_LCDC(PD, DATA11) | \
ATMEL_LCDC(PD, DATA12) | ATMEL_LCDC(PD, DATA13) | \
ATMEL_LCDC(PD, DATA14) | ATMEL_LCDC(PD, DATA15) | \
ATMEL_LCDC(PD, DATA16) | ATMEL_LCDC(PD, DATA17) | \
ATMEL_LCDC(PD, DATA18) | ATMEL_LCDC(PD, DATA19) | \
ATMEL_LCDC(PD, DATA20) | ATMEL_LCDC(PD, DATA21) | \
ATMEL_LCDC(PD, DATA22) | ATMEL_LCDC(PD, DATA23))
#define ATMEL_LCDC_ALT_24B_DATA ( \
ATMEL_LCDC(PE, DATA0) | ATMEL_LCDC(PE, DATA1) | \
ATMEL_LCDC(PE, DATA2) | ATMEL_LCDC(PE, DATA3) | \
ATMEL_LCDC(PE, DATA4) | ATMEL_LCDC(PC, DATA5) | \
ATMEL_LCDC(PD, DATA6) | ATMEL_LCDC(PD, DATA7) | \
ATMEL_LCDC(PE, DATA8) | ATMEL_LCDC(PE, DATA9) | \
ATMEL_LCDC(PE, DATA10) | ATMEL_LCDC(PE, DATA11) | \
ATMEL_LCDC(PE, DATA12) | ATMEL_LCDC(PD, DATA13) | \
ATMEL_LCDC(PD, DATA14) | ATMEL_LCDC(PD, DATA15) | \
ATMEL_LCDC(PE, DATA16) | ATMEL_LCDC(PE, DATA17) | \
ATMEL_LCDC(PE, DATA18) | ATMEL_LCDC(PE, DATA19) | \
ATMEL_LCDC(PE, DATA20) | ATMEL_LCDC(PE, DATA21) | \
ATMEL_LCDC(PD, DATA22) | ATMEL_LCDC(PD, DATA23))
#define ATMEL_LCDC_PRI_15B_DATA ( \
ATMEL_LCDC(PC, DATA0) | ATMEL_LCDC(PC, DATA1) | \
ATMEL_LCDC(PC, DATA2) | ATMEL_LCDC(PC, DATA3) | \
ATMEL_LCDC(PC, DATA4) | ATMEL_LCDC(PC, DATA5) | \
ATMEL_LCDC(PD, DATA8) | ATMEL_LCDC(PD, DATA9) | \
ATMEL_LCDC(PD, DATA10) | ATMEL_LCDC(PD, DATA11) | \
ATMEL_LCDC(PD, DATA12) | ATMEL_LCDC(PD, DATA16) | \
ATMEL_LCDC(PD, DATA17) | ATMEL_LCDC(PD, DATA18) | \
ATMEL_LCDC(PD, DATA19) | ATMEL_LCDC(PD, DATA20))
#define ATMEL_LCDC_ALT_15B_DATA ( \
ATMEL_LCDC(PE, DATA0) | ATMEL_LCDC(PE, DATA1) | \
ATMEL_LCDC(PE, DATA2) | ATMEL_LCDC(PE, DATA3) | \
ATMEL_LCDC(PE, DATA4) | ATMEL_LCDC(PC, DATA5) | \
ATMEL_LCDC(PE, DATA8) | ATMEL_LCDC(PE, DATA9) | \
ATMEL_LCDC(PE, DATA10) | ATMEL_LCDC(PE, DATA11) | \
ATMEL_LCDC(PE, DATA12) | ATMEL_LCDC(PE, DATA16) | \
ATMEL_LCDC(PE, DATA17) | ATMEL_LCDC(PE, DATA18) | \
ATMEL_LCDC(PE, DATA19) | ATMEL_LCDC(PE, DATA20))
#define ATMEL_LCDC_PRI_CONTROL ( \
ATMEL_LCDC(PC, CC) | ATMEL_LCDC(PC, DVAL) | \
ATMEL_LCDC(PC, MODE) | ATMEL_LCDC(PC, PWR))
#define ATMEL_LCDC_ALT_CONTROL ( \
ATMEL_LCDC(PE, CC) | ATMEL_LCDC(PE, DVAL) | \
ATMEL_LCDC(PE, MODE) | ATMEL_LCDC(PC, PWR))
#define ATMEL_LCDC_CONTROL ( \
ATMEL_LCDC(PC, HSYNC) | ATMEL_LCDC(PC, VSYNC) | \
ATMEL_LCDC(PC, PCLK))
#define ATMEL_LCDC_PRI_24BIT (ATMEL_LCDC_CONTROL | ATMEL_LCDC_PRI_24B_DATA)
#define ATMEL_LCDC_ALT_24BIT (ATMEL_LCDC_CONTROL | ATMEL_LCDC_ALT_24B_DATA)
#define ATMEL_LCDC_PRI_15BIT (ATMEL_LCDC_CONTROL | ATMEL_LCDC_PRI_15B_DATA)
#define ATMEL_LCDC_ALT_15BIT (ATMEL_LCDC_CONTROL | ATMEL_LCDC_ALT_15B_DATA)
#endif /* __ASM_ARCH_AT32AP700X_H__ */ #endif /* __ASM_ARCH_AT32AP700X_H__ */
...@@ -43,7 +43,7 @@ struct atmel_lcdfb_info; ...@@ -43,7 +43,7 @@ struct atmel_lcdfb_info;
struct platform_device * struct platform_device *
at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data, at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data,
unsigned long fbmem_start, unsigned long fbmem_len, unsigned long fbmem_start, unsigned long fbmem_len,
unsigned int pin_config); u64 pin_mask);
struct usba_platform_data; struct usba_platform_data;
struct platform_device * struct platform_device *
......
#ifndef __ASM_AVR32_ARCH_AT32AP_IO_H #ifndef __ASM_AVR32_ARCH_AT32AP_IO_H
#define __ASM_AVR32_ARCH_AT32AP_IO_H #define __ASM_AVR32_ARCH_AT32AP_IO_H
/* For "bizarre" halfword swapping */ #include <linux/swab.h>
#include <linux/byteorder/swabb.h>
#if defined(CONFIG_AP700X_32_BIT_SMC) #if defined(CONFIG_AP700X_32_BIT_SMC)
# define __swizzle_addr_b(addr) (addr ^ 3UL) # define __swizzle_addr_b(addr) (addr ^ 3UL)
......
...@@ -21,9 +21,10 @@ ...@@ -21,9 +21,10 @@
#define AT32_GPIOF_DEGLITCH 0x00000008 /* (IN) Filter glitches */ #define AT32_GPIOF_DEGLITCH 0x00000008 /* (IN) Filter glitches */
#define AT32_GPIOF_MULTIDRV 0x00000010 /* Enable multidriver option */ #define AT32_GPIOF_MULTIDRV 0x00000010 /* Enable multidriver option */
void at32_select_periph(unsigned int pin, unsigned int periph, void at32_select_periph(unsigned int port, unsigned int pin,
unsigned long flags); unsigned int periph, unsigned long flags);
void at32_select_gpio(unsigned int pin, unsigned long flags); void at32_select_gpio(unsigned int pin, unsigned long flags);
void at32_deselect_pin(unsigned int pin);
void at32_reserve_pin(unsigned int pin); void at32_reserve_pin(unsigned int pin);
#endif /* __ASM_ARCH_PORTMUX_H__ */ #endif /* __ASM_ARCH_PORTMUX_H__ */
...@@ -35,7 +35,6 @@ static int __init pdc_probe(struct platform_device *pdev) ...@@ -35,7 +35,6 @@ static int __init pdc_probe(struct platform_device *pdev)
} }
static struct platform_driver pdc_driver = { static struct platform_driver pdc_driver = {
.probe = pdc_probe,
.driver = { .driver = {
.name = "pdc", .name = "pdc",
}, },
...@@ -43,6 +42,6 @@ static struct platform_driver pdc_driver = { ...@@ -43,6 +42,6 @@ static struct platform_driver pdc_driver = {
static int __init pdc_init(void) static int __init pdc_init(void)
{ {
return platform_driver_register(&pdc_driver); return platform_driver_probe(&pdc_driver, pdc_probe);
} }
arch_initcall(pdc_init); arch_initcall(pdc_init);
...@@ -50,35 +50,48 @@ static struct pio_device *gpio_to_pio(unsigned int gpio) ...@@ -50,35 +50,48 @@ static struct pio_device *gpio_to_pio(unsigned int gpio)
} }
/* Pin multiplexing API */ /* Pin multiplexing API */
static DEFINE_SPINLOCK(pio_lock);
void __init at32_select_periph(unsigned int pin, unsigned int periph, void __init at32_select_periph(unsigned int port, u32 pin_mask,
unsigned long flags) unsigned int periph, unsigned long flags)
{ {
struct pio_device *pio; struct pio_device *pio;
unsigned int pin_index = pin & 0x1f;
u32 mask = 1 << pin_index;
pio = gpio_to_pio(pin); /* assign and verify pio */
pio = gpio_to_pio(port);
if (unlikely(!pio)) { if (unlikely(!pio)) {
printk("pio: invalid pin %u\n", pin); printk(KERN_WARNING "pio: invalid port %u\n", port);
goto fail; goto fail;
} }
if (unlikely(test_and_set_bit(pin_index, &pio->pinmux_mask) /* Test if any of the requested pins is already muxed */
|| gpiochip_is_requested(&pio->chip, pin_index))) { spin_lock(&pio_lock);
printk("%s: pin %u is busy\n", pio->name, pin_index); if (unlikely(pio->pinmux_mask & pin_mask)) {
printk(KERN_WARNING "%s: pin(s) busy (requested 0x%x, busy 0x%x)\n",
pio->name, pin_mask, pio->pinmux_mask & pin_mask);
spin_unlock(&pio_lock);
goto fail; goto fail;
} }
pio_writel(pio, PUER, mask); pio->pinmux_mask |= pin_mask;
/* enable pull ups */
pio_writel(pio, PUER, pin_mask);
/* select either peripheral A or B */
if (periph) if (periph)
pio_writel(pio, BSR, mask); pio_writel(pio, BSR, pin_mask);
else else
pio_writel(pio, ASR, mask); pio_writel(pio, ASR, pin_mask);
/* enable peripheral control */
pio_writel(pio, PDR, pin_mask);
pio_writel(pio, PDR, mask); /* Disable pull ups if not requested. */
if (!(flags & AT32_GPIOF_PULLUP)) if (!(flags & AT32_GPIOF_PULLUP))
pio_writel(pio, PUDR, mask); pio_writel(pio, PUDR, pin_mask);
spin_unlock(&pio_lock);
return; return;
...@@ -134,6 +147,25 @@ void __init at32_select_gpio(unsigned int pin, unsigned long flags) ...@@ -134,6 +147,25 @@ void __init at32_select_gpio(unsigned int pin, unsigned long flags)
dump_stack(); dump_stack();
} }
/*
* Undo a previous pin reservation. Will not affect the hardware
* configuration.
*/
void at32_deselect_pin(unsigned int pin)
{
struct pio_device *pio;
unsigned int pin_index = pin & 0x1f;
pio = gpio_to_pio(pin);
if (unlikely(!pio)) {
printk("pio: invalid pin %u\n", pin);
dump_stack();
return;
}
clear_bit(pin_index, &pio->pinmux_mask);
}
/* Reserve a pin, preventing anyone else from changing its configuration. */ /* Reserve a pin, preventing anyone else from changing its configuration. */
void __init at32_reserve_pin(unsigned int pin) void __init at32_reserve_pin(unsigned int pin)
{ {
...@@ -382,7 +414,6 @@ static int __init pio_probe(struct platform_device *pdev) ...@@ -382,7 +414,6 @@ static int __init pio_probe(struct platform_device *pdev)
} }
static struct platform_driver pio_driver = { static struct platform_driver pio_driver = {
.probe = pio_probe,
.driver = { .driver = {
.name = "pio", .name = "pio",
}, },
...@@ -390,7 +421,7 @@ static struct platform_driver pio_driver = { ...@@ -390,7 +421,7 @@ static struct platform_driver pio_driver = {
static int __init pio_init(void) static int __init pio_init(void)
{ {
return platform_driver_register(&pio_driver); return platform_driver_probe(&pio_driver, pio_probe);
} }
postcore_initcall(pio_init); postcore_initcall(pio_init);
......
...@@ -5,4 +5,4 @@ oprofile-y := $(addprefix ../../../drivers/oprofile/, \ ...@@ -5,4 +5,4 @@ oprofile-y := $(addprefix ../../../drivers/oprofile/, \
event_buffer.o oprofile_files.o \ event_buffer.o oprofile_files.o \
oprofilefs.o oprofile_stats.o \ oprofilefs.o oprofile_stats.o \
timer_int.o) timer_int.o)
oprofile-y += op_model_avr32.o oprofile-y += op_model_avr32.o backtrace.o
/*
* AVR32 specific backtracing code for oprofile
*
* Copyright 2008 Weinmann GmbH
*
* Author: Nikolaus Voss <n.voss@weinmann.de>
*
* Based on i386 oprofile backtrace code by John Levon and David Smith
*
* 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.
*
*/
#include <linux/oprofile.h>
#include <linux/sched.h>
#include <linux/uaccess.h>
/* The first two words of each frame on the stack look like this if we have
* frame pointers */
struct frame_head {
unsigned long lr;
struct frame_head *fp;
};
/* copied from arch/avr32/kernel/process.c */
static inline int valid_stack_ptr(struct thread_info *tinfo, unsigned long p)
{
return (p > (unsigned long)tinfo)
&& (p < (unsigned long)tinfo + THREAD_SIZE - 3);
}
/* copied from arch/x86/oprofile/backtrace.c */
static struct frame_head *dump_user_backtrace(struct frame_head *head)
{
struct frame_head bufhead[2];
/* Also check accessibility of one struct frame_head beyond */
if (!access_ok(VERIFY_READ, head, sizeof(bufhead)))
return NULL;
if (__copy_from_user_inatomic(bufhead, head, sizeof(bufhead)))
return NULL;
oprofile_add_trace(bufhead[0].lr);
/* frame pointers should strictly progress back up the stack
* (towards higher addresses) */
if (bufhead[0].fp <= head)
return NULL;
return bufhead[0].fp;
}
void avr32_backtrace(struct pt_regs * const regs, unsigned int depth)
{
/* Get first frame pointer */
struct frame_head *head = (struct frame_head *)(regs->r7);
if (!user_mode(regs)) {
#ifdef CONFIG_FRAME_POINTER
/*
* Traverse the kernel stack from frame to frame up to
* "depth" steps.
*/
while (depth-- && valid_stack_ptr(task_thread_info(current),
(unsigned long)head)) {
oprofile_add_trace(head->lr);
if (head->fp <= head)
break;
head = head->fp;
}
#endif
} else {
/* Assume we have frame pointers in user mode process */
while (depth-- && head)
head = dump_user_backtrace(head);
}
}
...@@ -22,6 +22,8 @@ ...@@ -22,6 +22,8 @@
#define AVR32_PERFCTR_IRQ_GROUP 0 #define AVR32_PERFCTR_IRQ_GROUP 0
#define AVR32_PERFCTR_IRQ_LINE 1 #define AVR32_PERFCTR_IRQ_LINE 1
void avr32_backtrace(struct pt_regs * const regs, unsigned int depth);
enum { PCCNT, PCNT0, PCNT1, NR_counter }; enum { PCCNT, PCNT0, PCNT1, NR_counter };
struct avr32_perf_counter { struct avr32_perf_counter {
...@@ -223,6 +225,8 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) ...@@ -223,6 +225,8 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
memcpy(ops, &avr32_perf_counter_ops, memcpy(ops, &avr32_perf_counter_ops,
sizeof(struct oprofile_operations)); sizeof(struct oprofile_operations));
ops->backtrace = avr32_backtrace;
printk(KERN_INFO "oprofile: using AVR32 performance monitoring.\n"); printk(KERN_INFO "oprofile: using AVR32 performance monitoring.\n");
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment