1/* Board-specific reboot/shutdown routines 2 * 3 * Copyright (c) 2009 Philippe Vachon <philippe@cowpig.ca> 4 * 5 * Copyright (C) 2009 Lemote Inc. 6 * Author: Wu Zhangjin, wuzhangjin@gmail.com 7 * 8 * This program is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU General Public License as published by the 10 * Free Software Foundation; either version 2 of the License, or (at your 11 * option) any later version. 12 */ 13 14#include <linux/io.h> 15#include <linux/delay.h> 16#include <linux/types.h> 17 18#include <asm/bootinfo.h> 19 20#include <loongson.h> 21 22#include <cs5536/cs5536.h> 23#include "ec_kb3310b.h" 24 25static void reset_cpu(void) 26{ 27 /* 28 * reset cpu to full speed, this is needed when enabling cpu frequency 29 * scalling 30 */ 31 LOONGSON_CHIPCFG(0) |= 0x7; 32} 33 34/* reset support for fuloong2f */ 35 36static void fl2f_reboot(void) 37{ 38 reset_cpu(); 39 40 /* send a reset signal to south bridge. 41 * 42 * NOTE: if enable "Power Management" in kernel, rtl8169 will not reset 43 * normally with this reset operation and it will not work in PMON, but 44 * you can type halt command and then reboot, seems the hardware reset 45 * logic not work normally. 46 */ 47 { 48 u32 hi, lo; 49 _rdmsr(DIVIL_MSR_REG(DIVIL_SOFT_RESET), &hi, &lo); 50 lo |= 0x00000001; 51 _wrmsr(DIVIL_MSR_REG(DIVIL_SOFT_RESET), hi, lo); 52 } 53} 54 55static void fl2f_shutdown(void) 56{ 57 u32 hi, lo, val; 58 int gpio_base; 59 60 /* get gpio base */ 61 _rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_GPIO), &hi, &lo); 62 gpio_base = lo & 0xff00; 63 64 /* make cs5536 gpio13 output enable */ 65 val = inl(gpio_base + GPIOL_OUT_EN); 66 val &= ~(1 << (16 + 13)); 67 val |= (1 << 13); 68 outl(val, gpio_base + GPIOL_OUT_EN); 69 mmiowb(); 70 /* make cs5536 gpio13 output low level voltage. */ 71 val = inl(gpio_base + GPIOL_OUT_VAL) & ~(1 << (13)); 72 val |= (1 << (16 + 13)); 73 outl(val, gpio_base + GPIOL_OUT_VAL); 74 mmiowb(); 75} 76 77/* reset support for yeeloong2f and mengloong2f notebook */ 78 79static void ml2f_reboot(void) 80{ 81 reset_cpu(); 82 83 /* sending an reset signal to EC(embedded controller) */ 84 ec_write(REG_RESET, BIT_RESET_ON); 85} 86 87#define yl2f89_reboot ml2f_reboot 88 89/* menglong(7inches) laptop has different shutdown logic from 8.9inches */ 90#define EC_SHUTDOWN_IO_PORT_HIGH 0xff2d 91#define EC_SHUTDOWN_IO_PORT_LOW 0xff2e 92#define EC_SHUTDOWN_IO_PORT_DATA 0xff2f 93#define REG_SHUTDOWN_HIGH 0xFC 94#define REG_SHUTDOWN_LOW 0x29 95#define BIT_SHUTDOWN_ON (1 << 1) 96 97static void ml2f_shutdown(void) 98{ 99 u8 val; 100 u64 i; 101 102 outb(REG_SHUTDOWN_HIGH, EC_SHUTDOWN_IO_PORT_HIGH); 103 outb(REG_SHUTDOWN_LOW, EC_SHUTDOWN_IO_PORT_LOW); 104 mmiowb(); 105 val = inb(EC_SHUTDOWN_IO_PORT_DATA); 106 outb(val & (~BIT_SHUTDOWN_ON), EC_SHUTDOWN_IO_PORT_DATA); 107 mmiowb(); 108 /* need enough wait here... how many microseconds needs? */ 109 for (i = 0; i < 0x10000; i++) 110 delay(); 111 outb(val | BIT_SHUTDOWN_ON, EC_SHUTDOWN_IO_PORT_DATA); 112 mmiowb(); 113} 114 115static void yl2f89_shutdown(void) 116{ 117 /* cpu-gpio0 output low */ 118 LOONGSON_GPIODATA &= ~0x00000001; 119 /* cpu-gpio0 as output */ 120 LOONGSON_GPIOIE &= ~0x00000001; 121} 122 123void mach_prepare_reboot(void) 124{ 125 switch (mips_machtype) { 126 case MACH_LEMOTE_FL2F: 127 case MACH_LEMOTE_NAS: 128 case MACH_LEMOTE_LL2F: 129 fl2f_reboot(); 130 break; 131 case MACH_LEMOTE_ML2F7: 132 ml2f_reboot(); 133 break; 134 case MACH_LEMOTE_YL2F89: 135 yl2f89_reboot(); 136 break; 137 default: 138 break; 139 } 140} 141 142void mach_prepare_shutdown(void) 143{ 144 switch (mips_machtype) { 145 case MACH_LEMOTE_FL2F: 146 case MACH_LEMOTE_NAS: 147 case MACH_LEMOTE_LL2F: 148 fl2f_shutdown(); 149 break; 150 case MACH_LEMOTE_ML2F7: 151 ml2f_shutdown(); 152 break; 153 case MACH_LEMOTE_YL2F89: 154 yl2f89_shutdown(); 155 break; 156 default: 157 break; 158 } 159} 160