提交 3696a8a4 编写于 作者: M Mike Rapoport 提交者: Russell King

[ARM] 4576/1: CM-X270 machine support

This patch provides core support for CM-X270 platform.
Signed-off-by: NMike Rapoport <mike@compulab.co.il>
Signed-off-by: NRussell King <rmk+kernel@arm.linux.org.uk>
上级 3e0cc7ee
此差异已折叠。
...@@ -63,6 +63,11 @@ config MACH_ZYLONITE ...@@ -63,6 +63,11 @@ config MACH_ZYLONITE
bool "PXA3xx Development Platform" bool "PXA3xx Development Platform"
select PXA3xx select PXA3xx
config MACH_ARMCORE
bool "CompuLab CM-X270 modules"
select PXA27x
select IWMMXT
endchoice endchoice
if PXA_SHARPSL if PXA_SHARPSL
......
...@@ -29,6 +29,8 @@ ifeq ($(CONFIG_MACH_ZYLONITE),y) ...@@ -29,6 +29,8 @@ ifeq ($(CONFIG_MACH_ZYLONITE),y)
obj-$(CONFIG_CPU_PXA320) += zylonite_pxa320.o obj-$(CONFIG_CPU_PXA320) += zylonite_pxa320.o
endif endif
obj-$(CONFIG_MACH_ARMCORE) += cm-x270.o
# Support for blinky lights # Support for blinky lights
led-y := leds.o led-y := leds.o
led-$(CONFIG_ARCH_LUBBOCK) += leds-lubbock.o led-$(CONFIG_ARCH_LUBBOCK) += leds-lubbock.o
...@@ -45,3 +47,7 @@ obj-$(CONFIG_PXA_SSP) += ssp.o ...@@ -45,3 +47,7 @@ obj-$(CONFIG_PXA_SSP) += ssp.o
ifeq ($(CONFIG_PXA27x),y) ifeq ($(CONFIG_PXA27x),y)
obj-$(CONFIG_PM) += standby.o obj-$(CONFIG_PM) += standby.o
endif endif
ifeq ($(CONFIG_PCI),y)
obj-$(CONFIG_MACH_ARMCORE) += cm-x270-pci.o
endif
/*
* 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
/*
* linux/arch/arm/mach-pxa/cm-x270.c
*
* 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/types.h>
#include <linux/pm.h>
#include <linux/fb.h>
#include <linux/platform_device.h>
#include <linux/irq.h>
#include <linux/sysdev.h>
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/dm9000.h>
#include <linux/rtc-v3020.h>
#include <linux/serial_8250.h>
#include <video/mbxfb.h>
#include <asm/mach/arch.h>
#include <asm/mach-types.h>
#include <asm/mach/map.h>
#include <asm/arch/pxa-regs.h>
#include <asm/arch/pxafb.h>
#include <asm/arch/ohci.h>
#include <asm/arch/mmc.h>
#include <asm/arch/bitfield.h>
#include <asm/arch/cm-x270.h>
#include <asm/hardware/it8152.h>
#include "generic.h"
#include "cm-x270-pci.h"
#define RTC_PHYS_BASE (PXA_CS1_PHYS + (5 << 22))
#define DM9000_PHYS_BASE (PXA_CS1_PHYS + (6 << 22))
static struct resource cmx270_dm9k_resource[] = {
[0] = {
.start = DM9000_PHYS_BASE,
.end = DM9000_PHYS_BASE + 4,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = DM9000_PHYS_BASE + 8,
.end = DM9000_PHYS_BASE + 8 + 500,
.flags = IORESOURCE_MEM,
},
[2] = {
.start = CMX270_ETHIRQ,
.end = CMX270_ETHIRQ,
.flags = IORESOURCE_IRQ,
}
};
/* for the moment we limit ourselves to 32bit IO until some
* better IO routines can be written and tested
*/
static struct dm9000_plat_data cmx270_dm9k_platdata = {
.flags = DM9000_PLATF_32BITONLY,
};
/* Ethernet device */
static struct platform_device cmx270_device_dm9k = {
.name = "dm9000",
.id = 0,
.num_resources = ARRAY_SIZE(cmx270_dm9k_resource),
.resource = cmx270_dm9k_resource,
.dev = {
.platform_data = &cmx270_dm9k_platdata,
}
};
/* audio device */
static struct platform_device cmx270_audio_device = {
.name = "pxa2xx-ac97",
.id = -1,
};
/* touchscreen controller */
static struct platform_device cmx270_ts_device = {
.name = "ucb1400_ts",
.id = -1,
};
/* RTC */
static struct resource cmx270_v3020_resource[] = {
[0] = {
.start = RTC_PHYS_BASE,
.end = RTC_PHYS_BASE + 4,
.flags = IORESOURCE_MEM,
},
};
struct v3020_platform_data cmx270_v3020_pdata = {
.leftshift = 16,
};
static struct platform_device cmx270_rtc_device = {
.name = "v3020",
.num_resources = ARRAY_SIZE(cmx270_v3020_resource),
.resource = cmx270_v3020_resource,
.id = -1,
.dev = {
.platform_data = &cmx270_v3020_pdata,
}
};
/*
* CM-X270 LEDs
*/
static struct platform_device cmx270_led_device = {
.name = "cm-x270-led",
.id = -1,
};
/* 2700G graphics */
static u64 fb_dma_mask = ~(u64)0;
static struct resource cmx270_2700G_resource[] = {
/* frame buffer memory including ODFB and External SDRAM */
[0] = {
.start = MARATHON_PHYS,
.end = MARATHON_PHYS + 0x02000000,
.flags = IORESOURCE_MEM,
},
/* Marathon registers */
[1] = {
.start = MARATHON_PHYS + 0x03fe0000,
.end = MARATHON_PHYS + 0x03ffffff,
.flags = IORESOURCE_MEM,
},
};
static unsigned long save_lcd_regs[10];
static int cmx270_marathon_probe(struct fb_info *fb)
{
/* save PXA-270 pin settings before enabling 2700G */
save_lcd_regs[0] = GPDR1;
save_lcd_regs[1] = GPDR2;
save_lcd_regs[2] = GAFR1_U;
save_lcd_regs[3] = GAFR2_L;
save_lcd_regs[4] = GAFR2_U;
/* Disable PXA-270 on-chip controller driving pins */
GPDR1 &= ~(0xfc000000);
GPDR2 &= ~(0x00c03fff);
GAFR1_U &= ~(0xfff00000);
GAFR2_L &= ~(0x0fffffff);
GAFR2_U &= ~(0x0000f000);
return 0;
}
static int cmx270_marathon_remove(struct fb_info *fb)
{
GPDR1 = save_lcd_regs[0];
GPDR2 = save_lcd_regs[1];
GAFR1_U = save_lcd_regs[2];
GAFR2_L = save_lcd_regs[3];
GAFR2_U = save_lcd_regs[4];
return 0;
}
static struct mbxfb_platform_data cmx270_2700G_data = {
.xres = {
.min = 240,
.max = 1200,
.defval = 640,
},
.yres = {
.min = 240,
.max = 1200,
.defval = 480,
},
.bpp = {
.min = 16,
.max = 32,
.defval = 16,
},
.memsize = 8*1024*1024,
.probe = cmx270_marathon_probe,
.remove = cmx270_marathon_remove,
};
static struct platform_device cmx270_2700G = {
.name = "mbx-fb",
.dev = {
.platform_data = &cmx270_2700G_data,
.dma_mask = &fb_dma_mask,
.coherent_dma_mask = 0xffffffff,
},
.num_resources = ARRAY_SIZE(cmx270_2700G_resource),
.resource = cmx270_2700G_resource,
.id = -1,
};
static u64 ata_dma_mask = ~(u64)0;
static struct platform_device cmx270_ata = {
.name = "pata_cm_x270",
.id = -1,
.dev = {
.dma_mask = &ata_dma_mask,
.coherent_dma_mask = 0xffffffff,
},
};
/* platform devices */
static struct platform_device *platform_devices[] __initdata = {
&cmx270_device_dm9k,
&cmx270_audio_device,
&cmx270_rtc_device,
&cmx270_2700G,
&cmx270_led_device,
&cmx270_ts_device,
&cmx270_ata,
};
/* Map PCI companion and IDE/General Purpose CS statically */
static struct map_desc cmx270_io_desc[] __initdata = {
[0] = { /* IDE/general purpose space */
.virtual = CMX270_IDE104_VIRT,
.pfn = __phys_to_pfn(CMX270_IDE104_PHYS),
.length = SZ_64M - SZ_8M,
.type = MT_DEVICE
},
[1] = { /* PCI bridge */
.virtual = CMX270_IT8152_VIRT,
.pfn = __phys_to_pfn(CMX270_IT8152_PHYS),
.length = SZ_64M,
.type = MT_DEVICE
},
};
/*
Display definitions
keep these for backwards compatibility, although symbolic names (as
e.g. in lpd270.c) looks better
*/
#define MTYPE_STN320x240 0
#define MTYPE_TFT640x480 1
#define MTYPE_CRT640x480 2
#define MTYPE_CRT800x600 3
#define MTYPE_TFT320x240 6
#define MTYPE_STN640x480 7
static struct pxafb_mode_info generic_stn_320x240_mode = {
.pixclock = 76923,
.bpp = 8,
.xres = 320,
.yres = 240,
.hsync_len = 3,
.vsync_len = 2,
.left_margin = 3,
.upper_margin = 0,
.right_margin = 3,
.lower_margin = 0,
.sync = (FB_SYNC_HOR_HIGH_ACT |
FB_SYNC_VERT_HIGH_ACT),
.cmap_greyscale = 0,
};
static struct pxafb_mach_info generic_stn_320x240 = {
.modes = &generic_stn_320x240_mode,
.num_modes = 1,
.lccr0 = 0,
.lccr3 = (LCCR3_PixClkDiv(0x03) |
LCCR3_Acb(0xff) |
LCCR3_PCP),
.cmap_inverse = 0,
.cmap_static = 0,
};
static struct pxafb_mode_info generic_tft_640x480_mode = {
.pixclock = 38461,
.bpp = 8,
.xres = 640,
.yres = 480,
.hsync_len = 60,
.vsync_len = 2,
.left_margin = 70,
.upper_margin = 10,
.right_margin = 70,
.lower_margin = 5,
.sync = 0,
.cmap_greyscale = 0,
};
static struct pxafb_mach_info generic_tft_640x480 = {
.modes = &generic_tft_640x480_mode,
.num_modes = 1,
.lccr0 = (LCCR0_PAS),
.lccr3 = (LCCR3_PixClkDiv(0x01) |
LCCR3_Acb(0xff) |
LCCR3_PCP),
.cmap_inverse = 0,
.cmap_static = 0,
};
static struct pxafb_mode_info generic_crt_640x480_mode = {
.pixclock = 38461,
.bpp = 8,
.xres = 640,
.yres = 480,
.hsync_len = 63,
.vsync_len = 2,
.left_margin = 81,
.upper_margin = 33,
.right_margin = 16,
.lower_margin = 10,
.sync = (FB_SYNC_HOR_HIGH_ACT |
FB_SYNC_VERT_HIGH_ACT),
.cmap_greyscale = 0,
};
static struct pxafb_mach_info generic_crt_640x480 = {
.modes = &generic_crt_640x480_mode,
.num_modes = 1,
.lccr0 = (LCCR0_PAS),
.lccr3 = (LCCR3_PixClkDiv(0x01) |
LCCR3_Acb(0xff)),
.cmap_inverse = 0,
.cmap_static = 0,
};
static struct pxafb_mode_info generic_crt_800x600_mode = {
.pixclock = 28846,
.bpp = 8,
.xres = 800,
.yres = 600,
.hsync_len = 63,
.vsync_len = 2,
.left_margin = 26,
.upper_margin = 21,
.right_margin = 26,
.lower_margin = 11,
.sync = (FB_SYNC_HOR_HIGH_ACT |
FB_SYNC_VERT_HIGH_ACT),
.cmap_greyscale = 0,
};
static struct pxafb_mach_info generic_crt_800x600 = {
.modes = &generic_crt_800x600_mode,
.num_modes = 1,
.lccr0 = (LCCR0_PAS),
.lccr3 = (LCCR3_PixClkDiv(0x02) |
LCCR3_Acb(0xff)),
.cmap_inverse = 0,
.cmap_static = 0,
};
static struct pxafb_mode_info generic_tft_320x240_mode = {
.pixclock = 134615,
.bpp = 16,
.xres = 320,
.yres = 240,
.hsync_len = 63,
.vsync_len = 7,
.left_margin = 75,
.upper_margin = 0,
.right_margin = 15,
.lower_margin = 15,
.sync = 0,
.cmap_greyscale = 0,
};
static struct pxafb_mach_info generic_tft_320x240 = {
.modes = &generic_tft_320x240_mode,
.num_modes = 1,
.lccr0 = (LCCR0_PAS),
.lccr3 = (LCCR3_PixClkDiv(0x06) |
LCCR3_Acb(0xff) |
LCCR3_PCP),
.cmap_inverse = 0,
.cmap_static = 0,
};
static struct pxafb_mode_info generic_stn_640x480_mode = {
.pixclock = 57692,
.bpp = 8,
.xres = 640,
.yres = 480,
.hsync_len = 4,
.vsync_len = 2,
.left_margin = 10,
.upper_margin = 5,
.right_margin = 10,
.lower_margin = 5,
.sync = (FB_SYNC_HOR_HIGH_ACT |
FB_SYNC_VERT_HIGH_ACT),
.cmap_greyscale = 0,
};
static struct pxafb_mach_info generic_stn_640x480 = {
.modes = &generic_stn_640x480_mode,
.num_modes = 1,
.lccr0 = 0,
.lccr3 = (LCCR3_PixClkDiv(0x02) |
LCCR3_Acb(0xff)),
.cmap_inverse = 0,
.cmap_static = 0,
};
static struct pxafb_mach_info *cmx270_display = &generic_crt_640x480;
static int __init cmx270_set_display(char *str)
{
int disp_type = simple_strtol(str, NULL, 0);
switch (disp_type) {
case MTYPE_STN320x240:
cmx270_display = &generic_stn_320x240;
break;
case MTYPE_TFT640x480:
cmx270_display = &generic_tft_640x480;
break;
case MTYPE_CRT640x480:
cmx270_display = &generic_crt_640x480;
break;
case MTYPE_CRT800x600:
cmx270_display = &generic_crt_800x600;
break;
case MTYPE_TFT320x240:
cmx270_display = &generic_tft_320x240;
break;
case MTYPE_STN640x480:
cmx270_display = &generic_stn_640x480;
break;
default: /* fallback to CRT 640x480 */
cmx270_display = &generic_crt_640x480;
break;
}
return 1;
}
/*
This should be done really early to get proper configuration for
frame buffer.
Indeed, pxafb parameters can be used istead, but CM-X270 bootloader
has limitied line length for kernel command line, and also it will
break compatibitlty with proprietary releases already in field.
*/
__setup("monitor=", cmx270_set_display);
/* PXA27x OHCI controller setup */
static int cmx270_ohci_init(struct device *dev)
{
/* Set the Power Control Polarity Low */
UHCHR = (UHCHR | UHCHR_PCPL) &
~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSE);
return 0;
}
static struct pxaohci_platform_data cmx270_ohci_platform_data = {
.port_mode = PMM_PERPORT_MODE,
.init = cmx270_ohci_init,
};
static int cmx270_mci_init(struct device *dev,
irq_handler_t cmx270_detect_int,
void *data)
{
int err;
/*
* setup GPIO for PXA27x MMC controller
*/
pxa_gpio_mode(GPIO32_MMCCLK_MD);
pxa_gpio_mode(GPIO112_MMCCMD_MD);
pxa_gpio_mode(GPIO92_MMCDAT0_MD);
pxa_gpio_mode(GPIO109_MMCDAT1_MD);
pxa_gpio_mode(GPIO110_MMCDAT2_MD);
pxa_gpio_mode(GPIO111_MMCDAT3_MD);
/* SB-X270 uses GPIO105 as SD power enable */
pxa_gpio_mode(105 | GPIO_OUT);
/* card detect IRQ on GPIO 83 */
pxa_gpio_mode(IRQ_TO_GPIO(CMX270_MMC_IRQ));
set_irq_type(CMX270_MMC_IRQ, IRQT_FALLING);
err = request_irq(CMX270_MMC_IRQ, cmx270_detect_int,
IRQF_DISABLED | IRQF_TRIGGER_FALLING,
"MMC card detect", data);
if (err) {
printk(KERN_ERR "cmx270_mci_init: MMC/SD: can't"
" request MMC card detect IRQ\n");
return -1;
}
return 0;
}
static void cmx270_mci_setpower(struct device *dev, unsigned int vdd)
{
struct pxamci_platform_data *p_d = dev->platform_data;
if ((1 << vdd) & p_d->ocr_mask) {
printk(KERN_DEBUG "%s: on\n", __FUNCTION__);
GPCR(105) = GPIO_bit(105);
} else {
GPSR(105) = GPIO_bit(105);
printk(KERN_DEBUG "%s: off\n", __FUNCTION__);
}
}
static void cmx270_mci_exit(struct device *dev, void *data)
{
free_irq(CMX270_MMC_IRQ, data);
}
static struct pxamci_platform_data cmx270_mci_platform_data = {
.ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
.init = cmx270_mci_init,
.setpower = cmx270_mci_setpower,
.exit = cmx270_mci_exit,
};
#ifdef CONFIG_PM
static unsigned long sleep_save_msc[10];
static int cmx270_suspend(struct sys_device *dev, pm_message_t state)
{
cmx270_pci_suspend();
/* save MSC registers */
sleep_save_msc[0] = MSC0;
sleep_save_msc[1] = MSC1;
sleep_save_msc[2] = MSC2;
/* setup power saving mode registers */
PCFR = 0x0;
PSLR = 0xff400000;
PMCR = 0x00000005;
PWER = 0x80000000;
PFER = 0x00000000;
PRER = 0x00000000;
PGSR0 = 0xC0018800;
PGSR1 = 0x004F0002;
PGSR2 = 0x6021C000;
PGSR3 = 0x00020000;
return 0;
}
static int cmx270_resume(struct sys_device *dev)
{
cmx270_pci_resume();
/* restore MSC registers */
MSC0 = sleep_save_msc[0];
MSC1 = sleep_save_msc[1];
MSC2 = sleep_save_msc[2];
return 0;
}
static struct sysdev_class cmx270_pm_sysclass = {
set_kset_name("pm"),
.resume = cmx270_resume,
.suspend = cmx270_suspend,
};
static struct sys_device cmx270_pm_device = {
.cls = &cmx270_pm_sysclass,
};
static int __init cmx270_pm_init(void)
{
int error;
error = sysdev_class_register(&cmx270_pm_sysclass);
if (error == 0)
error = sysdev_register(&cmx270_pm_device);
return error;
}
#else
static int __init cmx270_pm_init(void) { return 0; }
#endif
static void __init cmx270_init(void)
{
cmx270_pm_init();
set_pxa_fb_info(cmx270_display);
/* register CM-X270 platform devices */
platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
/* set MCI and OHCI platform parameters */
pxa_set_mci_info(&cmx270_mci_platform_data);
pxa_set_ohci_info(&cmx270_ohci_platform_data);
/* This enables the STUART */
pxa_gpio_mode(GPIO46_STRXD_MD);
pxa_gpio_mode(GPIO47_STTXD_MD);
/* This enables the BTUART */
pxa_gpio_mode(GPIO42_BTRXD_MD);
pxa_gpio_mode(GPIO43_BTTXD_MD);
pxa_gpio_mode(GPIO44_BTCTS_MD);
pxa_gpio_mode(GPIO45_BTRTS_MD);
}
static void __init cmx270_init_irq(void)
{
pxa27x_init_irq();
cmx270_pci_init_irq();
/* Setup interrupt for dm9000 */
pxa_gpio_mode(IRQ_TO_GPIO(CMX270_ETHIRQ));
set_irq_type(CMX270_ETHIRQ, IRQT_RISING);
/* Setup interrupt for 2700G */
pxa_gpio_mode(IRQ_TO_GPIO(CMX270_GFXIRQ));
set_irq_type(CMX270_GFXIRQ, IRQT_FALLING);
}
static void __init cmx270_map_io(void)
{
pxa_map_io();
iotable_init(cmx270_io_desc, ARRAY_SIZE(cmx270_io_desc));
}
MACHINE_START(ARMCORE, "Compulab CM-x270")
.boot_params = 0xa0000100,
.phys_io = 0x40000000,
.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.map_io = cmx270_map_io,
.init_irq = cmx270_init_irq,
.timer = &pxa_timer,
.init_machine = cmx270_init,
MACHINE_END
...@@ -108,6 +108,12 @@ config LEDS_GPIO ...@@ -108,6 +108,12 @@ config LEDS_GPIO
outputs. To be useful the particular board must have LEDs outputs. To be useful the particular board must have LEDs
and they must be connected to the GPIO lines. 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" comment "LED Triggers"
config LEDS_TRIGGERS config LEDS_TRIGGERS
......
...@@ -18,6 +18,7 @@ obj-$(CONFIG_LEDS_H1940) += leds-h1940.o ...@@ -18,6 +18,7 @@ obj-$(CONFIG_LEDS_H1940) += leds-h1940.o
obj-$(CONFIG_LEDS_COBALT_QUBE) += leds-cobalt-qube.o obj-$(CONFIG_LEDS_COBALT_QUBE) += leds-cobalt-qube.o
obj-$(CONFIG_LEDS_COBALT_RAQ) += leds-cobalt-raq.o obj-$(CONFIG_LEDS_COBALT_RAQ) += leds-cobalt-raq.o
obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o
obj-$(CONFIG_LEDS_CM_X270) += leds-cm-x270.o
# LED Triggers # LED Triggers
obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o
......
/*
* drivers/leds/leds-cm-x270.c
*
* Copyright 2007 CompuLab Ltd.
* Author: Mike Rapoport <mike@compulab.co.il>
*
* Based on leds-corgi.c
* Author: Richard Purdie <rpurdie@openedhand.com>
*
* 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/init.h>
#include <linux/platform_device.h>
#include <linux/leds.h>
#include <asm/arch/hardware.h>
#include <asm/arch/pxa-regs.h>
#define GPIO_RED_LED (93)
#define GPIO_GREEN_LED (94)
static void cmx270_red_set(struct led_classdev *led_cdev,
enum led_brightness value)
{
if (value)
GPCR(GPIO_RED_LED) = GPIO_bit(GPIO_RED_LED);
else
GPSR(GPIO_RED_LED) = GPIO_bit(GPIO_RED_LED);
}
static void cmx270_green_set(struct led_classdev *led_cdev,
enum led_brightness value)
{
if (value)
GPCR(GPIO_GREEN_LED) = GPIO_bit(GPIO_GREEN_LED);
else
GPSR(GPIO_GREEN_LED) = GPIO_bit(GPIO_GREEN_LED);
}
static struct led_classdev cmx270_red_led = {
.name = "cm-x270:red",
.default_trigger = "nand-disk",
.brightness_set = cmx270_red_set,
};
static struct led_classdev cmx270_green_led = {
.name = "cm-x270:green",
.default_trigger = "heartbeat",
.brightness_set = cmx270_green_set,
};
#ifdef CONFIG_PM
static int cmx270led_suspend(struct platform_device *dev, pm_message_t state)
{
led_classdev_suspend(&cmx270_red_led);
led_classdev_suspend(&cmx270_green_led);
return 0;
}
static int cmx270led_resume(struct platform_device *dev)
{
led_classdev_resume(&cmx270_red_led);
led_classdev_resume(&cmx270_green_led);
return 0;
}
#endif
static int cmx270led_probe(struct platform_device *pdev)
{
int ret;
ret = led_classdev_register(&pdev->dev, &cmx270_red_led);
if (ret < 0)
return ret;
ret = led_classdev_register(&pdev->dev, &cmx270_green_led);
if (ret < 0)
led_classdev_unregister(&cmx270_red_led);
return ret;
}
static int cmx270led_remove(struct platform_device *pdev)
{
led_classdev_unregister(&cmx270_red_led);
led_classdev_unregister(&cmx270_green_led);
return 0;
}
static struct platform_driver cmx270led_driver = {
.probe = cmx270led_probe,
.remove = cmx270led_remove,
#ifdef CONFIG_PM
.suspend = cmx270led_suspend,
.resume = cmx270led_resume,
#endif
.driver = {
.name = "cm-x270-led",
},
};
static int __init cmx270led_init(void)
{
return platform_driver_register(&cmx270led_driver);
}
static void __exit cmx270led_exit(void)
{
platform_driver_unregister(&cmx270led_driver);
}
module_init(cmx270led_init);
module_exit(cmx270led_exit);
MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>");
MODULE_DESCRIPTION("CM-x270 LED driver");
MODULE_LICENSE("GPL");
/*
* linux/include/asm/arch-pxa/cm-x270.h
*
* Copyright Compulab Ltd., 2003, 2007
* 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.
*/
/* CM-x270 device physical addresses */
#define CMX270_CS1_PHYS (PXA_CS1_PHYS)
#define MARATHON_PHYS (PXA_CS2_PHYS)
#define CMX270_IDE104_PHYS (PXA_CS3_PHYS)
#define CMX270_IT8152_PHYS (PXA_CS4_PHYS)
/* Statically mapped regions */
#define CMX270_VIRT_BASE (0xe8000000)
#define CMX270_IT8152_VIRT (CMX270_VIRT_BASE)
#define CMX270_IDE104_VIRT (CMX270_IT8152_VIRT + SZ_64M)
/* GPIO related definitions */
#define GPIO_IT8152_IRQ (22)
#define IRQ_GPIO_IT8152_IRQ IRQ_GPIO(GPIO_IT8152_IRQ)
#define PME_IRQ IRQ_GPIO(0)
#define CMX270_IDE_IRQ IRQ_GPIO(100)
#define CMX270_GPIRQ1 IRQ_GPIO(101)
#define CMX270_TOUCHIRQ IRQ_GPIO(96)
#define CMX270_ETHIRQ IRQ_GPIO(10)
#define CMX270_GFXIRQ IRQ_GPIO(95)
#define CMX270_NANDIRQ IRQ_GPIO(89)
#define CMX270_MMC_IRQ IRQ_GPIO(83)
/* PCMCIA related definitions */
#define PCC_DETECT(x) (GPLR(84 - (x)) & GPIO_bit(84 - (x)))
#define PCC_READY(x) (GPLR(82 - (x)) & GPIO_bit(82 - (x)))
#define PCMCIA_S0_CD_VALID IRQ_GPIO(84)
#define PCMCIA_S0_CD_VALID_EDGE GPIO_BOTH_EDGES
#define PCMCIA_S1_CD_VALID IRQ_GPIO(83)
#define PCMCIA_S1_CD_VALID_EDGE GPIO_BOTH_EDGES
#define PCMCIA_S0_RDYINT IRQ_GPIO(82)
#define PCMCIA_S1_RDYINT IRQ_GPIO(81)
#define PCMCIA_RESET_GPIO 53
...@@ -30,6 +30,10 @@ typedef enum { ...@@ -30,6 +30,10 @@ typedef enum {
DMA_PRIO_LOW = 2 DMA_PRIO_LOW = 2
} pxa_dma_prio; } pxa_dma_prio;
#if defined(CONFIG_MACH_ARMCORE) && defined(CONFIG_PCI)
#define HAVE_ARCH_PCI_SET_DMA_MASK 1
#endif
/* /*
* DMA registration * DMA registration
*/ */
......
...@@ -215,4 +215,10 @@ extern unsigned int get_memclk_frequency_10khz(void); ...@@ -215,4 +215,10 @@ extern unsigned int get_memclk_frequency_10khz(void);
#endif #endif
#if defined(CONFIG_MACH_ARMCORE) && defined(CONFIG_PCI)
#define PCIBIOS_MIN_IO 0
#define PCIBIOS_MIN_MEM 0
#define pcibios_assign_all_busses() 1
#endif
#endif /* _ASM_ARCH_HARDWARE_H */ #endif /* _ASM_ARCH_HARDWARE_H */
...@@ -210,3 +210,24 @@ ...@@ -210,3 +210,24 @@
#define IRQ_LOCOMO_GPIO_BASE (IRQ_BOARD_START + 1) #define IRQ_LOCOMO_GPIO_BASE (IRQ_BOARD_START + 1)
#define IRQ_LOCOMO_LT_BASE (IRQ_BOARD_START + 2) #define IRQ_LOCOMO_LT_BASE (IRQ_BOARD_START + 2)
#define IRQ_LOCOMO_SPI_BASE (IRQ_BOARD_START + 3) #define IRQ_LOCOMO_SPI_BASE (IRQ_BOARD_START + 3)
/* ITE8152 irqs */
/* add IT8152 IRQs beyond BOARD_END */
#ifdef CONFIG_PCI_HOST_ITE8152
#define IT8152_IRQ(x) (IRQ_GPIO(IRQ_BOARD_END) + 1 + (x))
/* IRQ-sources in 3 groups - local devices, LPC (serial), and external PCI */
#define IT8152_LD_IRQ_COUNT 9
#define IT8152_LP_IRQ_COUNT 16
#define IT8152_PD_IRQ_COUNT 15
/* Priorities: */
#define IT8152_PD_IRQ(i) IT8152_IRQ(i)
#define IT8152_LP_IRQ(i) (IT8152_IRQ(i) + IT8152_PD_IRQ_COUNT)
#define IT8152_LD_IRQ(i) (IT8152_IRQ(i) + IT8152_PD_IRQ_COUNT + IT8152_LP_IRQ_COUNT)
#define IT8152_LAST_IRQ IT8152_LD_IRQ(IT8152_LD_IRQ_COUNT - 1)
#undef NR_IRQS
#define NR_IRQS (IT8152_LAST_IRQ+1)
#endif
...@@ -39,4 +39,14 @@ ...@@ -39,4 +39,14 @@
*/ */
#define NODE_MEM_SIZE_BITS 26 #define NODE_MEM_SIZE_BITS 26
#if !defined(__ASSEMBLY__) && defined(CONFIG_MACH_ARMCORE) && defined(CONFIG_PCI)
void cmx270_pci_adjust_zones(int node, unsigned long *size,
unsigned long *holes);
#define arch_adjust_zones(node, size, holes) \
cmx270_pci_adjust_zones(node, size, holes)
#define ISA_DMA_THRESHOLD (PHYS_OFFSET + SZ_64M - 1)
#endif
#endif #endif
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册