Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

MIPS: Lemote 2F: Add reset support

Fuloong 2F, Yeeloong 2F and Menglong 2F have different reset / shutdown
logic.

Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
Cc: zhangfx@lemote.com
Cc: yanh@lemote.com
Cc: huhb@lemote.com
Cc: Nicholas Mc Guire <hofrat@hofr.at>
Cc: Arnaud Patard <apatard@mandriva.com>
Cc: loongson-dev@googlegroups.com
Cc: linux-mips@linux-mips.org
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>

authored by

Wu Zhangjin and committed by
Ralf Baechle
2ee98e0f 6616db78

+180 -1
+7
arch/mips/include/asm/mach-loongson/loongson.h
··· 42 42 extern void __init mach_init_irq(void); 43 43 extern void mach_irq_dispatch(unsigned int pending); 44 44 45 + /* We need this in some places... */ 46 + #define delay() ({ \ 47 + int x; \ 48 + for (x = 0; x < 100000; x++) \ 49 + __asm__ __volatile__(""); \ 50 + }) 51 + 45 52 #define LOONGSON_REG(x) \ 46 53 (*(volatile u32 *)((char *)CKSEG1ADDR(LOONGSON_REG_BASE) + (x))) 47 54
+1 -1
arch/mips/loongson/lemote-2f/Makefile
··· 2 2 # Makefile for lemote loongson2f family machines 3 3 # 4 4 5 - obj-y += irq.o 5 + obj-y += irq.o reset.o
+172
arch/mips/loongson/lemote-2f/reset.c
··· 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, wuzj@lemote.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 + 24 + static void reset_cpu(void) 25 + { 26 + /* 27 + * reset cpu to full speed, this is needed when enabling cpu frequency 28 + * scalling 29 + */ 30 + LOONGSON_CHIPCFG0 |= 0x7; 31 + } 32 + 33 + /* reset support for fuloong2f */ 34 + 35 + static void fl2f_reboot(void) 36 + { 37 + reset_cpu(); 38 + 39 + /* send a reset signal to south bridge. 40 + * 41 + * NOTE: if enable "Power Management" in kernel, rtl8169 will not reset 42 + * normally with this reset operation and it will not work in PMON, but 43 + * you can type halt command and then reboot, seems the hardware reset 44 + * logic not work normally. 45 + */ 46 + { 47 + u32 hi, lo; 48 + _rdmsr(DIVIL_MSR_REG(DIVIL_SOFT_RESET), &hi, &lo); 49 + lo |= 0x00000001; 50 + _wrmsr(DIVIL_MSR_REG(DIVIL_SOFT_RESET), hi, lo); 51 + } 52 + } 53 + 54 + static void fl2f_shutdown(void) 55 + { 56 + u32 hi, lo, val; 57 + int gpio_base; 58 + 59 + /* get gpio base */ 60 + _rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_GPIO), &hi, &lo); 61 + gpio_base = lo & 0xff00; 62 + 63 + /* make cs5536 gpio13 output enable */ 64 + val = inl(gpio_base + GPIOL_OUT_EN); 65 + val &= ~(1 << (16 + 13)); 66 + val |= (1 << 13); 67 + outl(val, gpio_base + GPIOL_OUT_EN); 68 + mmiowb(); 69 + /* make cs5536 gpio13 output low level voltage. */ 70 + val = inl(gpio_base + GPIOL_OUT_VAL) & ~(1 << (13)); 71 + val |= (1 << (16 + 13)); 72 + outl(val, gpio_base + GPIOL_OUT_VAL); 73 + mmiowb(); 74 + } 75 + 76 + /* reset support for yeeloong2f and mengloong2f notebook */ 77 + 78 + /* 79 + * The following registers are determined by the EC index configuration. 80 + * 1. fill the PORT_HIGH as EC register high part. 81 + * 2. fill the PORT_LOW as EC register low part. 82 + * 3. fill the PORT_DATA as EC register write data or get the data from it. 83 + */ 84 + 85 + #define EC_IO_PORT_HIGH 0x0381 86 + #define EC_IO_PORT_LOW 0x0382 87 + #define EC_IO_PORT_DATA 0x0383 88 + #define REG_RESET_HIGH 0xF4 /* reset the machine auto-clear : rd/wr */ 89 + #define REG_RESET_LOW 0xEC 90 + #define BIT_RESET_ON (1 << 0) 91 + 92 + void ml2f_reboot(void) 93 + { 94 + reset_cpu(); 95 + 96 + /* sending an reset signal to EC(embedded controller) */ 97 + outb(REG_RESET_HIGH, EC_IO_PORT_HIGH); 98 + outb(REG_RESET_LOW, EC_IO_PORT_LOW); 99 + mmiowb(); 100 + outb(BIT_RESET_ON, EC_IO_PORT_DATA); 101 + mmiowb(); 102 + } 103 + 104 + #define yl2f89_reboot ml2f_reboot 105 + 106 + /* menglong(7inches) laptop has different shutdown logic from 8.9inches */ 107 + #define EC_SHUTDOWN_IO_PORT_HIGH 0xff2d 108 + #define EC_SHUTDOWN_IO_PORT_LOW 0xff2e 109 + #define EC_SHUTDOWN_IO_PORT_DATA 0xff2f 110 + #define REG_SHUTDOWN_HIGH 0xFC 111 + #define REG_SHUTDOWN_LOW 0x29 112 + #define BIT_SHUTDOWN_ON (1 << 1) 113 + 114 + static void ml2f_shutdown(void) 115 + { 116 + u8 val; 117 + u64 i; 118 + 119 + outb(REG_SHUTDOWN_HIGH, EC_SHUTDOWN_IO_PORT_HIGH); 120 + outb(REG_SHUTDOWN_LOW, EC_SHUTDOWN_IO_PORT_LOW); 121 + mmiowb(); 122 + val = inb(EC_SHUTDOWN_IO_PORT_DATA); 123 + outb(val & (~BIT_SHUTDOWN_ON), EC_SHUTDOWN_IO_PORT_DATA); 124 + mmiowb(); 125 + /* need enough wait here... how many microseconds needs? */ 126 + for (i = 0; i < 0x10000; i++) 127 + delay(); 128 + outb(val | BIT_SHUTDOWN_ON, EC_SHUTDOWN_IO_PORT_DATA); 129 + mmiowb(); 130 + } 131 + 132 + static void yl2f89_shutdown(void) 133 + { 134 + /* cpu-gpio0 output low */ 135 + LOONGSON_GPIODATA &= ~0x00000001; 136 + /* cpu-gpio0 as output */ 137 + LOONGSON_GPIOIE &= ~0x00000001; 138 + } 139 + 140 + void mach_prepare_reboot(void) 141 + { 142 + switch (mips_machtype) { 143 + case MACH_LEMOTE_FL2F: 144 + fl2f_reboot(); 145 + break; 146 + case MACH_LEMOTE_ML2F7: 147 + ml2f_reboot(); 148 + break; 149 + case MACH_LEMOTE_YL2F89: 150 + yl2f89_reboot(); 151 + break; 152 + default: 153 + break; 154 + } 155 + } 156 + 157 + void mach_prepare_shutdown(void) 158 + { 159 + switch (mips_machtype) { 160 + case MACH_LEMOTE_FL2F: 161 + fl2f_shutdown(); 162 + break; 163 + case MACH_LEMOTE_ML2F7: 164 + ml2f_shutdown(); 165 + break; 166 + case MACH_LEMOTE_YL2F89: 167 + yl2f89_shutdown(); 168 + break; 169 + default: 170 + break; 171 + } 172 + }