Commit 7b71051f authored by Paul Mackerras's avatar Paul Mackerras

Merge samba.org:/stuff/paulus/kernel/linux-2.5

into samba.org:/stuff/paulus/kernel/for-linus-ppc
parents 7c6c04c2 1e050781
......@@ -23,11 +23,10 @@ map(unsigned int phys, unsigned int virt, unsigned int size)
char *method;
ihandle mmu_ihandle;
int misc;
unsigned int phys;
unsigned int virt;
unsigned int size;
unsigned int virt;
unsigned int phys;
int ret0;
int ret1;
} args;
if (of_prom_mmu == 0) {
......@@ -36,10 +35,10 @@ map(unsigned int phys, unsigned int virt, unsigned int size)
}
args.service = "call-method";
args.nargs = 6;
args.nret = 2;
args.nret = 1;
args.method = "map";
args.mmu_ihandle = of_prom_mmu;
args.misc = -1;
args.misc = 0;
args.phys = phys;
args.virt = virt;
args.size = size;
......
......@@ -38,9 +38,9 @@ static char heap[SCRATCH_SIZE];
static unsigned long ram_start = 0;
static unsigned long ram_end = 0x1000000;
static unsigned long prog_start = 0x800000;
static unsigned long prog_size = 0x800000;
static unsigned long prog_start = 0x900000;
static unsigned long prog_size = 0x700000;
typedef void (*kernel_start_t)(int, int, void *);
......
......@@ -181,26 +181,8 @@ __after_mmu_off:
bl setup_disp_bat
#endif
#else /* CONFIG_POWER4 */
/*
* Load up the SDR1 and segment register values now
* since we don't have the BATs.
* Also make sure we are running in 32-bit mode.
*/
bl reloc_offset
addis r14,r3,_SDR1@ha /* get the value from _SDR1 */
lwz r14,_SDR1@l(r14) /* assume hash table below 4GB */
mtspr SDR1,r14
slbia
lis r4,0x2000 /* set pseudo-segment reg 12 */
ori r5,r4,0x0ccc
mtsr 12,r5
ori r4,r4,0x0888 /* set pseudo-segment reg 8 */
mtsr 8,r4 /* (for access to serial port) */
mfmsr r0
clrldi r0,r0,1
sync
mtmsr r0
isync
bl initial_mm_power4
#endif /* CONFIG_POWER4 */
/*
......@@ -1637,6 +1619,34 @@ setup_disp_bat:
#endif /* !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT) */
#else /* CONFIG_POWER4 */
/*
* Load up the SDR1 and segment register values now
* since we don't have the BATs.
* Also make sure we are running in 32-bit mode.
*/
initial_mm_power4:
addis r14,r3,_SDR1@ha /* get the value from _SDR1 */
lwz r14,_SDR1@l(r14) /* assume hash table below 4GB */
mtspr SDR1,r14
slbia
lis r4,0x2000 /* set pseudo-segment reg 12 */
ori r5,r4,0x0ccc
mtsr 12,r5
ori r5,r4,0x0888 /* set pseudo-segment reg 8 */
mtsr 8,r5 /* (for access to serial port) */
ori r5,r4,0x0999 /* set pseudo-segment reg 8 */
mtsr 9,r5 /* (for access to screen) */
mfmsr r0
clrldi r0,r0,1
sync
mtmsr r0
isync
blr
/*
* On 970 (G5), we pre-set a few bits in HID0 & HID1
*/
ppc970_setup_hid:
li r0,0
sync
......
......@@ -367,11 +367,17 @@ EXPORT_SYMBOL(next_mmu_context);
EXPORT_SYMBOL(set_context);
EXPORT_SYMBOL(handle_mm_fault); /* For MOL */
EXPORT_SYMBOL_NOVERS(disarm_decr);
extern long mol_trampoline;
EXPORT_SYMBOL(mol_trampoline); /* For MOL */
#ifdef CONFIG_PPC_STD_MMU
EXPORT_SYMBOL(flush_hash_pages); /* For MOL */
#ifdef CONFIG_SMP
extern int mmu_hash_lock;
EXPORT_SYMBOL(mmu_hash_lock); /* For MOL */
#endif /* CONFIG_SMP */
extern long *intercept_table;
EXPORT_SYMBOL(intercept_table);
#endif
#endif /* CONFIG_PPC_STD_MMU */
EXPORT_SYMBOL(cur_cpu_spec);
#ifdef CONFIG_PPC_PMAC
extern unsigned long agp_special_page;
......
......@@ -56,6 +56,7 @@ static struct files_struct init_files = INIT_FILES;
static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
struct mm_struct init_mm = INIT_MM(init_mm);
EXPORT_SYMBOL(init_mm);
/* this is 8kB-aligned so we can get to the thread_info struct
at the base of it from the stack pointer with 1 integer instruction. */
......
......@@ -417,6 +417,21 @@ _GLOBAL(hash_page_patch_C)
lwz r6,next_slot@l(r4)
addi r6,r6,PTE_SIZE
andi. r6,r6,7*PTE_SIZE
#ifdef CONFIG_POWER4
/*
* Since we don't have BATs on POWER4, we rely on always having
* PTEs in the hash table to map the hash table and the code
* that manipulates it in virtual mode, namely flush_hash_page and
* flush_hash_segments. Otherwise we can get a DSI inside those
* routines which leads to a deadlock on the hash_table_lock on
* SMP machines. We avoid this by never overwriting the first
* PTE of each PTEG if it is already valid.
* -- paulus.
*/
bne 102f
li r6,PTE_SIZE
102:
#endif /* CONFIG_POWER4 */
stw r6,next_slot@l(r4)
add r4,r3,r6
......
......@@ -211,6 +211,17 @@ void __init MMU_init_hw(void)
#define MIN_N_HPTEG 1024 /* min 64kB hash table */
#endif
#ifdef CONFIG_POWER4
/* The hash table has already been allocated and initialized
in prom.c */
n_hpteg = Hash_size >> LG_HPTEG_SIZE;
lg_n_hpteg = __ilog2(n_hpteg);
/* Remove the hash table from the available memory */
if (Hash)
reserve_phys_mem(__pa(Hash), Hash_size);
#else /* CONFIG_POWER4 */
/*
* Allow 1 HPTE (1/8 HPTEG) for each page of memory.
* This is less than the recommended amount, but then
......@@ -224,13 +235,7 @@ void __init MMU_init_hw(void)
++lg_n_hpteg; /* round up if not power of 2 */
n_hpteg = 1 << lg_n_hpteg;
}
Hash_size = n_hpteg << LG_HPTEG_SIZE;
Hash_mask = n_hpteg - 1;
hmask = Hash_mask >> (16 - LG_HPTEG_SIZE);
mb2 = mb = 32 - LG_HPTEG_SIZE - lg_n_hpteg;
if (lg_n_hpteg > 16)
mb2 = 16 - LG_HPTEG_SIZE;
/*
* Find some memory for the hash table.
......@@ -240,6 +245,7 @@ void __init MMU_init_hw(void)
cacheable_memzero(Hash, Hash_size);
_SDR1 = __pa(Hash) | SDR1_LOW_BITS;
Hash_end = (PTE *) ((unsigned long)Hash + Hash_size);
#endif /* CONFIG_POWER4 */
printk("Total memory = %ldMB; using %ldkB for hash table (at %p)\n",
total_memory >> 20, Hash_size >> 10, Hash);
......@@ -249,6 +255,12 @@ void __init MMU_init_hw(void)
* Patch up the instructions in hashtable.S:create_hpte
*/
if ( ppc_md.progress ) ppc_md.progress("hash:patch", 0x345);
Hash_mask = n_hpteg - 1;
hmask = Hash_mask >> (16 - LG_HPTEG_SIZE);
mb2 = mb = 32 - LG_HPTEG_SIZE - lg_n_hpteg;
if (lg_n_hpteg > 16)
mb2 = 16 - LG_HPTEG_SIZE;
hash_page_patch_A[0] = (hash_page_patch_A[0] & ~0xffff)
| ((unsigned int)(Hash) >> 16);
hash_page_patch_A[1] = (hash_page_patch_A[1] & ~0x7c0) | (mb << 6);
......
......@@ -51,6 +51,7 @@
#include <asm/time.h>
#include <asm/open_pic.h>
#include <asm/cacheflush.h>
#include <asm/keylargo.h>
/*
* Powersurge (old powermac SMP) support.
......@@ -108,9 +109,16 @@ static volatile u32 *psurge_start;
/* what sort of powersurge board we have */
static int psurge_type = PSURGE_NONE;
/* L2 and L3 cache settings to pass from CPU0 to CPU1 */
volatile static long int core99_l2_cache;
volatile static long int core99_l3_cache;
/* Timebase freeze GPIO */
static unsigned int core99_tb_gpio;
/* Sync flag for HW tb sync */
static volatile int sec_tb_reset = 0;
static void __init
core99_init_caches(int cpu)
{
......@@ -380,7 +388,6 @@ static void __init smp_psurge_kick_cpu(int nr)
*/
static void __init psurge_dual_sync_tb(int cpu_nr)
{
static volatile int sec_tb_reset = 0;
int t;
set_dec(tb_ticks_per_jiffy);
......@@ -408,8 +415,15 @@ smp_psurge_setup_cpu(int cpu_nr)
{
if (cpu_nr == 0) {
if (num_online_cpus() < 2)
/* If we failed to start the second CPU, we should still
* send it an IPI to start the timebase & DEC or we might
* have them stuck.
*/
if (num_online_cpus() < 2) {
if (psurge_type == PSURGE_DUAL)
psurge_set_ipi(1);
return;
}
/* reset the entry point so if we get another intr we won't
* try to startup again */
out_be32(psurge_start, 0x100);
......@@ -421,19 +435,42 @@ smp_psurge_setup_cpu(int cpu_nr)
psurge_dual_sync_tb(cpu_nr);
}
void __init
smp_psurge_take_timebase(void)
{
/* Dummy implementation */
}
void __init
smp_psurge_give_timebase(void)
{
/* Dummy implementation */
}
static int __init
smp_core99_probe(void)
{
extern int powersave_nap;
struct device_node *cpus;
int i, ncpus = 1;
extern int powersave_nap;
u32 *tbprop;
if (ppc_md.progress) ppc_md.progress("smp_core99_probe", 0x345);
cpus = find_type_devices("cpu");
if (cpus)
while ((cpus = cpus->next) != NULL)
++ncpus;
if (cpus == NULL)
return 0;
tbprop = (u32 *)get_property(cpus, "timebase-enable", NULL);
if (tbprop)
core99_tb_gpio = *tbprop;
else
core99_tb_gpio = KL_GPIO_TB_ENABLE;
while ((cpus = cpus->next) != NULL)
++ncpus;
printk("smp_core99_probe: found %d cpus\n", ncpus);
if (ncpus > 1) {
openpic_request_IPIs();
for (i = 1; i < ncpus; ++i)
......@@ -517,14 +554,59 @@ smp_core99_setup_cpu(int cpu_nr)
if (ppc_md.progress) ppc_md.progress("core99_setup_cpu 0 done", 0x349);
}
void __init
smp_core99_take_timebase(void)
{
/* Secondary processor "takes" the timebase by freezing
* it, resetting its local TB and telling CPU 0 to go on
*/
pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, core99_tb_gpio, 4);
pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, core99_tb_gpio, 0);
mb();
set_dec(tb_ticks_per_jiffy);
set_tb(0, 0);
last_jiffy_stamp(smp_processor_id()) = 0;
mb();
sec_tb_reset = 1;
}
void __init
smp_core99_give_timebase(void)
{
unsigned int t;
/* Primary processor waits for secondary to have frozen
* the timebase, resets local TB, and kick timebase again
*/
/* wait for the secondary to have reset its TB before proceeding */
for (t = 1000; t > 0 && !sec_tb_reset; --t)
udelay(1000);
if (t == 0)
printk(KERN_WARNING "Timeout waiting sync on second CPU\n");
set_dec(tb_ticks_per_jiffy);
set_tb(0, 0);
last_jiffy_stamp(smp_processor_id()) = 0;
mb();
/* Now, restart the timebase by leaving the GPIO to an open collector */
pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, core99_tb_gpio, 0);
pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, core99_tb_gpio, 0);
smp_tb_synchronized = 1;
}
/* PowerSurge-style Macs */
struct smp_ops_t psurge_smp_ops __pmacdata = {
.message_pass = smp_psurge_message_pass,
.probe = smp_psurge_probe,
.kick_cpu = smp_psurge_kick_cpu,
.setup_cpu = smp_psurge_setup_cpu,
.give_timebase = smp_generic_give_timebase,
.take_timebase = smp_generic_take_timebase,
.give_timebase = smp_psurge_give_timebase,
.take_timebase = smp_psurge_take_timebase,
};
/* Core99 Macs (dual G4s) */
......@@ -533,6 +615,6 @@ struct smp_ops_t core99_smp_ops __pmacdata = {
.probe = smp_core99_probe,
.kick_cpu = smp_core99_kick_cpu,
.setup_cpu = smp_core99_setup_cpu,
.give_timebase = smp_generic_give_timebase,
.take_timebase = smp_generic_take_timebase,
.give_timebase = smp_core99_give_timebase,
.take_timebase = smp_core99_take_timebase,
};
......@@ -166,7 +166,7 @@ via_calibrate_decr(void)
{
struct device_node *vias;
volatile unsigned char *via;
int count = VIA_TIMER_FREQ_6 / HZ;
int count = VIA_TIMER_FREQ_6 / 100;
unsigned int dstart, dend;
vias = find_devices("via-cuda");
......@@ -196,7 +196,7 @@ via_calibrate_decr(void)
;
dend = get_dec();
tb_ticks_per_jiffy = (dstart - dend) / 6;
tb_ticks_per_jiffy = (dstart - dend) / (6 * (HZ/100));
tb_to_us = mulhwu_scale_factor(dstart - dend, 60000);
printk(KERN_INFO "via_calibrate_decr: ticks per jiffy = %u (%u ticks)\n",
......@@ -260,7 +260,9 @@ pmac_calibrate_decr(void)
* calibration. That's better since the VIA itself seems
* to be slightly off. --BenH
*/
if (!machine_is_compatible("MacRISC2"))
if (!machine_is_compatible("MacRISC2") &&
!machine_is_compatible("MacRISC3") &&
!machine_is_compatible("MacRISC4"))
if (via_calibrate_decr())
return;
......
......@@ -97,9 +97,9 @@ static int of_device_probe(struct device *dev)
static int of_device_remove(struct device *dev)
{
struct of_device * of_dev = to_of_device(dev);
struct of_platform_driver * drv = to_of_platform_driver(of_dev->dev.driver);
struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
if (drv && drv->remove)
if (dev->driver && drv->remove)
drv->remove(of_dev);
return 0;
}
......@@ -107,10 +107,10 @@ static int of_device_remove(struct device *dev)
static int of_device_suspend(struct device *dev, u32 state)
{
struct of_device * of_dev = to_of_device(dev);
struct of_platform_driver * drv = to_of_platform_driver(of_dev->dev.driver);
struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
int error = 0;
if (drv && drv->suspend)
if (dev->driver && drv->suspend)
error = drv->suspend(of_dev, state);
return error;
}
......@@ -118,10 +118,10 @@ static int of_device_suspend(struct device *dev, u32 state)
static int of_device_resume(struct device * dev)
{
struct of_device * of_dev = to_of_device(dev);
struct of_platform_driver * drv = to_of_platform_driver(of_dev->dev.driver);
struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
int error = 0;
if (drv && drv->resume)
if (dev->driver && drv->resume)
error = drv->resume(of_dev);
return error;
}
......
......@@ -611,8 +611,8 @@ adbhid_input_register(int id, int default_id, int original_handler_id,
/* HACK WARNING!! This should go away as soon there is an utility
* to control that for event devices.
*/
adbhid[id]->input.rep[REP_DELAY] = HZ/2; /* input layer default: HZ/4 */
adbhid[id]->input.rep[REP_PERIOD] = HZ/15; /* input layer default: HZ/33 */
adbhid[id]->input.rep[REP_DELAY] = 500; /* input layer default: 250 */
adbhid[id]->input.rep[REP_PERIOD] = 66; /* input layer default: 33 */
}
}
......
......@@ -1461,6 +1461,15 @@ imsttfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
unsigned long addr, size;
struct imstt_par *par;
struct fb_info *info;
#ifdef CONFIG_PPC_OF
struct device_node *dp;
dp = pci_device_to_OF_node(pdev);
if(dp)
printk(KERN_INFO "%s: OF name %s\n",__FUNCTION__, dp->name);
else
printk(KERN_ERR "imsttfb: no OF node for pci device\n");
#endif /* CONFIG_PPC_OF */
size = sizeof(struct fb_info) + sizeof(struct imstt_par) +
sizeof(u32) * 16;
......@@ -1488,6 +1497,11 @@ imsttfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
switch (pdev->device) {
case PCI_DEVICE_ID_IMS_TT128: /* IMS,tt128mbA */
par->ramdac = IBM;
#ifdef CONFIG_PPC_OF
if (dp && ((strcmp(dp->name, "IMS,tt128mb8") == 0) ||
(strcmp(dp->name, "IMS,tt128mb8A") == 0)))
par->ramdac = TVP;
#endif /* CONFIG_PPC_OF */
break;
case PCI_DEVICE_ID_IMS_TT3D: /* IMS,tt3d */
par->ramdac = TVP;
......
......@@ -87,6 +87,10 @@
#define SPRN_CTR 0x009 /* Count Register */
#define SPRN_DABR 0x3F5 /* Data Address Breakpoint Register */
#define SPRN_DAR 0x013 /* Data Address Register */
#define SPRN_TBRL 0x10C /* Time Base Read Lower Register (user, R/O) */
#define SPRN_TBRU 0x10D /* Time Base Read Upper Register (user, R/O) */
#define SPRN_TBWL 0x11C /* Time Base Lower Register (super, R/W) */
#define SPRN_TBWU 0x11D /* Time Base Upper Register (super, R/W) */
#define SPRN_DBAT0L 0x219 /* Data BAT 0 Lower Register */
#define SPRN_DBAT0U 0x218 /* Data BAT 0 Upper Register */
#define SPRN_DBAT1L 0x21B /* Data BAT 1 Lower Register */
......@@ -397,6 +401,10 @@
#define THRM2 SPRN_THRM2 /* Thermal Management Register 2 */
#define THRM3 SPRN_THRM3 /* Thermal Management Register 3 */
#define XER SPRN_XER
#define TBRL SPRN_TBRL /* Time Base Read Lower Register */
#define TBRU SPRN_TBRU /* Time Base Read Upper Register */
#define TBWL SPRN_TBWL /* Time Base Write Lower Register */
#define TBWU SPRN_TBWU /* Time Base Write Upper Register */
/* Processor Version Register */
......
......@@ -59,14 +59,10 @@ do { \
#define SPRN_SPRG5R 0x105 /* Special Purpose Register General 5 Read */
#define SPRN_SPRG6R 0x106 /* Special Purpose Register General 6 Read */
#define SPRN_SPRG7R 0x107 /* Special Purpose Register General 7 Read */
#define SPRN_TBRL 0x10C /* Time Base Read Lower Register (user, R/O) */
#define SPRN_TBRU 0x10D /* Time Base Read Upper Register (user, R/O) */
#define SPRN_SPRG4W 0x114 /* Special Purpose Register General 4 Write */
#define SPRN_SPRG5W 0x115 /* Special Purpose Register General 5 Write */
#define SPRN_SPRG6W 0x116 /* Special Purpose Register General 6 Write */
#define SPRN_SPRG7W 0x117 /* Special Purpose Register General 7 Write */
#define SPRN_TBWL 0x11C /* Time Base Lower Register (super, R/W) */
#define SPRN_TBWU 0x11D /* Time Base Upper Register (super, R/W) */
#define SPRN_DBCR2 0x136 /* Debug Control Register 2 */
#define SPRN_IAC3 0x13A /* Instruction Address Compare 3 */
#define SPRN_IAC4 0x13B /* Instruction Address Compare 4 */
......@@ -252,10 +248,6 @@ do { \
#define SPRG5W SPRN_SPRG5W
#define SPRG6W SPRN_SPRG6W
#define SPRG7W SPRN_SPRG7W
#define TBRL SPRN_TBRL /* Time Base Read Lower Register */
#define TBRU SPRN_TBRU /* Time Base Read Upper Register */
#define TBWL SPRN_TBWL /* Time Base Write Lower Register */
#define TBWU SPRN_TBWU /* Time Base Write Upper Register */
/*
* The IBM-403 is an even more odd special case, as it is much
......
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