linux/arch/sparc/kernel/tadpole.c
<<
>>
Prefs
   1/* tadpole.c: Probing for the tadpole clock stopping h/w at boot time.
   2 *
   3 * Copyright (C) 1996 David Redman (djhr@tadpole.co.uk)
   4 */
   5
   6#include <linux/string.h>
   7#include <linux/kernel.h>
   8#include <linux/sched.h>
   9#include <linux/init.h>
  10
  11#include <asm/asi.h>
  12#include <asm/oplib.h>
  13#include <asm/io.h>
  14
  15#define MACIO_SCSI_CSR_ADDR     0x78400000
  16#define MACIO_EN_DMA            0x00000200
  17#define CLOCK_INIT_DONE         1
  18
  19static int clk_state;
  20static volatile unsigned char *clk_ctrl;
  21void (*cpu_pwr_save)(void);
  22
  23static inline unsigned int ldphys(unsigned int addr)
  24{
  25        unsigned long data;
  26    
  27        __asm__ __volatile__("\n\tlda [%1] %2, %0\n\t" : 
  28                             "=r" (data) :
  29                             "r" (addr), "i" (ASI_M_BYPASS));
  30        return data;
  31}
  32
  33static void clk_init(void)
  34{
  35        __asm__ __volatile__("mov 0x6c, %%g1\n\t"
  36                             "mov 0x4c, %%g2\n\t"
  37                             "mov 0xdf, %%g3\n\t"
  38                             "stb %%g1, [%0+3]\n\t"
  39                             "stb %%g2, [%0+3]\n\t"
  40                             "stb %%g3, [%0+3]\n\t" : :
  41                             "r" (clk_ctrl) :
  42                             "g1", "g2", "g3");
  43}
  44
  45static void clk_slow(void)
  46{
  47        __asm__ __volatile__("mov 0xcc, %%g2\n\t"
  48                             "mov 0x4c, %%g3\n\t"
  49                             "mov 0xcf, %%g4\n\t"
  50                             "mov 0xdf, %%g5\n\t"
  51                             "stb %%g2, [%0+3]\n\t"
  52                             "stb %%g3, [%0+3]\n\t"
  53                             "stb %%g4, [%0+3]\n\t"
  54                             "stb %%g5, [%0+3]\n\t" : :
  55                             "r" (clk_ctrl) :
  56                             "g2", "g3", "g4", "g5");
  57}
  58
  59/*
  60 * Tadpole is guaranteed to be UP, using local_irq_save.
  61 */
  62static void tsu_clockstop(void)
  63{
  64        unsigned int mcsr;
  65        unsigned long flags;
  66
  67        if (!clk_ctrl)
  68                return;
  69        if (!(clk_state & CLOCK_INIT_DONE)) {
  70                local_irq_save(flags);
  71                clk_init();
  72                clk_state |= CLOCK_INIT_DONE;       /* all done */
  73                local_irq_restore(flags);
  74                return;
  75        }
  76        if (!(clk_ctrl[2] & 1))
  77                return;               /* no speed up yet */
  78
  79        local_irq_save(flags);
  80
  81        /* if SCSI DMA in progress, don't slow clock */
  82        mcsr = ldphys(MACIO_SCSI_CSR_ADDR);
  83        if ((mcsr&MACIO_EN_DMA) != 0) {
  84                local_irq_restore(flags);
  85                return;
  86        }
  87        /* TODO... the minimum clock setting ought to increase the
  88         * memory refresh interval..
  89         */
  90        clk_slow();
  91        local_irq_restore(flags);
  92}
  93
  94static void swift_clockstop(void)
  95{
  96        if (!clk_ctrl)
  97                return;
  98        clk_ctrl[0] = 0;
  99}
 100
 101void __init clock_stop_probe(void)
 102{
 103        unsigned int node, clk_nd;
 104        char name[20];
 105    
 106        prom_getstring(prom_root_node, "name", name, sizeof(name));
 107        if (strncmp(name, "Tadpole", 7))
 108                return;
 109        node = prom_getchild(prom_root_node);
 110        node = prom_searchsiblings(node, "obio");
 111        node = prom_getchild(node);
 112        clk_nd = prom_searchsiblings(node, "clk-ctrl");
 113        if (!clk_nd)
 114                return;
 115        printk("Clock Stopping h/w detected... ");
 116        clk_ctrl = (char *) prom_getint(clk_nd, "address");
 117        clk_state = 0;
 118        if (name[10] == '\0') {
 119                cpu_pwr_save = tsu_clockstop;
 120                printk("enabled (S3)\n");
 121        } else if ((name[10] == 'X') || (name[10] == 'G')) {
 122                cpu_pwr_save = swift_clockstop;
 123                printk("enabled (%s)\n",name+7);
 124        } else
 125                printk("disabled %s\n",name+7);
 126}
 127