@@ -45,17 +45,17 @@
/*
* Define the address range of the kernel non-linear virtual area
*/
-#define H_KERN_VIRT_START ASM_CONST(0xD000000000000000)
-#define H_KERN_VIRT_SIZE ASM_CONST(0x0000100000000000)
+#define KERN_VIRT_START ASM_CONST(0xD000000000000000)
+#define KERN_VIRT_SIZE ASM_CONST(0x0000100000000000)
/*
* The vmalloc space starts at the beginning of that region, and
* occupies half of it on hash CPUs and a quarter of it on Book3E
* (we keep a quarter for the virtual memmap)
*/
-#define H_VMALLOC_START H_KERN_VIRT_START
-#define H_VMALLOC_SIZE (H_KERN_VIRT_SIZE >> 1)
-#define H_VMALLOC_END (H_VMALLOC_START + H_VMALLOC_SIZE)
+#define VMALLOC_START KERN_VIRT_START
+#define VMALLOC_SIZE (KERN_VIRT_SIZE >> 1)
+#define VMALLOC_END (VMALLOC_START + VMALLOC_SIZE)
/*
* Region IDs
@@ -64,7 +64,7 @@
#define REGION_MASK (0xfUL << REGION_SHIFT)
#define REGION_ID(ea) (((unsigned long)(ea)) >> REGION_SHIFT)
-#define VMALLOC_REGION_ID (REGION_ID(H_VMALLOC_START))
+#define VMALLOC_REGION_ID (REGION_ID(VMALLOC_START))
#define KERNEL_REGION_ID (REGION_ID(PAGE_OFFSET))
#define VMEMMAP_REGION_ID (0xfUL) /* Server only */
#define USER_REGION_ID (0UL)
@@ -73,7 +73,7 @@
* Defines the address of the vmemap area, in its own region on
* hash table CPUs.
*/
-#define H_VMEMMAP_BASE (VMEMMAP_REGION_ID << REGION_SHIFT)
+#define VMEMMAP_BASE (VMEMMAP_REGION_ID << REGION_SHIFT)
#ifdef CONFIG_PPC_MM_SLICES
#define HAVE_ARCH_UNMAPPED_AREA
@@ -218,18 +218,6 @@ extern unsigned long __pte_frag_size_shift;
#define PUD_MASKED_BITS 0xc0000000000000ffUL
/* Bits to mask out from a PGD to get to the PUD page */
#define PGD_MASKED_BITS 0xc0000000000000ffUL
-
-extern unsigned long __vmalloc_start;
-extern unsigned long __vmalloc_end;
-#define VMALLOC_START __vmalloc_start
-#define VMALLOC_END __vmalloc_end
-
-extern unsigned long __kernel_virt_start;
-extern unsigned long __kernel_virt_size;
-#define KERN_VIRT_START __kernel_virt_start
-#define KERN_VIRT_SIZE __kernel_virt_size
-extern struct page *vmemmap;
-extern unsigned long ioremap_bot;
#endif /* __ASSEMBLY__ */
#include <asm/book3s/64/hash.h>
@@ -242,6 +230,7 @@ extern unsigned long ioremap_bot;
#endif
#include <asm/barrier.h>
+
/*
* The second half of the kernel virtual space is used for IO mappings,
* it's itself carved into the PIO region (ISA and PHB IO space) and
@@ -260,6 +249,8 @@ extern unsigned long ioremap_bot;
#define IOREMAP_BASE (PHB_IO_END)
#define IOREMAP_END (KERN_VIRT_START + KERN_VIRT_SIZE)
+#define vmmemap ((struct page *)VMEMMAP_BASE)
+
/* Advertise special mapping type for AGP */
#define HAVE_PAGE_AGP
@@ -31,74 +31,6 @@
RADIX_PUD_INDEX_SIZE + RADIX_PGD_INDEX_SIZE + PAGE_SHIFT)
#define RADIX_PGTABLE_RANGE (ASM_CONST(1) << RADIX_PGTABLE_EADDR_SIZE)
-/*
- * We support 52 bit address space, Use top bit for kernel
- * virtual mapping. Also make sure kernel fit in the top
- * quadrant.
- *
- * +------------------+
- * +------------------+ Kernel virtual map (0xc008000000000000)
- * | |
- * | |
- * | |
- * 0b11......+------------------+ Kernel linear map (0xc....)
- * | |
- * | 2 quadrant |
- * | |
- * 0b10......+------------------+
- * | |
- * | 1 quadrant |
- * | |
- * 0b01......+------------------+
- * | |
- * | 0 quadrant |
- * | |
- * 0b00......+------------------+
- *
- *
- * 3rd quadrant expanded:
- * +------------------------------+
- * | |
- * | |
- * | |
- * +------------------------------+ Kernel IO map end (0xc010000000000000)
- * | |
- * | |
- * | 1/2 of virtual map |
- * | |
- * | |
- * +------------------------------+ Kernel IO map start
- * | |
- * | 1/4 of virtual map |
- * | |
- * +------------------------------+ Kernel vmemap start
- * | |
- * | 1/4 of virtual map |
- * | |
- * +------------------------------+ Kernel virt start (0xc008000000000000)
- * | |
- * | |
- * | |
- * +------------------------------+ Kernel linear (0xc.....)
- */
-
-#define RADIX_KERN_VIRT_START ASM_CONST(0xc008000000000000)
-#define RADIX_KERN_VIRT_SIZE ASM_CONST(0x0008000000000000)
-
-/*
- * The vmalloc space starts at the beginning of that region, and
- * occupies a quarter of it on radix config.
- * (we keep a quarter for the virtual memmap)
- */
-#define RADIX_VMALLOC_START RADIX_KERN_VIRT_START
-#define RADIX_VMALLOC_SIZE (RADIX_KERN_VIRT_SIZE >> 2)
-#define RADIX_VMALLOC_END (RADIX_VMALLOC_START + RADIX_VMALLOC_SIZE)
-/*
- * Defines the address of the vmemap area, in its own region on
- * hash table CPUs.
- */
-#define RADIX_VMEMMAP_BASE (RADIX_VMALLOC_END)
-
#ifndef __ASSEMBLY__
#define RADIX_PTE_TABLE_SIZE (sizeof(pte_t) << RADIX_PTE_INDEX_SIZE)
#define RADIX_PMD_TABLE_SIZE (sizeof(pmd_t) << RADIX_PMD_INDEX_SIZE)
@@ -72,6 +72,13 @@ _GLOBAL(__start)
/* NOP this out unconditionally */
BEGIN_FTR_SECTION
FIXUP_ENDIAN
+/* Hack for PWRficient platforms: Due to CFE(?) bug, the 64-bit
+ * word at 0x8 needs to be set to 0. Patch it up here once we're
+ * done executing it (we can be lazy and avoid invalidating
+ * icache)
+ */
+li r0,0
+std 0,8(0)
b __start_initialization_multiplatform
END_FTR_SECTION(0, 1)
@@ -723,6 +723,19 @@ void pci_process_bridge_OF_ranges(struct pci_controller *hose,
isa_io_base =
(unsigned long)hose->io_base_virt;
#endif /* CONFIG_PPC32 */
+
+
+#ifdef CONFIG_PPC_PASEMI_SB600
+ /* Workaround for lack of device tree. New for kernel 3.17: range.cpu_addr instead of cpu_addr and range.size instead of size Ch. Zigotzky */
+ if (primary) {
+ __ioremap_at(range.cpu_addr, (void *)ISA_IO_BASE,
+ range.size,pgprot_val(pgprot_noncached(__pgprot(0))));
+ hose->io_base_virt = (void *)_IO_BASE;
+ /* _IO_BASE needs unsigned long long for the kernel 3.17 Ch. Zigotzky */
+ printk("Initialised io_base_virt 0x%lx _IO_BASE 0x%llx\n", (unsigned long)hose->io_base_virt, (unsigned long long)_IO_BASE);
+ }
+#endif
+
/* pci_io_size and io_base_phys always represent IO
* space starting at 0 so we factor in pci_addr
*/
@@ -1182,6 +1195,7 @@ static void pcibios_allocate_bus_resources(struct pci_bus *bus)
&ioport_resource : &iomem_resource;
else {
pr = pci_find_parent_resource(bus->self, res);
+#ifndef CONFIG_PPC_PASEMI_SB600
if (pr == res) {
/* this happens when the generic PCI
* code (wrongly) decides that this
@@ -1189,6 +1203,7 @@ static void pcibios_allocate_bus_resources(struct pci_bus *bus)
*/
continue;
}
+#endif
}
pr_debug("PCI: %s (bus %d) bridge rsrc %d: %pR, parent %p (%s)\n",
@@ -1607,8 +1622,9 @@ void pcibios_scan_phb(struct pci_controller *hose)
pr_debug("PCI: Scanning PHB %s\n", of_node_full_name(node));
/* Get some IO space for the new PHB */
+#ifndef CONFIG_PPC_PASEMI_SB600
pcibios_setup_phb_io_space(hose);
-
+#endif
/* Wire up PHB bus resources */
pcibios_setup_phb_resources(hose, &resources);
@@ -38,7 +38,7 @@
* ISA drivers use hard coded offsets. If no ISA bus exists nothing
* is mapped on the first 64K of IO space
*/
-unsigned long pci_io_base;
+unsigned long pci_io_base = ISA_IO_BASE;
EXPORT_SYMBOL(pci_io_base);
static int __init pcibios_init(void)
@@ -47,7 +47,6 @@ static int __init pcibios_init(void)
printk(KERN_INFO "PCI: Probing PCI hardware\n");
- pci_io_base = ISA_IO_BASE;
/* For now, override phys_mem_access_prot. If we need it,g
* later, we may move that initialization to each ppc_md
*/
@@ -76,7 +76,15 @@ EXPORT_SYMBOL(ppc_md);
struct machdep_calls *machine_id;
EXPORT_SYMBOL(machine_id);
+#ifdef CONFIG_PPC_PASEMI_SB600
+/* FIXME!!
+ * Current PASemi code does not correctly update the value of boot_cpuid
+ * As a temporary fix we use the default 0, which is known to work
+ */
+int boot_cpuid = 0;
+#else
int boot_cpuid = -1;
+#endif
EXPORT_SYMBOL_GPL(boot_cpuid);
unsigned long klimit = (unsigned long) _end;
@@ -910,14 +910,6 @@ void __init hash__early_init_mmu(void)
__pmd_val_bits = 0;
__pud_val_bits = 0;
__pgd_val_bits = 0;
-
- __kernel_virt_start = H_KERN_VIRT_START;
- __kernel_virt_size = H_KERN_VIRT_SIZE;
- __vmalloc_start = H_VMALLOC_START;
- __vmalloc_end = H_VMALLOC_END;
- vmemmap = (struct page *)H_VMEMMAP_BASE;
- ioremap_bot = IOREMAP_BASE;
-
/* Initialize the MMU Hash table and create the linear mapping
* of memory. Has to be done before SLB initialization as this is
* currently where the page size encoding is obtained.
@@ -325,12 +325,6 @@ void __init radix__early_init_mmu(void)
__pud_val_bits = RADIX_PUD_VAL_BITS;
__pgd_val_bits = RADIX_PGD_VAL_BITS;
- __kernel_virt_start = RADIX_KERN_VIRT_START;
- __kernel_virt_size = RADIX_KERN_VIRT_SIZE;
- __vmalloc_start = RADIX_VMALLOC_START;
- __vmalloc_end = RADIX_VMALLOC_END;
- vmemmap = (struct page *)RADIX_VMEMMAP_BASE;
- ioremap_bot = IOREMAP_BASE;
/*
* For now radix also use the same frag size
*/
@@ -94,24 +94,12 @@ unsigned long __pud_val_bits;
EXPORT_SYMBOL(__pud_val_bits);
unsigned long __pgd_val_bits;
EXPORT_SYMBOL(__pgd_val_bits);
-unsigned long __kernel_virt_start;
-EXPORT_SYMBOL(__kernel_virt_start);
-unsigned long __kernel_virt_size;
-EXPORT_SYMBOL(__kernel_virt_size);
-unsigned long __vmalloc_start;
-EXPORT_SYMBOL(__vmalloc_start);
-unsigned long __vmalloc_end;
-EXPORT_SYMBOL(__vmalloc_end);
-struct page *vmemmap;
-EXPORT_SYMBOL(vmemmap);
unsigned long __pte_frag_nr;
EXPORT_SYMBOL(__pte_frag_nr);
unsigned long __pte_frag_size_shift;
EXPORT_SYMBOL(__pte_frag_size_shift);
-unsigned long ioremap_bot;
-#else /* !CONFIG_PPC_BOOK3S_64 */
+#endif /* !CONFIG_PPC_BOOK3S_64 */
unsigned long ioremap_bot = IOREMAP_BASE;
-#endif
/**
* __ioremap_at - Low level function to establish the page tables
@@ -91,7 +91,7 @@ slb_miss_kernel_load_vmemmap:
* can be demoted from 64K -> 4K dynamically on some machines
*/
clrldi r11,r10,48
- cmpldi r11,(H_VMALLOC_SIZE >> 28) - 1
+ cmpldi r11,(VMALLOC_SIZE >> 28) - 1
bgt 5f
lhz r11,PACAVMALLOCSLLP(r13)
b 6f
@@ -14,6 +14,13 @@ config PPC_PASEMI
menu "PA Semi PWRficient options"
depends on PPC_PASEMI
+config PPC_PASEMI_SB600
+ bool "Nemo SB600 South Bridge Support"
+ depends on PPC_PASEMI
+ select PPC_I8259
+ help
+ Workarounds for the SB600 South Bridge.
+
config PPC_PASEMI_IOMMU
bool "PA Semi IOMMU support"
depends on PPC_PASEMI
@@ -1,3 +1,9 @@
+/* This is a modified copy of
+* usr/src/linux-2.6.39.4/arch/powerpc/platforms/pasemi/iommu.c
+* The mod is on line 150
+* By Len Karpowicz <twotat2z@embarqmail.com
+*/
+
/*
* Copyright (C) 2005-2008, PA Semi, Inc
*
@@ -147,8 +153,11 @@ static void iommu_table_iobmap_setup(void)
iommu_table_iobmap.it_page_shift = IOBMAP_PAGE_SHIFT;
/* it_size is in number of entries */
- iommu_table_iobmap.it_size =
- 0x80000000 >> iommu_table_iobmap.it_page_shift;
+
+/* Note: changed 0x80000000 to 0x7FFFFFFF for SBLive! SB0220 */
+/* out of range problem on A-EON AmigaOne X1000 */
+ iommu_table_iobmap.it_size = 0x7FFFFFFF >> IOBMAP_PAGE_SHIFT;
+
/* Initialize the common IOMMU code */
iommu_table_iobmap.it_base = (unsigned long)iob_l2_base;
@@ -108,6 +108,69 @@ static int workaround_5945(struct pci_bus *bus, unsigned int devfn,
return 1;
}
+#ifdef CONFIG_PPC_PASEMI_SB600
+static int sb600_bus = 5;
+static void __iomem *iob_mapbase = NULL;
+
+static int pa_pxp_read_config(struct pci_bus *bus, unsigned int devfn,
+ int offset, int len, u32 *val);
+
+static void sb600_set_flag(int bus)
+{
+ struct resource res;
+ struct device_node *dn;
+ struct pci_bus *busp;
+ u32 val;
+ int err;
+
+ if (sb600_bus == -1)
+ {
+ busp = pci_find_bus(0, 0);
+ pa_pxp_read_config(busp, PCI_DEVFN(17,0), PCI_SECONDARY_BUS, 1, &val);
+
+ sb600_bus = val;
+
+ printk(KERN_CRIT "NEMO SB600 on bus %d.\n",sb600_bus);
+ }
+
+ if (iob_mapbase == NULL)
+ {
+ dn = of_find_compatible_node(NULL, "io-bridge", "pasemi,1682m-iob");
+ if (!dn)
+ {
+ printk(KERN_CRIT "NEMO SB600 missing iob node\n");
+ return;
+ }
+
+ err = of_address_to_resource(dn, 0, &res);
+ of_node_put(dn);
+
+ if (err)
+ {
+ printk(KERN_CRIT "NEMO SB600 missing resource\n");
+ return;
+ }
+
+ printk(KERN_CRIT "NEMO SB600 IOB base %08lx\n",res.start);
+
+ iob_mapbase = ioremap(res.start + 0x100, 0x94);
+ }
+
+ if (iob_mapbase != NULL)
+ {
+ if (bus == sb600_bus)
+ {
+ out_le32(iob_mapbase + 4, in_le32(iob_mapbase + 4) | 0x800);
+ }
+ else
+ {
+ out_le32(iob_mapbase + 4, in_le32(iob_mapbase + 4) & ~0x800);
+ }
+ }
+}
+#endif
+
+
static int pa_pxp_read_config(struct pci_bus *bus, unsigned int devfn,
int offset, int len, u32 *val)
{
@@ -126,6 +189,10 @@ static int pa_pxp_read_config(struct pci_bus *bus, unsigned int devfn,
addr = pa_pxp_cfg_addr(hose, bus->number, devfn, offset);
+#ifdef CONFIG_PPC_PASEMI_SB600
+ sb600_set_flag(bus->number);
+#endif
+
/*
* Note: the caller has already checked that offset is
* suitably aligned and that len is 1, 2 or 4.
@@ -34,6 +34,7 @@
#include <asm/prom.h>
#include <asm/iommu.h>
#include <asm/machdep.h>
+#include <asm/i8259.h>
#include <asm/mpic.h>
#include <asm/smp.h>
#include <asm/time.h>
@@ -72,6 +73,17 @@ static void pas_restart(char *cmd)
out_le32(reset_reg, 0x6000000);
}
+#ifdef CONFIG_PPC_PASEMI_SB600
+void pas_shutdown(void)
+{
+ /* (added by DStevens 19/06/13)
+ Set the PLD bit that makes the SB600 think the power button is being pressed */
+ void __iomem *pld_map = ioremap(0xf5000000,4096);
+ while (1)
+ out_8(pld_map+7,0x01);
+}
+#endif
+
#ifdef CONFIG_SMP
static arch_spinlock_t timebase_lock;
static unsigned long timebase;
@@ -183,6 +195,56 @@ static int __init pas_setup_mce_regs(void)
}
machine_device_initcall(pasemi, pas_setup_mce_regs);
+#ifdef CONFIG_PPC_PASEMI_SB600
+static unsigned sb600_irq_to_vector(int irq)
+{
+ switch(irq) {
+ case 3: return 216;
+ case 4: return 217;
+ case 5: return 218;
+ case 6: return 219;
+ case 7: return 220;
+ case 8: return 222;
+ case 9: return 212;
+ case 10: return 213;
+ case 11: return 214;
+ case 12: return 215;
+ case 14: return 221;
+ default: return 0;
+ }
+}
+
+static void sb600_8259_cascade(struct irq_desc *desc)
+{
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+ unsigned int cascade_irq = i8259_irq();
+ unsigned vector = sb600_irq_to_vector(cascade_irq);
+ if (vector > 0)
+ generic_handle_irq(vector);
+ outb(0x20, 0xA0); /* Non-specific EOI */
+ outb(0x20, 0x20); /* Non-specific EOI to cascade */
+ chip->irq_eoi(&desc->irq_data);
+}
+extern void i8259_unmask_irq(struct irq_data *d);
+
+__init void sb600_8259_init(void)
+{
+ int gpio_virq;
+
+ // Connect legacy i8259 controller in SB600
+ printk("Init i8259\n");
+ i8259_init(NULL, 0);
+
+ gpio_virq = irq_create_mapping(NULL, 3);
+ irq_set_irq_type(gpio_virq, IRQ_TYPE_LEVEL_HIGH);
+ irq_set_chained_handler(gpio_virq, sb600_8259_cascade);
+ mpic_unmask_irq(irq_get_irq_data(gpio_virq));
+
+ // Initial mapping for RTC
+ irq_create_mapping(NULL, 222);
+}
+#endif
+
static __init void pas_init_IRQ(void)
{
struct device_node *np;
@@ -246,6 +308,12 @@ static __init void pas_init_IRQ(void)
of_node_put(mpic_node);
of_node_put(root);
+
+
+#ifdef CONFIG_PPC_PASEMI_SB600
+ sb600_8259_init();
+#endif
+
}
static void __init pas_progress(char *s, unsigned short hex)
@@ -403,12 +471,39 @@ static const struct of_device_id pasemi_bus_ids[] = {
{},
};
-static int __init pasemi_publish_devices(void)
-{
- pasemi_pcmcia_init();
+#ifdef CONFIG_PPC_PASEMI_SB600
+
+/*
+ This should come from OF tree. See sysdev/rtc_cmos_setup for details. Need to get i8259 supported correctly first, so that
+ as the standard support hard-codes IRQ 8.
+ */
+
+
+static struct resource rtc_resource[] = {{
+ .name = "rtc",
+ .start = 0x70,
+ .end = 0x71,
+ .flags = IORESOURCE_IO,
+}, {
+ .name = "rtc",
+ .start = 222,
+ .end = 222,
+ .flags = IORESOURCE_IRQ,
+}};
- /* Publish OF platform devices for SDC and other non-PCI devices */
- of_platform_bus_probe(NULL, pasemi_bus_ids, NULL);
+#endif
+
+
+ static int __init pasemi_publish_devices(void)
+ {
+ pasemi_pcmcia_init();
+
+ /* Publish OF platform devices for SDC and other non-PCI devices */
+ of_platform_bus_probe(NULL, pasemi_bus_ids, NULL);
+
+#ifdef CONFIG_PPC_PASEMI_SB600
+ platform_device_register_simple("rtc_cmos", -1, rtc_resource, 2);
+#endif
return 0;
}
@@ -430,9 +525,13 @@ static int __init pas_probe(void)
alloc_iobmap_l2();
+#ifdef CONFIG_PPC_PASEMI_SB600
+ pm_power_off = pas_shutdown; // Varisys provided a way to turn us off
+#endif
return 1;
}
+
define_machine(pasemi) {
.name = "PA Semi PWRficient",
.probe = pas_probe,
@@ -445,4 +544,7 @@ define_machine(pasemi) {
.calibrate_decr = generic_calibrate_decr,
.progress = pas_progress,
.machine_check_exception = pas_machine_check_handler,
+#if 0 // def CONFIG_PPC_PASEMI_SB600
+ .pci_probe_mode = sb600_pci_probe_mode,
+#endif
};
@@ -103,11 +103,11 @@ static void i8259_set_irq_mask(int irq_nr)
outb(cached_21,0x21);
}
-static void i8259_mask_irq(struct irq_data *d)
+void i8259_mask_irq(struct irq_data *d)
{
unsigned long flags;
- pr_debug("i8259_mask_irq(%d)\n", d->irq);
+ printk("i8259_mask_irq(%d)\n", d->irq);
raw_spin_lock_irqsave(&i8259_lock, flags);
if (d->irq < 8)
@@ -118,11 +118,11 @@ static void i8259_mask_irq(struct irq_data *d)
raw_spin_unlock_irqrestore(&i8259_lock, flags);
}
-static void i8259_unmask_irq(struct irq_data *d)
+void i8259_unmask_irq(struct irq_data *d)
{
unsigned long flags;
- pr_debug("i8259_unmask_irq(%d)\n", d->irq);
+ printk("i8259_unmask_irq(%d)\n", d->irq);
raw_spin_lock_irqsave(&i8259_lock, flags);
if (d->irq < 8)
@@ -231,6 +231,8 @@ void i8259_init(struct device_node *node, unsigned long intack_addr)
/* initialize the controller */
raw_spin_lock_irqsave(&i8259_lock, flags);
+ printk("About to write to i8259\n");
+
/* Mask all first */
outb(0xff, 0xA1);
outb(0xff, 0x21);
@@ -261,8 +263,12 @@ void i8259_init(struct device_node *node, unsigned long intack_addr)
outb(cached_A1, 0xA1);
outb(cached_21, 0x21);
+ printk("Done write to i8259\n");
+
raw_spin_unlock_irqrestore(&i8259_lock, flags);
+#ifndef CONFIG_PPC_PASEMI_SB600
+
/* create a legacy host */
i8259_host = irq_domain_add_legacy_isa(node, &i8259_host_ops, NULL);
if (i8259_host == NULL) {
@@ -270,6 +276,8 @@ void i8259_init(struct device_node *node, unsigned long intack_addr)
return;
}
+#endif
+
/* reserve our resources */
/* XXX should we continue doing that ? it seems to cause problems
* with further requesting of PCI IO resources for that range...
@@ -661,6 +661,56 @@ static inline void mpic_eoi(struct mpic *mpic)
* Linux descriptor level callbacks
*/
+#ifdef CONFIG_PPC_PASEMI_SB600
+
+static int sb600_vector_to_irq(unsigned vector)
+{
+ switch(vector) {
+ case 212: return 9;
+ case 213: return 10;
+ case 214: return 11;
+ case 215: return 12;
+ case 216: return 3;
+ case 217: return 4;
+ case 218: return 5;
+ case 219: return 6;
+ case 220: return 7;
+ case 221: return 14;
+ case 222: return 8;
+ default: return -1;
+ }
+}
+
+extern void i8259_mask_irq(struct irq_data *d);
+extern void i8259_unmask_irq(struct irq_data *d);
+
+int sb600_unmask_irq(unsigned irq)
+{
+ int vector = sb600_vector_to_irq(irq);
+ if (vector >= 0) {
+ i8259_unmask_irq(irq_get_irq_data(vector));
+ return 1;
+ } else
+ return 0;
+}
+
+int sb600_mask_irq(unsigned irq)
+{
+ int vector = sb600_vector_to_irq(irq);
+ if (vector >= 0) {
+ i8259_mask_irq(irq_get_irq_data(vector));
+ return 1;
+ } else
+ return 0;
+}
+
+int sb600_end_irq(unsigned irq)
+{
+ int vector = sb600_vector_to_irq(irq);
+ return (vector >= 0);
+}
+
+#endif
void mpic_unmask_irq(struct irq_data *d)
{
@@ -668,7 +718,12 @@ void mpic_unmask_irq(struct irq_data *d)
struct mpic *mpic = mpic_from_irq_data(d);
unsigned int src = irqd_to_hwirq(d);
- DBG("%p: %s: enable_irq: %d (src %d)\n", mpic, mpic->name, d->irq, src);
+#ifdef CONFIG_PPC_PASEMI_SB600
+ if (sb600_unmask_irq(src))
+ return;
+#endif
+
+ DBG("%p: %s: enable_irq: %d (src %d)\n", mpic, mpic->name, irq, src);
mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI),
mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) &
@@ -689,7 +744,12 @@ void mpic_mask_irq(struct irq_data *d)
struct mpic *mpic = mpic_from_irq_data(d);
unsigned int src = irqd_to_hwirq(d);
- DBG("%s: disable_irq: %d (src %d)\n", mpic->name, d->irq, src);
+#ifdef CONFIG_PPC_PASEMI_SB600
+ if (sb600_mask_irq(src))
+ return;
+#endif
+
+ DBG("%s: disable_irq: %d (src %d)\n", mpic->name, irq, src);
mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI),
mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) |
@@ -709,6 +769,14 @@ void mpic_end_irq(struct irq_data *d)
{
struct mpic *mpic = mpic_from_irq_data(d);
+#ifdef CONFIG_PPC_PASEMI_SB600
+ unsigned int src = irqd_to_hwirq(d);
+
+ if (src >= 212 && src <= 222)
+ return;
+#endif
+
+
#ifdef DEBUG_IRQ
DBG("%s: end_irq: %d\n", mpic->name, d->irq);
#endif
@@ -2429,9 +2429,9 @@ int ata_pci_sff_activate_host(struct ata_host *host,
if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) {
u8 tmp8, mask;
- /* TODO: What if one channel is in native mode ... */
+ /* Don't look at dummy ports in the mask */
pci_read_config_byte(pdev, PCI_CLASS_PROG, &tmp8);
- mask = (1 << 2) | (1 << 0);
+ mask = (! ata_port_is_dummy(host->ports[1]) << 2) | (! ata_port_is_dummy(host->ports[0]) << 0);
if ((tmp8 & mask) != mask)
legacy_mode = 1;
}
@@ -278,6 +278,11 @@ static int atiixp_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
};
const struct ata_port_info *ppi[] = { &info, &info };
+#ifdef CONFIG_PPC_PASEMI_SB600
+ // Second port not wired on SB600, and config bit cannot be set by BIOS
+ ppi[1] = &ata_dummy_port_info;
+#endif
+
return ata_pci_bmdma_init_one(pdev, ppi, &atiixp_sht, NULL,
ATA_HOST_PARALLEL_SCAN);
}
@@ -41,14 +41,36 @@ static int pata_of_platform_probe(struct platform_device *ofdev)
return -EINVAL;
}
- ret = of_address_to_resource(dn, 1, &ctl_res);
- if (ret) {
- dev_err(&ofdev->dev, "can't get CTL address from "
- "device tree\n");
- return -EINVAL;
+ if (of_device_is_compatible(dn, "electra-ide")) {
+ /* Altstatus is really at offset 0x3f6 from the primary window
+ * on electra-ide. Adjust ctl_res and io_res accordingly.
+ */
+ ctl_res = io_res;
+ ctl_res.start = ctl_res.start+0x3f6;
+ io_res.end = ctl_res.start-1;
+
+#ifdef CONFIG_PPC_PASEMI_SB600
+ } else if (of_device_is_compatible(dn, "electra-cf")) {
+ /* Task regs are at 0x800, with alt status @ 0x80e in the primary window
+ * on electra-cf. Adjust ctl_res and io_res accordingly.
+ */
+ ctl_res = io_res;
+ io_res.start += 0x800;
+ ctl_res.start = ctl_res.start + 0x80e;
+ io_res.end = ctl_res.start-1;
+#endif
+ } else {
+ ret = of_address_to_resource(dn, 1, &ctl_res);
+ if (ret) {
+ dev_err(&ofdev->dev, "can't get CTL address from "
+ "device tree\n");
+ return -EINVAL;
+ }
}
irq_res = platform_get_resource(ofdev, IORESOURCE_IRQ, 0);
+ if (irq_res)
+ irq_res->flags = 0;
prop = of_get_property(dn, "reg-shift", NULL);
if (prop)
@@ -65,6 +87,11 @@ static int pata_of_platform_probe(struct platform_device *ofdev)
dev_info(&ofdev->dev, "pio-mode unspecified, assuming PIO0\n");
}
+#ifdef CONFIG_PPC_PASEMI_SB600
+ irq_res = 0; // force irq off (doesn't seem to work)
+#endif
+
+
pio_mask = 1 << pio_mode;
pio_mask |= (1 << pio_mode) - 1;
@@ -74,7 +101,11 @@ static int pata_of_platform_probe(struct platform_device *ofdev)
static struct of_device_id pata_of_platform_match[] = {
{ .compatible = "ata-generic", },
- { },
+ { .compatible = "electra-ide", },
+#ifdef CONFIG_PPC_PASEMI_SB600
+ { .compatible = "electra-cf",},
+#endif
+ {},
};
MODULE_DEVICE_TABLE(of, pata_of_platform_match);
@@ -226,7 +226,10 @@ static void radeon_set_power_state(struct radeon_device *rdev)
/* set memory clock */
if (rdev->asic->pm.set_memory_clock && (mclk != rdev->pm.current_mclk)) {
radeon_pm_debug_check_in_vbl(rdev, false);
+ /* D.Stevens 2012 for the A-EON AmigaOne X1000: Setting memory clock only works on CAICOS and 6570, don't set for anything else (We ignore 6570 here */
+ if (rdev->family == CHIP_CAICOS) {
radeon_set_memory_clock(rdev, mclk);
+ }
radeon_pm_debug_check_in_vbl(rdev, true);
rdev->pm.current_mclk = mclk;
DRM_DEBUG_DRIVER("Setting: m: %d\n", mclk);
@@ -1223,7 +1226,7 @@ static void radeon_pm_resume_old(struct radeon_device *rdev)
SET_VOLTAGE_TYPE_ASIC_VDDCI);
if (rdev->pm.default_sclk)
radeon_set_engine_clock(rdev, rdev->pm.default_sclk);
- if (rdev->pm.default_mclk)
+ if (rdev->pm.default_mclk && (rdev->family == CHIP_CAICOS)) /* Fix for PPC systems HD6000 >6570 by A-EON Core Linux Support Team */
radeon_set_memory_clock(rdev, rdev->pm.default_mclk);
}
/* asic init will reset the default power state */
@@ -1274,7 +1277,7 @@ dpm_resume_fail:
SET_VOLTAGE_TYPE_ASIC_VDDCI);
if (rdev->pm.default_sclk)
radeon_set_engine_clock(rdev, rdev->pm.default_sclk);
- if (rdev->pm.default_mclk)
+ if (rdev->pm.default_mclk && (rdev->family == CHIP_CAICOS)) /* Fix for PPC & > HD6570 by A-EON Linux Core Support Team */
radeon_set_memory_clock(rdev, rdev->pm.default_mclk);
}
}
@@ -1321,7 +1324,7 @@ static int radeon_pm_init_old(struct radeon_device *rdev)
SET_VOLTAGE_TYPE_ASIC_VDDCI);
if (rdev->pm.default_sclk)
radeon_set_engine_clock(rdev, rdev->pm.default_sclk);
- if (rdev->pm.default_mclk)
+ if (rdev->pm.default_mclk && (rdev->family == CHIP_CAICOS)) // D.Stevens 2013: fix for >HD6570 on PPC
radeon_set_memory_clock(rdev, rdev->pm.default_mclk);
}
}
@@ -1412,7 +1415,7 @@ dpm_failed:
SET_VOLTAGE_TYPE_ASIC_VDDCI);
if (rdev->pm.default_sclk)
radeon_set_engine_clock(rdev, rdev->pm.default_sclk);
- if (rdev->pm.default_mclk)
+ if (rdev->pm.default_mclk && (rdev->family == CHIP_CAICOS)) // D.Stevens 2013: Fix for >HD6570 on ppc
radeon_set_memory_clock(rdev, rdev->pm.default_mclk);
}
DRM_ERROR("radeon: dpm initialization failed\n");
@@ -432,7 +432,16 @@ struct resource *pci_find_parent_resource(const struct pci_dev *dev,
pci_bus_for_each_resource(bus, r, i) {
if (!r)
continue;
+#ifdef CONFIG_PPC_PASEMI_SB600
+ /* The new code here checks for resources that are not allocated, and no longer
+ * returns these, however the SB600 code uses this feature to allocate IO ranges
+ * in the ISA map, and this breaks booting on the AmigaOneX1000.
+ * Temporary fix to get the kernel working, remove the resource allocated check.
+ */
+ if (resource_contains(r, res)) {
+#else
if (res->start && resource_contains(r, res)) {
+#endif
/*
* If the window is prefetchable but the BAR is
@@ -368,7 +368,11 @@ static void pci_read_bridge_io(struct pci_bus *child)
limit |= ((unsigned long) io_limit_hi << 16);
}
- if (base <= limit) {
+ if (base <= limit
+ #ifdef CONFIG_PPC_PASEMI_SB600
+ || child->busn_res.start == 5
+ #endif
+ ) {
res->flags = (io_base_lo & PCI_IO_RANGE_TYPE_MASK) | IORESOURCE_IO;
region.start = base;
region.end = limit + io_granularity - 1;
@@ -1836,6 +1840,8 @@ static int only_one_child(struct pci_bus *bus)
if (!parent || !pci_is_pcie(parent))
return 0;
+ #ifndef CONFIG_PPC_PASEMI_SB600
+ // SB600 has non-zero devices on non-root bus.
if (pci_pcie_type(parent) == PCI_EXP_TYPE_ROOT_PORT)
return 1;
@@ -1848,6 +1854,7 @@ static int only_one_child(struct pci_bus *bus)
if (parent->has_secondary_link &&
!pci_has_flag(PCI_SCAN_ALL_PCIE_DEVS))
return 1;
+ #endif
return 0;
}
@@ -242,6 +242,13 @@ static int cmos_read_alarm(struct device *dev, struct rtc_wkalrm *t)
}
rtc_control = CMOS_READ(RTC_CONTROL);
+
+#ifdef CONFIG_PPC_PASEMI_SB600
+ // Nemo BIOS does not init RTC
+ rtc_control = rtc_control | RTC_24H;
+ CMOS_WRITE(rtc_control, RTC_CONTROL);
+#endif
+
spin_unlock_irq(&rtc_lock);
if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
@@ -166,6 +166,7 @@ enum {
STAC_D965_VERBS,
STAC_DELL_3ST,
STAC_DELL_BIOS,
+ STAC_NEMO_DEFAULT,
STAC_DELL_BIOS_AMIC,
STAC_DELL_BIOS_SPDIF,
STAC_927X_DELL_DMIC,
@@ -1360,6 +1361,23 @@ static const struct hda_pintbl oqo9200_pin_configs[] = {
{}
};
+static const struct hda_pintbl nemo_pin_configs[] = {
+ { 0x0a, 0x02214020 },
+ { 0x0b, 0x02A19080 },
+ { 0x0c, 0x0181304E },
+ { 0x0d, 0x01014010 },
+ { 0x0e, 0x01A19040 },
+ { 0x0f, 0x01011012 },
+ { 0x10, 0x01016011 },
+ { 0x11, 0x01012014 },
+ { 0x12, 0x103301F0 },
+ { 0x13, 0x00000000 },
+ { 0x14, 0x00000000 },
+ { 0x21, 0x01442170 },
+ { 0x22, 0x00000000 },
+ { 0x23, 0x00000000 },
+ {}
+};
static void stac9200_fixup_panasonic(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
@@ -3883,6 +3901,10 @@ static const struct hda_fixup stac927x_fixups[] = {
.type = HDA_FIXUP_PINS,
.v.pins = d965_5st_no_fp_pin_configs,
},
+ [STAC_NEMO_DEFAULT] = {
+ .type = HDA_FIXUP_PINS,
+ .v.pins = nemo_pin_configs,
+ },
[STAC_DELL_3ST] = {
.type = HDA_FIXUP_PINS,
.v.pins = dell_3st_pin_configs,
@@ -3939,6 +3961,7 @@ static const struct hda_model_fixup stac927x_models[] = {
{ .id = STAC_D965_5ST_NO_FP, .name = "5stack-no-fp" },
{ .id = STAC_DELL_3ST, .name = "dell-3stack" },
{ .id = STAC_DELL_BIOS, .name = "dell-bios" },
+ { .id = STAC_NEMO_DEFAULT, .name = "nemo-default" },
{ .id = STAC_DELL_BIOS_AMIC, .name = "dell-bios-amic" },
{ .id = STAC_927X_VOLKNOB, .name = "volknob" },
{}
@@ -3977,6 +4000,8 @@ static const struct snd_pci_quirk stac927x_fixup_tbl[] = {
"Intel D965", STAC_D965_5ST),
SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_INTEL, 0xff00, 0x2500,
"Intel D965", STAC_D965_5ST),
+ /* Nemo */
+ SND_PCI_QUIRK(0x1888, 0x1000, "AmigaOne X1000", STAC_NEMO_DEFAULT),
/* volume-knob fixes */
SND_PCI_QUIRK_VENDOR(0x10cf, "FSC", STAC_927X_VOLKNOB),
{} /* terminator */
@@ -5036,6 +5061,7 @@ static const struct hda_device_id snd_hda_id_sigmatel[] = {
HDA_CODEC_ENTRY(0x83847683, "STAC9221D A2", patch_stac922x),
HDA_CODEC_ENTRY(0x83847618, "STAC9227", patch_stac927x),
HDA_CODEC_ENTRY(0x83847619, "STAC9227", patch_stac927x),
+ HDA_CODEC_ENTRY(0x83847638, "STAC92HD700", patch_stac927x),
HDA_CODEC_ENTRY(0x83847616, "STAC9228", patch_stac927x),
HDA_CODEC_ENTRY(0x83847617, "STAC9228", patch_stac927x),
HDA_CODEC_ENTRY(0x83847614, "STAC9229", patch_stac927x),