Commit 3696a8a4 authored by Mike Rapoport's avatar Mike Rapoport Committed by Russell King

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

This patch provides core support for CM-X270 platform.
Signed-off-by: default avatarMike Rapoport <mike@compulab.co.il>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent 3e0cc7ee
This diff is collapsed.
...@@ -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
This diff is collapsed.
...@@ -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%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment