Merge branch 'for-2.6.22' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc

* 'for-2.6.22' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc: (255 commits)
  [POWERPC] Remove dev_dbg redefinition in drivers/ps3/vuart.c
  [POWERPC] remove kernel module option for booke wdt
  [POWERPC] Avoid putting cpu node twice
  [POWERPC] Spinlock initializer cleanup
  [POWERPC] ppc4xx_sgdma needs dma-mapping.h
  [POWERPC] arch/powerpc/sysdev/timer.c build fix
  [POWERPC] get_property cleanups
  [POWERPC] Remove the unused HTDMSOUND driver
  [POWERPC] cell: cbe_cpufreq cleanup and crash fix
  [POWERPC] Declare enable_kernel_spe in a header
  [POWERPC] Add dt_xlate_addr() to bootwrapper
  [POWERPC] bootwrapper: CONFIG_ -> CONFIG_DEVICE_TREE
  [POWERPC] Don't define a custom bd_t for Xilixn Virtex based boards.
  [POWERPC] Add sane defaults for Xilinx EDK generated xparameters files
  [POWERPC] Add uartlite boot console driver for the zImage wrapper
  [POWERPC] Stop using ppc_sys for Xilinx Virtex boards
  [POWERPC] New registration for common Xilinx Virtex ppc405 platform devices
  [POWERPC] Merge common virtex header files
  [POWERPC] Rework Kconfig dependancies for Xilinx Virtex ppc405 platform
  [POWERPC] Clean up cpufreq Kconfig dependencies
  ...
This commit is contained in:
Linus Torvalds
2007-04-30 08:10:12 -07:00
376 changed files with 11566 additions and 7912 deletions

View File

@ -11,12 +11,17 @@ obj-$(CONFIG_PPC_PMI) += pmi.o
obj-$(CONFIG_U3_DART) += dart_iommu.o
obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o
obj-$(CONFIG_FSL_SOC) += fsl_soc.o
obj-$(CONFIG_FSL_PCIE) += fsl_pcie.o
obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o
obj-$(CONFIG_QUICC_ENGINE) += qe_lib/
# contains only the suspend handler for time
obj-$(CONFIG_PM) += timer.o
ifeq ($(CONFIG_PPC_MERGE),y)
obj-$(CONFIG_PPC_I8259) += i8259.o
obj-$(CONFIG_PPC_83xx) += ipic.o
obj-$(CONFIG_4xx) += uic.o
endif
# Temporary hack until we have migrated to asm-powerpc

View File

@ -333,7 +333,7 @@ void iommu_init_early_dart(void)
ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_dart;
/* Setup pci_dma ops */
pci_dma_ops = &dma_iommu_ops;
set_pci_dma_ops(&dma_iommu_ops);
return;
}
@ -343,7 +343,7 @@ void iommu_init_early_dart(void)
ppc_md.pci_dma_bus_setup = NULL;
/* Setup pci_dma ops */
pci_dma_ops = &dma_direct_ops;
set_pci_dma_ops(&dma_direct_ops);
}

View File

@ -26,7 +26,7 @@
unsigned int dcr_resource_start(struct device_node *np, unsigned int index)
{
unsigned int ds;
const u32 *dr = get_property(np, "dcr-reg", &ds);
const u32 *dr = of_get_property(np, "dcr-reg", &ds);
if (dr == NULL || ds & 1 || index >= (ds / 8))
return 0;
@ -37,7 +37,7 @@ unsigned int dcr_resource_start(struct device_node *np, unsigned int index)
unsigned int dcr_resource_len(struct device_node *np, unsigned int index)
{
unsigned int ds;
const u32 *dr = get_property(np, "dcr-reg", &ds);
const u32 *dr = of_get_property(np, "dcr-reg", &ds);
if (dr == NULL || ds & 1 || index >= (ds / 8))
return 0;
@ -53,9 +53,9 @@ static struct device_node * find_dcr_parent(struct device_node * node)
const u32 *p;
for (par = of_node_get(node); par;) {
if (get_property(par, "dcr-controller", NULL))
if (of_get_property(par, "dcr-controller", NULL))
break;
p = get_property(par, "dcr-parent", NULL);
p = of_get_property(par, "dcr-parent", NULL);
tmp = par;
if (p == NULL)
par = of_get_parent(par);
@ -80,13 +80,13 @@ u64 of_translate_dcr_address(struct device_node *dev,
return OF_BAD_ADDR;
/* Stride is not properly defined yet, default to 0x10 for Axon */
p = get_property(dp, "dcr-mmio-stride", NULL);
p = of_get_property(dp, "dcr-mmio-stride", NULL);
stride = (p == NULL) ? 0x10 : *p;
/* XXX FIXME: Which property name is to use of the 2 following ? */
p = get_property(dp, "dcr-mmio-range", NULL);
p = of_get_property(dp, "dcr-mmio-range", NULL);
if (p == NULL)
p = get_property(dp, "dcr-mmio-space", NULL);
p = of_get_property(dp, "dcr-mmio-space", NULL);
if (p == NULL)
return OF_BAD_ADDR;

View File

@ -0,0 +1,171 @@
/*
* Support for indirect PCI bridges.
*
* Copyright (C) 1998 Gabriel Paubert.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
* "Temporary" MPC8548 Errata file -
* The standard indirect_pci code should work with future silicon versions.
*/
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/string.h>
#include <linux/init.h>
#include <linux/bootmem.h>
#include <asm/io.h>
#include <asm/prom.h>
#include <asm/pci-bridge.h>
#include <asm/machdep.h>
#define PCI_CFG_OUT out_be32
/* ERRATA PCI-Ex 14 PCIE Controller timeout */
#define PCIE_FIX out_be32(hose->cfg_addr+0x4, 0x0400ffff)
static int
indirect_read_config_pcie(struct pci_bus *bus, unsigned int devfn, int offset,
int len, u32 *val)
{
struct pci_controller *hose = bus->sysdata;
volatile void __iomem *cfg_data;
u32 temp;
if (ppc_md.pci_exclude_device)
if (ppc_md.pci_exclude_device(bus->number, devfn))
return PCIBIOS_DEVICE_NOT_FOUND;
/* Possible artifact of CDCpp50937 needs further investigation */
if (devfn != 0x0 && bus->number == 0xff)
return PCIBIOS_DEVICE_NOT_FOUND;
PCIE_FIX;
if (bus->number == 0xff) {
PCI_CFG_OUT(hose->cfg_addr,
(0x80000000 | ((offset & 0xf00) << 16) |
((bus->number - hose->bus_offset) << 16)
| (devfn << 8) | ((offset & 0xfc) )));
} else {
PCI_CFG_OUT(hose->cfg_addr,
(0x80000001 | ((offset & 0xf00) << 16) |
((bus->number - hose->bus_offset) << 16)
| (devfn << 8) | ((offset & 0xfc) )));
}
/*
* Note: the caller has already checked that offset is
* suitably aligned and that len is 1, 2 or 4.
*/
/* ERRATA PCI-Ex 12 - Configuration Address/Data Alignment */
cfg_data = hose->cfg_data;
PCIE_FIX;
temp = in_le32(cfg_data);
switch (len) {
case 1:
*val = (temp >> (((offset & 3))*8)) & 0xff;
break;
case 2:
*val = (temp >> (((offset & 3))*8)) & 0xffff;
break;
default:
*val = temp;
break;
}
return PCIBIOS_SUCCESSFUL;
}
static int
indirect_write_config_pcie(struct pci_bus *bus, unsigned int devfn, int offset,
int len, u32 val)
{
struct pci_controller *hose = bus->sysdata;
volatile void __iomem *cfg_data;
u32 temp;
if (ppc_md.pci_exclude_device)
if (ppc_md.pci_exclude_device(bus->number, devfn))
return PCIBIOS_DEVICE_NOT_FOUND;
/* Possible artifact of CDCpp50937 needs further investigation */
if (devfn != 0x0 && bus->number == 0xff)
return PCIBIOS_DEVICE_NOT_FOUND;
PCIE_FIX;
if (bus->number == 0xff) {
PCI_CFG_OUT(hose->cfg_addr,
(0x80000000 | ((offset & 0xf00) << 16) |
((bus->number - hose->bus_offset) << 16)
| (devfn << 8) | ((offset & 0xfc) )));
} else {
PCI_CFG_OUT(hose->cfg_addr,
(0x80000001 | ((offset & 0xf00) << 16) |
((bus->number - hose->bus_offset) << 16)
| (devfn << 8) | ((offset & 0xfc) )));
}
/*
* Note: the caller has already checked that offset is
* suitably aligned and that len is 1, 2 or 4.
*/
/* ERRATA PCI-Ex 12 - Configuration Address/Data Alignment */
cfg_data = hose->cfg_data;
switch (len) {
case 1:
PCIE_FIX;
temp = in_le32(cfg_data);
temp = (temp & ~(0xff << ((offset & 3) * 8))) |
(val << ((offset & 3) * 8));
PCIE_FIX;
out_le32(cfg_data, temp);
break;
case 2:
PCIE_FIX;
temp = in_le32(cfg_data);
temp = (temp & ~(0xffff << ((offset & 3) * 8)));
temp |= (val << ((offset & 3) * 8)) ;
PCIE_FIX;
out_le32(cfg_data, temp);
break;
default:
PCIE_FIX;
out_le32(cfg_data, val);
break;
}
PCIE_FIX;
return PCIBIOS_SUCCESSFUL;
}
static struct pci_ops indirect_pcie_ops = {
indirect_read_config_pcie,
indirect_write_config_pcie
};
void __init
setup_indirect_pcie_nomap(struct pci_controller* hose, void __iomem * cfg_addr,
void __iomem * cfg_data)
{
hose->cfg_addr = cfg_addr;
hose->cfg_data = cfg_data;
hose->ops = &indirect_pcie_ops;
}
void __init
setup_indirect_pcie(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data)
{
unsigned long base = cfg_addr & PAGE_MASK;
void __iomem *mbase, *addr, *data;
mbase = ioremap(base, PAGE_SIZE);
addr = mbase + (cfg_addr & ~PAGE_MASK);
if ((cfg_data & PAGE_MASK) != base)
mbase = ioremap(cfg_data & PAGE_MASK, PAGE_SIZE);
data = mbase + (cfg_data & ~PAGE_MASK);
setup_indirect_pcie_nomap(hose, addr, data);
}

View File

@ -0,0 +1,94 @@
/*
* MPC85xx/86xx PCI Express structure define
*
* Copyright 2007 Freescale Semiconductor, Inc
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
*/
#ifdef __KERNEL__
#ifndef __POWERPC_FSL_PCIE_H
#define __POWERPC_FSL_PCIE_H
/* PCIE Express IO block registers in 85xx/86xx */
struct ccsr_pex {
__be32 __iomem pex_config_addr; /* 0x.000 - PCI Express Configuration Address Register */
__be32 __iomem pex_config_data; /* 0x.004 - PCI Express Configuration Data Register */
u8 __iomem res1[4];
__be32 __iomem pex_otb_cpl_tor; /* 0x.00c - PCI Express Outbound completion timeout register */
__be32 __iomem pex_conf_tor; /* 0x.010 - PCI Express configuration timeout register */
u8 __iomem res2[12];
__be32 __iomem pex_pme_mes_dr; /* 0x.020 - PCI Express PME and message detect register */
__be32 __iomem pex_pme_mes_disr; /* 0x.024 - PCI Express PME and message disable register */
__be32 __iomem pex_pme_mes_ier; /* 0x.028 - PCI Express PME and message interrupt enable register */
__be32 __iomem pex_pmcr; /* 0x.02c - PCI Express power management command register */
u8 __iomem res3[3024];
__be32 __iomem pexotar0; /* 0x.c00 - PCI Express outbound translation address register 0 */
__be32 __iomem pexotear0; /* 0x.c04 - PCI Express outbound translation extended address register 0*/
u8 __iomem res4[8];
__be32 __iomem pexowar0; /* 0x.c10 - PCI Express outbound window attributes register 0*/
u8 __iomem res5[12];
__be32 __iomem pexotar1; /* 0x.c20 - PCI Express outbound translation address register 1 */
__be32 __iomem pexotear1; /* 0x.c24 - PCI Express outbound translation extended address register 1*/
__be32 __iomem pexowbar1; /* 0x.c28 - PCI Express outbound window base address register 1*/
u8 __iomem res6[4];
__be32 __iomem pexowar1; /* 0x.c30 - PCI Express outbound window attributes register 1*/
u8 __iomem res7[12];
__be32 __iomem pexotar2; /* 0x.c40 - PCI Express outbound translation address register 2 */
__be32 __iomem pexotear2; /* 0x.c44 - PCI Express outbound translation extended address register 2*/
__be32 __iomem pexowbar2; /* 0x.c48 - PCI Express outbound window base address register 2*/
u8 __iomem res8[4];
__be32 __iomem pexowar2; /* 0x.c50 - PCI Express outbound window attributes register 2*/
u8 __iomem res9[12];
__be32 __iomem pexotar3; /* 0x.c60 - PCI Express outbound translation address register 3 */
__be32 __iomem pexotear3; /* 0x.c64 - PCI Express outbound translation extended address register 3*/
__be32 __iomem pexowbar3; /* 0x.c68 - PCI Express outbound window base address register 3*/
u8 __iomem res10[4];
__be32 __iomem pexowar3; /* 0x.c70 - PCI Express outbound window attributes register 3*/
u8 __iomem res11[12];
__be32 __iomem pexotar4; /* 0x.c80 - PCI Express outbound translation address register 4 */
__be32 __iomem pexotear4; /* 0x.c84 - PCI Express outbound translation extended address register 4*/
__be32 __iomem pexowbar4; /* 0x.c88 - PCI Express outbound window base address register 4*/
u8 __iomem res12[4];
__be32 __iomem pexowar4; /* 0x.c90 - PCI Express outbound window attributes register 4*/
u8 __iomem res13[12];
u8 __iomem res14[256];
__be32 __iomem pexitar3; /* 0x.da0 - PCI Express inbound translation address register 3 */
u8 __iomem res15[4];
__be32 __iomem pexiwbar3; /* 0x.da8 - PCI Express inbound window base address register 3 */
__be32 __iomem pexiwbear3; /* 0x.dac - PCI Express inbound window base extended address register 3 */
__be32 __iomem pexiwar3; /* 0x.db0 - PCI Express inbound window attributes register 3 */
u8 __iomem res16[12];
__be32 __iomem pexitar2; /* 0x.dc0 - PCI Express inbound translation address register 2 */
u8 __iomem res17[4];
__be32 __iomem pexiwbar2; /* 0x.dc8 - PCI Express inbound window base address register 2 */
__be32 __iomem pexiwbear2; /* 0x.dcc - PCI Express inbound window base extended address register 2 */
__be32 __iomem pexiwar2; /* 0x.dd0 - PCI Express inbound window attributes register 2 */
u8 __iomem res18[12];
__be32 __iomem pexitar1; /* 0x.de0 - PCI Express inbound translation address register 2 */
u8 __iomem res19[4];
__be32 __iomem pexiwbar1; /* 0x.de8 - PCI Express inbound window base address register 2 */
__be32 __iomem pexiwbear1; /* 0x.dec - PCI Express inbound window base extended address register 2 */
__be32 __iomem pexiwar1; /* 0x.df0 - PCI Express inbound window attributes register 2 */
u8 __iomem res20[12];
__be32 __iomem pex_err_dr; /* 0x.e00 - PCI Express error detect register */
u8 __iomem res21[4];
__be32 __iomem pex_err_en; /* 0x.e08 - PCI Express error interrupt enable register */
u8 __iomem res22[4];
__be32 __iomem pex_err_disr; /* 0x.e10 - PCI Express error disable register */
u8 __iomem res23[12];
__be32 __iomem pex_err_cap_stat; /* 0x.e20 - PCI Express error capture status register */
u8 __iomem res24[4];
__be32 __iomem pex_err_cap_r0; /* 0x.e28 - PCI Express error capture register 0 */
__be32 __iomem pex_err_cap_r1; /* 0x.e2c - PCI Express error capture register 0 */
__be32 __iomem pex_err_cap_r2; /* 0x.e30 - PCI Express error capture register 0 */
__be32 __iomem pex_err_cap_r3; /* 0x.e34 - PCI Express error capture register 0 */
};
#endif /* __POWERPC_FSL_PCIE_H */
#endif /* __KERNEL__ */

View File

@ -52,7 +52,7 @@ phys_addr_t get_immrbase(void)
soc = of_find_node_by_type(NULL, "soc");
if (soc) {
unsigned int size;
const void *prop = get_property(soc, "reg", &size);
const void *prop = of_get_property(soc, "reg", &size);
if (prop)
immrbase = of_translate_address(soc, prop);
@ -78,8 +78,8 @@ u32 get_brgfreq(void)
node = of_find_node_by_type(NULL, "cpm");
if (node) {
unsigned int size;
const unsigned int *prop = get_property(node, "brg-frequency",
&size);
const unsigned int *prop = of_get_property(node,
"brg-frequency", &size);
if (prop)
brgfreq = *prop;
@ -103,8 +103,8 @@ u32 get_baudrate(void)
node = of_find_node_by_type(NULL, "serial");
if (node) {
unsigned int size;
const unsigned int *prop = get_property(node, "current-speed",
&size);
const unsigned int *prop = of_get_property(node,
"current-speed", &size);
if (prop)
fs_baudrate = *prop;
@ -153,7 +153,8 @@ static int __init gfar_mdio_of_init(void)
while ((child = of_get_next_child(np, child)) != NULL) {
int irq = irq_of_parse_and_map(child, 0);
if (irq != NO_IRQ) {
const u32 *id = get_property(child, "reg", NULL);
const u32 *id = of_get_property(child,
"reg", NULL);
mdio_data.irq[*id] = irq;
}
}
@ -209,7 +210,7 @@ static int __init gfar_of_init(void)
of_irq_to_resource(np, 0, &r[1]);
model = get_property(np, "model", NULL);
model = of_get_property(np, "model", NULL);
/* If we aren't the FEC we have multiple interrupts */
if (model && strcasecmp(model, "FEC")) {
@ -253,7 +254,7 @@ static int __init gfar_of_init(void)
FSL_GIANFAR_DEV_HAS_VLAN |
FSL_GIANFAR_DEV_HAS_EXTENDED_HASH;
ph = get_property(np, "phy-handle", NULL);
ph = of_get_property(np, "phy-handle", NULL);
phy = of_find_node_by_phandle(*ph);
if (phy == NULL) {
@ -263,7 +264,7 @@ static int __init gfar_of_init(void)
mdio = of_get_parent(phy);
id = get_property(phy, "reg", NULL);
id = of_get_property(phy, "reg", NULL);
ret = of_address_to_resource(mdio, 0, &res);
if (ret) {
of_node_put(phy);
@ -325,11 +326,11 @@ static int __init fsl_i2c_of_init(void)
}
i2c_data.device_flags = 0;
flags = get_property(np, "dfsrr", NULL);
flags = of_get_property(np, "dfsrr", NULL);
if (flags)
i2c_data.device_flags |= FSL_I2C_DEV_SEPARATE_DFSRR;
flags = get_property(np, "fsl5200-clocking", NULL);
flags = of_get_property(np, "fsl5200-clocking", NULL);
if (flags)
i2c_data.device_flags |= FSL_I2C_DEV_CLOCK_5200;
@ -374,7 +375,7 @@ static int __init mpc83xx_wdt_init(void)
goto nosoc;
}
freq = get_property(soc, "bus-frequency", NULL);
freq = of_get_property(soc, "bus-frequency", NULL);
if (!freq) {
ret = -ENODEV;
goto err;
@ -466,15 +467,15 @@ static int __init fsl_usb_of_init(void)
usb_data.operating_mode = FSL_USB2_MPH_HOST;
prop = get_property(np, "port0", NULL);
prop = of_get_property(np, "port0", NULL);
if (prop)
usb_data.port_enables |= FSL_USB2_PORT0_ENABLED;
prop = get_property(np, "port1", NULL);
prop = of_get_property(np, "port1", NULL);
if (prop)
usb_data.port_enables |= FSL_USB2_PORT1_ENABLED;
prop = get_property(np, "phy_type", NULL);
prop = of_get_property(np, "phy_type", NULL);
usb_data.phy_mode = determine_usb_phy(prop);
ret =
@ -501,7 +502,7 @@ static int __init fsl_usb_of_init(void)
of_irq_to_resource(np, 0, &r[1]);
prop = get_property(np, "dr_mode", NULL);
prop = of_get_property(np, "dr_mode", NULL);
if (!prop || !strcmp(prop, "host")) {
usb_data.operating_mode = FSL_USB2_DR_HOST;
@ -538,7 +539,7 @@ static int __init fsl_usb_of_init(void)
goto err;
}
prop = get_property(np, "phy_type", NULL);
prop = of_get_property(np, "phy_type", NULL);
usb_data.phy_mode = determine_usb_phy(prop);
if (usb_dev_dr_host) {
@ -633,7 +634,7 @@ static int __init fs_enet_of_init(void)
goto err;
}
model = get_property(np, "model", NULL);
model = of_get_property(np, "model", NULL);
if (model == NULL) {
ret = -ENODEV;
goto unreg;
@ -643,7 +644,7 @@ static int __init fs_enet_of_init(void)
if (mac_addr)
memcpy(fs_enet_data.macaddr, mac_addr, 6);
ph = get_property(np, "phy-handle", NULL);
ph = of_get_property(np, "phy-handle", NULL);
phy = of_find_node_by_phandle(*ph);
if (phy == NULL) {
@ -651,12 +652,12 @@ static int __init fs_enet_of_init(void)
goto unreg;
}
phy_addr = get_property(phy, "reg", NULL);
phy_addr = of_get_property(phy, "reg", NULL);
fs_enet_data.phy_addr = *phy_addr;
phy_irq = get_property(phy, "interrupts", NULL);
phy_irq = of_get_property(phy, "interrupts", NULL);
id = get_property(np, "device-id", NULL);
id = of_get_property(np, "device-id", NULL);
fs_enet_data.fs_no = *id;
strcpy(fs_enet_data.fs_type, model);
@ -668,8 +669,10 @@ static int __init fs_enet_of_init(void)
goto unreg;
}
fs_enet_data.clk_rx = *((u32 *) get_property(np, "rx-clock", NULL));
fs_enet_data.clk_tx = *((u32 *) get_property(np, "tx-clock", NULL));
fs_enet_data.clk_rx = *((u32 *)of_get_property(np,
"rx-clock", NULL));
fs_enet_data.clk_tx = *((u32 *)of_get_property(np,
"tx-clock", NULL));
if (strstr(model, "FCC")) {
int fcc_index = *id - 1;
@ -690,7 +693,7 @@ static int __init fs_enet_of_init(void)
fs_enet_data.bus_id = (char*)&bus_id[(*id)];
fs_enet_data.init_ioports = init_fcc_ioports;
mdio_bb_prop = get_property(phy, "bitbang", NULL);
mdio_bb_prop = of_get_property(phy, "bitbang", NULL);
if (mdio_bb_prop) {
struct platform_device *fs_enet_mdio_bb_dev;
struct fs_mii_bb_platform_info fs_enet_mdio_bb_data;
@ -796,10 +799,10 @@ static int __init cpm_uart_of_init(void)
goto err;
}
id = get_property(np, "device-id", NULL);
id = of_get_property(np, "device-id", NULL);
cpm_uart_data.fs_no = *id;
model = (char*)get_property(np, "model", NULL);
model = of_get_property(np, "model", NULL);
strcpy(cpm_uart_data.fs_type, model);
cpm_uart_data.uart_clk = ppc_proc_freq;
@ -808,8 +811,10 @@ static int __init cpm_uart_of_init(void)
cpm_uart_data.tx_buf_size = 32;
cpm_uart_data.rx_num_fifo = 4;
cpm_uart_data.rx_buf_size = 32;
cpm_uart_data.clk_rx = *((u32 *) get_property(np, "rx-clock", NULL));
cpm_uart_data.clk_tx = *((u32 *) get_property(np, "tx-clock", NULL));
cpm_uart_data.clk_rx = *((u32 *)of_get_property(np,
"rx-clock", NULL));
cpm_uart_data.clk_tx = *((u32 *)of_get_property(np,
"tx-clock", NULL));
ret =
platform_device_add_data(cpm_uart_dev, &cpm_uart_data,
@ -833,7 +838,7 @@ arch_initcall(cpm_uart_of_init);
#ifdef CONFIG_8xx
extern void init_scc_ioports(struct fs_platform_info*);
extern int platform_device_skip(char *model, int id);
extern int platform_device_skip(const char *model, int id);
static int __init fs_enet_mdio_of_init(void)
{
@ -900,21 +905,22 @@ static int __init fs_enet_of_init(void)
struct resource r[4];
struct device_node *phy = NULL, *mdio = NULL;
struct fs_platform_info fs_enet_data;
unsigned int *id, *phy_addr;
const unsigned int *id;
const unsigned int *phy_addr;
void *mac_addr;
phandle *ph;
char *model;
const phandle *ph;
const char *model;
memset(r, 0, sizeof(r));
memset(&fs_enet_data, 0, sizeof(fs_enet_data));
model = (char *)get_property(np, "model", NULL);
model = of_get_property(np, "model", NULL);
if (model == NULL) {
ret = -ENODEV;
goto unreg;
}
id = (u32 *) get_property(np, "device-id", NULL);
id = of_get_property(np, "device-id", NULL);
fs_enet_data.fs_no = *id;
if (platform_device_skip(model, *id))
@ -929,12 +935,12 @@ static int __init fs_enet_of_init(void)
if (mac_addr)
memcpy(fs_enet_data.macaddr, mac_addr, 6);
ph = (phandle *) get_property(np, "phy-handle", NULL);
ph = of_get_property(np, "phy-handle", NULL);
if (ph != NULL)
phy = of_find_node_by_phandle(*ph);
if (phy != NULL) {
phy_addr = (u32 *) get_property(phy, "reg", NULL);
phy_addr = of_get_property(phy, "reg", NULL);
fs_enet_data.phy_addr = *phy_addr;
fs_enet_data.has_phy = 1;
@ -947,7 +953,7 @@ static int __init fs_enet_of_init(void)
}
}
model = (char*)get_property(np, "model", NULL);
model = of_get_property(np, "model", NULL);
strcpy(fs_enet_data.fs_type, model);
if (strstr(model, "FEC")) {
@ -1038,8 +1044,8 @@ static int __init cpm_smc_uart_of_init(void)
i++) {
struct resource r[3];
struct fs_uart_platform_info cpm_uart_data;
int *id;
char *model;
const int *id;
const char *model;
memset(r, 0, sizeof(r));
memset(&cpm_uart_data, 0, sizeof(cpm_uart_data));
@ -1066,10 +1072,10 @@ static int __init cpm_smc_uart_of_init(void)
goto err;
}
model = (char*)get_property(np, "model", NULL);
model = of_get_property(np, "model", NULL);
strcpy(cpm_uart_data.fs_type, model);
id = (int*)get_property(np, "device-id", NULL);
id = of_get_property(np, "device-id", NULL);
cpm_uart_data.fs_no = *id;
cpm_uart_data.uart_clk = ppc_proc_freq;

View File

@ -304,7 +304,7 @@ static void __init mpic_test_broken_ipi(struct mpic *mpic)
}
}
#ifdef CONFIG_MPIC_BROKEN_U3
#ifdef CONFIG_MPIC_U3_HT_IRQS
/* Test if an interrupt is sourced from HyperTransport (used on broken U3s)
* to force the edge setting on the MPIC and do the ack workaround.
@ -476,7 +476,7 @@ static void __init mpic_scan_ht_pics(struct mpic *mpic)
}
}
#else /* CONFIG_MPIC_BROKEN_U3 */
#else /* CONFIG_MPIC_U3_HT_IRQS */
static inline int mpic_is_ht_interrupt(struct mpic *mpic, unsigned int source)
{
@ -487,7 +487,7 @@ static void __init mpic_scan_ht_pics(struct mpic *mpic)
{
}
#endif /* CONFIG_MPIC_BROKEN_U3 */
#endif /* CONFIG_MPIC_U3_HT_IRQS */
#define mpic_irq_to_hw(virq) ((unsigned int)irq_map[virq].hwirq)
@ -615,7 +615,7 @@ static void mpic_end_irq(unsigned int irq)
mpic_eoi(mpic);
}
#ifdef CONFIG_MPIC_BROKEN_U3
#ifdef CONFIG_MPIC_U3_HT_IRQS
static void mpic_unmask_ht_irq(unsigned int irq)
{
@ -665,7 +665,7 @@ static void mpic_end_ht_irq(unsigned int irq)
mpic_ht_end_irq(mpic, src);
mpic_eoi(mpic);
}
#endif /* !CONFIG_MPIC_BROKEN_U3 */
#endif /* !CONFIG_MPIC_U3_HT_IRQS */
#ifdef CONFIG_SMP
@ -788,7 +788,7 @@ static struct irq_chip mpic_ipi_chip = {
};
#endif /* CONFIG_SMP */
#ifdef CONFIG_MPIC_BROKEN_U3
#ifdef CONFIG_MPIC_U3_HT_IRQS
static struct irq_chip mpic_irq_ht_chip = {
.startup = mpic_startup_ht_irq,
.shutdown = mpic_shutdown_ht_irq,
@ -797,7 +797,7 @@ static struct irq_chip mpic_irq_ht_chip = {
.eoi = mpic_end_ht_irq,
.set_type = mpic_set_irq_type,
};
#endif /* CONFIG_MPIC_BROKEN_U3 */
#endif /* CONFIG_MPIC_U3_HT_IRQS */
static int mpic_host_match(struct irq_host *h, struct device_node *node)
@ -837,11 +837,11 @@ static int mpic_host_map(struct irq_host *h, unsigned int virq,
/* Default chip */
chip = &mpic->hc_irq;
#ifdef CONFIG_MPIC_BROKEN_U3
#ifdef CONFIG_MPIC_U3_HT_IRQS
/* Check for HT interrupts, override vecpri */
if (mpic_is_ht_interrupt(mpic, hw))
chip = &mpic->hc_ht_irq;
#endif /* CONFIG_MPIC_BROKEN_U3 */
#endif /* CONFIG_MPIC_U3_HT_IRQS */
DBG("mpic: mapping to irq chip @%p\n", chip);
@ -937,12 +937,12 @@ struct mpic * __init mpic_alloc(struct device_node *node,
mpic->hc_irq.typename = name;
if (flags & MPIC_PRIMARY)
mpic->hc_irq.set_affinity = mpic_set_affinity;
#ifdef CONFIG_MPIC_BROKEN_U3
#ifdef CONFIG_MPIC_U3_HT_IRQS
mpic->hc_ht_irq = mpic_irq_ht_chip;
mpic->hc_ht_irq.typename = name;
if (flags & MPIC_PRIMARY)
mpic->hc_ht_irq.set_affinity = mpic_set_affinity;
#endif /* CONFIG_MPIC_BROKEN_U3 */
#endif /* CONFIG_MPIC_U3_HT_IRQS */
#ifdef CONFIG_SMP
mpic->hc_ipi = mpic_ipi_chip;
@ -970,7 +970,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,
mpic->spurious_vec = intvec_top;
/* Check for "big-endian" in device-tree */
if (node && get_property(node, "big-endian", NULL) != NULL)
if (node && of_get_property(node, "big-endian", NULL) != NULL)
mpic->flags |= MPIC_BIG_ENDIAN;
@ -986,13 +986,13 @@ struct mpic * __init mpic_alloc(struct device_node *node,
BUG_ON(paddr == 0 && node == NULL);
/* If no physical address passed in, check if it's dcr based */
if (paddr == 0 && get_property(node, "dcr-reg", NULL) != NULL)
if (paddr == 0 && of_get_property(node, "dcr-reg", NULL) != NULL)
mpic->flags |= MPIC_USES_DCR;
#ifdef CONFIG_PPC_DCR
if (mpic->flags & MPIC_USES_DCR) {
const u32 *dbasep;
dbasep = get_property(node, "dcr-reg", NULL);
dbasep = of_get_property(node, "dcr-reg", NULL);
BUG_ON(dbasep == NULL);
mpic->dcr_base = *dbasep;
mpic->reg_type = mpic_access_dcr;
@ -1006,7 +1006,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,
*/
if (paddr == 0 && !(mpic->flags & MPIC_USES_DCR)) {
const u32 *reg;
reg = get_property(node, "reg", NULL);
reg = of_get_property(node, "reg", NULL);
BUG_ON(reg == NULL);
paddr = of_translate_address(node, reg);
BUG_ON(paddr == OF_BAD_ADDR);
@ -1142,7 +1142,7 @@ void __init mpic_init(struct mpic *mpic)
/* Do the HT PIC fixups on U3 broken mpic */
DBG("MPIC flags: %x\n", mpic->flags);
if ((mpic->flags & MPIC_BROKEN_U3) && (mpic->flags & MPIC_PRIMARY))
if ((mpic->flags & MPIC_U3_HT_IRQS) && (mpic->flags & MPIC_PRIMARY))
mpic_scan_ht_pics(mpic);
for (i = 0; i < mpic->num_sources; i++) {

View File

@ -33,7 +33,7 @@
#include <asm/of_platform.h>
#include <asm/io.h>
#include <asm/pmi.h>
#include <asm/prom.h>
struct pmi_data {
struct list_head handler;
@ -49,21 +49,6 @@ struct pmi_data {
};
static void __iomem *of_iomap(struct device_node *np)
{
struct resource res;
if (of_address_to_resource(np, 0, &res))
return NULL;
pr_debug("Resource start: 0x%lx\n", res.start);
pr_debug("Resource end: 0x%lx\n", res.end);
return ioremap(res.start, 1 + res.end - res.start);
}
static int pmi_irq_handler(int irq, void *dev_id)
{
struct pmi_data *data;
@ -118,6 +103,7 @@ out:
static struct of_device_id pmi_match[] = {
{ .type = "ibm,pmi", .name = "ibm,pmi" },
{ .type = "ibm,pmi" },
{},
};
@ -153,7 +139,7 @@ static int pmi_of_probe(struct of_device *dev,
goto out;
}
data->pmi_reg = of_iomap(np);
data->pmi_reg = of_iomap(np, 0);
if (!data->pmi_reg) {
printk(KERN_ERR "pmi: invalid register address.\n");
rc = -EFAULT;
@ -279,6 +265,9 @@ void pmi_register_handler(struct of_device *device,
struct pmi_data *data;
data = device->dev.driver_data;
if (!data)
return;
spin_lock(&data->handler_spinlock);
list_add_tail(&handler->node, &data->handler);
spin_unlock(&data->handler_spinlock);
@ -289,11 +278,13 @@ void pmi_unregister_handler(struct of_device *device,
struct pmi_handler *handler)
{
struct pmi_data *data;
data = device->dev.driver_data;
if (!data)
return;
pr_debug("pmi: unregistering handler %p\n", handler);
data = device->dev.driver_data;
spin_lock(&data->handler_spinlock);
list_del(&handler->node);
spin_unlock(&data->handler_spinlock);

View File

@ -2,11 +2,8 @@
# QE Communication options
#
menu "QE Options"
depends on QUICC_ENGINE
config UCC_SLOW
bool "UCC Slow Protocols Support"
bool
default n
select UCC
help
@ -14,10 +11,9 @@ config UCC_SLOW
protocols: UART, BISYNC, QMC
config UCC_FAST
bool "UCC Fast Protocols Support"
bool
default n
select UCC
select UCC_SLOW
help
This option provides qe_lib support to UCC fast
protocols: HDLC, Ethernet, ATM, transparent
@ -26,5 +22,3 @@ config UCC
bool
default y if UCC_FAST || UCC_SLOW
endmenu

View File

@ -71,7 +71,7 @@ phys_addr_t get_qe_base(void)
qe = of_find_node_by_type(NULL, "qe");
if (qe) {
unsigned int size;
const void *prop = get_property(qe, "reg", &size);
const void *prop = of_get_property(qe, "reg", &size);
qebase = of_translate_address(qe, prop);
of_node_put(qe);
};
@ -158,7 +158,7 @@ unsigned int get_brg_clk(void)
qe = of_find_node_by_type(NULL, "qe");
if (qe) {
unsigned int size;
const u32 *prop = get_property(qe, "brg-frequency", &size);
const u32 *prop = of_get_property(qe, "brg-frequency", &size);
brg_clk = *prop;
of_node_put(qe);
};

View File

@ -53,7 +53,7 @@ int par_io_init(struct device_node *np)
return ret;
par_io = ioremap(res.start, res.end - res.start + 1);
num_ports = get_property(np, "num-ports", NULL);
num_ports = of_get_property(np, "num-ports", NULL);
if (num_ports)
num_par_io_ports = *num_ports;
@ -161,7 +161,7 @@ int par_io_of_config(struct device_node *np)
return -1;
}
ph = get_property(np, "pio-handle", NULL);
ph = of_get_property(np, "pio-handle", NULL);
if (ph == 0) {
printk(KERN_ERR "pio-handle not available \n");
return -1;
@ -169,7 +169,7 @@ int par_io_of_config(struct device_node *np)
pio = of_find_node_by_phandle(*ph);
pio_map = get_property(pio, "pio-map", &pio_map_len);
pio_map = of_get_property(pio, "pio-map", &pio_map_len);
if (pio_map == NULL) {
printk(KERN_ERR "pio-map is not set! \n");
return -1;

View File

@ -187,7 +187,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
uccs->us_pram = qe_muram_addr(uccs->us_pram_offset);
/* Init Guemr register */
if ((ret = ucc_init_guemr((struct ucc_common *) (us_info->regs)))) {
if ((ret = ucc_init_guemr((struct ucc_common *) us_regs))) {
printk(KERN_ERR "%s: cannot init GUEMR", __FUNCTION__);
ucc_slow_free(uccs);
return ret;
@ -195,7 +195,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
/* Set UCC to slow type */
if ((ret = ucc_set_type(us_info->ucc_num,
(struct ucc_common *) (us_info->regs),
(struct ucc_common *) us_regs,
UCC_SPEED_TYPE_SLOW))) {
printk(KERN_ERR "%s: cannot set UCC type", __FUNCTION__);
ucc_slow_free(uccs);

View File

@ -0,0 +1,71 @@
/*
* Common code to keep time when machine suspends.
*
* Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
*
* GPLv2
*/
#include <linux/time.h>
#include <linux/sysdev.h>
#include <asm/rtc.h>
static unsigned long suspend_rtc_time;
/*
* Reset the time after a sleep.
*/
static int timer_resume(struct sys_device *dev)
{
struct timeval tv;
struct timespec ts;
struct rtc_time cur_rtc_tm;
unsigned long cur_rtc_time, diff;
/* get current RTC time and convert to seconds */
get_rtc_time(&cur_rtc_tm);
rtc_tm_to_time(&cur_rtc_tm, &cur_rtc_time);
diff = cur_rtc_time - suspend_rtc_time;
/* adjust time of day by seconds that elapsed while
* we were suspended */
do_gettimeofday(&tv);
ts.tv_sec = tv.tv_sec + diff;
ts.tv_nsec = tv.tv_usec * NSEC_PER_USEC;
do_settimeofday(&ts);
return 0;
}
static int timer_suspend(struct sys_device *dev, pm_message_t state)
{
struct rtc_time suspend_rtc_tm;
WARN_ON(!ppc_md.get_rtc_time);
get_rtc_time(&suspend_rtc_tm);
rtc_tm_to_time(&suspend_rtc_tm, &suspend_rtc_time);
return 0;
}
static struct sysdev_class timer_sysclass = {
.resume = timer_resume,
.suspend = timer_suspend,
set_kset_name("timer"),
};
static struct sys_device device_timer = {
.id = 0,
.cls = &timer_sysclass,
};
static int time_init_device(void)
{
int error = sysdev_class_register(&timer_sysclass);
if (!error)
error = sysdev_register(&device_timer);
return error;
}
device_initcall(time_init_device);

View File

@ -48,7 +48,7 @@ phys_addr_t get_csrbase(void)
tsi = of_find_node_by_type(NULL, "tsi-bridge");
if (tsi) {
unsigned int size;
const void *prop = get_property(tsi, "reg", &size);
const void *prop = of_get_property(tsi, "reg", &size);
tsi108_csr_base = of_translate_address(tsi, prop);
of_node_put(tsi);
};
@ -77,10 +77,10 @@ static int __init tsi108_eth_of_init(void)
struct resource r[2];
struct device_node *phy;
hw_info tsi_eth_data;
unsigned int *id;
unsigned int *phy_id;
const unsigned int *id;
const unsigned int *phy_id;
const void *mac_addr;
phandle *ph;
const phandle *ph;
memset(r, 0, sizeof(r));
memset(&tsi_eth_data, 0, sizeof(tsi_eth_data));
@ -107,10 +107,10 @@ static int __init tsi108_eth_of_init(void)
goto err;
}
mac_addr = get_property(np, "address", NULL);
mac_addr = of_get_property(np, "address", NULL);
memcpy(tsi_eth_data.mac_addr, mac_addr, 6);
ph = (phandle *) get_property(np, "phy-handle", NULL);
ph = of_get_property(np, "phy-handle", NULL);
phy = of_find_node_by_phandle(*ph);
if (phy == NULL) {
@ -118,8 +118,8 @@ static int __init tsi108_eth_of_init(void)
goto unreg;
}
id = (u32 *) get_property(phy, "reg", NULL);
phy_id = (u32 *) get_property(phy, "phy-id", NULL);
id = of_get_property(phy, "reg", NULL);
phy_id = of_get_property(phy, "phy-id", NULL);
ret = of_address_to_resource(phy, 0, &res);
if (ret) {
of_node_put(phy);

View File

@ -211,7 +211,7 @@ int __init tsi108_setup_pci(struct device_node *dev)
has_address = (of_address_to_resource(dev, 0, &rsrc) == 0);
/* Get bus range if any */
bus_range = get_property(dev, "bus-range", &len);
bus_range = of_get_property(dev, "bus-range", &len);
if (bus_range == NULL || len < 2 * sizeof(int)) {
printk(KERN_WARNING "Can't get bus-range for %s, assume"
" bus 0\n", dev->full_name);

342
arch/powerpc/sysdev/uic.c Normal file
View File

@ -0,0 +1,342 @@
/*
* arch/powerpc/sysdev/uic.c
*
* IBM PowerPC 4xx Universal Interrupt Controller
*
* Copyright 2007 David Gibson <dwg@au1.ibm.com>, IBM Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/reboot.h>
#include <linux/slab.h>
#include <linux/stddef.h>
#include <linux/sched.h>
#include <linux/signal.h>
#include <linux/sysdev.h>
#include <linux/device.h>
#include <linux/bootmem.h>
#include <linux/spinlock.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/prom.h>
#include <asm/dcr.h>
#define NR_UIC_INTS 32
#define UIC_SR 0x0
#define UIC_ER 0x2
#define UIC_CR 0x3
#define UIC_PR 0x4
#define UIC_TR 0x5
#define UIC_MSR 0x6
#define UIC_VR 0x7
#define UIC_VCR 0x8
#define uic_irq_to_hw(virq) (irq_map[virq].hwirq)
struct uic *primary_uic;
struct uic {
int index;
int dcrbase;
spinlock_t lock;
/* The remapper for this UIC */
struct irq_host *irqhost;
/* For secondary UICs, the cascade interrupt's irqaction */
struct irqaction cascade;
/* The device node of the interrupt controller */
struct device_node *of_node;
};
static void uic_unmask_irq(unsigned int virq)
{
struct uic *uic = get_irq_chip_data(virq);
unsigned int src = uic_irq_to_hw(virq);
unsigned long flags;
u32 er;
spin_lock_irqsave(&uic->lock, flags);
er = mfdcr(uic->dcrbase + UIC_ER);
er |= 1 << (31 - src);
mtdcr(uic->dcrbase + UIC_ER, er);
spin_unlock_irqrestore(&uic->lock, flags);
}
static void uic_mask_irq(unsigned int virq)
{
struct uic *uic = get_irq_chip_data(virq);
unsigned int src = uic_irq_to_hw(virq);
unsigned long flags;
u32 er;
spin_lock_irqsave(&uic->lock, flags);
er = mfdcr(uic->dcrbase + UIC_ER);
er &= ~(1 << (31 - src));
mtdcr(uic->dcrbase + UIC_ER, er);
spin_unlock_irqrestore(&uic->lock, flags);
}
static void uic_ack_irq(unsigned int virq)
{
struct uic *uic = get_irq_chip_data(virq);
unsigned int src = uic_irq_to_hw(virq);
unsigned long flags;
spin_lock_irqsave(&uic->lock, flags);
mtdcr(uic->dcrbase + UIC_SR, 1 << (31-src));
spin_unlock_irqrestore(&uic->lock, flags);
}
static int uic_set_irq_type(unsigned int virq, unsigned int flow_type)
{
struct uic *uic = get_irq_chip_data(virq);
unsigned int src = uic_irq_to_hw(virq);
struct irq_desc *desc = get_irq_desc(virq);
unsigned long flags;
int trigger, polarity;
u32 tr, pr, mask;
switch (flow_type & IRQ_TYPE_SENSE_MASK) {
case IRQ_TYPE_NONE:
uic_mask_irq(virq);
return 0;
case IRQ_TYPE_EDGE_RISING:
trigger = 1; polarity = 1;
break;
case IRQ_TYPE_EDGE_FALLING:
trigger = 1; polarity = 0;
break;
case IRQ_TYPE_LEVEL_HIGH:
trigger = 0; polarity = 1;
break;
case IRQ_TYPE_LEVEL_LOW:
trigger = 0; polarity = 0;
break;
default:
return -EINVAL;
}
mask = ~(1 << (31 - src));
spin_lock_irqsave(&uic->lock, flags);
tr = mfdcr(uic->dcrbase + UIC_TR);
pr = mfdcr(uic->dcrbase + UIC_PR);
tr = (tr & mask) | (trigger << (31-src));
pr = (pr & mask) | (polarity << (31-src));
mtdcr(uic->dcrbase + UIC_PR, pr);
mtdcr(uic->dcrbase + UIC_TR, tr);
desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
if (trigger)
desc->status |= IRQ_LEVEL;
spin_unlock_irqrestore(&uic->lock, flags);
return 0;
}
static struct irq_chip uic_irq_chip = {
.typename = " UIC ",
.unmask = uic_unmask_irq,
.mask = uic_mask_irq,
/* .mask_ack = uic_mask_irq_and_ack, */
.ack = uic_ack_irq,
.set_type = uic_set_irq_type,
};
static int uic_host_match(struct irq_host *h, struct device_node *node)
{
struct uic *uic = h->host_data;
return uic->of_node == node;
}
static int uic_host_map(struct irq_host *h, unsigned int virq,
irq_hw_number_t hw)
{
struct uic *uic = h->host_data;
set_irq_chip_data(virq, uic);
/* Despite the name, handle_level_irq() works for both level
* and edge irqs on UIC. FIXME: check this is correct */
set_irq_chip_and_handler(virq, &uic_irq_chip, handle_level_irq);
/* Set default irq type */
set_irq_type(virq, IRQ_TYPE_NONE);
return 0;
}
static int uic_host_xlate(struct irq_host *h, struct device_node *ct,
u32 *intspec, unsigned int intsize,
irq_hw_number_t *out_hwirq, unsigned int *out_type)
{
/* UIC intspecs must have 2 cells */
BUG_ON(intsize != 2);
*out_hwirq = intspec[0];
*out_type = intspec[1];
return 0;
}
static struct irq_host_ops uic_host_ops = {
.match = uic_host_match,
.map = uic_host_map,
.xlate = uic_host_xlate,
};
irqreturn_t uic_cascade(int virq, void *data)
{
struct uic *uic = data;
u32 msr;
int src;
int subvirq;
msr = mfdcr(uic->dcrbase + UIC_MSR);
src = 32 - ffs(msr);
subvirq = irq_linear_revmap(uic->irqhost, src);
generic_handle_irq(subvirq);
return IRQ_HANDLED;
}
static struct uic * __init uic_init_one(struct device_node *node)
{
struct uic *uic;
const u32 *indexp, *dcrreg;
int len;
BUG_ON(! device_is_compatible(node, "ibm,uic"));
uic = alloc_bootmem(sizeof(*uic));
if (! uic)
return NULL; /* FIXME: panic? */
memset(uic, 0, sizeof(*uic));
spin_lock_init(&uic->lock);
uic->of_node = of_node_get(node);
indexp = of_get_property(node, "cell-index", &len);
if (!indexp || (len != sizeof(u32))) {
printk(KERN_ERR "uic: Device node %s has missing or invalid "
"cell-index property\n", node->full_name);
return NULL;
}
uic->index = *indexp;
dcrreg = of_get_property(node, "dcr-reg", &len);
if (!dcrreg || (len != 2*sizeof(u32))) {
printk(KERN_ERR "uic: Device node %s has missing or invalid "
"dcr-reg property\n", node->full_name);
return NULL;
}
uic->dcrbase = *dcrreg;
uic->irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR, NR_UIC_INTS,
&uic_host_ops, -1);
if (! uic->irqhost) {
of_node_put(node);
return NULL; /* FIXME: panic? */
}
uic->irqhost->host_data = uic;
/* Start with all interrupts disabled, level and non-critical */
mtdcr(uic->dcrbase + UIC_ER, 0);
mtdcr(uic->dcrbase + UIC_CR, 0);
mtdcr(uic->dcrbase + UIC_TR, 0);
/* Clear any pending interrupts, in case the firmware left some */
mtdcr(uic->dcrbase + UIC_SR, 0xffffffff);
printk ("UIC%d (%d IRQ sources) at DCR 0x%x\n", uic->index,
NR_UIC_INTS, uic->dcrbase);
return uic;
}
void __init uic_init_tree(void)
{
struct device_node *np;
struct uic *uic;
const u32 *interrupts;
/* First locate and initialize the top-level UIC */
np = of_find_compatible_node(NULL, NULL, "ibm,uic");
while (np) {
interrupts = of_get_property(np, "interrupts", NULL);
if (! interrupts)
break;
np = of_find_compatible_node(np, NULL, "ibm,uic");
}
BUG_ON(!np); /* uic_init_tree() assumes there's a UIC as the
* top-level interrupt controller */
primary_uic = uic_init_one(np);
if (! primary_uic)
panic("Unable to initialize primary UIC %s\n", np->full_name);
irq_set_default_host(primary_uic->irqhost);
of_node_put(np);
/* The scan again for cascaded UICs */
np = of_find_compatible_node(NULL, NULL, "ibm,uic");
while (np) {
interrupts = of_get_property(np, "interrupts", NULL);
if (interrupts) {
/* Secondary UIC */
int cascade_virq;
int ret;
uic = uic_init_one(np);
if (! uic)
panic("Unable to initialize a secondary UIC %s\n",
np->full_name);
cascade_virq = irq_of_parse_and_map(np, 0);
uic->cascade.handler = uic_cascade;
uic->cascade.name = "UIC cascade";
uic->cascade.dev_id = uic;
ret = setup_irq(cascade_virq, &uic->cascade);
if (ret)
printk(KERN_ERR "Failed to setup_irq(%d) for "
"UIC%d cascade\n", cascade_virq,
uic->index);
/* FIXME: setup critical cascade?? */
}
np = of_find_compatible_node(np, NULL, "ibm,uic");
}
}
/* Return an interrupt vector or NO_IRQ if no interrupt is pending. */
unsigned int uic_get_irq(void)
{
u32 msr;
int src;
BUG_ON(! primary_uic);
msr = mfdcr(primary_uic->dcrbase + UIC_MSR);
src = 32 - ffs(msr);
return irq_linear_revmap(primary_uic->irqhost, src);
}