diff options
Diffstat (limited to 'arch/arm/mach-pxa')
-rw-r--r-- | arch/arm/mach-pxa/Kconfig | 29 | ||||
-rw-r--r-- | arch/arm/mach-pxa/Makefile | 9 | ||||
-rw-r--r-- | arch/arm/mach-pxa/generic.c | 8 | ||||
-rw-r--r-- | arch/arm/mach-pxa/generic.h | 8 | ||||
-rw-r--r-- | arch/arm/mach-pxa/irq.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-pxa/mfp.c | 235 | ||||
-rw-r--r-- | arch/arm/mach-pxa/pxa300.c | 93 | ||||
-rw-r--r-- | arch/arm/mach-pxa/pxa320.c | 88 | ||||
-rw-r--r-- | arch/arm/mach-pxa/pxa3xx.c | 216 | ||||
-rw-r--r-- | arch/arm/mach-pxa/zylonite.c | 184 | ||||
-rw-r--r-- | arch/arm/mach-pxa/zylonite_pxa300.c | 188 | ||||
-rw-r--r-- | arch/arm/mach-pxa/zylonite_pxa320.c | 173 |
12 files changed, 1229 insertions, 4 deletions
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index 5ebec6d88b5..e895188cadc 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig @@ -1,6 +1,24 @@ 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,10 @@ config MACH_EM_X270 bool "CompuLab EM-x270 platform" select PXA27x +config MACH_ZYLONITE + bool "PXA3xx Development Platform" + select PXA3xx + endchoice if PXA_SHARPSL @@ -130,6 +152,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 diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile index 8970928fbca..bfdd0c5fcd7 100644 --- a/arch/arm/mach-pxa/Makefile +++ b/arch/arm/mach-pxa/Makefile @@ -6,6 +6,9 @@ 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 @@ -20,6 +23,12 @@ obj-$(CONFIG_MACH_POODLE) += poodle.o corgi_ssp.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 + # Support for blinky lights led-y := leds.o led-$(CONFIG_ARCH_LUBBOCK) += leds-lubbock.o diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c index eed95eaf58c..2263a84844a 100644 --- a/arch/arm/mach-pxa/generic.c +++ b/arch/arm/mach-pxa/generic.c @@ -51,8 +51,10 @@ unsigned int get_clk_frequency_khz(int info) { if (cpu_is_pxa21x() || cpu_is_pxa25x()) return pxa25x_get_clk_frequency_khz(info); - else + 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); @@ -63,8 +65,10 @@ unsigned int get_memclk_frequency_10khz(void) { if (cpu_is_pxa21x() || cpu_is_pxa25x()) return pxa25x_get_memclk_frequency_10khz(); - else + else if (cpu_is_pxa27x()) return pxa27x_get_memclk_frequency_10khz(); + else + return pxa3xx_get_memclk_frequency_10khz(); } EXPORT_SYMBOL(get_memclk_frequency_10khz); diff --git a/arch/arm/mach-pxa/generic.h b/arch/arm/mach-pxa/generic.h index 2c4fe617cfc..b30f240a16c 100644 --- a/arch/arm/mach-pxa/generic.h +++ b/arch/arm/mach-pxa/generic.h @@ -18,6 +18,7 @@ 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); @@ -44,3 +45,10 @@ extern unsigned pxa27x_get_memclk_frequency_10khz(void); #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 diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c index 294cc6758d5..07acb45b16e 100644 --- a/arch/arm/mach-pxa/irq.c +++ b/arch/arm/mach-pxa/irq.c @@ -65,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. diff --git a/arch/arm/mach-pxa/mfp.c b/arch/arm/mach-pxa/mfp.c new file mode 100644 index 00000000000..5cd3cadbbd1 --- /dev/null +++ b/arch/arm/mach-pxa/mfp.c @@ -0,0 +1,235 @@ +/* + * 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)); +} diff --git a/arch/arm/mach-pxa/pxa300.c b/arch/arm/mach-pxa/pxa300.c new file mode 100644 index 00000000000..5363b132265 --- /dev/null +++ b/arch/arm/mach-pxa/pxa300.c @@ -0,0 +1,93 @@ +/* + * 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); diff --git a/arch/arm/mach-pxa/pxa320.c b/arch/arm/mach-pxa/pxa320.c new file mode 100644 index 00000000000..cd9eba5b3df --- /dev/null +++ b/arch/arm/mach-pxa/pxa320.c @@ -0,0 +1,88 @@ +/* + * 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); diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c new file mode 100644 index 00000000000..39f0de8c189 --- /dev/null +++ b/arch/arm/mach-pxa/pxa3xx.c @@ -0,0 +1,216 @@ +/* + * 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); diff --git a/arch/arm/mach-pxa/zylonite.c b/arch/arm/mach-pxa/zylonite.c new file mode 100644 index 00000000000..3f18d760dd1 --- /dev/null +++ b/arch/arm/mach-pxa/zylonite.c @@ -0,0 +1,184 @@ +/* + * 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 diff --git a/arch/arm/mach-pxa/zylonite_pxa300.c b/arch/arm/mach-pxa/zylonite_pxa300.c new file mode 100644 index 00000000000..b5fbd2f4c69 --- /dev/null +++ b/arch/arm/mach-pxa/zylonite_pxa300.c @@ -0,0 +1,188 @@ +/* + * 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); + } +} diff --git a/arch/arm/mach-pxa/zylonite_pxa320.c b/arch/arm/mach-pxa/zylonite_pxa320.c new file mode 100644 index 00000000000..63cb36be086 --- /dev/null +++ b/arch/arm/mach-pxa/zylonite_pxa320.c @@ -0,0 +1,173 @@ +/* + * linux/arch/arm/mach-pxa/zylonite_pxa320.c + * + * PXA320 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/arch/gpio.h> +#include <asm/arch/mfp-pxa320.h> +#include <asm/arch/zylonite.h> + +#define ARRAY_AND_SIZE(x) (x), ARRAY_SIZE(x) + +static mfp_cfg_t mfp_cfg[] __initdata = { + /* LCD */ + GPIO6_2_LCD_LDD_0, + GPIO7_2_LCD_LDD_1, + GPIO8_2_LCD_LDD_2, + GPIO9_2_LCD_LDD_3, + GPIO10_2_LCD_LDD_4, + GPIO11_2_LCD_LDD_5, + GPIO12_2_LCD_LDD_6, + GPIO13_2_LCD_LDD_7, + GPIO63_LCD_LDD_8, + GPIO64_LCD_LDD_9, + GPIO65_LCD_LDD_10, + GPIO66_LCD_LDD_11, + GPIO67_LCD_LDD_12, + GPIO68_LCD_LDD_13, + GPIO69_LCD_LDD_14, + GPIO70_LCD_LDD_15, + GPIO71_LCD_LDD_16, + GPIO72_LCD_LDD_17, + GPIO73_LCD_CS_N, + GPIO74_LCD_VSYNC, + GPIO14_2_LCD_FCLK, + GPIO15_2_LCD_LCLK, + GPIO16_2_LCD_PCLK, + GPIO17_2_LCD_BIAS, + + /* FFUART */ + GPIO41_UART1_RXD, + GPIO42_UART1_TXD, + GPIO43_UART1_CTS, + GPIO44_UART1_DCD, + GPIO45_UART1_DSR, + GPIO46_UART1_RI, + GPIO47_UART1_DTR, + GPIO48_UART1_RTS, + + /* AC97 */ + GPIO34_AC97_SYSCLK, + GPIO35_AC97_SDATA_IN_0, + GPIO37_AC97_SDATA_OUT, + GPIO38_AC97_SYNC, + GPIO39_AC97_BITCLK, + GPIO40_AC97_nACRESET, + + /* I2C */ + GPIO32_I2C_SCL, + GPIO33_I2C_SDA, + + /* Keypad */ + GPIO105_KP_DKIN_0, + GPIO106_KP_DKIN_1, + GPIO113_KP_MKIN_0, + GPIO114_KP_MKIN_1, + GPIO115_KP_MKIN_2, + GPIO116_KP_MKIN_3, + GPIO117_KP_MKIN_4, + GPIO118_KP_MKIN_5, + GPIO119_KP_MKIN_6, + GPIO120_KP_MKIN_7, + GPIO121_KP_MKOUT_0, + GPIO122_KP_MKOUT_1, + GPIO123_KP_MKOUT_2, + GPIO124_KP_MKOUT_3, + GPIO125_KP_MKOUT_4, + GPIO126_KP_MKOUT_5, + GPIO127_KP_MKOUT_6, + GPIO5_2_KP_MKOUT_7, + + /* Ethernet */ + GPIO4_nCS3, + GPIO90_GPIO, +}; + +#define NUM_LCD_DETECT_PINS 7 + +static int lcd_detect_pins[] __initdata = { + MFP_PIN_GPIO72, /* LCD_LDD_17 - ORIENT */ + MFP_PIN_GPIO71, /* LCD_LDD_16 - LCDID[5] */ + MFP_PIN_GPIO17_2, /* LCD_BIAS - LCDID[4] */ + MFP_PIN_GPIO15_2, /* LCD_LCLK - LCDID[3] */ + MFP_PIN_GPIO14_2, /* LCD_FCLK - LCDID[2] */ + MFP_PIN_GPIO73, /* LCD_CS_N - LCDID[1] */ + MFP_PIN_GPIO74, /* LCD_VSYNC - LCDID[0] */ + /* + * set the MFP_PIN_GPIO 14/15/17 to alternate function other than + * GPIO to avoid input level confliction with 14_2, 15_2, 17_2 + */ + MFP_PIN_GPIO14, + MFP_PIN_GPIO15, + MFP_PIN_GPIO17, +}; + +static int lcd_detect_mfpr[] __initdata = { + /* AF0, DS 1X, Pull Neither, Edge Clear */ + 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, + 0xc442, /* Backlight, Pull-Up, AF2 */ + 0x8445, /* AF5 */ + 0x8445, /* AF5 */ +}; + +static void __init zylonite_detect_lcd_panel(void) +{ + unsigned long mfpr_save[ARRAY_SIZE(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 < ARRAY_SIZE(lcd_detect_pins); i++) { + mfpr_save[i] = pxa3xx_mfp_read(lcd_detect_pins[i]); + pxa3xx_mfp_write(lcd_detect_pins[i], lcd_detect_mfpr[i]); + } + + 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 < ARRAY_SIZE(lcd_detect_pins); i++) + pxa3xx_mfp_write(lcd_detect_pins[i], mfpr_save[i]); +} + +void __init zylonite_pxa320_init(void) +{ + if (cpu_is_pxa320()) { + /* initialize MFP */ + pxa3xx_mfp_config(ARRAY_AND_SIZE(mfp_cfg)); + + /* detect LCD panel */ + zylonite_detect_lcd_panel(); + + /* GPIO pin assignment */ + gpio_backlight = mfp_to_gpio(MFP_PIN_GPIO14); + gpio_eth_irq = mfp_to_gpio(MFP_PIN_GPIO9); + } +} |