Commit 789448b7 authored by Richard Henderson's avatar Richard Henderson

[ALPHA] Forward port SRM restore code from 2.4.

From Jay Estabrook <Jay.Estabrook@compaq.com>.
parent efaaaacf
......@@ -47,15 +47,6 @@
#define vip volatile int *
/* Save CIA configuration data as the console had it set up. */
struct
{
unsigned int w_base;
unsigned int w_mask;
unsigned int t_base;
} saved_config[4] __attribute((common));
/*
* Given a bus, device, and function number, compute resulting
* configuration space address. It is therefore not safe to have
......@@ -566,6 +557,77 @@ verify_tb_operation(void)
alpha_mv.mv_pci_tbi = NULL;
goto exit;
}
#if defined(ALPHA_RESTORE_SRM_SETUP)
/* Save CIA configuration data as the console had it set up. */
struct
{
unsigned int hae_mem;
unsigned int hae_io;
unsigned int pci_dac_offset;
unsigned int err_mask;
unsigned int cia_ctrl;
unsigned int cia_cnfg;
struct {
unsigned int w_base;
unsigned int w_mask;
unsigned int t_base;
} window[4];
} saved_config __attribute((common));
void
cia_save_srm_settings(int is_pyxis)
{
int i;
/* Save some important registers. */
saved_config.err_mask = *(vip)CIA_IOC_ERR_MASK;
saved_config.cia_ctrl = *(vip)CIA_IOC_CIA_CTRL;
saved_config.hae_mem = *(vip)CIA_IOC_HAE_MEM;
saved_config.hae_io = *(vip)CIA_IOC_HAE_IO;
saved_config.pci_dac_offset = *(vip)CIA_IOC_PCI_W_DAC;
if (is_pyxis)
saved_config.cia_cnfg = *(vip)CIA_IOC_CIA_CNFG;
else
saved_config.cia_cnfg = 0;
/* Save DMA windows configuration. */
for (i = 0; i < 4; i++) {
saved_config.window[i].w_base = *(vip)CIA_IOC_PCI_Wn_BASE(i);
saved_config.window[i].w_mask = *(vip)CIA_IOC_PCI_Wn_MASK(i);
saved_config.window[i].t_base = *(vip)CIA_IOC_PCI_Tn_BASE(i);
}
mb();
}
void
cia_restore_srm_settings(void)
{
int i;
for (i = 0; i < 4; i++) {
*(vip)CIA_IOC_PCI_Wn_BASE(i) = saved_config.window[i].w_base;
*(vip)CIA_IOC_PCI_Wn_MASK(i) = saved_config.window[i].w_mask;
*(vip)CIA_IOC_PCI_Tn_BASE(i) = saved_config.window[i].t_base;
}
*(vip)CIA_IOC_HAE_MEM = saved_config.hae_mem;
*(vip)CIA_IOC_HAE_IO = saved_config.hae_io;
*(vip)CIA_IOC_PCI_W_DAC = saved_config.pci_dac_offset;
*(vip)CIA_IOC_ERR_MASK = saved_config.err_mask;
*(vip)CIA_IOC_CIA_CTRL = saved_config.cia_ctrl;
if (saved_config.cia_cnfg) /* Must be pyxis. */
*(vip)CIA_IOC_CIA_CNFG = saved_config.cia_cnfg;
mb();
}
#else /* ALPHA_RESTORE_SRM_SETUP */
#define cia_save_srm_settings(p) do {} while (0)
#define cia_restore_srm_settings() do {} while (0)
#endif /* ALPHA_RESTORE_SRM_SETUP */
static void __init
do_init_arch(int is_pyxis)
......@@ -577,6 +639,9 @@ do_init_arch(int is_pyxis)
printk("pci: cia revision %d%s\n",
cia_rev, is_pyxis ? " (pyxis)" : "");
if (alpha_using_srm)
cia_save_srm_settings(is_pyxis);
/* Set up error reporting. */
temp = *(vip)CIA_IOC_ERR_MASK;
temp &= ~(CIA_ERR_CPU_PE | CIA_ERR_MEM_NEM | CIA_ERR_PA_PTE_INV
......@@ -646,24 +711,6 @@ do_init_arch(int is_pyxis)
hose->dense_io_base = CIA_BW_IO - IDENT_ADDR;
}
/* Save CIA configuration data as the console had it set up. */
saved_config[0].w_base = *(vip)CIA_IOC_PCI_W0_BASE;
saved_config[0].w_mask = *(vip)CIA_IOC_PCI_W0_MASK;
saved_config[0].t_base = *(vip)CIA_IOC_PCI_T0_BASE;
saved_config[1].w_base = *(vip)CIA_IOC_PCI_W1_BASE;
saved_config[1].w_mask = *(vip)CIA_IOC_PCI_W1_MASK;
saved_config[1].t_base = *(vip)CIA_IOC_PCI_T1_BASE;
saved_config[2].w_base = *(vip)CIA_IOC_PCI_W2_BASE;
saved_config[2].w_mask = *(vip)CIA_IOC_PCI_W2_MASK;
saved_config[2].t_base = *(vip)CIA_IOC_PCI_T2_BASE;
saved_config[3].w_base = *(vip)CIA_IOC_PCI_W3_BASE;
saved_config[3].w_mask = *(vip)CIA_IOC_PCI_W3_MASK;
saved_config[3].t_base = *(vip)CIA_IOC_PCI_T3_BASE;
/*
* Set up the PCI to main memory translation windows.
*
......@@ -761,21 +808,8 @@ pyxis_init_arch(void)
void
cia_kill_arch(int mode)
{
*(vip)CIA_IOC_PCI_W0_BASE = saved_config[0].w_base;
*(vip)CIA_IOC_PCI_W0_MASK = saved_config[0].w_mask;
*(vip)CIA_IOC_PCI_T0_BASE = saved_config[0].t_base;
*(vip)CIA_IOC_PCI_W1_BASE = saved_config[1].w_base;
*(vip)CIA_IOC_PCI_W1_MASK = saved_config[1].w_mask;
*(vip)CIA_IOC_PCI_T1_BASE = saved_config[1].t_base;
*(vip)CIA_IOC_PCI_W2_BASE = saved_config[2].w_base;
*(vip)CIA_IOC_PCI_W2_MASK = saved_config[2].w_mask;
*(vip)CIA_IOC_PCI_T2_BASE = saved_config[2].t_base;
*(vip)CIA_IOC_PCI_W3_BASE = saved_config[3].w_base;
*(vip)CIA_IOC_PCI_W3_MASK = saved_config[3].w_mask;
*(vip)CIA_IOC_PCI_T3_BASE = saved_config[3].t_base;
if (alpha_using_srm)
cia_restore_srm_settings();
}
void __init
......
......@@ -242,7 +242,7 @@ void
lca_pci_tbi(struct pci_controller *hose, dma_addr_t start, dma_addr_t end)
{
wmb();
*(vip)LCA_IOC_TBIA = 0;
*(vulp)LCA_IOC_TBIA = 0;
mb();
}
......@@ -268,21 +268,25 @@ lca_init_arch(void)
/*
* Set up the PCI to main memory translation windows.
*
* Window 0 is direct access 1GB at 1GB
* Window 1 is scatter-gather 8MB at 8MB (for isa)
* Mimic the SRM settings for the direct-map window.
* Window 0 is scatter-gather 8MB at 8MB (for isa).
* Window 1 is direct access 1GB at 1GB.
*
* Note that we do not try to save any of the DMA window CSRs
* before setting them, since we cannot read those CSRs on LCA.
*/
hose->sg_isa = iommu_arena_new(hose, 0x00800000, 0x00800000, 0);
hose->sg_pci = NULL;
__direct_map_base = 0x40000000;
__direct_map_size = 0x40000000;
*(vulp)LCA_IOC_W_BASE0 = __direct_map_base | (2UL << 32);
*(vulp)LCA_IOC_W_MASK0 = (__direct_map_size - 1) & 0xfff00000;
*(vulp)LCA_IOC_T_BASE0 = 0;
*(vulp)LCA_IOC_W_BASE0 = hose->sg_isa->dma_base | (3UL << 32);
*(vulp)LCA_IOC_W_MASK0 = (hose->sg_isa->size - 1) & 0xfff00000;
*(vulp)LCA_IOC_T_BASE0 = virt_to_phys(hose->sg_isa->ptes);
*(vulp)LCA_IOC_W_BASE1 = hose->sg_isa->dma_base | (3UL << 32);
*(vulp)LCA_IOC_W_MASK1 = (hose->sg_isa->size - 1) & 0xfff00000;
*(vulp)LCA_IOC_T_BASE1 = virt_to_phys(hose->sg_isa->ptes);
*(vulp)LCA_IOC_W_BASE1 = __direct_map_base | (2UL << 32);
*(vulp)LCA_IOC_W_MASK1 = (__direct_map_size - 1) & 0xfff00000;
*(vulp)LCA_IOC_T_BASE1 = 0;
*(vulp)LCA_IOC_TB_ENA = 0x80;
......@@ -294,6 +298,15 @@ lca_init_arch(void)
* data parity errors.
*/
*(vulp)LCA_IOC_PAR_DIS = 1UL<<5;
/*
* Finally, set up for restoring the correct HAE if using SRM.
* Again, since we cannot read many of the CSRs on the LCA,
* one of which happens to be the HAE, we save the value that
* the SRM will expect...
*/
if (alpha_using_srm)
srm_hae = 0x80000000UL;
}
/*
......
......@@ -21,6 +21,7 @@
#include <linux/bootmem.h>
#include <linux/module.h>
#include <linux/cache.h>
#include <linux/slab.h>
#include <asm/machvec.h>
#include "proto.h"
......@@ -44,7 +45,11 @@ const char *const pci_mem_names[] = {
const char pci_hae0_name[] = "HAE0";
/* Indicate whether we respect the PCI setup left by console. */
int __initdata pci_probe_only;
/*
* Make this long-lived so that we know when shutting down
* whether we probed only or not.
*/
int pci_probe_only;
/*
* The PCI controller list.
......@@ -202,6 +207,52 @@ pcibios_setup(char *str)
return str;
}
#ifdef ALPHA_RESTORE_SRM_SETUP
static struct pdev_srm_saved_conf *srm_saved_configs;
void __init
pdev_save_srm_config(struct pci_dev *dev)
{
struct pdev_srm_saved_conf *tmp;
static int printed = 0;
if (!alpha_using_srm || pci_probe_only)
return;
if (!printed) {
printk(KERN_INFO "pci: enabling save/restore of SRM state\n");
printed = 1;
}
tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
if (!tmp) {
printk(KERN_ERR "%s: kmalloc() failed!\n", __FUNCTION__);
return;
}
tmp->next = srm_saved_configs;
tmp->dev = dev;
pci_save_state(dev, tmp->regs);
srm_saved_configs = tmp;
}
void
pci_restore_srm_config(void)
{
struct pdev_srm_saved_conf *tmp;
/* No need to restore if probed only. */
if (pci_probe_only)
return;
/* Restore SRM config. */
for (tmp = srm_saved_configs; tmp; tmp = tmp->next) {
pci_restore_state(tmp->dev, tmp->regs);
}
}
#endif
void __init
pcibios_fixup_resource(struct resource *res, struct resource *root)
{
......@@ -260,6 +311,8 @@ pcibios_fixup_bus(struct pci_bus *bus)
for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) {
struct pci_dev *dev = pci_dev_b(ln);
pdev_save_srm_config(dev);
if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI)
pcibios_fixup_device_resources(dev, bus);
}
......@@ -269,8 +322,6 @@ void __init
pcibios_update_irq(struct pci_dev *dev, int irq)
{
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
/* ??? FIXME -- record old value for shutdown. */
}
/* Most Alphas have straight-forward swizzling needs. */
......@@ -278,20 +329,16 @@ pcibios_update_irq(struct pci_dev *dev, int irq)
u8 __init
common_swizzle(struct pci_dev *dev, u8 *pinp)
{
struct pci_controller *hose = dev->sysdata;
if (dev->bus != hose->bus) {
u8 pin = *pinp;
do {
while (dev->bus->parent) {
pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
/* Move up the chain of bridges. */
dev = dev->bus->self;
} while (dev->bus->parent);
}
*pinp = pin;
/* The slot is the slot of the last bridge. */
}
return PCI_SLOT(dev->devfn);
}
......
......@@ -147,6 +147,33 @@ struct pci_iommu_arena
unsigned int align_entry;
};
#if defined(CONFIG_ALPHA_SRM) && \
(defined(CONFIG_ALPHA_CIA) || defined(CONFIG_ALPHA_LCA))
# define NEED_SRM_SAVE_RESTORE
#else
# undef NEED_SRM_SAVE_RESTORE
#endif
#if defined(CONFIG_ALPHA_GENERIC) || defined(NEED_SRM_SAVE_RESTORE)
# define ALPHA_RESTORE_SRM_SETUP
#else
# undef ALPHA_RESTORE_SRM_SETUP
#endif
#ifdef ALPHA_RESTORE_SRM_SETUP
/* Store PCI device configuration left by SRM here. */
struct pdev_srm_saved_conf
{
struct pdev_srm_saved_conf *next;
struct pci_dev *dev;
u32 regs[16];
};
extern void pci_restore_srm_config(void);
#else
#define pdev_save_srm_config(dev) do {} while (0)
#define pci_restore_srm_config() do {} while (0)
#endif
/* The hose list. */
extern struct pci_controller *hose_head, **hose_tail;
......
......@@ -129,7 +129,7 @@ common_shutdown_1(void *generic_ptr)
/* This has the effect of resetting the VGA video origin. */
take_over_console(&dummy_con, 0, MAX_NR_CONSOLES-1, 1);
#endif
/* reset_for_srm(); */
pci_restore_srm_config();
set_hae(srm_hae);
}
......
......@@ -223,6 +223,7 @@ alcor_kill_arch(int mode)
{
cia_kill_arch(mode);
#ifndef ALPHA_RESTORE_SRM_SETUP
switch(mode) {
case LINUX_REBOOT_CMD_RESTART:
/* Who said DEC engineer's have no sense of humor? ;-) */
......@@ -238,6 +239,29 @@ alcor_kill_arch(int mode)
}
halt();
#endif
}
static void __init
alcor_init_pci(void)
{
struct pci_dev *dev;
cia_init_pci();
/*
* Now we can look to see if we are really running on an XLT-type
* motherboard, by looking for a 21040 TULIP in slot 6, which is
* built into XLT and BRET/MAVERICK, but not available on ALCOR.
*/
dev = pci_find_device(PCI_VENDOR_ID_DEC,
PCI_DEVICE_ID_DEC_TULIP,
NULL);
if (dev && dev->devfn == PCI_DEVFN(6,0)) {
alpha_mv.sys.cia.gru_int_req_bits = XLT_GRU_INT_REQ_BITS;
printk(KERN_INFO "%s: Detected AS500 or XLT motherboard.\n",
__FUNCTION__);
}
}
......@@ -262,7 +286,7 @@ struct alpha_machine_vector alcor_mv __initmv = {
.init_arch = cia_init_arch,
.init_irq = alcor_init_irq,
.init_rtc = common_init_rtc,
.init_pci = cia_init_pci,
.init_pci = alcor_init_pci,
.kill_arch = alcor_kill_arch,
.pci_map_irq = alcor_map_irq,
.pci_swizzle = common_swizzle,
......@@ -290,7 +314,7 @@ struct alpha_machine_vector xlt_mv __initmv = {
.init_arch = cia_init_arch,
.init_irq = alcor_init_irq,
.init_rtc = common_init_rtc,
.init_pci = cia_init_pci,
.init_pci = alcor_init_pci,
.kill_arch = alcor_kill_arch,
.pci_map_irq = alcor_map_irq,
.pci_swizzle = common_swizzle,
......
......@@ -240,6 +240,7 @@ miata_kill_arch(int mode)
{
cia_kill_arch(mode);
#ifndef ALPHA_RESTORE_SRM_SETUP
switch(mode) {
case LINUX_REBOOT_CMD_RESTART:
/* Who said DEC engineers have no sense of humor? ;-) */
......@@ -255,6 +256,7 @@ miata_kill_arch(int mode)
}
halt();
#endif
}
......
......@@ -36,6 +36,14 @@
#include "pci_impl.h"
#include "machvec_impl.h"
#if defined(ALPHA_RESTORE_SRM_SETUP)
/* Save LCA configuration data as the console had it set up. */
struct
{
unsigned int orig_route_tab; /* for SAVE/RESTORE */
} saved_config __attribute((common));
#endif
static void __init
sio_init_irq(void)
......@@ -77,6 +85,15 @@ alphabook1_init_arch(void)
static void __init
sio_pci_route(void)
{
#if defined(ALPHA_RESTORE_SRM_SETUP)
/* First, read and save the original setting. */
pci_bus_read_config_dword(pci_isa_hose->bus, PCI_DEVFN(7, 0), 0x60,
&saved_config.orig_route_tab);
printk("%s: PIRQ original 0x%x new 0x%x\n", __FUNCTION__,
saved_config.orig_route_tab, alpha_mv.sys.sio.route_tab);
#endif
/* Now override with desired setting. */
pci_bus_write_config_dword(pci_isa_hose->bus, PCI_DEVFN(7, 0), 0x60,
alpha_mv.sys.sio.route_tab);
}
......@@ -245,6 +262,21 @@ alphabook1_init_pci(void)
outb(0x0f, 0x3ce); outb(orig, 0x3cf); /* (re)lock PR0-4 */
}
void
sio_kill_arch(int mode)
{
#if defined(ALPHA_RESTORE_SRM_SETUP)
/* Since we cannot read the PCI DMA Window CSRs, we
* cannot restore them here.
*
* However, we CAN read the PIRQ route register, so restore it
* now...
*/
pci_bus_write_config_dword(pci_isa_hose->bus, PCI_DEVFN(7, 0), 0x60,
saved_config.orig_route_tab);
#endif
}
/*
* The System Vectors
......@@ -269,7 +301,7 @@ struct alpha_machine_vector alphabook1_mv __initmv = {
.init_irq = sio_init_irq,
.init_rtc = common_init_rtc,
.init_pci = alphabook1_init_pci,
.kill_arch = NULL,
.kill_arch = sio_kill_arch,
.pci_map_irq = noname_map_irq,
.pci_swizzle = common_swizzle,
......@@ -300,6 +332,7 @@ struct alpha_machine_vector avanti_mv __initmv = {
.init_irq = sio_init_irq,
.init_rtc = common_init_rtc,
.init_pci = noname_init_pci,
.kill_arch = sio_kill_arch,
.pci_map_irq = noname_map_irq,
.pci_swizzle = common_swizzle,
......@@ -329,6 +362,7 @@ struct alpha_machine_vector noname_mv __initmv = {
.init_irq = sio_init_irq,
.init_rtc = common_init_rtc,
.init_pci = noname_init_pci,
.kill_arch = sio_kill_arch,
.pci_map_irq = noname_map_irq,
.pci_swizzle = common_swizzle,
......@@ -367,6 +401,7 @@ struct alpha_machine_vector p2k_mv __initmv = {
.init_irq = sio_init_irq,
.init_rtc = common_init_rtc,
.init_pci = noname_init_pci,
.kill_arch = sio_kill_arch,
.pci_map_irq = p2k_map_irq,
.pci_swizzle = common_swizzle,
......@@ -396,6 +431,7 @@ struct alpha_machine_vector xl_mv __initmv = {
.init_irq = sio_init_irq,
.init_rtc = common_init_rtc,
.init_pci = noname_init_pci,
.kill_arch = sio_kill_arch,
.pci_map_irq = noname_map_irq,
.pci_swizzle = common_swizzle,
......
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