Commit 0181b61a authored by Russell King's avatar Russell King Committed by Russell King

Merge branch 'pxa' into devel

parents 92633b72 87944f33
......@@ -339,14 +339,14 @@ config ARCH_PNX4008
This enables support for Philips PNX4008 mobile platform.
config ARCH_PXA
bool "PXA2xx-based"
bool "PXA2xx/PXA3xx-based"
depends on MMU
select ARCH_MTD_XIP
select GENERIC_GPIO
select GENERIC_TIME
select GENERIC_CLOCKEVENTS
help
Support for Intel's PXA2XX processor line.
Support for Intel/Marvell's PXA2xx/PXA3xx processor line.
config ARCH_RPC
bool "RiscPC"
......@@ -489,7 +489,7 @@ source arch/arm/mm/Kconfig
config IWMMXT
bool "Enable iWMMXt support"
depends on CPU_XSCALE || CPU_XSC3
default y if PXA27x
default y if PXA27x || PXA3xx
help
Enable support for iWMMXt context switching at run time if
running on a CPU that supports it.
......
......@@ -33,10 +33,6 @@ __XScale_start:
bic r0, r0, #0x1000 @ clear Icache
mcr p15, 0, r0, c1, c0, 0
#ifdef CONFIG_ARCH_LUBBOCK
mov r7, #MACH_TYPE_LUBBOCK
#endif
#ifdef CONFIG_ARCH_COTULLA_IDP
mov r7, #MACH_TYPE_COTULLA_IDP
#endif
......
......@@ -17,3 +17,4 @@ obj-$(CONFIG_SHARPSL_PM) += sharpsl_pm.o
obj-$(CONFIG_SHARP_SCOOP) += scoop.o
obj-$(CONFIG_ARCH_IXP2000) += uengine.o
obj-$(CONFIG_ARCH_IXP23XX) += uengine.o
obj-$(CONFIG_PCI_HOST_ITE8152) += it8152.o
This diff is collapsed.
This diff is collapsed.
......@@ -279,6 +279,25 @@ static void __devinit pci_fixup_cy82c693(struct pci_dev *dev)
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693, pci_fixup_cy82c693);
static void __init pci_fixup_it8152(struct pci_dev *dev)
{
int i;
/* fixup for ITE 8152 devices */
/* FIXME: add defines for class 0x68000 and 0x80103 */
if ((dev->class >> 8) == PCI_CLASS_BRIDGE_HOST ||
dev->class == 0x68000 ||
dev->class == 0x80103) {
for (i = 0; i < PCI_NUM_RESOURCES; i++) {
dev->resource[i].start = 0;
dev->resource[i].end = 0;
dev->resource[i].flags = 0;
}
}
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_8152, pci_fixup_it8152);
void __devinit pcibios_update_irq(struct pci_dev *dev, int irq)
{
if (debug_pci)
......@@ -292,9 +311,12 @@ void __devinit pcibios_update_irq(struct pci_dev *dev, int irq)
*/
static inline int pdev_bad_for_parity(struct pci_dev *dev)
{
return (dev->vendor == PCI_VENDOR_ID_INTERG &&
(dev->device == PCI_DEVICE_ID_INTERG_2000 ||
dev->device == PCI_DEVICE_ID_INTERG_2010));
return ((dev->vendor == PCI_VENDOR_ID_INTERG &&
(dev->device == PCI_DEVICE_ID_INTERG_2000 ||
dev->device == PCI_DEVICE_ID_INTERG_2010)) ||
(dev->vendor == PCI_VENDOR_ID_ITE &&
dev->device == PCI_DEVICE_ID_ITE_8152));
}
/*
......
if ARCH_PXA
menu "Intel PXA2xx Implementations"
menu "Intel PXA2xx/PXA3xx Implementations"
if PXA3xx
menu "Supported PXA3xx Processor Variants"
config CPU_PXA300
bool "PXA300 (codename Monahans-L)"
config CPU_PXA310
bool "PXA310 (codename Monahans-LV)"
select CPU_PXA300
config CPU_PXA320
bool "PXA320 (codename Monahans-P)"
endmenu
endif
choice
prompt "Select target board"
......@@ -41,6 +59,15 @@ config MACH_EM_X270
bool "CompuLab EM-x270 platform"
select PXA27x
config MACH_ZYLONITE
bool "PXA3xx Development Platform"
select PXA3xx
config MACH_ARMCORE
bool "CompuLab CM-X270 modules"
select PXA27x
select IWMMXT
endchoice
if PXA_SHARPSL
......@@ -130,6 +157,11 @@ config PXA27x
help
Select code specific to PXA27x variants
config PXA3xx
bool
help
Select code specific to PXA3xx variants
config PXA_SHARP_C7xx
bool
select PXA_SSP
......
......@@ -3,36 +3,51 @@
#
# Common support (must be linked before board specific support)
obj-y += clock.o generic.o irq.o dma.o time.o
obj-$(CONFIG_PXA25x) += pxa25x.o
obj-$(CONFIG_PXA27x) += pxa27x.o
obj-y += clock.o generic.o irq.o dma.o time.o
obj-$(CONFIG_PXA25x) += pxa25x.o
obj-$(CONFIG_PXA27x) += pxa27x.o
obj-$(CONFIG_PXA3xx) += pxa3xx.o mfp.o
obj-$(CONFIG_CPU_PXA300) += pxa300.o
obj-$(CONFIG_CPU_PXA320) += pxa320.o
# Specific board support
obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o
obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o
obj-$(CONFIG_MACH_LOGICPD_PXA270) += lpd270.o
obj-$(CONFIG_MACH_MAINSTONE) += mainstone.o
obj-$(CONFIG_ARCH_PXA_IDP) += idp.o
obj-$(CONFIG_MACH_MAINSTONE) += mainstone.o
obj-$(CONFIG_ARCH_PXA_IDP) += idp.o
obj-$(CONFIG_MACH_TRIZEPS4) += trizeps4.o
obj-$(CONFIG_PXA_SHARP_C7xx) += corgi.o corgi_ssp.o corgi_lcd.o sharpsl_pm.o corgi_pm.o
obj-$(CONFIG_PXA_SHARP_Cxx00) += spitz.o corgi_ssp.o corgi_lcd.o sharpsl_pm.o spitz_pm.o
obj-$(CONFIG_MACH_AKITA) += akita-ioexp.o
obj-$(CONFIG_MACH_POODLE) += poodle.o corgi_ssp.o
obj-$(CONFIG_MACH_TOSA) += tosa.o
obj-$(CONFIG_MACH_EM_X270) += em-x270.o
obj-$(CONFIG_MACH_TOSA) += tosa.o
obj-$(CONFIG_MACH_EM_X270) += em-x270.o
ifeq ($(CONFIG_MACH_ZYLONITE),y)
obj-y += zylonite.o
obj-$(CONFIG_CPU_PXA300) += zylonite_pxa300.o
obj-$(CONFIG_CPU_PXA320) += zylonite_pxa320.o
endif
obj-$(CONFIG_MACH_ARMCORE) += cm-x270.o
# Support for blinky lights
led-y := leds.o
led-$(CONFIG_ARCH_LUBBOCK) += leds-lubbock.o
led-$(CONFIG_MACH_MAINSTONE) += leds-mainstone.o
led-$(CONFIG_ARCH_PXA_IDP) += leds-idp.o
led-$(CONFIG_MACH_TRIZEPS4) += leds-trizeps4.o
led-$(CONFIG_ARCH_LUBBOCK) += leds-lubbock.o
led-$(CONFIG_MACH_MAINSTONE) += leds-mainstone.o
led-$(CONFIG_ARCH_PXA_IDP) += leds-idp.o
led-$(CONFIG_MACH_TRIZEPS4) += leds-trizeps4.o
obj-$(CONFIG_LEDS) += $(led-y)
obj-$(CONFIG_LEDS) += $(led-y)
# Misc features
obj-$(CONFIG_PM) += pm.o sleep.o
obj-$(CONFIG_PXA_SSP) += ssp.o
obj-$(CONFIG_PM) += pm.o sleep.o
obj-$(CONFIG_PXA_SSP) += ssp.o
ifeq ($(CONFIG_PXA27x),y)
obj-$(CONFIG_PM) += standby.o
obj-$(CONFIG_PM) += standby.o
endif
ifeq ($(CONFIG_PCI),y)
obj-$(CONFIG_MACH_ARMCORE) += cm-x270-pci.o
endif
......@@ -9,19 +9,15 @@
#include <linux/string.h>
#include <linux/clk.h>
#include <linux/spinlock.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <asm/arch/pxa-regs.h>
#include <asm/hardware.h>
struct clk {
struct list_head node;
unsigned long rate;
struct module *owner;
const char *name;
unsigned int enabled;
void (*enable)(void);
void (*disable)(void);
};
#include "devices.h"
#include "generic.h"
#include "clock.h"
static LIST_HEAD(clocks);
static DEFINE_MUTEX(clocks_mutex);
......@@ -33,7 +29,8 @@ struct clk *clk_get(struct device *dev, const char *id)
mutex_lock(&clocks_mutex);
list_for_each_entry(p, &clocks, node) {
if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
if (strcmp(id, p->name) == 0 &&
(p->dev == NULL || p->dev == dev)) {
clk = p;
break;
}
......@@ -46,7 +43,6 @@ EXPORT_SYMBOL(clk_get);
void clk_put(struct clk *clk)
{
module_put(clk->owner);
}
EXPORT_SYMBOL(clk_put);
......@@ -56,8 +52,12 @@ int clk_enable(struct clk *clk)
spin_lock_irqsave(&clocks_lock, flags);
if (clk->enabled++ == 0)
clk->enable();
clk->ops->enable(clk);
spin_unlock_irqrestore(&clocks_lock, flags);
if (clk->delay)
udelay(clk->delay);
return 0;
}
EXPORT_SYMBOL(clk_enable);
......@@ -70,54 +70,75 @@ void clk_disable(struct clk *clk)
spin_lock_irqsave(&clocks_lock, flags);
if (--clk->enabled == 0)
clk->disable();
clk->ops->disable(clk);
spin_unlock_irqrestore(&clocks_lock, flags);
}
EXPORT_SYMBOL(clk_disable);
unsigned long clk_get_rate(struct clk *clk)
{
return clk->rate;
unsigned long rate;
rate = clk->rate;
if (clk->ops->getrate)
rate = clk->ops->getrate(clk);
return rate;
}
EXPORT_SYMBOL(clk_get_rate);
static void clk_gpio27_enable(void)
static void clk_gpio27_enable(struct clk *clk)
{
pxa_gpio_mode(GPIO11_3_6MHz_MD);
}
static void clk_gpio27_disable(void)
static void clk_gpio27_disable(struct clk *clk)
{
}
static struct clk clk_gpio27 = {
.name = "GPIO27_CLK",
.rate = 3686400,
static const struct clkops clk_gpio27_ops = {
.enable = clk_gpio27_enable,
.disable = clk_gpio27_disable,
};
int clk_register(struct clk *clk)
void clk_cken_enable(struct clk *clk)
{
mutex_lock(&clocks_mutex);
list_add(&clk->node, &clocks);
mutex_unlock(&clocks_mutex);
return 0;
CKEN |= 1 << clk->cken;
}
EXPORT_SYMBOL(clk_register);
void clk_unregister(struct clk *clk)
void clk_cken_disable(struct clk *clk)
{
CKEN &= ~(1 << clk->cken);
}
const struct clkops clk_cken_ops = {
.enable = clk_cken_enable,
.disable = clk_cken_disable,
};
static struct clk common_clks[] = {
{
.name = "GPIO27_CLK",
.ops = &clk_gpio27_ops,
.rate = 3686400,
},
};
void clks_register(struct clk *clks, size_t num)
{
int i;
mutex_lock(&clocks_mutex);
list_del(&clk->node);
for (i = 0; i < num; i++)
list_add(&clks[i].node, &clocks);
mutex_unlock(&clocks_mutex);
}
EXPORT_SYMBOL(clk_unregister);
static int __init clk_init(void)
{
clk_register(&clk_gpio27);
clks_register(common_clks, ARRAY_SIZE(common_clks));
return 0;
}
arch_initcall(clk_init);
struct clk;
struct clkops {
void (*enable)(struct clk *);
void (*disable)(struct clk *);
unsigned long (*getrate)(struct clk *);
};
struct clk {
struct list_head node;
const char *name;
struct device *dev;
const struct clkops *ops;
unsigned long rate;
unsigned int cken;
unsigned int delay;
unsigned int enabled;
};
#define INIT_CKEN(_name, _cken, _rate, _delay, _dev) \
{ \
.name = _name, \
.dev = _dev, \
.ops = &clk_cken_ops, \
.rate = _rate, \
.cken = CKEN_##_cken, \
.delay = _delay, \
}
#define INIT_CK(_name, _cken, _ops, _dev) \
{ \
.name = _name, \
.dev = _dev, \
.ops = _ops, \
.cken = CKEN_##_cken, \
}
extern const struct clkops clk_cken_ops;
void clk_cken_enable(struct clk *clk);
void clk_cken_disable(struct clk *clk);
void clks_register(struct clk *clks, size_t num);
/*
* linux/arch/arm/mach-pxa/cm-x270-pci.c
*
* PCI bios-type initialisation for PCI machines
*
* Bits taken from various places.
*
* Copyright (C) 2007 Compulab, Ltd.
* Mike Rapoport <mike@compulab.co.il>
*
* 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/kernel.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/irq.h>
#include <asm/mach/pci.h>
#include <asm/arch/cm-x270.h>
#include <asm/arch/pxa-regs.h>
#include <asm/mach-types.h>
#include <asm/hardware/it8152.h>
unsigned long it8152_base_address = CMX270_IT8152_VIRT;
/*
* Only first 64MB of memory can be accessed via PCI.
* We use GFP_DMA to allocate safe buffers to do map/unmap.
* This is really ugly and we need a better way of specifying
* DMA-capable regions of memory.
*/
void __init cmx270_pci_adjust_zones(int node, unsigned long *zone_size,
unsigned long *zhole_size)
{
unsigned int sz = SZ_64M >> PAGE_SHIFT;
printk(KERN_INFO "Adjusting zones for CM-x270\n");
/*
* Only adjust if > 64M on current system
*/
if (node || (zone_size[0] <= sz))
return;
zone_size[1] = zone_size[0] - sz;
zone_size[0] = sz;
zhole_size[1] = zhole_size[0];
zhole_size[0] = 0;
}
static void cmx270_it8152_irq_demux(unsigned int irq, struct irq_desc *desc)
{
/* clear our parent irq */
GEDR(GPIO_IT8152_IRQ) = GPIO_bit(GPIO_IT8152_IRQ);
it8152_irq_demux(irq, desc);
}
void __cmx270_pci_init_irq(void)
{
it8152_init_irq();
pxa_gpio_mode(IRQ_TO_GPIO(GPIO_IT8152_IRQ));
set_irq_type(IRQ_GPIO(GPIO_IT8152_IRQ), IRQT_RISING);
set_irq_chained_handler(IRQ_GPIO(GPIO_IT8152_IRQ),
cmx270_it8152_irq_demux);
}
#ifdef CONFIG_PM
static unsigned long sleep_save_ite[10];
void __cmx270_pci_suspend(void)
{
/* save ITE state */
sleep_save_ite[0] = __raw_readl(IT8152_INTC_PDCNIMR);
sleep_save_ite[1] = __raw_readl(IT8152_INTC_LPCNIMR);
sleep_save_ite[2] = __raw_readl(IT8152_INTC_LPNIAR);
/* Clear ITE IRQ's */
__raw_writel((0), IT8152_INTC_PDCNIRR);
__raw_writel((0), IT8152_INTC_LPCNIRR);
}
void __cmx270_pci_resume(void)
{
/* restore IT8152 state */
__raw_writel((sleep_save_ite[0]), IT8152_INTC_PDCNIMR);
__raw_writel((sleep_save_ite[1]), IT8152_INTC_LPCNIMR);
__raw_writel((sleep_save_ite[2]), IT8152_INTC_LPNIAR);
}
#else
void cmx270_pci_suspend(void) {}
void cmx270_pci_resume(void) {}
#endif
/* PCI IRQ mapping*/
static int __init cmx270_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
{
int irq;
printk(KERN_DEBUG "===> %s: %s slot=%x, pin=%x\n", __FUNCTION__,
pci_name(dev), slot, pin);
irq = it8152_pci_map_irq(dev, slot, pin);
if (irq)
return irq;
/*
Here comes the ugly part. The routing is baseboard specific,
but defining a platform for each possible base of CM-x270 is
unrealistic. Here we keep mapping for ATXBase and SB-x270.
*/
/* ATXBASE PCI slot */
if (slot == 7)
return IT8152_PCI_INTA;
/* ATXBase/SB-x270 CardBus */
if (slot == 8 || slot == 0)
return IT8152_PCI_INTB;
/* ATXBase Ethernet */
if (slot == 9)
return IT8152_PCI_INTA;
/* SB-x270 Ethernet */
if (slot == 16)
return IT8152_PCI_INTA;
/* PC104+ interrupt routing */
if ((slot == 17) || (slot == 19))
return IT8152_PCI_INTA;
if ((slot == 18) || (slot == 20))
return IT8152_PCI_INTB;
return(0);
}
static struct pci_bus * __init
cmx270_pci_scan_bus(int nr, struct pci_sys_data *sys)
{
printk(KERN_INFO "Initializing CM-X270 PCI subsystem\n");
__raw_writel(0x800, IT8152_PCI_CFG_ADDR);
if (__raw_readl(IT8152_PCI_CFG_DATA) == 0x81521283) {
printk(KERN_INFO "PCI Bridge found.\n");
/* set PCI I/O base at 0 */
writel(0x848, IT8152_PCI_CFG_ADDR);
writel(0, IT8152_PCI_CFG_DATA);
/* set PCI memory base at 0 */
writel(0x840, IT8152_PCI_CFG_ADDR);
writel(0, IT8152_PCI_CFG_DATA);
writel(0x20, IT8152_GPIO_GPDR);
/* CardBus Controller on ATXbase baseboard */
writel(0x4000, IT8152_PCI_CFG_ADDR);
if (readl(IT8152_PCI_CFG_DATA) == 0xAC51104C) {
printk(KERN_INFO "CardBus Bridge found.\n");
/* Configure socket 0 */
writel(0x408C, IT8152_PCI_CFG_ADDR);
writel(0x1022, IT8152_PCI_CFG_DATA);
writel(0x4080, IT8152_PCI_CFG_ADDR);
writel(0x3844d060, IT8152_PCI_CFG_DATA);
writel(0x4090, IT8152_PCI_CFG_ADDR);
writel(((readl(IT8152_PCI_CFG_DATA) & 0xffff) |
0x60440000),
IT8152_PCI_CFG_DATA);
writel(0x4018, IT8152_PCI_CFG_ADDR);
writel(0xb0000000, IT8152_PCI_CFG_DATA);
/* Configure socket 1 */
writel(0x418C, IT8152_PCI_CFG_ADDR);
writel(0x1022, IT8152_PCI_CFG_DATA);
writel(0x4180, IT8152_PCI_CFG_ADDR);
writel(0x3844d060, IT8152_PCI_CFG_DATA);
writel(0x4190, IT8152_PCI_CFG_ADDR);
writel(((readl(IT8152_PCI_CFG_DATA) & 0xffff) |
0x60440000),
IT8152_PCI_CFG_DATA);
writel(0x4118, IT8152_PCI_CFG_ADDR);
writel(0xb0000000, IT8152_PCI_CFG_DATA);
}
}
return it8152_pci_scan_bus(nr, sys);
}
static struct hw_pci cmx270_pci __initdata = {
.swizzle = pci_std_swizzle,
.map_irq = cmx270_pci_map_irq,
.nr_controllers = 1,
.setup = it8152_pci_setup,
.scan = cmx270_pci_scan_bus,
};
static int __init cmx270_init_pci(void)
{
if (machine_is_armcore())
pci_common_init(&cmx270_pci);
return 0;
}
subsys_initcall(cmx270_init_pci);
extern void __cmx270_pci_init_irq(void);
extern void __cmx270_pci_suspend(void);
extern void __cmx270_pci_resume(void);
#ifdef CONFIG_PCI
#define cmx270_pci_init_irq __cmx270_pci_init_irq
#define cmx270_pci_suspend __cmx270_pci_suspend
#define cmx270_pci_resume __cmx270_pci_resume
#else
#define cmx270_pci_init_irq() do {} while (0)
#define cmx270_pci_suspend() do {} while (0)
#define cmx270_pci_resume() do {} while (0)
#endif
This diff is collapsed.
......@@ -9,3 +9,6 @@ extern struct platform_device pxa_device_i2c;
extern struct platform_device pxa_device_i2s;
extern struct platform_device pxa_device_ficp;
extern struct platform_device pxa_device_rtc;
extern struct platform_device pxa27x_device_i2c_power;
extern struct platform_device pxa27x_device_ohci;
......@@ -25,10 +25,6 @@
#include <linux/pm.h>
#include <linux/string.h>
#include <linux/sched.h>
#include <asm/cnt32_to_63.h>
#include <asm/div64.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/system.h>
......@@ -47,66 +43,39 @@
#include "generic.h"
/*
* This is the PXA2xx sched_clock implementation. This has a resolution
* of at least 308ns and a maximum value that depends on the value of
* CLOCK_TICK_RATE.
*
* The return value is guaranteed to be monotonic in that range as
* long as there is always less than 582 seconds between successive
* calls to this function.
* Get the clock frequency as reflected by CCCR and the turbo flag.
* We assume these values have been applied via a fcs.
* If info is not 0 we also display the current settings.
*/
unsigned long long sched_clock(void)
unsigned int get_clk_frequency_khz(int info)
{
unsigned long long v = cnt32_to_63(OSCR);
/* Note: top bit ov v needs cleared unless multiplier is even. */
#if CLOCK_TICK_RATE == 3686400
/* 1E9 / 3686400 => 78125 / 288, max value = 32025597s (370 days). */
/* The <<1 is used to get rid of tick.hi top bit */
v *= 78125<<1;
do_div(v, 288<<1);
#elif CLOCK_TICK_RATE == 3250000
/* 1E9 / 3250000 => 4000 / 13, max value = 709490156s (8211 days) */
v *= 4000;
do_div(v, 13);
#elif CLOCK_TICK_RATE == 3249600
/* 1E9 / 3249600 => 625000 / 2031, max value = 4541295s (52 days) */
v *= 625000;
do_div(v, 2031);
#else
#warning "consider fixing sched_clock for your value of CLOCK_TICK_RATE"
/*
* 96-bit math to perform tick * NSEC_PER_SEC / CLOCK_TICK_RATE for
* any value of CLOCK_TICK_RATE. Max value is in the 80 thousand
* years range and truncation to unsigned long long limits it to
* sched_clock's max range of ~584 years. This is nice but with
* higher computation cost.
*/
{
union {
unsigned long long val;
struct { unsigned long lo, hi; };
} x;
unsigned long long y;
x.val = v;
x.hi &= 0x7fffffff;
y = (unsigned long long)x.lo * NSEC_PER_SEC;
x.lo = y;
y = (y >> 32) + (unsigned long long)x.hi * NSEC_PER_SEC;
x.hi = do_div(y, CLOCK_TICK_RATE);
do_div(x.val, CLOCK_TICK_RATE);
x.hi += y;
v = x.val;
}
#endif
if (cpu_is_pxa21x() || cpu_is_pxa25x())
return pxa25x_get_clk_frequency_khz(info);
else if (cpu_is_pxa27x())
return pxa27x_get_clk_frequency_khz(info);
else
return pxa3xx_get_clk_frequency_khz(info);
}
EXPORT_SYMBOL(get_clk_frequency_khz);
return v;
/*
* Return the current memory clock frequency in units of 10kHz
*/
unsigned int get_memclk_frequency_10khz(void)
{
if (cpu_is_pxa21x() || cpu_is_pxa25x())
return pxa25x_get_memclk_frequency_10khz();
else if (cpu_is_pxa27x())
return pxa27x_get_memclk_frequency_10khz();
else
return pxa3xx_get_memclk_frequency_10khz();
}
EXPORT_SYMBOL(get_memclk_frequency_10khz);
/*
* Handy function to set GPIO alternate functions
*/
int pxa_last_gpio;
int pxa_gpio_mode(int gpio_mode)
{
......@@ -115,7 +84,7 @@ int pxa_gpio_mode(int gpio_mode)
int fn = (gpio_mode & GPIO_MD_MASK_FN) >> 8;
int gafr;
if (gpio > PXA_LAST_GPIO)
if (gpio > pxa_last_gpio)
return -EINVAL;
local_irq_save(flags);
......@@ -136,6 +105,44 @@ int pxa_gpio_mode(int gpio_mode)
EXPORT_SYMBOL(pxa_gpio_mode);
int gpio_direction_input(unsigned gpio)
{
unsigned long flags;
u32 mask;
if (gpio > pxa_last_gpio)
return -EINVAL;
mask = GPIO_bit(gpio);
local_irq_save(flags);
GPDR(gpio) &= ~mask;
local_irq_restore(flags);
return 0;
}
EXPORT_SYMBOL(gpio_direction_input);
int gpio_direction_output(unsigned gpio, int value)
{
unsigned long flags;
u32 mask;
if (gpio > pxa_last_gpio)
return -EINVAL;
mask = GPIO_bit(gpio);
local_irq_save(flags);
if (value)
GPSR(gpio) = mask;
else
GPCR(gpio) = mask;
GPDR(gpio) |= mask;
local_irq_restore(flags);
return 0;
}
EXPORT_SYMBOL(gpio_direction_output);
/*
* Return GPIO level
*/
......@@ -159,7 +166,7 @@ EXPORT_SYMBOL(pxa_gpio_set_value);
/*
* Routine to safely enable or disable a clock in the CKEN
*/
void pxa_set_cken(int clock, int enable)
void __pxa_set_cken(int clock, int enable)
{
unsigned long flags;
local_irq_save(flags);
......@@ -172,7 +179,7 @@ void pxa_set_cken(int clock, int enable)
local_irq_restore(flags);
}
EXPORT_SYMBOL(pxa_set_cken);
EXPORT_SYMBOL(__pxa_set_cken);
/*
* Intel PXA2xx internal register mapping.
......@@ -329,21 +336,80 @@ void __init set_pxa_fb_parent(struct device *parent_dev)
pxa_device_fb.dev.parent = parent_dev;
}
static struct resource pxa_resource_ffuart[] = {
{
.start = __PREG(FFUART),
.end = __PREG(FFUART) + 35,
.flags = IORESOURCE_MEM,
}, {
.start = IRQ_FFUART,
.end = IRQ_FFUART,
.flags = IORESOURCE_IRQ,
}
};
struct platform_device pxa_device_ffuart= {
.name = "pxa2xx-uart",
.id = 0,
.resource = pxa_resource_ffuart,
.num_resources = ARRAY_SIZE(pxa_resource_ffuart),
};
static struct resource pxa_resource_btuart[] = {
{
.start = __PREG(BTUART),
.end = __PREG(BTUART) + 35,
.flags = IORESOURCE_MEM,
}, {
.start = IRQ_BTUART,
.end = IRQ_BTUART,
.flags = IORESOURCE_IRQ,
}
};
struct platform_device pxa_device_btuart = {
.name = "pxa2xx-uart",
.id = 1,
.resource = pxa_resource_btuart,
.num_resources = ARRAY_SIZE(pxa_resource_btuart),
};
static struct resource pxa_resource_stuart[] = {
{
.start = __PREG(STUART),
.end = __PREG(STUART) + 35,
.flags = IORESOURCE_MEM,
}, {
.start = IRQ_STUART,
.end = IRQ_STUART,
.flags = IORESOURCE_IRQ,
}
};
struct platform_device pxa_device_stuart = {
.name = "pxa2xx-uart",
.id = 2,
.resource = pxa_resource_stuart,
.num_resources = ARRAY_SIZE(pxa_resource_stuart),
};
static struct resource pxa_resource_hwuart[] = {
{
.start = __PREG(HWUART),
.end = __PREG(HWUART) + 47,
.flags = IORESOURCE_MEM,
}, {
.start = IRQ_HWUART,
.end = IRQ_HWUART,
.flags = IORESOURCE_IRQ,
}
};
struct platform_device pxa_device_hwuart = {
.name = "pxa2xx-uart",
.id = 3,
.resource = pxa_resource_hwuart,
.num_resources = ARRAY_SIZE(pxa_resource_hwuart),
};
static struct resource pxai2c_resources[] = {
......
......@@ -15,14 +15,40 @@ extern struct sys_timer pxa_timer;
extern void __init pxa_init_irq_low(void);
extern void __init pxa_init_irq_high(void);
extern void __init pxa_init_irq_gpio(int gpio_nr);
extern void __init pxa_init_irq_set_wake(int (*set_wake)(unsigned int, unsigned int));
extern void __init pxa25x_init_irq(void);
extern void __init pxa27x_init_irq(void);
extern void __init pxa3xx_init_irq(void);
extern void __init pxa_map_io(void);
extern unsigned int get_clk_frequency_khz(int info);
extern int pxa_last_gpio;
#define SET_BANK(__nr,__start,__size) \
mi->bank[__nr].start = (__start), \
mi->bank[__nr].size = (__size), \
mi->bank[__nr].node = (((unsigned)(__start) - PHYS_OFFSET) >> 27)
#ifdef CONFIG_PXA25x
extern unsigned pxa25x_get_clk_frequency_khz(int);
extern unsigned pxa25x_get_memclk_frequency_10khz(void);
#else
#define pxa25x_get_clk_frequency_khz(x) (0)
#define pxa25x_get_memclk_frequency_10khz() (0)
#endif
#ifdef CONFIG_PXA27x
extern unsigned pxa27x_get_clk_frequency_khz(int);
extern unsigned pxa27x_get_memclk_frequency_10khz(void);
#else
#define pxa27x_get_clk_frequency_khz(x) (0)
#define pxa27x_get_memclk_frequency_10khz() (0)
#endif
#ifdef CONFIG_PXA3xx
extern unsigned pxa3xx_get_clk_frequency_khz(int);
extern unsigned pxa3xx_get_memclk_frequency_10khz(void);
#else
#define pxa3xx_get_clk_frequency_khz(x) (0)
#define pxa3xx_get_memclk_frequency_10khz() (0)
#endif
......@@ -38,33 +38,11 @@ static void pxa_unmask_low_irq(unsigned int irq)
ICMR |= (1 << irq);
}
static int pxa_set_wake(unsigned int irq, unsigned int on)
{
u32 mask;
switch (irq) {
case IRQ_RTCAlrm:
mask = PWER_RTC;
break;
#ifdef CONFIG_PXA27x
/* REVISIT can handle USBH1, USBH2, USB, MSL, USIM, ... */
#endif
default:
return -EINVAL;
}
if (on)
PWER |= mask;
else
PWER &= ~mask;
return 0;
}
static struct irq_chip pxa_internal_chip_low = {
.name = "SC",
.ack = pxa_mask_low_irq,
.mask = pxa_mask_low_irq,
.unmask = pxa_unmask_low_irq,
.set_wake = pxa_set_wake,
};
void __init pxa_init_irq_low(void)
......@@ -87,7 +65,7 @@ void __init pxa_init_irq_low(void)
}
}
#ifdef CONFIG_PXA27x
#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
/*
* This is for the second set of internal IRQs as found on the PXA27x.
......@@ -125,26 +103,6 @@ void __init pxa_init_irq_high(void)
}
#endif
/* Note that if an input/irq line ever gets changed to an output during
* suspend, the relevant PWER, PRER, and PFER bits should be cleared.
*/
#ifdef CONFIG_PXA27x
/* PXA27x: Various gpios can issue wakeup events. This logic only
* handles the simple cases, not the WEMUX2 and WEMUX3 options
*/
#define PXA27x_GPIO_NOWAKE_MASK \
((1 << 8) | (1 << 7) | (1 << 6) | (1 << 5) | (1 << 2))
#define WAKEMASK(gpio) \
(((gpio) <= 15) \
? ((1 << (gpio)) & ~PXA27x_GPIO_NOWAKE_MASK) \
: ((gpio == 35) ? (1 << 24) : 0))
#else
/* pxa 210, 250, 255, 26x: gpios 0..15 can issue wakeups */
#define WAKEMASK(gpio) (((gpio) <= 15) ? (1 << (gpio)) : 0)
#endif
/*
* PXA GPIO edge detection for IRQs:
* IRQs are generated on Falling-Edge, Rising-Edge, or both.
......@@ -158,11 +116,9 @@ static long GPIO_IRQ_mask[4];
static int pxa_gpio_irq_type(unsigned int irq, unsigned int type)
{
int gpio, idx;
u32 mask;
gpio = IRQ_TO_GPIO(irq);
idx = gpio >> 5;
mask = WAKEMASK(gpio);
if (type == IRQT_PROBE) {
/* Don't mess with enabled GPIOs using preconfigured edges or
......@@ -182,19 +138,15 @@ static int pxa_gpio_irq_type(unsigned int irq, unsigned int type)
if (type & __IRQT_RISEDGE) {
/* printk("rising "); */
__set_bit (gpio, GPIO_IRQ_rising_edge);
PRER |= mask;
} else {
__clear_bit (gpio, GPIO_IRQ_rising_edge);
PRER &= ~mask;
}
if (type & __IRQT_FALEDGE) {
/* printk("falling "); */
__set_bit (gpio, GPIO_IRQ_falling_edge);
PFER |= mask;
} else {
__clear_bit (gpio, GPIO_IRQ_falling_edge);
PFER &= ~mask;
}
/* printk("edges\n"); */
......@@ -213,29 +165,12 @@ static void pxa_ack_low_gpio(unsigned int irq)
GEDR0 = (1 << (irq - IRQ_GPIO0));
}
static int pxa_set_gpio_wake(unsigned int irq, unsigned int on)
{
int gpio = IRQ_TO_GPIO(irq);
u32 mask = WAKEMASK(gpio);
if (!mask)
return -EINVAL;
if (on)
PWER |= mask;
else
PWER &= ~mask;
return 0;
}
static struct irq_chip pxa_low_gpio_chip = {
.name = "GPIO-l",
.ack = pxa_ack_low_gpio,
.mask = pxa_mask_low_irq,
.unmask = pxa_unmask_low_irq,
.set_type = pxa_gpio_irq_type,
.set_wake = pxa_set_gpio_wake,
};
/*
......@@ -342,13 +277,14 @@ static struct irq_chip pxa_muxed_gpio_chip = {
.mask = pxa_mask_muxed_gpio,
.unmask = pxa_unmask_muxed_gpio,
.set_type = pxa_gpio_irq_type,
.set_wake = pxa_set_gpio_wake,
};
void __init pxa_init_irq_gpio(int gpio_nr)
{
int irq, i;
pxa_last_gpio = gpio_nr - 1;
/* clear all GPIO edge detects */
for (i = 0; i < gpio_nr; i += 32) {
GFER(i) = 0;
......@@ -375,3 +311,13 @@ void __init pxa_init_irq_gpio(int gpio_nr)
set_irq_chip(IRQ_GPIO_2_x, &pxa_internal_chip_low);
set_irq_chained_handler(IRQ_GPIO_2_x, pxa_gpio_demux_handler);
}
void __init pxa_init_irq_set_wake(int (*set_wake)(unsigned int, unsigned int))
{
pxa_internal_chip_low.set_wake = set_wake;
#ifdef CONFIG_PXA27x
pxa_internal_chip_high.set_wake = set_wake;
#endif
pxa_low_gpio_chip.set_wake = set_wake;
pxa_muxed_gpio_chip.set_wake = set_wake;
}
......@@ -512,6 +512,25 @@ static void __init lubbock_map_io(void)
pxa_gpio_mode(GPIO44_BTCTS_MD);
pxa_gpio_mode(GPIO45_BTRTS_MD);
GPSR(GPIO48_nPOE) =
GPIO_bit(GPIO48_nPOE) |
GPIO_bit(GPIO49_nPWE) |
GPIO_bit(GPIO50_nPIOR) |
GPIO_bit(GPIO51_nPIOW) |
GPIO_bit(GPIO52_nPCE_1) |
GPIO_bit(GPIO53_nPCE_2);
pxa_gpio_mode(GPIO48_nPOE_MD);
pxa_gpio_mode(GPIO49_nPWE_MD);
pxa_gpio_mode(GPIO50_nPIOR_MD);
pxa_gpio_mode(GPIO51_nPIOW_MD);
pxa_gpio_mode(GPIO52_nPCE_1_MD);
pxa_gpio_mode(GPIO53_nPCE_2_MD);
pxa_gpio_mode(GPIO54_pSKTSEL_MD);
pxa_gpio_mode(GPIO55_nPREG_MD);
pxa_gpio_mode(GPIO56_nPWAIT_MD);
pxa_gpio_mode(GPIO57_nIOIS16_MD);
/* This is for the SMC chip select */
pxa_gpio_mode(GPIO79_nCS_3_MD);
......
......@@ -444,6 +444,25 @@ static void __init mainstone_init(void)
*/
pxa_gpio_mode(GPIO45_SYSCLK_AC97_MD);
GPSR(GPIO48_nPOE) =
GPIO_bit(GPIO48_nPOE) |
GPIO_bit(GPIO49_nPWE) |
GPIO_bit(GPIO50_nPIOR) |
GPIO_bit(GPIO51_nPIOW) |
GPIO_bit(GPIO85_nPCE_1) |
GPIO_bit(GPIO54_nPCE_2);
pxa_gpio_mode(GPIO48_nPOE_MD);
pxa_gpio_mode(GPIO49_nPWE_MD);
pxa_gpio_mode(GPIO50_nPIOR_MD);
pxa_gpio_mode(GPIO51_nPIOW_MD);
pxa_gpio_mode(GPIO85_nPCE_1_MD);
pxa_gpio_mode(GPIO54_nPCE_2_MD);
pxa_gpio_mode(GPIO79_pSKTSEL_MD);
pxa_gpio_mode(GPIO55_nPREG_MD);
pxa_gpio_mode(GPIO56_nPWAIT_MD);
pxa_gpio_mode(GPIO57_nIOIS16_MD);
platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
/* reading Mainstone's "Virtual Configuration Register"
......
/*
* linux/arch/arm/mach-pxa/mfp.c
*
* PXA3xx Multi-Function Pin Support
*
* Copyright (C) 2007 Marvell Internation Ltd.
*
* 2007-08-21: eric miao <eric.y.miao@gmail.com>
* initial version
*
* 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/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/io.h>
#include <asm/hardware.h>
#include <asm/arch/mfp.h>
/* mfp_spin_lock is used to ensure that MFP register configuration
* (most likely a read-modify-write operation) is atomic, and that
* mfp_table[] is consistent
*/
static DEFINE_SPINLOCK(mfp_spin_lock);
static void __iomem *mfpr_mmio_base = (void __iomem *)&__REG(MFPR_BASE);
static struct pxa3xx_mfp_pin mfp_table[MFP_PIN_MAX];
#define mfpr_readl(off) \
__raw_readl(mfpr_mmio_base + (off))
#define mfpr_writel(off, val) \
__raw_writel(val, mfpr_mmio_base + (off))
/*
* perform a read-back of any MFPR register to make sure the
* previous writings are finished
*/
#define mfpr_sync() (void)__raw_readl(mfpr_mmio_base + 0)
static inline void __mfp_config(int pin, unsigned long val)
{
unsigned long off = mfp_table[pin].mfpr_off;
mfp_table[pin].mfpr_val = val;
mfpr_writel(off, val);
}
void pxa3xx_mfp_config(mfp_cfg_t *mfp_cfgs, int num)
{
int i, pin;
unsigned long val, flags;
mfp_cfg_t *mfp_cfg = mfp_cfgs;
spin_lock_irqsave(&mfp_spin_lock, flags);
for (i = 0; i < num; i++, mfp_cfg++) {
pin = MFP_CFG_PIN(*mfp_cfg);
val = MFP_CFG_VAL(*mfp_cfg);
BUG_ON(pin >= MFP_PIN_MAX);
__mfp_config(pin, val);
}
mfpr_sync();
spin_unlock_irqrestore(&mfp_spin_lock, flags);
}
unsigned long pxa3xx_mfp_read(int mfp)
{
unsigned long val, flags;
BUG_ON(mfp >= MFP_PIN_MAX);
spin_lock_irqsave(&mfp_spin_lock, flags);
val = mfpr_readl(mfp_table[mfp].mfpr_off);
spin_unlock_irqrestore(&mfp_spin_lock, flags);
return val;
}
void pxa3xx_mfp_write(int mfp, unsigned long val)
{
unsigned long flags;
BUG_ON(mfp >= MFP_PIN_MAX);
spin_lock_irqsave(&mfp_spin_lock, flags);
mfpr_writel(mfp_table[mfp].mfpr_off, val);
mfpr_sync();
spin_unlock_irqrestore(&mfp_spin_lock, flags);
}
void pxa3xx_mfp_set_afds(int mfp, int af, int ds)
{
uint32_t mfpr_off, mfpr_val;
unsigned long flags;
BUG_ON(mfp >= MFP_PIN_MAX);
spin_lock_irqsave(&mfp_spin_lock, flags);
mfpr_off = mfp_table[mfp].mfpr_off;
mfpr_val = mfpr_readl(mfpr_off);
mfpr_val &= ~(MFPR_AF_MASK | MFPR_DRV_MASK);
mfpr_val |= (((af & 0x7) << MFPR_ALT_OFFSET) |
((ds & 0x7) << MFPR_DRV_OFFSET));
mfpr_writel(mfpr_off, mfpr_val);
mfpr_sync();
spin_unlock_irqrestore(&mfp_spin_lock, flags);
}
void pxa3xx_mfp_set_rdh(int mfp, int rdh)
{
uint32_t mfpr_off, mfpr_val;
unsigned long flags;
BUG_ON(mfp >= MFP_PIN_MAX);
spin_lock_irqsave(&mfp_spin_lock, flags);
mfpr_off = mfp_table[mfp].mfpr_off;
mfpr_val = mfpr_readl(mfpr_off);
mfpr_val &= ~MFPR_RDH_MASK;
if (likely(rdh))
mfpr_val |= (1u << MFPR_SS_OFFSET);
mfpr_writel(mfpr_off, mfpr_val);
mfpr_sync();
spin_unlock_irqrestore(&mfp_spin_lock, flags);
}
void pxa3xx_mfp_set_lpm(int mfp, int lpm)
{
uint32_t mfpr_off, mfpr_val;
unsigned long flags;
BUG_ON(mfp >= MFP_PIN_MAX);
spin_lock_irqsave(&mfp_spin_lock, flags);
mfpr_off = mfp_table[mfp].mfpr_off;
mfpr_val = mfpr_readl(mfpr_off);
mfpr_val &= ~MFPR_LPM_MASK;
if (lpm & 0x1) mfpr_val |= 1u << MFPR_SON_OFFSET;
if (lpm & 0x2) mfpr_val |= 1u << MFPR_SD_OFFSET;
if (lpm & 0x4) mfpr_val |= 1u << MFPR_PU_OFFSET;
if (lpm & 0x8) mfpr_val |= 1u << MFPR_PD_OFFSET;
if (lpm &0x10) mfpr_val |= 1u << MFPR_PS_OFFSET;
mfpr_writel(mfpr_off, mfpr_val);
mfpr_sync();
spin_unlock_irqrestore(&mfp_spin_lock, flags);
}
void pxa3xx_mfp_set_pull(int mfp, int pull)
{
uint32_t mfpr_off, mfpr_val;
unsigned long flags;
BUG_ON(mfp >= MFP_PIN_MAX);
spin_lock_irqsave(&mfp_spin_lock, flags);
mfpr_off = mfp_table[mfp].mfpr_off;
mfpr_val = mfpr_readl(mfpr_off);
mfpr_val &= ~MFPR_PULL_MASK;
mfpr_val |= ((pull & 0x7u) << MFPR_PD_OFFSET);
mfpr_writel(mfpr_off, mfpr_val);
mfpr_sync();
spin_unlock_irqrestore(&mfp_spin_lock, flags);
}
void pxa3xx_mfp_set_edge(int mfp, int edge)
{
uint32_t mfpr_off, mfpr_val;
unsigned long flags;
BUG_ON(mfp >= MFP_PIN_MAX);
spin_lock_irqsave(&mfp_spin_lock, flags);
mfpr_off = mfp_table[mfp].mfpr_off;
mfpr_val = mfpr_readl(mfpr_off);
mfpr_val &= ~MFPR_EDGE_MASK;
mfpr_val |= (edge & 0x3u) << MFPR_ERE_OFFSET;
mfpr_val |= (!edge & 0x1) << MFPR_EC_OFFSET;
mfpr_writel(mfpr_off, mfpr_val);
mfpr_sync();
spin_unlock_irqrestore(&mfp_spin_lock, flags);
}
void __init pxa3xx_mfp_init_addr(struct pxa3xx_mfp_addr_map *map)
{
struct pxa3xx_mfp_addr_map *p;
unsigned long offset, flags;
int i;
spin_lock_irqsave(&mfp_spin_lock, flags);
for (p = map; p->start != MFP_PIN_INVALID; p++) {
offset = p->offset;
i = p->start;
do {
mfp_table[i].mfpr_off = offset;
mfp_table[i].mfpr_val = 0;
offset += 4; i++;
} while ((i <= p->end) && (p->end != -1));
}
spin_unlock_irqrestore(&mfp_spin_lock, flags);
}
void __init pxa3xx_init_mfp(void)
{
memset(mfp_table, 0, sizeof(mfp_table));
}
......@@ -30,6 +30,7 @@
#include "generic.h"
#include "devices.h"
#include "clock.h"
/*
* Various clock factors driven by the CCCR register.
......@@ -53,7 +54,7 @@ static unsigned char N2_clk_mult[8] = { 0, 0, 2, 3, 4, 0, 6, 0 };
* We assume these values have been applied via a fcs.
* If info is not 0 we also display the current settings.
*/
unsigned int get_clk_frequency_khz(int info)
unsigned int pxa25x_get_clk_frequency_khz(int info)
{
unsigned long cccr, turbo;
unsigned int l, L, m, M, n2, N;
......@@ -86,27 +87,48 @@ unsigned int get_clk_frequency_khz(int info)
return (turbo & 1) ? (N/1000) : (M/1000);
}
EXPORT_SYMBOL(get_clk_frequency_khz);
/*
* Return the current memory clock frequency in units of 10kHz
*/
unsigned int get_memclk_frequency_10khz(void)
unsigned int pxa25x_get_memclk_frequency_10khz(void)
{
return L_clk_mult[(CCCR >> 0) & 0x1f] * BASE_CLK / 10000;
}
EXPORT_SYMBOL(get_memclk_frequency_10khz);
/*
* Return the current LCD clock frequency in units of 10kHz
*/
unsigned int get_lcdclk_frequency_10khz(void)
static unsigned long clk_pxa25x_lcd_getrate(struct clk *clk)
{
return get_memclk_frequency_10khz();
return pxa25x_get_memclk_frequency_10khz() * 10000;
}
EXPORT_SYMBOL(get_lcdclk_frequency_10khz);
static const struct clkops clk_pxa25x_lcd_ops = {
.enable = clk_cken_enable,
.disable = clk_cken_disable,
.getrate = clk_pxa25x_lcd_getrate,
};
/*
* 3.6864MHz -> OST, GPIO, SSP, PWM, PLLs (95.842MHz, 147.456MHz)
* 95.842MHz -> MMC 19.169MHz, I2C 31.949MHz, FICP 47.923MHz, USB 47.923MHz
* 147.456MHz -> UART 14.7456MHz, AC97 12.288MHz, I2S 5.672MHz (allegedly)
*/
static struct clk pxa25x_clks[] = {
INIT_CK("LCDCLK", LCD, &clk_pxa25x_lcd_ops, &pxa_device_fb.dev),
INIT_CKEN("UARTCLK", FFUART, 14745600, 1, &pxa_device_ffuart.dev),
INIT_CKEN("UARTCLK", BTUART, 14745600, 1, &pxa_device_btuart.dev),
INIT_CKEN("UARTCLK", BTUART, 14745600, 1, &pxa_device_btuart.dev),
INIT_CKEN("UARTCLK", STUART, 14745600, 1, NULL),
INIT_CKEN("UDCCLK", USB, 47923000, 5, &pxa_device_udc.dev),
INIT_CKEN("MMCCLK", MMC, 19169000, 0, &pxa_device_mci.dev),
INIT_CKEN("I2CCLK", I2C, 31949000, 0, &pxa_device_i2c.dev),
/*
INIT_CKEN("PWMCLK", PWM0, 3686400, 0, NULL),
INIT_CKEN("PWMCLK", PWM0, 3686400, 0, NULL),
INIT_CKEN("SSPCLK", SSP, 3686400, 0, NULL),
INIT_CKEN("I2SCLK", I2S, 14745600, 0, NULL),
INIT_CKEN("NSSPCLK", NSSP, 3686400, 0, NULL),
*/
INIT_CKEN("FICPCLK", FICP, 47923000, 0, NULL),
};
#ifdef CONFIG_PM
......@@ -205,10 +227,52 @@ static void __init pxa25x_init_pm(void)
}
#endif
/* PXA25x: supports wakeup from GPIO0..GPIO15 and RTC alarm
*/
static int pxa25x_set_wake(unsigned int irq, unsigned int on)
{
int gpio = IRQ_TO_GPIO(irq);
uint32_t gpio_bit, mask = 0;
if (gpio >= 0 && gpio <= 15) {
gpio_bit = GPIO_bit(gpio);
mask = gpio_bit;
if (on) {
if (GRER(gpio) | gpio_bit)
PRER |= gpio_bit;
else
PRER &= ~gpio_bit;
if (GFER(gpio) | gpio_bit)
PFER |= gpio_bit;
else
PFER &= ~gpio_bit;
}
goto set_pwer;
}
if (irq == IRQ_RTCAlrm) {
mask = PWER_RTC;
goto set_pwer;
}
return -EINVAL;
set_pwer:
if (on)
PWER |= mask;
else
PWER &=~mask;
return 0;
}
void __init pxa25x_init_irq(void)
{
pxa_init_irq_low();
pxa_init_irq_gpio(85);
pxa_init_irq_set_wake(pxa25x_set_wake);
}
static struct platform_device *pxa25x_devices[] __initdata = {
......@@ -229,6 +293,8 @@ static int __init pxa25x_init(void)
int ret = 0;
if (cpu_is_pxa21x() || cpu_is_pxa25x()) {
clks_register(pxa25x_clks, ARRAY_SIZE(pxa25x_clks));
if ((ret = pxa_init_dma(16)))
return ret;
#ifdef CONFIG_PM
......
......@@ -27,6 +27,7 @@
#include "generic.h"
#include "devices.h"
#include "clock.h"
/* Crystal clock: 13MHz */
#define BASE_CLK 13000000
......@@ -36,7 +37,7 @@
* We assume these values have been applied via a fcs.
* If info is not 0 we also display the current settings.
*/
unsigned int get_clk_frequency_khz( int info)
unsigned int pxa27x_get_clk_frequency_khz(int info)
{
unsigned long ccsr, clkcfg;
unsigned int l, L, m, M, n2, N, S;
......@@ -79,7 +80,7 @@ unsigned int get_clk_frequency_khz( int info)
* Return the current mem clock frequency in units of 10kHz as
* reflected by CCCR[A], B, and L
*/
unsigned int get_memclk_frequency_10khz(void)
unsigned int pxa27x_get_memclk_frequency_10khz(void)
{
unsigned long ccsr, clkcfg;
unsigned int l, L, m, M;
......@@ -104,7 +105,7 @@ unsigned int get_memclk_frequency_10khz(void)
/*
* Return the current LCD clock frequency in units of 10kHz as
*/
unsigned int get_lcdclk_frequency_10khz(void)
static unsigned int pxa27x_get_lcdclk_frequency_10khz(void)
{
unsigned long ccsr;
unsigned int l, L, k, K;
......@@ -120,9 +121,47 @@ unsigned int get_lcdclk_frequency_10khz(void)
return (K / 10000);
}
EXPORT_SYMBOL(get_clk_frequency_khz);
EXPORT_SYMBOL(get_memclk_frequency_10khz);
EXPORT_SYMBOL(get_lcdclk_frequency_10khz);
static unsigned long clk_pxa27x_lcd_getrate(struct clk *clk)
{
return pxa27x_get_lcdclk_frequency_10khz() * 10000;
}
static const struct clkops clk_pxa27x_lcd_ops = {
.enable = clk_cken_enable,
.disable = clk_cken_disable,
.getrate = clk_pxa27x_lcd_getrate,
};
static struct clk pxa27x_clks[] = {
INIT_CK("LCDCLK", LCD, &clk_pxa27x_lcd_ops, &pxa_device_fb.dev),
INIT_CK("CAMCLK", CAMERA, &clk_pxa27x_lcd_ops, NULL),
INIT_CKEN("UARTCLK", FFUART, 14857000, 1, &pxa_device_ffuart.dev),
INIT_CKEN("UARTCLK", BTUART, 14857000, 1, &pxa_device_btuart.dev),
INIT_CKEN("UARTCLK", STUART, 14857000, 1, NULL),
INIT_CKEN("I2SCLK", I2S, 14682000, 0, &pxa_device_i2s.dev),
INIT_CKEN("I2CCLK", I2C, 32842000, 0, &pxa_device_i2c.dev),
INIT_CKEN("UDCCLK", USB, 48000000, 5, &pxa_device_udc.dev),
INIT_CKEN("MMCCLK", MMC, 19500000, 0, &pxa_device_mci.dev),
INIT_CKEN("FICPCLK", FICP, 48000000, 0, &pxa_device_ficp.dev),
INIT_CKEN("USBCLK", USB, 48000000, 0, &pxa27x_device_ohci.dev),
INIT_CKEN("I2CCLK", PWRI2C, 13000000, 0, &pxa27x_device_i2c_power.dev),
INIT_CKEN("KBDCLK", KEYPAD, 32768, 0, NULL),
/*
INIT_CKEN("PWMCLK", PWM0, 13000000, 0, NULL),
INIT_CKEN("SSPCLK", SSP1, 13000000, 0, NULL),
INIT_CKEN("SSPCLK", SSP2, 13000000, 0, NULL),
INIT_CKEN("SSPCLK", SSP3, 13000000, 0, NULL),
INIT_CKEN("MSLCLK", MSL, 48000000, 0, NULL),
INIT_CKEN("USIMCLK", USIM, 48000000, 0, NULL),
INIT_CKEN("MSTKCLK", MEMSTK, 19500000, 0, NULL),
INIT_CKEN("IMCLK", IM, 0, 0, NULL),
INIT_CKEN("MEMCLK", MEMC, 0, 0, NULL),
*/
};
#ifdef CONFIG_PM
......@@ -267,6 +306,69 @@ static void __init pxa27x_init_pm(void)
}
#endif
/* PXA27x: Various gpios can issue wakeup events. This logic only
* handles the simple cases, not the WEMUX2 and WEMUX3 options
*/
#define PXA27x_GPIO_NOWAKE_MASK \
((1 << 8) | (1 << 7) | (1 << 6) | (1 << 5) | (1 << 2))
#define WAKEMASK(gpio) \
(((gpio) <= 15) \
? ((1 << (gpio)) & ~PXA27x_GPIO_NOWAKE_MASK) \
: ((gpio == 35) ? (1 << 24) : 0))
static int pxa27x_set_wake(unsigned int irq, unsigned int on)
{
int gpio = IRQ_TO_GPIO(irq);
uint32_t mask;
if ((gpio >= 0 && gpio <= 15) || (gpio == 35)) {
if (WAKEMASK(gpio) == 0)
return -EINVAL;
mask = WAKEMASK(gpio);
if (on) {
if (GRER(gpio) | GPIO_bit(gpio))
PRER |= mask;
else
PRER &= ~mask;
if (GFER(gpio) | GPIO_bit(gpio))
PFER |= mask;
else
PFER &= ~mask;
}
goto set_pwer;
}
switch (irq) {
case IRQ_RTCAlrm:
mask = PWER_RTC;
break;
case IRQ_USB:
mask = 1u << 26;
break;
default:
return -EINVAL;
}
set_pwer:
if (on)
PWER |= mask;
else
PWER &=~mask;
return 0;
}
void __init pxa27x_init_irq(void)
{
pxa_init_irq_low();
pxa_init_irq_high();
pxa_init_irq_gpio(128);
pxa_init_irq_set_wake(pxa27x_set_wake);
}
/*
* device registration specific to PXA27x.
*/
......@@ -286,7 +388,7 @@ static struct resource pxa27x_ohci_resources[] = {
},
};
static struct platform_device pxa27x_device_ohci = {
struct platform_device pxa27x_device_ohci = {
.name = "pxa27x-ohci",
.id = -1,
.dev = {
......@@ -314,7 +416,7 @@ static struct resource i2c_power_resources[] = {
},
};
static struct platform_device pxa27x_device_i2c_power = {
struct platform_device pxa27x_device_i2c_power = {
.name = "pxa2xx-i2c",
.id = 1,
.resource = i2c_power_resources,
......@@ -336,17 +438,12 @@ static struct platform_device *devices[] __initdata = {
&pxa27x_device_ohci,
};
void __init pxa27x_init_irq(void)
{
pxa_init_irq_low();
pxa_init_irq_high();
pxa_init_irq_gpio(128);
}
static int __init pxa27x_init(void)
{
int ret = 0;
if (cpu_is_pxa27x()) {
clks_register(pxa27x_clks, ARRAY_SIZE(pxa27x_clks));
if ((ret = pxa_init_dma(32)))
return ret;
#ifdef CONFIG_PM
......
/*
* linux/arch/arm/mach-pxa/pxa300.c
*
* Code specific to PXA300/PXA310
*
* Copyright (C) 2007 Marvell Internation Ltd.
*
* 2007-08-21: eric miao <eric.y.miao@gmail.com>
* initial version
*
* 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/module.h>
#include <linux/kernel.h>
#include <asm/hardware.h>
#include <asm/arch/mfp-pxa300.h>
static struct pxa3xx_mfp_addr_map pxa300_mfp_addr_map[] __initdata = {
MFP_ADDR_X(GPIO0, GPIO2, 0x00b4),
MFP_ADDR_X(GPIO3, GPIO26, 0x027c),
MFP_ADDR_X(GPIO27, GPIO127, 0x0400),
MFP_ADDR_X(GPIO0_2, GPIO6_2, 0x02ec),
MFP_ADDR(nBE0, 0x0204),
MFP_ADDR(nBE1, 0x0208),
MFP_ADDR(nLUA, 0x0244),
MFP_ADDR(nLLA, 0x0254),
MFP_ADDR(DF_CLE_nOE, 0x0240),
MFP_ADDR(DF_nRE_nOE, 0x0200),
MFP_ADDR(DF_ALE_nWE, 0x020C),
MFP_ADDR(DF_INT_RnB, 0x00C8),
MFP_ADDR(DF_nCS0, 0x0248),
MFP_ADDR(DF_nCS1, 0x0278),
MFP_ADDR(DF_nWE, 0x00CC),
MFP_ADDR(DF_ADDR0, 0x0210),
MFP_ADDR(DF_ADDR1, 0x0214),
MFP_ADDR(DF_ADDR2, 0x0218),
MFP_ADDR(DF_ADDR3, 0x021C),
MFP_ADDR(DF_IO0, 0x0220),
MFP_ADDR(DF_IO1, 0x0228),
MFP_ADDR(DF_IO2, 0x0230),
MFP_ADDR(DF_IO3, 0x0238),
MFP_ADDR(DF_IO4, 0x0258),
MFP_ADDR(DF_IO5, 0x0260),
MFP_ADDR(DF_IO6, 0x0268),
MFP_ADDR(DF_IO7, 0x0270),
MFP_ADDR(DF_IO8, 0x0224),
MFP_ADDR(DF_IO9, 0x022C),
MFP_ADDR(DF_IO10, 0x0234),
MFP_ADDR(DF_IO11, 0x023C),
MFP_ADDR(DF_IO12, 0x025C),
MFP_ADDR(DF_IO13, 0x0264),
MFP_ADDR(DF_IO14, 0x026C),
MFP_ADDR(DF_IO15, 0x0274),
MFP_ADDR_END,
};
/* override pxa300 MFP register addresses */
static struct pxa3xx_mfp_addr_map pxa310_mfp_addr_map[] __initdata = {
MFP_ADDR_X(GPIO30, GPIO98, 0x0418),
MFP_ADDR_X(GPIO7_2, GPIO12_2, 0x052C),
MFP_ADDR(ULPI_STP, 0x040C),
MFP_ADDR(ULPI_NXT, 0x0410),
MFP_ADDR(ULPI_DIR, 0x0414),
MFP_ADDR_END,
};
static int __init pxa300_init(void)
{
if (cpu_is_pxa300() || cpu_is_pxa310()) {
pxa3xx_init_mfp();
pxa3xx_mfp_init_addr(pxa300_mfp_addr_map);
}
if (cpu_is_pxa310())
pxa3xx_mfp_init_addr(pxa310_mfp_addr_map);
return 0;
}
core_initcall(pxa300_init);
/*
* linux/arch/arm/mach-pxa/pxa320.c
*
* Code specific to PXA320
*
* Copyright (C) 2007 Marvell Internation Ltd.
*
* 2007-08-21: eric miao <eric.y.miao@gmail.com>
* initial version
*
* 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/module.h>
#include <linux/kernel.h>
#include <asm/hardware.h>
#include <asm/arch/mfp.h>
#include <asm/arch/mfp-pxa320.h>
static struct pxa3xx_mfp_addr_map pxa320_mfp_addr_map[] __initdata = {
MFP_ADDR_X(GPIO0, GPIO4, 0x0124),
MFP_ADDR_X(GPIO5, GPIO26, 0x028C),
MFP_ADDR_X(GPIO27, GPIO62, 0x0400),
MFP_ADDR_X(GPIO63, GPIO73, 0x04B4),
MFP_ADDR_X(GPIO74, GPIO98, 0x04F0),
MFP_ADDR_X(GPIO99, GPIO127, 0x0600),
MFP_ADDR_X(GPIO0_2, GPIO5_2, 0x0674),
MFP_ADDR_X(GPIO6_2, GPIO13_2, 0x0494),
MFP_ADDR_X(GPIO14_2, GPIO17_2, 0x04E0),
MFP_ADDR(nXCVREN, 0x0138),
MFP_ADDR(DF_CLE_nOE, 0x0204),
MFP_ADDR(DF_nADV1_ALE, 0x0208),
MFP_ADDR(DF_SCLK_S, 0x020C),
MFP_ADDR(DF_SCLK_E, 0x0210),
MFP_ADDR(nBE0, 0x0214),
MFP_ADDR(nBE1, 0x0218),
MFP_ADDR(DF_nADV2_ALE, 0x021C),
MFP_ADDR(DF_INT_RnB, 0x0220),
MFP_ADDR(DF_nCS0, 0x0224),
MFP_ADDR(DF_nCS1, 0x0228),
MFP_ADDR(DF_nWE, 0x022C),
MFP_ADDR(DF_nRE_nOE, 0x0230),
MFP_ADDR(nLUA, 0x0234),
MFP_ADDR(nLLA, 0x0238),
MFP_ADDR(DF_ADDR0, 0x023C),
MFP_ADDR(DF_ADDR1, 0x0240),
MFP_ADDR(DF_ADDR2, 0x0244),
MFP_ADDR(DF_ADDR3, 0x0248),
MFP_ADDR(DF_IO0, 0x024C),
MFP_ADDR(DF_IO8, 0x0250),
MFP_ADDR(DF_IO1, 0x0254),
MFP_ADDR(DF_IO9, 0x0258),
MFP_ADDR(DF_IO2, 0x025C),
MFP_ADDR(DF_IO10, 0x0260),
MFP_ADDR(DF_IO3, 0x0264),
MFP_ADDR(DF_IO11, 0x0268),
MFP_ADDR(DF_IO4, 0x026C),
MFP_ADDR(DF_IO12, 0x0270),
MFP_ADDR(DF_IO5, 0x0274),
MFP_ADDR(DF_IO13, 0x0278),
MFP_ADDR(DF_IO6, 0x027C),
MFP_ADDR(DF_IO14, 0x0280),
MFP_ADDR(DF_IO7, 0x0284),
MFP_ADDR(DF_IO15, 0x0288),
MFP_ADDR_END,
};
static void __init pxa320_init_mfp(void)
{
pxa3xx_init_mfp();
pxa3xx_mfp_init_addr(pxa320_mfp_addr_map);
}
static int __init pxa320_init(void)
{
if (cpu_is_pxa320())
pxa320_init_mfp();
return 0;
}
core_initcall(pxa320_init);
/*
* linux/arch/arm/mach-pxa/pxa3xx.c
*
* code specific to pxa3xx aka Monahans
*
* Copyright (C) 2006 Marvell International Ltd.
*
* 2007-09-02: eric miao <eric.y.miao@gmail.com>
* initial version
*
* 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/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/pm.h>
#include <linux/platform_device.h>
#include <linux/irq.h>
#include <asm/hardware.h>
#include <asm/arch/pxa3xx-regs.h>
#include <asm/arch/ohci.h>
#include <asm/arch/pm.h>
#include <asm/arch/dma.h>
#include <asm/arch/ssp.h>
#include "generic.h"
#include "devices.h"
#include "clock.h"
/* Crystal clock: 13MHz */
#define BASE_CLK 13000000
/* Ring Oscillator Clock: 60MHz */
#define RO_CLK 60000000
#define ACCR_D0CS (1 << 26)
/* crystal frequency to static memory controller multiplier (SMCFS) */
static unsigned char smcfs_mult[8] = { 6, 0, 8, 0, 0, 16, };
/* crystal frequency to HSIO bus frequency multiplier (HSS) */
static unsigned char hss_mult[4] = { 8, 12, 16, 0 };
/*
* Get the clock frequency as reflected by CCSR and the turbo flag.
* We assume these values have been applied via a fcs.
* If info is not 0 we also display the current settings.
*/
unsigned int pxa3xx_get_clk_frequency_khz(int info)
{
unsigned long acsr, xclkcfg;
unsigned int t, xl, xn, hss, ro, XL, XN, CLK, HSS;
/* Read XCLKCFG register turbo bit */
__asm__ __volatile__("mrc\tp14, 0, %0, c6, c0, 0" : "=r"(xclkcfg));
t = xclkcfg & 0x1;
acsr = ACSR;
xl = acsr & 0x1f;
xn = (acsr >> 8) & 0x7;
hss = (acsr >> 14) & 0x3;
XL = xl * BASE_CLK;
XN = xn * XL;
ro = acsr & ACCR_D0CS;
CLK = (ro) ? RO_CLK : ((t) ? XN : XL);
HSS = (ro) ? RO_CLK : hss_mult[hss] * BASE_CLK;
if (info) {
pr_info("RO Mode clock: %d.%02dMHz (%sactive)\n",
RO_CLK / 1000000, (RO_CLK % 1000000) / 10000,
(ro) ? "" : "in");
pr_info("Run Mode clock: %d.%02dMHz (*%d)\n",
XL / 1000000, (XL % 1000000) / 10000, xl);
pr_info("Turbo Mode clock: %d.%02dMHz (*%d, %sactive)\n",
XN / 1000000, (XN % 1000000) / 10000, xn,
(t) ? "" : "in");
pr_info("HSIO bus clock: %d.%02dMHz\n",
HSS / 1000000, (HSS % 1000000) / 10000);
}
return CLK;
}
/*
* Return the current static memory controller clock frequency
* in units of 10kHz
*/
unsigned int pxa3xx_get_memclk_frequency_10khz(void)
{
unsigned long acsr;
unsigned int smcfs, clk = 0;
acsr = ACSR;
smcfs = (acsr >> 23) & 0x7;
clk = (acsr & ACCR_D0CS) ? RO_CLK : smcfs_mult[smcfs] * BASE_CLK;
return (clk / 10000);
}
/*
* Return the current HSIO bus clock frequency
*/
static unsigned long clk_pxa3xx_hsio_getrate(struct clk *clk)
{
unsigned long acsr;
unsigned int hss, hsio_clk;
acsr = ACSR;
hss = (acsr >> 14) & 0x3;
hsio_clk = (acsr & ACCR_D0CS) ? RO_CLK : hss_mult[hss] * BASE_CLK;
return hsio_clk;
}
static void clk_pxa3xx_cken_enable(struct clk *clk)
{
unsigned long mask = 1ul << (clk->cken & 0x1f);
local_irq_disable();
if (clk->cken < 32)
CKENA |= mask;
else
CKENB |= mask;
local_irq_enable();
}
static void clk_pxa3xx_cken_disable(struct clk *clk)
{
unsigned long mask = 1ul << (clk->cken & 0x1f);
local_irq_disable();
if (clk->cken < 32)
CKENA &= ~mask;
else
CKENB &= ~mask;
local_irq_enable();
}
static const struct clkops clk_pxa3xx_hsio_ops = {
.enable = clk_pxa3xx_cken_enable,
.disable = clk_pxa3xx_cken_disable,
.getrate = clk_pxa3xx_hsio_getrate,
};
static struct clk pxa3xx_clks[] = {
INIT_CK("LCDCLK", LCD, &clk_pxa3xx_hsio_ops, &pxa_device_fb.dev),
INIT_CK("CAMCLK", CAMERA, &clk_pxa3xx_hsio_ops, NULL),
INIT_CKEN("UARTCLK", FFUART, 14857000, 1, &pxa_device_ffuart.dev),
INIT_CKEN("UARTCLK", BTUART, 14857000, 1, &pxa_device_btuart.dev),
INIT_CKEN("UARTCLK", STUART, 14857000, 1, NULL),
INIT_CKEN("I2CCLK", I2C, 32842000, 0, &pxa_device_i2c.dev),
INIT_CKEN("UDCCLK", UDC, 48000000, 5, &pxa_device_udc.dev),
};
void __init pxa3xx_init_irq(void)
{
/* enable CP6 access */
u32 value;
__asm__ __volatile__("mrc p15, 0, %0, c15, c1, 0\n": "=r"(value));
value |= (1 << 6);
__asm__ __volatile__("mcr p15, 0, %0, c15, c1, 0\n": :"r"(value));
pxa_init_irq_low();
pxa_init_irq_high();
pxa_init_irq_gpio(128);
}
/*
* device registration specific to PXA3xx.
*/
static struct platform_device *devices[] __initdata = {
&pxa_device_mci,
&pxa_device_udc,
&pxa_device_fb,
&pxa_device_ffuart,
&pxa_device_btuart,
&pxa_device_stuart,
&pxa_device_i2c,
&pxa_device_i2s,
&pxa_device_ficp,
&pxa_device_rtc,
};
static int __init pxa3xx_init(void)
{
int ret = 0;
if (cpu_is_pxa3xx()) {
clks_register(pxa3xx_clks, ARRAY_SIZE(pxa3xx_clks));
if ((ret = pxa_init_dma(32)))
return ret;
return platform_add_devices(devices, ARRAY_SIZE(devices));
}
return 0;
}
subsys_initcall(pxa3xx_init);
......@@ -16,10 +16,48 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/clockchips.h>
#include <linux/sched.h>
#include <asm/div64.h>
#include <asm/cnt32_to_63.h>
#include <asm/mach/irq.h>
#include <asm/mach/time.h>
#include <asm/arch/pxa-regs.h>
#include <asm/mach-types.h>
/*
* This is PXA's sched_clock implementation. This has a resolution
* of at least 308 ns and a maximum value of 208 days.
*
* The return value is guaranteed to be monotonic in that range as
* long as there is always less than 582 seconds between successive
* calls to sched_clock() which should always be the case in practice.
*/
#define OSCR2NS_SCALE_FACTOR 10
static unsigned long oscr2ns_scale;
static void __init set_oscr2ns_scale(unsigned long oscr_rate)
{
unsigned long long v = 1000000000ULL << OSCR2NS_SCALE_FACTOR;
do_div(v, oscr_rate);
oscr2ns_scale = v;
/*
* We want an even value to automatically clear the top bit
* returned by cnt32_to_63() without an additional run time
* instruction. So if the LSB is 1 then round it up.
*/
if (oscr2ns_scale & 1)
oscr2ns_scale++;
}
unsigned long long sched_clock(void)
{
unsigned long long v = cnt32_to_63(OSCR);
return (v * oscr2ns_scale) >> OSCR2NS_SCALE_FACTOR;
}
static irqreturn_t
pxa_ost0_interrupt(int irq, void *dev_id)
......@@ -149,18 +187,29 @@ static struct irqaction pxa_ost0_irq = {
static void __init pxa_timer_init(void)
{
unsigned long clock_tick_rate;
OIER = 0;
OSSR = OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3;
if (cpu_is_pxa21x() || cpu_is_pxa25x())
clock_tick_rate = 3686400;
else if (machine_is_mainstone())
clock_tick_rate = 3249600;
else
clock_tick_rate = 3250000;
set_oscr2ns_scale(clock_tick_rate);
ckevt_pxa_osmr0.mult =
div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, ckevt_pxa_osmr0.shift);
div_sc(clock_tick_rate, NSEC_PER_SEC, ckevt_pxa_osmr0.shift);
ckevt_pxa_osmr0.max_delta_ns =
clockevent_delta2ns(0x7fffffff, &ckevt_pxa_osmr0);
ckevt_pxa_osmr0.min_delta_ns =
clockevent_delta2ns(MIN_OSCR_DELTA, &ckevt_pxa_osmr0) + 1;
cksrc_pxa_oscr0.mult =
clocksource_hz2mult(CLOCK_TICK_RATE, cksrc_pxa_oscr0.shift);
clocksource_hz2mult(clock_tick_rate, cksrc_pxa_oscr0.shift);
setup_irq(IRQ_OST0, &pxa_ost0_irq);
......
/*
* linux/arch/arm/mach-pxa/zylonite.c
*
* Support for the PXA3xx Development Platform (aka Zylonite)
*
* Copyright (C) 2006 Marvell International Ltd.
*
* 2007-09-04: eric miao <eric.y.miao@gmail.com>
* rewrite to align with latest kernel
*
* 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/module.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/hardware.h>
#include <asm/arch/gpio.h>
#include <asm/arch/pxafb.h>
#include <asm/arch/zylonite.h>
#include "generic.h"
int gpio_backlight;
int gpio_eth_irq;
int lcd_id;
int lcd_orientation;
static struct resource smc91x_resources[] = {
[0] = {
.start = ZYLONITE_ETH_PHYS + 0x300,
.end = ZYLONITE_ETH_PHYS + 0xfffff,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = -1, /* for run-time assignment */
.end = -1,
.flags = IORESOURCE_IRQ,
}
};
static struct platform_device smc91x_device = {
.name = "smc91x",
.id = 0,
.num_resources = ARRAY_SIZE(smc91x_resources),
.resource = smc91x_resources,
};
#if defined(CONFIG_FB_PXA) || (CONFIG_FB_PXA_MODULES)
static void zylonite_backlight_power(int on)
{
gpio_set_value(gpio_backlight, on);
}
static struct pxafb_mode_info toshiba_ltm035a776c_mode = {
.pixclock = 110000,
.xres = 240,
.yres = 320,
.bpp = 16,
.hsync_len = 4,
.left_margin = 6,
.right_margin = 4,
.vsync_len = 2,
.upper_margin = 2,
.lower_margin = 3,
.sync = FB_SYNC_VERT_HIGH_ACT,
};
static struct pxafb_mode_info toshiba_ltm04c380k_mode = {
.pixclock = 50000,
.xres = 640,
.yres = 480,
.bpp = 16,
.hsync_len = 1,
.left_margin = 0x9f,
.right_margin = 1,
.vsync_len = 44,
.upper_margin = 0,
.lower_margin = 0,
.sync = FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
};
static struct pxafb_mach_info zylonite_toshiba_lcd_info = {
.num_modes = 1,
.lccr0 = LCCR0_Act,
.lccr3 = LCCR3_PCP,
.pxafb_backlight_power = zylonite_backlight_power,
};
static struct pxafb_mode_info sharp_ls037_modes[] = {
[0] = {
.pixclock = 158000,
.xres = 240,
.yres = 320,
.bpp = 16,
.hsync_len = 4,
.left_margin = 39,
.right_margin = 39,
.vsync_len = 1,
.upper_margin = 2,
.lower_margin = 3,
.sync = 0,
},
[1] = {
.pixclock = 39700,
.xres = 480,
.yres = 640,
.bpp = 16,
.hsync_len = 8,
.left_margin = 81,
.right_margin = 81,
.vsync_len = 1,
.upper_margin = 2,
.lower_margin = 7,
.sync = 0,
},
};
static struct pxafb_mach_info zylonite_sharp_lcd_info = {
.modes = sharp_ls037_modes,
.num_modes = 2,
.lccr0 = LCCR0_Act,
.lccr3 = LCCR3_PCP | LCCR3_HSP | LCCR3_VSP,
.pxafb_backlight_power = zylonite_backlight_power,
};
static void __init zylonite_init_lcd(void)
{
/* backlight GPIO: output, default on */
gpio_direction_output(gpio_backlight, 1);
if (lcd_id & 0x20) {
set_pxa_fb_info(&zylonite_sharp_lcd_info);
return;
}
/* legacy LCD panels, it would be handy here if LCD panel type can
* be decided at run-time
*/
if (1)
zylonite_toshiba_lcd_info.modes = &toshiba_ltm035a776c_mode;
else
zylonite_toshiba_lcd_info.modes = &toshiba_ltm04c380k_mode;
set_pxa_fb_info(&zylonite_toshiba_lcd_info);
}
#else
static inline void zylonite_init_lcd(void) {}
#endif
static void __init zylonite_init(void)
{
/* board-processor specific initialization */
zylonite_pxa300_init();
zylonite_pxa320_init();
/*
* Note: We depend that the bootloader set
* the correct value to MSC register for SMC91x.
*/
smc91x_resources[1].start = gpio_to_irq(gpio_eth_irq);
smc91x_resources[1].end = gpio_to_irq(gpio_eth_irq);
platform_device_register(&smc91x_device);
zylonite_init_lcd();
}
MACHINE_START(ZYLONITE, "PXA3xx Platform Development Kit (aka Zylonite)")
.phys_io = 0x40000000,
.boot_params = 0xa0000100,
.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.map_io = pxa_map_io,
.init_irq = pxa3xx_init_irq,
.timer = &pxa_timer,
.init_machine = zylonite_init,
MACHINE_END
/*
* linux/arch/arm/mach-pxa/zylonite_pxa300.c
*
* PXA300/PXA310 specific support code for the
* PXA3xx Development Platform (aka Zylonite)
*
* Copyright (C) 2007 Marvell Internation Ltd.
* 2007-08-21: eric miao <eric.y.miao@gmail.com>
* initial version
*
* 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/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/gpio.h>
#include <asm/arch/mfp-pxa300.h>
#include <asm/arch/zylonite.h>
#define ARRAY_AND_SIZE(x) (x), ARRAY_SIZE(x)
/* PXA300/PXA310 common configurations */
static mfp_cfg_t common_mfp_cfg[] __initdata = {
/* LCD */
GPIO54_LCD_LDD_0,
GPIO55_LCD_LDD_1,
GPIO56_LCD_LDD_2,
GPIO57_LCD_LDD_3,
GPIO58_LCD_LDD_4,
GPIO59_LCD_LDD_5,
GPIO60_LCD_LDD_6,
GPIO61_LCD_LDD_7,
GPIO62_LCD_LDD_8,
GPIO63_LCD_LDD_9,
GPIO64_LCD_LDD_10,
GPIO65_LCD_LDD_11,
GPIO66_LCD_LDD_12,
GPIO67_LCD_LDD_13,
GPIO68_LCD_LDD_14,
GPIO69_LCD_LDD_15,
GPIO70_LCD_LDD_16,
GPIO71_LCD_LDD_17,
GPIO72_LCD_FCLK,
GPIO73_LCD_LCLK,
GPIO74_LCD_PCLK,
GPIO75_LCD_BIAS,
GPIO76_LCD_VSYNC,
GPIO127_LCD_CS_N,
/* BTUART */
GPIO111_UART2_RTS,
GPIO112_UART2_RXD,
GPIO113_UART2_TXD,
GPIO114_UART2_CTS,
/* STUART */
GPIO109_UART3_TXD,
GPIO110_UART3_RXD,
/* AC97 */
GPIO23_AC97_nACRESET,
GPIO24_AC97_SYSCLK,
GPIO29_AC97_BITCLK,
GPIO25_AC97_SDATA_IN_0,
GPIO27_AC97_SDATA_OUT,
GPIO28_AC97_SYNC,
/* Keypad */
GPIO107_KP_DKIN_0,
GPIO108_KP_DKIN_1,
GPIO115_KP_MKIN_0,
GPIO116_KP_MKIN_1,
GPIO117_KP_MKIN_2,
GPIO118_KP_MKIN_3,
GPIO119_KP_MKIN_4,
GPIO120_KP_MKIN_5,
GPIO2_2_KP_MKIN_6,
GPIO3_2_KP_MKIN_7,
GPIO121_KP_MKOUT_0,
GPIO122_KP_MKOUT_1,
GPIO123_KP_MKOUT_2,
GPIO124_KP_MKOUT_3,
GPIO125_KP_MKOUT_4,
GPIO4_2_KP_MKOUT_5,
GPIO5_2_KP_MKOUT_6,
GPIO6_2_KP_MKOUT_7,
};
static mfp_cfg_t pxa300_mfp_cfg[] __initdata = {
/* FFUART */
GPIO30_UART1_RXD,
GPIO31_UART1_TXD,
GPIO32_UART1_CTS,
GPIO37_UART1_RTS,
GPIO33_UART1_DCD,
GPIO34_UART1_DSR,
GPIO35_UART1_RI,
GPIO36_UART1_DTR,
/* Ethernet */
GPIO2_nCS3,
GPIO99_GPIO,
};
static mfp_cfg_t pxa310_mfp_cfg[] __initdata = {
/* FFUART */
GPIO99_UART1_RXD,
GPIO100_UART1_TXD,
GPIO101_UART1_CTS,
GPIO106_UART1_RTS,
/* Ethernet */
GPIO2_nCS3,
GPIO102_GPIO,
};
#define NUM_LCD_DETECT_PINS 7
static int lcd_detect_pins[] __initdata = {
MFP_PIN_GPIO71, /* LCD_LDD_17 - ORIENT */
MFP_PIN_GPIO70, /* LCD_LDD_16 - LCDID[5] */
MFP_PIN_GPIO75, /* LCD_BIAS - LCDID[4] */
MFP_PIN_GPIO73, /* LCD_LCLK - LCDID[3] */
MFP_PIN_GPIO72, /* LCD_FCLK - LCDID[2] */
MFP_PIN_GPIO127,/* LCD_CS_N - LCDID[1] */
MFP_PIN_GPIO76, /* LCD_VSYNC - LCDID[0] */
};
static void __init zylonite_detect_lcd_panel(void)
{
unsigned long mfpr_save[NUM_LCD_DETECT_PINS];
int i, gpio, id = 0;
/* save the original MFP settings of these pins and configure
* them as GPIO Input, DS01X, Pull Neither, Edge Clear
*/
for (i = 0; i < NUM_LCD_DETECT_PINS; i++) {
mfpr_save[i] = pxa3xx_mfp_read(lcd_detect_pins[i]);
pxa3xx_mfp_write(lcd_detect_pins[i], 0x8440);
}
for (i = 0; i < NUM_LCD_DETECT_PINS; i++) {
id = id << 1;
gpio = mfp_to_gpio(lcd_detect_pins[i]);
gpio_direction_input(gpio);
if (gpio_get_value(gpio))
id = id | 0x1;
}
/* lcd id, flush out bit 1 */
lcd_id = id & 0x3d;
/* lcd orientation, portrait or landscape */
lcd_orientation = (id >> 6) & 0x1;
/* restore the original MFP settings */
for (i = 0; i < NUM_LCD_DETECT_PINS; i++)
pxa3xx_mfp_write(lcd_detect_pins[i], mfpr_save[i]);
}
void __init zylonite_pxa300_init(void)
{
if (cpu_is_pxa300() || cpu_is_pxa310()) {
/* initialize MFP */
pxa3xx_mfp_config(ARRAY_AND_SIZE(common_mfp_cfg));
/* detect LCD panel */
zylonite_detect_lcd_panel();
/* GPIO pin assignment */
gpio_backlight = mfp_to_gpio(MFP_PIN_GPIO20);
}
if (cpu_is_pxa300()) {
pxa3xx_mfp_config(ARRAY_AND_SIZE(pxa300_mfp_cfg));
gpio_eth_irq = mfp_to_gpio(MFP_PIN_GPIO99);
}
if (cpu_is_pxa310()) {
pxa3xx_mfp_config(ARRAY_AND_SIZE(pxa310_mfp_cfg));
gpio_eth_irq = mfp_to_gpio(MFP_PIN_GPIO102);
}
}
This diff is collapsed.
......@@ -322,7 +322,7 @@ config CPU_SA1100
# XScale
config CPU_XSCALE
bool
depends on ARCH_IOP32X || ARCH_IOP33X || ARCH_PXA || ARCH_IXP4XX || ARCH_IXP2000
depends on ARCH_IOP32X || ARCH_IOP33X || PXA25x || PXA27x || ARCH_IXP4XX || ARCH_IXP2000
default y
select CPU_32v5
select CPU_ABRT_EV5T
......@@ -333,7 +333,7 @@ config CPU_XSCALE
# XScale Core Version 3
config CPU_XSC3
bool
depends on ARCH_IXP23XX || ARCH_IOP13XX
depends on ARCH_IXP23XX || ARCH_IOP13XX || PXA3xx
default y
select CPU_32v5
select CPU_ABRT_EV5T
......
This diff is collapsed.
This diff is collapsed.
......@@ -108,6 +108,12 @@ config LEDS_GPIO
outputs. To be useful the particular board must have LEDs
and they must be connected to the GPIO lines.
config LEDS_CM_X270
tristate "LED Support for the CM-X270 LEDs"
depends on LEDS_CLASS && MACH_ARMCORE
help
This option enables support for the CM-X270 LEDs.
comment "LED Triggers"
config LEDS_TRIGGERS
......
......@@ -18,6 +18,7 @@ obj-$(CONFIG_LEDS_H1940) += leds-h1940.o
obj-$(CONFIG_LEDS_COBALT_QUBE) += leds-cobalt-qube.o
obj-$(CONFIG_LEDS_COBALT_RAQ) += leds-cobalt-raq.o
obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o
obj-$(CONFIG_LEDS_CM_X270) += leds-cm-x270.o
# LED Triggers
obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -69,4 +69,5 @@ sa1100_cs-$(CONFIG_SA1100_SIMPAD) += sa1100_simpad.o
pxa2xx_cs-$(CONFIG_ARCH_LUBBOCK) += pxa2xx_lubbock.o sa1111_generic.o
pxa2xx_cs-$(CONFIG_MACH_MAINSTONE) += pxa2xx_mainstone.o
pxa2xx_cs-$(CONFIG_PXA_SHARPSL) += pxa2xx_sharpsl.o
pxa2xx_cs-$(CONFIG_MACH_ARMCORE) += pxa2xx_cm_x270.o
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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