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
bool "PXA3xx Development Platform"
select PXA3xx
config MACH_ARMCORE
bool "CompuLab CM-X270 modules"
select PXA27x
select IWMMXT
endchoice
if PXA_SHARPSL
......
......@@ -29,6 +29,8 @@ ifeq ($(CONFIG_MACH_ZYLONITE),y)
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
......@@ -45,3 +47,7 @@ obj-$(CONFIG_PXA_SSP) += ssp.o
ifeq ($(CONFIG_PXA27x),y)
obj-$(CONFIG_PM) += standby.o
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
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
......
/*
* 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 {
DMA_PRIO_LOW = 2
} pxa_dma_prio;
#if defined(CONFIG_MACH_ARMCORE) && defined(CONFIG_PCI)
#define HAVE_ARCH_PCI_SET_DMA_MASK 1
#endif
/*
* DMA registration
*/
......
......@@ -215,4 +215,10 @@ extern unsigned int get_memclk_frequency_10khz(void);
#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 */
......@@ -210,3 +210,24 @@
#define IRQ_LOCOMO_GPIO_BASE (IRQ_BOARD_START + 1)
#define IRQ_LOCOMO_LT_BASE (IRQ_BOARD_START + 2)
#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 @@
*/
#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
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