diff options
Diffstat (limited to 'packages/linux/compulab-pxa270-2.6.22/0004-cm-x270-it8152.patch')
-rw-r--r-- | packages/linux/compulab-pxa270-2.6.22/0004-cm-x270-it8152.patch | 496 |
1 files changed, 496 insertions, 0 deletions
diff --git a/packages/linux/compulab-pxa270-2.6.22/0004-cm-x270-it8152.patch b/packages/linux/compulab-pxa270-2.6.22/0004-cm-x270-it8152.patch new file mode 100644 index 0000000000..274eaf24d8 --- /dev/null +++ b/packages/linux/compulab-pxa270-2.6.22/0004-cm-x270-it8152.patch @@ -0,0 +1,496 @@ +From 1306abec905df1ff5cf2b1d91ac0d94d18d96c5b Mon Sep 17 00:00:00 2001 +From: Cliff Brake <cbrake@happy.dev.bec-systems.com> +Date: Fri, 20 Jul 2007 19:00:07 -0400 +Subject: [PATCH] cm-x270-it8152 + +--- + arch/arm/common/Makefile | 1 + + arch/arm/common/it8152.c | 272 +++++++++++++++++++++++++++++++++++++ + arch/arm/kernel/bios32.c | 28 ++++- + include/asm-arm/hardware/it8152.h | 104 ++++++++++++++ + include/asm-arm/pci.h | 7 + + include/linux/pci_ids.h | 1 + + 6 files changed, 410 insertions(+), 3 deletions(-) + create mode 100644 arch/arm/common/it8152.c + create mode 100644 include/asm-arm/hardware/it8152.h + +diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile +index e1289a2..3d0b9fa 100644 +--- a/arch/arm/common/Makefile ++++ b/arch/arm/common/Makefile +@@ -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 +diff --git a/arch/arm/common/it8152.c b/arch/arm/common/it8152.c +new file mode 100644 +index 0000000..8563610 +--- /dev/null ++++ b/arch/arm/common/it8152.c +@@ -0,0 +1,272 @@ ++/* ++ * arch/arm/common/it8152.c: PCI functions for IT8152 ++ * ++ * Compulab Ltd, 2002-2006 ++ * ++ * The DMA bouncing is taken from arch/arm/mach-ixp4xx/common-pci.c ++ * (see this file for respective copyrights) ++ * ++ * 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/sched.h> ++#include <linux/kernel.h> ++#include <linux/pci.h> ++#include <linux/ptrace.h> ++#include <linux/interrupt.h> ++#include <linux/mm.h> ++#include <linux/slab.h> ++#include <linux/init.h> ++#include <linux/ioport.h> ++#include <asm/mach/map.h> ++ ++ ++#include <asm/io.h> ++#include <asm/irq.h> ++#include <asm/system.h> ++#include <asm/mach/pci.h> ++#include <asm/hardware/it8152.h> ++ ++#define MAX_SLOTS 21 ++ ++static unsigned long ++it8152_pci_dev_base_address(struct pci_bus *bus, unsigned int devfn) ++{ ++ unsigned long addr = 0; ++ ++ if (bus->number == 0) { ++ if (devfn < PCI_DEVFN(MAX_SLOTS, 0)) ++ addr = (devfn << 8); ++ } else ++ addr = (bus->number << 16) | (devfn << 8); ++ ++ return addr; ++} ++ ++static int ++it8152_pci_read_config(struct pci_bus *bus, unsigned int devfn, int where, ++ int size, u32 *value) ++{ ++ unsigned long addr = it8152_pci_dev_base_address(bus, devfn); ++ u32 v; ++ int shift; ++ ++#ifdef CONFIG_MACH_ARMCORE ++ if(devfn!=0) IT8152_GPIO_GPLR=0x00; ++#endif ++ shift = (where & 3); ++ ++ IT8152_PCI_CFG_ADDR = (addr + where); ++ v = (IT8152_PCI_CFG_DATA >> (8 * (shift))); ++ ++ *value = v; ++ ++#ifdef CONFIG_MACH_ARMCORE ++ if(devfn!=0) IT8152_GPIO_GPLR=0x20; ++#endif ++ ++ return PCIBIOS_SUCCESSFUL; ++} ++ ++ ++static int ++it8152_pci_write_config(struct pci_bus *bus, unsigned int devfn, int where, ++ int size, u32 value) ++{ ++ unsigned long addr = it8152_pci_dev_base_address(bus, devfn); ++ u32 v, vtemp, mask=0; ++ int shift; ++ ++#ifdef CONFIG_MACH_ARMCORE ++ if(devfn!=0) IT8152_GPIO_GPLR=0x00; ++#endif ++ ++ if(size==1) mask=0xff; ++ if(size==2) mask=0xffff; ++ ++ shift = (where & 3); ++ ++ IT8152_PCI_CFG_ADDR = addr + where; ++ vtemp = IT8152_PCI_CFG_DATA; ++ ++ if(mask) vtemp &= ~(mask << (8 * shift)); ++ else vtemp = 0; ++ ++ v = (value << (8 * shift)); ++ IT8152_PCI_CFG_ADDR = addr + where; ++ IT8152_PCI_CFG_DATA = (v | vtemp); ++ ++#ifdef CONFIG_MACH_ARMCORE ++ if(devfn!=0) IT8152_GPIO_GPLR=0x20; ++#endif ++ ++ return PCIBIOS_SUCCESSFUL; ++} ++ ++static struct pci_ops it8152_ops = { ++ .read = it8152_pci_read_config, ++ .write = it8152_pci_write_config, ++}; ++ ++static struct resource it8152_io = { ++ .name = "IT8152 PCI I/O region", ++ .flags = IORESOURCE_IO, ++}; ++ ++static struct resource it8152_mem1 = { ++ .name = "First IT8152 PCI memory region", ++ .start = 0x10000000, ++ .end = 0x13e00000, ++ .flags = IORESOURCE_MEM, ++}; ++ ++/* ++ * The following functions are needed for DMA bouncing. ++ * ITE8152 chip can addrees up to 64MByte, so all the devices ++ * connected to ITE8152 (PCI and USB) should have limited DMA window ++ */ ++ ++/* ++ * Setup DMA mask to 64MB on devices connected to ITE8152. Ignore all ++ * other devices. ++ */ ++static int it8152_pci_platform_notify(struct device *dev) ++{ ++ if ( dev->bus == &pci_bus_type ) { ++ if ( dev->dma_mask ) ++ *dev->dma_mask = (SZ_64M - 1) | PHYS_OFFSET; ++ dev->coherent_dma_mask = (SZ_64M - 1) | PHYS_OFFSET; ++ dmabounce_register_dev(dev, 2048, 4096); ++ } ++ return 0; ++} ++ ++static int it8152_pci_platform_notify_remove(struct device *dev) ++{ ++ if ( dev->bus == &pci_bus_type ) { ++ dmabounce_unregister_dev(dev); ++ } ++ return 0; ++} ++ ++int dma_needs_bounce(struct device *dev, dma_addr_t dma_addr, size_t size) ++{ ++ dev_dbg(dev, "%s: dma_addr %08x, size %08x\n", ++ __FUNCTION__, dma_addr, size); ++ return (dev->bus == &pci_bus_type ) && ++ ((dma_addr + size - PHYS_OFFSET) >= SZ_64M); ++} ++ ++/* ++ * 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 it8152_adjust_zones(int node, unsigned long *zone_size, ++ unsigned long *zhole_size) ++{ ++ unsigned int sz = SZ_64M >> PAGE_SHIFT; ++ ++ /* ++ * 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; ++} ++ ++/* ++ * We override these so we properly do dmabounce otherwise drivers ++ * are able to set the dma_mask to 0xffffffff and we can no longer ++ * trap bounces. :( ++ * ++ * We just return true on everyhing except for < 64MB in which case ++ * we will fail miseralby and die since we can't handle that case. ++ */ ++int ++pci_set_dma_mask(struct pci_dev *dev, u64 mask) ++{ ++ printk(KERN_INFO "===> %s: %s %x\n", __FUNCTION__, dev->dev.bus_id, mask); ++ if (mask >= PHYS_OFFSET + SZ_64M - 1 ) ++ return 0; ++ ++ return -EIO; ++} ++ ++int ++pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask) ++{ ++ printk(KERN_INFO "===> %s: %s %x\n", __FUNCTION__, dev->dev.bus_id, mask); ++ if (mask >= PHYS_OFFSET + SZ_64M - 1 ) ++ return 0; ++ ++ return -EIO; ++} ++ ++EXPORT_SYMBOL(pci_set_dma_mask); ++EXPORT_SYMBOL(pci_set_consistent_dma_mask); ++ ++ ++int __init it8152_pci_setup(int nr, struct pci_sys_data *sys) ++{ ++ it8152_io.start = IT8152_IO_BASE + 0x12000; ++ it8152_io.end = IT8152_IO_BASE + 0x100000; ++ ++ if (request_resource(&ioport_resource, &it8152_io)) { ++ printk(KERN_ERR "PCI: unable to allocate IO region\n"); ++ return -EBUSY; ++ } ++ if (request_resource(&iomem_resource, &it8152_mem1)) { ++ printk(KERN_ERR "PCI: unable to allocate memory region\n"); ++ return -EBUSY; ++ } ++ ++ sys->resource[0] = &it8152_io; ++ sys->resource[1] = &it8152_mem1; ++ ++ if (platform_notify || platform_notify_remove) { ++ printk(KERN_ERR "PCI: Can't use platform_notify\n"); ++ return -EBUSY; ++ } ++ ++ platform_notify = it8152_pci_platform_notify; ++ platform_notify_remove = it8152_pci_platform_notify_remove; ++ ++ return 1; ++} ++ ++/* ++ * If we set up a device for bus mastering, we need to check the latency ++ * timer as we don't have even crappy BIOSes to set it properly. ++ * The implementation is from arch/i386/pci/i386.c ++ */ ++unsigned int pcibios_max_latency = 255; ++ ++void pcibios_set_master(struct pci_dev *dev) ++{ ++ u8 lat; ++ ++ pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); ++ if (lat < 16) ++ lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency; ++ else if (lat > pcibios_max_latency) ++ lat = pcibios_max_latency; ++ else ++ return; ++ printk(KERN_DEBUG "PCI: Setting latency timer of device %s to %d\n", pci_name(dev), lat); ++ pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat); ++} ++ ++ ++struct pci_bus * __init it8152_pci_scan_bus(int nr, struct pci_sys_data *sys) ++{ ++ return pci_scan_bus(nr, &it8152_ops, sys); ++} ++ +diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c +index 240c448..d8d2352 100644 +--- a/arch/arm/kernel/bios32.c ++++ b/arch/arm/kernel/bios32.c +@@ -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)); ++ + } + + /* +diff --git a/include/asm-arm/hardware/it8152.h b/include/asm-arm/hardware/it8152.h +new file mode 100644 +index 0000000..d28210d +--- /dev/null ++++ b/include/asm-arm/hardware/it8152.h +@@ -0,0 +1,104 @@ ++/* ++ * arch/arm/mach-pxa/it8152.h ++ * ++ * Compulab Ltd., 2006 ++ * ++ * ITE 8152 companion chip definitions ++ */ ++ ++ ++/* #define CMX270_IT8152_VIRT (CMX270_VIRT_BASE) */ ++ ++ ++extern unsigned long it8152_base_address; ++ ++#define IT8152_IO_BASE (it8152_base_address + 0x03e00000) ++#define IT8152_CFGREG_BASE (it8152_base_address + 0x03f00000) ++ ++/* #define IRQ_GPIO_IT8152_IRQ IRQ_GPIO(GPIO_IT8152_IRQ) */ ++ ++#define IT8152_SHORT_IO(x) (*((volatile unsigned short *)(IT8152_CFGREG_BASE+(x)))) ++#define IT8152_LONG_IO(x) (*((volatile unsigned long *)(IT8152_CFGREG_BASE+(x)))) ++ ++ ++#define IT8152_PCI_MEMBASE (*((volatile unsigned long *)(it8152_base_address))) ++/* #define IT8152_PCI_IOBASE (*((volatile unsigned long *)(it8152_base_address + 0x3e00000))) */ ++ ++#define IT8152_PCI_IACK (*((volatile unsigned long *)(it8152_base_address + 0x3f00808))) ++#define IT8152_PCI_CFG_ADDR (*((volatile unsigned long *)(it8152_base_address + 0x3f00800))) ++#define IT8152_PCI_CFG_DATA (*((volatile unsigned long *)(it8152_base_address + 0x3f00804))) ++ ++#define IT_BUSNUM_SHF 16 ++#define IT_DEVNUM_SHF 11 ++#define IT_FUNCNUM_SHF 8 ++#define IT_REGNUM_SHF 2 ++ ++/* Power management & PLL registers */ ++#define IT8152_PMPLL_DSR IT8152_LONG_IO(0x00) ++#define IT8152_PMPLL_DSSR IT8152_LONG_IO(0x04) ++#define IT8152_PMPLL_PLLCR IT8152_LONG_IO(0x20) ++#define IT8152_PMPLL_MFSR IT8152_LONG_IO(0x24) ++ ++/* Memory controller */ ++#define IT8152_MC_REG_OFFSET 0x100 ++ ++#define IT8152_MC_SDCR IT8152_LONG_IO(IT8152_MC_REG_OFFSET + 0x00) ++#define IT8152_MC_PCICR IT8152_LONG_IO(IT8152_MC_REG_OFFSET + 0x04) ++ ++/* Interrupt related definitions */ ++#define IT8152_INTC_REG_OFFSET 0x300 ++ ++#define IT8152_INTC_LDCNIRR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x00) ++#define IT8152_INTC_LDPNIRR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x04) ++#define IT8152_INTC_LDCNIMR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x08) ++#define IT8152_INTC_LDPNIMR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x0C) ++#define IT8152_INTC_LDNITR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x10) ++#define IT8152_INTC_LDNIAR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x14) ++#define IT8152_INTC_LPCNIRR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x20) ++#define IT8152_INTC_LPPNIRR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x24) ++#define IT8152_INTC_LPCNIMR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x28) ++#define IT8152_INTC_LPPNIMR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x2C) ++#define IT8152_INTC_LPNITR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x30) ++#define IT8152_INTC_LPNIAR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x34) ++#define IT8152_INTC_PDCNIRR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x40) ++#define IT8152_INTC_PDPNIRR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x44) ++#define IT8152_INTC_PDCNIMR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x48) ++#define IT8152_INTC_PDPNIMR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x4C) ++#define IT8152_INTC_PDNITR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x50) ++#define IT8152_INTC_PDNIAR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x54) ++#define IT8152_INTC_INTC_TYPER IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0xFC) ++ ++#define IT8152_UART_BASE IT8152_LONG_IO(0x200) ++ ++#define IT8152_GPIO_REG_OFFSET 0x500 ++ ++#define IT8152_GPIO_GPLR IT8152_LONG_IO(IT8152_GPIO_REG_OFFSET) ++#define IT8152_GPIO_GPCR12 IT8152_LONG_IO(IT8152_GPIO_REG_OFFSET + 0x04) ++#define IT8152_GPIO_GPCR34 IT8152_LONG_IO(IT8152_GPIO_REG_OFFSET + 0x08) ++ ++ ++/* Interrupt bit definitions */ ++#define PCISERR_BIT (1<<14) ++#define H2PTADR_BIT (1<<13) ++#define H2PMAR_BIT (1<<12) ++#define PCI_INTD_BIT (1<<11) ++#define PCI_INTC_BIT (1<<10) ++#define PCI_INTB_BIT (1<<9) ++#define PCI_INTA_BIT (1<<8) ++#define CDMA_INT_BIT (1<<2) ++#define USB_INT_BIT (1<<1) ++#define AUDIO_INT_BIT (1<<0) ++ ++/* IT8152 UART */ ++#define ITESER_BIT (1<<5) ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/include/asm-arm/pci.h b/include/asm-arm/pci.h +index f21abd4..2cf30bf 100644 +--- a/include/asm-arm/pci.h ++++ b/include/asm-arm/pci.h +@@ -8,10 +8,17 @@ + + #define pcibios_scan_all_fns(a, b) 0 + ++#ifdef CONFIG_PCI_HOST_ITE8152 ++/* ITE bridge requires setting latency timer to avoid early bus access ++ termination by PIC bus mater devices ++*/ ++extern void pcibios_set_master(struct pci_dev *dev); ++#else + static inline void pcibios_set_master(struct pci_dev *dev) + { + /* No special bus mastering setup handling */ + } ++#endif + + static inline void pcibios_penalize_isa_irq(int irq, int active) + { +diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h +index 5b1c999..b4c81d5 100644 +--- a/include/linux/pci_ids.h ++++ b/include/linux/pci_ids.h +@@ -1650,6 +1650,7 @@ + #define PCI_DEVICE_ID_ITE_8211 0x8211 + #define PCI_DEVICE_ID_ITE_8212 0x8212 + #define PCI_DEVICE_ID_ITE_8213 0x8213 ++#define PCI_DEVICE_ID_ITE_8152 0x8152 + #define PCI_DEVICE_ID_ITE_8872 0x8872 + #define PCI_DEVICE_ID_ITE_IT8330G_0 0xe886 + +-- +1.5.1.6 + |