|
@@ -1,4267 +0,0 @@
|
|
|
-diff -Nur linux-2.6.36.orig/arch/mips/Kconfig linux-2.6.36/arch/mips/Kconfig
|
|
|
|
|
|
-+++ linux-2.6.36/arch/mips/Kconfig 2010-11-18 11:47:59.000000000 +0100
|
|
|
-@@ -205,7 +205,7 @@
|
|
|
-
|
|
|
- config MACH_LOONGSON
|
|
|
- bool "Loongson family of machines"
|
|
|
-- select SYS_SUPPORTS_ZBOOT
|
|
|
-+ select SYS_SUPPORTS_ZBOOT_UART16550
|
|
|
- help
|
|
|
- This enables the support of Loongson family of machines.
|
|
|
-
|
|
|
-@@ -1093,6 +1093,8 @@
|
|
|
- bool "Loongson 2E"
|
|
|
- depends on SYS_HAS_CPU_LOONGSON2E
|
|
|
- select CPU_LOONGSON2
|
|
|
-+ select GENERIC_GPIO
|
|
|
-+ select ARCH_REQUIRE_GPIOLIB
|
|
|
- help
|
|
|
- The Loongson 2E processor implements the MIPS III instruction set
|
|
|
- with many extensions.
|
|
|
-@@ -2012,6 +2014,18 @@
|
|
|
- source "kernel/time/Kconfig"
|
|
|
-
|
|
|
- #
|
|
|
-+# High Resolution sched_clock() Configuration
|
|
|
-+#
|
|
|
-+
|
|
|
-+config CPU_HAS_FIXED_C0_COUNT
|
|
|
-+ bool
|
|
|
-+
|
|
|
-+config CPU_SUPPORTS_HR_SCHED_CLOCK
|
|
|
-+ bool
|
|
|
-+ depends on CPU_HAS_FIXED_C0_COUNT || !CPU_FREQ
|
|
|
-+ default y
|
|
|
-+
|
|
|
-+#
|
|
|
- # Timer Interrupt Frequency Configuration
|
|
|
- #
|
|
|
-
|
|
|
-diff -Nur linux-2.6.36.orig/arch/mips/include/asm/dma-mapping.h linux-2.6.36/arch/mips/include/asm/dma-mapping.h
|
|
|
|
|
|
-+++ linux-2.6.36/arch/mips/include/asm/dma-mapping.h 2010-11-18 11:47:59.000000000 +0100
|
|
|
-@@ -65,4 +65,8 @@
|
|
|
- extern void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
|
|
|
- enum dma_data_direction direction);
|
|
|
-
|
|
|
-+#define ARCH_HAS_DMA_MMAP_COHERENT
|
|
|
-+extern int dma_mmap_coherent(struct device *dev, struct vm_area_struct *vma,
|
|
|
-+ void *cpu_addr, dma_addr_t handle, size_t size);
|
|
|
-+
|
|
|
- #endif /* _ASM_DMA_MAPPING_H */
|
|
|
-diff -Nur linux-2.6.36.orig/arch/mips/include/asm/mach-loongson/cs5536/cs5536.h linux-2.6.36/arch/mips/include/asm/mach-loongson/cs5536/cs5536.h
|
|
|
|
|
|
-+++ linux-2.6.36/arch/mips/include/asm/mach-loongson/cs5536/cs5536.h 2010-11-18 11:47:59.000000000 +0100
|
|
|
-@@ -255,21 +255,12 @@
|
|
|
- * IDE STANDARD
|
|
|
- */
|
|
|
- #define IDE_CAP 0x00
|
|
|
--#define IDE_CONFIG 0x01
|
|
|
--#define IDE_SMI 0x02
|
|
|
--#define IDE_ERROR 0x03
|
|
|
--#define IDE_PM 0x04
|
|
|
--#define IDE_DIAG 0x05
|
|
|
--
|
|
|
--/*
|
|
|
-- * IDE SPEC.
|
|
|
-- */
|
|
|
- #define IDE_IO_BAR 0x08
|
|
|
- #define IDE_CFG 0x10
|
|
|
- #define IDE_DTC 0x12
|
|
|
- #define IDE_CAST 0x13
|
|
|
- #define IDE_ETC 0x14
|
|
|
--#define IDE_INTERNAL_PM 0x15
|
|
|
-+#define IDE_PM 0x15
|
|
|
-
|
|
|
- /*
|
|
|
- * ACC STANDARD
|
|
|
-@@ -301,5 +292,40 @@
|
|
|
- /* GPIO : I/O SPACE; REG : 32BITS */
|
|
|
- #define GPIOL_OUT_VAL 0x00
|
|
|
- #define GPIOL_OUT_EN 0x04
|
|
|
-+#define GPIOL_OUT_AUX1_SEL 0x10
|
|
|
-+/* SMB : I/O SPACE, REG : 8BITS WIDTH */
|
|
|
-+#define SMB_SDA 0x00
|
|
|
-+#define SMB_STS 0x01
|
|
|
-+#define SMB_STS_SLVSTP (1 << 7)
|
|
|
-+#define SMB_STS_SDAST (1 << 6)
|
|
|
-+#define SMB_STS_BER (1 << 5)
|
|
|
-+#define SMB_STS_NEGACK (1 << 4)
|
|
|
-+#define SMB_STS_STASTR (1 << 3)
|
|
|
-+#define SMB_STS_NMATCH (1 << 2)
|
|
|
-+#define SMB_STS_MASTER (1 << 1)
|
|
|
-+#define SMB_STS_XMIT (1 << 0)
|
|
|
-+#define SMB_CTRL_STS 0x02
|
|
|
-+#define SMB_CSTS_TGSTL (1 << 5)
|
|
|
-+#define SMB_CSTS_TSDA (1 << 4)
|
|
|
-+#define SMB_CSTS_GCMTCH (1 << 3)
|
|
|
-+#define SMB_CSTS_MATCH (1 << 2)
|
|
|
-+#define SMB_CSTS_BB (1 << 1)
|
|
|
-+#define SMB_CSTS_BUSY (1 << 0)
|
|
|
-+#define SMB_CTRL1 0x03
|
|
|
-+#define SMB_CTRL1_STASTRE (1 << 7)
|
|
|
-+#define SMB_CTRL1_NMINTE (1 << 6)
|
|
|
-+#define SMB_CTRL1_GCMEN (1 << 5)
|
|
|
-+#define SMB_CTRL1_ACK (1 << 4)
|
|
|
-+#define SMB_CTRL1_RSVD (1 << 3)
|
|
|
-+#define SMB_CTRL1_INTEN (1 << 2)
|
|
|
-+#define SMB_CTRL1_STOP (1 << 1)
|
|
|
-+#define SMB_CTRL1_START (1 << 0)
|
|
|
-+#define SMB_ADDR 0x04
|
|
|
-+#define SMB_ADDR_SAEN (1 << 7)
|
|
|
-+#define SMB_CONTROLLER_ADDR (0xef << 0)
|
|
|
-+#define SMB_CTRL2 0x05
|
|
|
-+#define SMB_FREQ (0x20 << 1)
|
|
|
-+#define SMB_ENABLE (0x01 << 0)
|
|
|
-+#define SMB_CTRL3 0x06
|
|
|
-
|
|
|
- #endif /* _CS5536_H */
|
|
|
-diff -Nur linux-2.6.36.orig/arch/mips/include/asm/mach-loongson/cs5536/cs5536_mfgpt.h linux-2.6.36/arch/mips/include/asm/mach-loongson/cs5536/cs5536_mfgpt.h
|
|
|
|
|
|
-+++ linux-2.6.36/arch/mips/include/asm/mach-loongson/cs5536/cs5536_mfgpt.h 2010-11-18 11:47:59.000000000 +0100
|
|
|
-@@ -32,4 +32,9 @@
|
|
|
- #define MFGPT0_CNT (MFGPT_BASE + 4)
|
|
|
- #define MFGPT0_SETUP (MFGPT_BASE + 6)
|
|
|
-
|
|
|
-+#define MFGPT2_CMP1 (MFGPT_BASE + 0x10)
|
|
|
-+#define MFGPT2_CMP2 (MFGPT_BASE + 0x12)
|
|
|
-+#define MFGPT2_CNT (MFGPT_BASE + 0x14)
|
|
|
-+#define MFGPT2_SETUP (MFGPT_BASE + 0x16)
|
|
|
-+
|
|
|
- #endif /*!_CS5536_MFGPT_H */
|
|
|
-diff -Nur linux-2.6.36.orig/arch/mips/include/asm/mach-loongson/ec_kb3310b.h linux-2.6.36/arch/mips/include/asm/mach-loongson/ec_kb3310b.h
|
|
|
|
|
|
-+++ linux-2.6.36/arch/mips/include/asm/mach-loongson/ec_kb3310b.h 2010-11-18 11:47:59.000000000 +0100
|
|
|
-@@ -0,0 +1,191 @@
|
|
|
-+/*
|
|
|
-+ * KB3310B Embedded Controller
|
|
|
-+ *
|
|
|
-+ * Copyright (C) 2008 Lemote Inc.
|
|
|
-+ * Author: liujl <liujl@lemote.com>, 2008-03-14
|
|
|
-+ * Copyright (C) 2009 Lemote Inc.
|
|
|
-+ * Author: Wu Zhangjin <wuzhangjin@gmail.com>
|
|
|
-+ *
|
|
|
-+ * This program is free software; you can redistribute it and/or modify
|
|
|
-+ * it under the terms of the GNU General Public License as published by
|
|
|
-+ * the Free Software Foundation; either version 2 of the License, or
|
|
|
-+ * (at your option) any later version.
|
|
|
-+ */
|
|
|
-+
|
|
|
-+#ifndef _EC_KB3310B_H
|
|
|
-+#define _EC_KB3310B_H
|
|
|
-+
|
|
|
-+extern unsigned char ec_read(unsigned short addr);
|
|
|
-+extern void ec_write(unsigned short addr, unsigned char val);
|
|
|
-+extern int ec_query_seq(unsigned char cmd);
|
|
|
-+extern int ec_query_event_num(void);
|
|
|
-+extern int ec_get_event_num(void);
|
|
|
-+
|
|
|
-+typedef int (*sci_handler) (int status);
|
|
|
-+extern sci_handler yeeloong_report_lid_status;
|
|
|
-+
|
|
|
-+#define SCI_IRQ_NUM 0x0A
|
|
|
-+
|
|
|
-+/*
|
|
|
-+ * The following registers are determined by the EC index configuration.
|
|
|
-+ * 1, fill the PORT_HIGH as EC register high part.
|
|
|
-+ * 2, fill the PORT_LOW as EC register low part.
|
|
|
-+ * 3, fill the PORT_DATA as EC register write data or get the data from it.
|
|
|
-+ */
|
|
|
-+#define EC_IO_PORT_HIGH 0x0381
|
|
|
-+#define EC_IO_PORT_LOW 0x0382
|
|
|
-+#define EC_IO_PORT_DATA 0x0383
|
|
|
-+
|
|
|
-+/*
|
|
|
-+ * EC delay time is 500us for register and status access
|
|
|
-+ */
|
|
|
-+#define EC_REG_DELAY 500 /* unit : us */
|
|
|
-+#define EC_CMD_TIMEOUT 0x1000
|
|
|
-+
|
|
|
-+/*
|
|
|
-+ * EC access port for SCI communication
|
|
|
-+ */
|
|
|
-+#define EC_CMD_PORT 0x66
|
|
|
-+#define EC_STS_PORT 0x66
|
|
|
-+#define EC_DAT_PORT 0x62
|
|
|
-+#define CMD_INIT_IDLE_MODE 0xdd
|
|
|
-+#define CMD_EXIT_IDLE_MODE 0xdf
|
|
|
-+#define CMD_INIT_RESET_MODE 0xd8
|
|
|
-+#define CMD_REBOOT_SYSTEM 0x8c
|
|
|
-+#define CMD_GET_EVENT_NUM 0x84
|
|
|
-+#define CMD_PROGRAM_PIECE 0xda
|
|
|
-+
|
|
|
-+/* Temperature & Fan registers */
|
|
|
-+#define REG_TEMPERATURE_VALUE 0xF458
|
|
|
-+#define REG_FAN_AUTO_MAN_SWITCH 0xF459
|
|
|
-+#define BIT_FAN_AUTO 0
|
|
|
-+#define BIT_FAN_MANUAL 1
|
|
|
-+#define REG_FAN_CONTROL 0xF4D2
|
|
|
-+#define BIT_FAN_CONTROL_ON (1 << 0)
|
|
|
-+#define BIT_FAN_CONTROL_OFF (0 << 0)
|
|
|
-+#define REG_FAN_STATUS 0xF4DA
|
|
|
-+#define BIT_FAN_STATUS_ON (1 << 0)
|
|
|
-+#define BIT_FAN_STATUS_OFF (0 << 0)
|
|
|
-+#define REG_FAN_SPEED_HIGH 0xFE22
|
|
|
-+#define REG_FAN_SPEED_LOW 0xFE23
|
|
|
-+#define REG_FAN_SPEED_LEVEL 0xF4CC
|
|
|
-+/* Fan speed divider */
|
|
|
-+#define FAN_SPEED_DIVIDER 480000 /* (60*1000*1000/62.5/2)*/
|
|
|
-+
|
|
|
-+/* Battery registers */
|
|
|
-+#define REG_BAT_DESIGN_CAP_HIGH 0xF77D
|
|
|
-+#define REG_BAT_DESIGN_CAP_LOW 0xF77E
|
|
|
-+#define REG_BAT_FULLCHG_CAP_HIGH 0xF780
|
|
|
-+#define REG_BAT_FULLCHG_CAP_LOW 0xF781
|
|
|
-+#define REG_BAT_DESIGN_VOL_HIGH 0xF782
|
|
|
-+#define REG_BAT_DESIGN_VOL_LOW 0xF783
|
|
|
-+#define REG_BAT_CURRENT_HIGH 0xF784
|
|
|
-+#define REG_BAT_CURRENT_LOW 0xF785
|
|
|
-+#define REG_BAT_VOLTAGE_HIGH 0xF786
|
|
|
-+#define REG_BAT_VOLTAGE_LOW 0xF787
|
|
|
-+#define REG_BAT_TEMPERATURE_HIGH 0xF788
|
|
|
-+#define REG_BAT_TEMPERATURE_LOW 0xF789
|
|
|
-+#define REG_BAT_RELATIVE_CAP_HIGH 0xF492
|
|
|
-+#define REG_BAT_RELATIVE_CAP_LOW 0xF493
|
|
|
-+#define REG_BAT_VENDOR 0xF4C4
|
|
|
-+#define FLAG_BAT_VENDOR_SANYO 0x01
|
|
|
-+#define FLAG_BAT_VENDOR_SIMPLO 0x02
|
|
|
-+#define REG_BAT_CELL_COUNT 0xF4C6
|
|
|
-+#define FLAG_BAT_CELL_3S1P 0x03
|
|
|
-+#define FLAG_BAT_CELL_3S2P 0x06
|
|
|
-+#define REG_BAT_CHARGE 0xF4A2
|
|
|
-+#define FLAG_BAT_CHARGE_DISCHARGE 0x01
|
|
|
-+#define FLAG_BAT_CHARGE_CHARGE 0x02
|
|
|
-+#define FLAG_BAT_CHARGE_ACPOWER 0x00
|
|
|
-+#define REG_BAT_STATUS 0xF4B0
|
|
|
-+#define BIT_BAT_STATUS_LOW (1 << 5)
|
|
|
-+#define BIT_BAT_STATUS_DESTROY (1 << 2)
|
|
|
-+#define BIT_BAT_STATUS_FULL (1 << 1)
|
|
|
-+#define BIT_BAT_STATUS_IN (1 << 0)
|
|
|
-+#define REG_BAT_CHARGE_STATUS 0xF4B1
|
|
|
-+#define BIT_BAT_CHARGE_STATUS_OVERTEMP (1 << 2)
|
|
|
-+#define BIT_BAT_CHARGE_STATUS_PRECHG (1 << 1)
|
|
|
-+#define REG_BAT_STATE 0xF482
|
|
|
-+#define BIT_BAT_STATE_CHARGING (1 << 1)
|
|
|
-+#define BIT_BAT_STATE_DISCHARGING (1 << 0)
|
|
|
-+#define REG_BAT_POWER 0xF440
|
|
|
-+#define BIT_BAT_POWER_S3 (1 << 2)
|
|
|
-+#define BIT_BAT_POWER_ON (1 << 1)
|
|
|
-+#define BIT_BAT_POWER_ACIN (1 << 0)
|
|
|
-+
|
|
|
-+/* Audio: rd/wr */
|
|
|
-+#define REG_AUDIO_VOLUME 0xF46C
|
|
|
-+#define REG_AUDIO_MUTE 0xF4E7
|
|
|
-+#define REG_AUDIO_BEEP 0xF4D0
|
|
|
-+/* USB port power or not: rd/wr */
|
|
|
-+#define REG_USB0_FLAG 0xF461
|
|
|
-+#define REG_USB1_FLAG 0xF462
|
|
|
-+#define REG_USB2_FLAG 0xF463
|
|
|
-+#define BIT_USB_FLAG_ON 1
|
|
|
-+#define BIT_USB_FLAG_OFF 0
|
|
|
-+/* LID */
|
|
|
-+#define REG_LID_DETECT 0xF4BD
|
|
|
-+#define BIT_LID_DETECT_ON 1
|
|
|
-+#define BIT_LID_DETECT_OFF 0
|
|
|
-+/* CRT */
|
|
|
-+#define REG_CRT_DETECT 0xF4AD
|
|
|
-+#define BIT_CRT_DETECT_PLUG 1
|
|
|
-+#define BIT_CRT_DETECT_UNPLUG 0
|
|
|
-+/* LCD backlight brightness adjust: 9 levels */
|
|
|
-+#define REG_DISPLAY_BRIGHTNESS 0xF4F5
|
|
|
-+/* Black screen Status */
|
|
|
-+#define BIT_DISPLAY_LCD_ON 1
|
|
|
-+#define BIT_DISPLAY_LCD_OFF 0
|
|
|
-+/* LCD backlight control: off/restore */
|
|
|
-+#define REG_BACKLIGHT_CTRL 0xF7BD
|
|
|
-+#define BIT_BACKLIGHT_ON 1
|
|
|
-+#define BIT_BACKLIGHT_OFF 0
|
|
|
-+/* Reset the machine auto-clear: rd/wr */
|
|
|
-+#define REG_RESET 0xF4EC
|
|
|
-+#define BIT_RESET_ON 1
|
|
|
-+/* Light the led: rd/wr */
|
|
|
-+#define REG_LED 0xF4C8
|
|
|
-+#define BIT_LED_RED_POWER (1 << 0)
|
|
|
-+#define BIT_LED_ORANGE_POWER (1 << 1)
|
|
|
-+#define BIT_LED_GREEN_CHARGE (1 << 2)
|
|
|
-+#define BIT_LED_RED_CHARGE (1 << 3)
|
|
|
-+#define BIT_LED_NUMLOCK (1 << 4)
|
|
|
-+/* Test led mode, all led on/off */
|
|
|
-+#define REG_LED_TEST 0xF4C2
|
|
|
-+#define BIT_LED_TEST_IN 1
|
|
|
-+#define BIT_LED_TEST_OUT 0
|
|
|
-+/* Camera on/off */
|
|
|
-+#define REG_CAMERA_STATUS 0xF46A
|
|
|
-+#define BIT_CAMERA_STATUS_ON 1
|
|
|
-+#define BIT_CAMERA_STATUS_OFF 0
|
|
|
-+#define REG_CAMERA_CONTROL 0xF7B7
|
|
|
-+#define BIT_CAMERA_CONTROL_OFF 0
|
|
|
-+#define BIT_CAMERA_CONTROL_ON 1
|
|
|
-+/* Wlan Status */
|
|
|
-+#define REG_WLAN 0xF4FA
|
|
|
-+#define BIT_WLAN_ON 1
|
|
|
-+#define BIT_WLAN_OFF 0
|
|
|
-+#define REG_DISPLAY_LCD 0xF79F
|
|
|
-+
|
|
|
-+/* SCI Event Number from EC */
|
|
|
-+enum {
|
|
|
-+ EVENT_LID = 0x23, /* Turn on/off LID */
|
|
|
-+ EVENT_SWITCHVIDEOMODE, /* Fn+F3 for display switch */
|
|
|
-+ EVENT_SLEEP, /* Fn+F1 for entering sleep mode */
|
|
|
-+ EVENT_OVERTEMP, /* Over-temperature happened */
|
|
|
-+ EVENT_CRT_DETECT, /* CRT is connected */
|
|
|
-+ EVENT_CAMERA, /* Camera on/off */
|
|
|
-+ EVENT_USB_OC2, /* USB2 Over Current occurred */
|
|
|
-+ EVENT_USB_OC0, /* USB0 Over Current occurred */
|
|
|
-+ EVENT_DISPLAYTOGGLE, /* Fn+F2, Turn on/off backlight */
|
|
|
-+ EVENT_AUDIO_MUTE, /* Fn+F4, Mute on/off */
|
|
|
-+ EVENT_DISPLAY_BRIGHTNESS,/* Fn+^/V, LCD backlight brightness adjust */
|
|
|
-+ EVENT_AC_BAT, /* AC & Battery relative issue */
|
|
|
-+ EVENT_AUDIO_VOLUME, /* Fn+<|>, Volume adjust */
|
|
|
-+ EVENT_WLAN, /* Wlan on/off */
|
|
|
-+};
|
|
|
-+
|
|
|
-+#define EVENT_START EVENT_LID
|
|
|
-+#define EVENT_END EVENT_WLAN
|
|
|
-+
|
|
|
-+#endif /* !_EC_KB3310B_H */
|
|
|
-diff -Nur linux-2.6.36.orig/arch/mips/include/asm/mach-loongson/loongson.h linux-2.6.36/arch/mips/include/asm/mach-loongson/loongson.h
|
|
|
|
|
|
-+++ linux-2.6.36/arch/mips/include/asm/mach-loongson/loongson.h 2010-11-18 11:47:59.000000000 +0100
|
|
|
-@@ -42,6 +42,12 @@
|
|
|
- #endif
|
|
|
- }
|
|
|
-
|
|
|
-+/*
|
|
|
-+ * Copy kernel command line from arcs_cmdline
|
|
|
-+ */
|
|
|
-+#include <asm/setup.h>
|
|
|
-+extern char loongson_cmdline[COMMAND_LINE_SIZE];
|
|
|
-+
|
|
|
- /* irq operation functions */
|
|
|
- extern void bonito_irqdispatch(void);
|
|
|
- extern void __init bonito_irq_init(void);
|
|
|
-diff -Nur linux-2.6.36.orig/arch/mips/kernel/csrc-r4k.c linux-2.6.36/arch/mips/kernel/csrc-r4k.c
|
|
|
|
|
|
-+++ linux-2.6.36/arch/mips/kernel/csrc-r4k.c 2010-11-18 11:47:59.000000000 +0100
|
|
|
-@@ -6,10 +6,66 @@
|
|
|
- * Copyright (C) 2007 by Ralf Baechle
|
|
|
- */
|
|
|
- #include <linux/clocksource.h>
|
|
|
-+#include <linux/cnt32_to_63.h>
|
|
|
- #include <linux/init.h>
|
|
|
-+#include <linux/timer.h>
|
|
|
-
|
|
|
- #include <asm/time.h>
|
|
|
-
|
|
|
-+#ifdef CONFIG_CPU_SUPPORTS_HR_SCHED_CLOCK
|
|
|
-+/*
|
|
|
-+ * MIPS sched_clock implementation.
|
|
|
-+ *
|
|
|
-+ * Because the hardware timer period is quite short and because cnt32_to_63()
|
|
|
-+ * needs to be called at least once per half period to work properly, a kernel
|
|
|
-+ * timer is set up to ensure this requirement is always met.
|
|
|
-+ *
|
|
|
-+ * Please refer to include/linux/cnt32_to_63.h and arch/arm/plat-orion/time.c
|
|
|
-+ */
|
|
|
-+#define CLOCK2NS_SCALE_FACTOR 8
|
|
|
-+
|
|
|
-+static unsigned long clock2ns_scale __read_mostly;
|
|
|
-+
|
|
|
-+unsigned long long notrace sched_clock(void)
|
|
|
-+{
|
|
|
-+ unsigned long long v = cnt32_to_63(read_c0_count());
|
|
|
-+ return (v * clock2ns_scale) >> CLOCK2NS_SCALE_FACTOR;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static struct timer_list cnt32_to_63_keepwarm_timer;
|
|
|
-+
|
|
|
-+static void cnt32_to_63_keepwarm(unsigned long data)
|
|
|
-+{
|
|
|
-+ mod_timer(&cnt32_to_63_keepwarm_timer, round_jiffies(jiffies + data));
|
|
|
-+ sched_clock();
|
|
|
-+}
|
|
|
-+#endif
|
|
|
-+
|
|
|
-+static inline void setup_hres_sched_clock(unsigned long clock)
|
|
|
-+{
|
|
|
-+#ifdef CONFIG_CPU_SUPPORTS_HR_SCHED_CLOCK
|
|
|
-+ unsigned long long v;
|
|
|
-+ unsigned long data;
|
|
|
-+
|
|
|
-+ v = NSEC_PER_SEC;
|
|
|
-+ v <<= CLOCK2NS_SCALE_FACTOR;
|
|
|
-+ v += clock/2;
|
|
|
-+ do_div(v, clock);
|
|
|
-+ /*
|
|
|
-+ * We want an even value to automatically clear the top bit
|
|
|
-+ * returned by cnt32_to_63() without an additional run time
|
|
|
-+ * instruction. So if the LSB is 1 then round it up.
|
|
|
-+ */
|
|
|
-+ if (v & 1)
|
|
|
-+ v++;
|
|
|
-+ clock2ns_scale = v;
|
|
|
-+
|
|
|
-+ data = 0x80000000UL / clock * HZ;
|
|
|
-+ setup_timer(&cnt32_to_63_keepwarm_timer, cnt32_to_63_keepwarm, data);
|
|
|
-+ mod_timer(&cnt32_to_63_keepwarm_timer, round_jiffies(jiffies + data));
|
|
|
-+#endif
|
|
|
-+}
|
|
|
-+
|
|
|
- static cycle_t c0_hpt_read(struct clocksource *cs)
|
|
|
- {
|
|
|
- return read_c0_count();
|
|
|
-@@ -27,6 +83,8 @@
|
|
|
- if (!cpu_has_counter || !mips_hpt_frequency)
|
|
|
- return -ENXIO;
|
|
|
-
|
|
|
-+ setup_hres_sched_clock(mips_hpt_frequency);
|
|
|
-+
|
|
|
- /* Calculate a somewhat reasonable rating value */
|
|
|
- clocksource_mips.rating = 200 + mips_hpt_frequency / 10000000;
|
|
|
-
|
|
|
-diff -Nur linux-2.6.36.orig/arch/mips/kernel/time.c linux-2.6.36/arch/mips/kernel/time.c
|
|
|
|
|
|
-+++ linux-2.6.36/arch/mips/kernel/time.c 2010-11-18 11:47:59.000000000 +0100
|
|
|
-@@ -119,6 +119,11 @@
|
|
|
-
|
|
|
- void __init time_init(void)
|
|
|
- {
|
|
|
-+#ifdef CONFIG_HR_SCHED_CLOCK
|
|
|
-+ if (!mips_clockevent_init() || !cpu_has_mfc0_count_bug())
|
|
|
-+ write_c0_count(0);
|
|
|
-+#endif
|
|
|
-+
|
|
|
- plat_time_init();
|
|
|
-
|
|
|
- if (!mips_clockevent_init() || !cpu_has_mfc0_count_bug())
|
|
|
-diff -Nur linux-2.6.36.orig/arch/mips/loongson/common/cmdline.c linux-2.6.36/arch/mips/loongson/common/cmdline.c
|
|
|
|
|
|
-+++ linux-2.6.36/arch/mips/loongson/common/cmdline.c 2010-11-18 11:47:59.000000000 +0100
|
|
|
-@@ -17,10 +17,15 @@
|
|
|
- * Free Software Foundation; either version 2 of the License, or (at your
|
|
|
- * option) any later version.
|
|
|
- */
|
|
|
-+#include <linux/module.h>
|
|
|
- #include <asm/bootinfo.h>
|
|
|
-
|
|
|
- #include <loongson.h>
|
|
|
-
|
|
|
-+/* the kernel command line copied from arcs_cmdline */
|
|
|
-+char loongson_cmdline[COMMAND_LINE_SIZE];
|
|
|
-+EXPORT_SYMBOL(loongson_cmdline);
|
|
|
-+
|
|
|
- void __init prom_init_cmdline(void)
|
|
|
- {
|
|
|
- int prom_argc;
|
|
|
-@@ -50,4 +55,26 @@
|
|
|
- strcat(arcs_cmdline, " root=/dev/hda1");
|
|
|
-
|
|
|
- prom_init_machtype();
|
|
|
-+
|
|
|
-+ /* append machine specific command line */
|
|
|
-+ switch (mips_machtype) {
|
|
|
-+ case MACH_LEMOTE_LL2F:
|
|
|
-+ if ((strstr(arcs_cmdline, "video=")) == NULL)
|
|
|
-+ strcat(arcs_cmdline, " video=sisfb:1360x768-16@60");
|
|
|
-+ break;
|
|
|
-+ case MACH_LEMOTE_FL2F:
|
|
|
-+ if ((strstr(arcs_cmdline, "ide_core.ignore_cable=")) == NULL)
|
|
|
-+ strcat(arcs_cmdline, " ide_core.ignore_cable=0");
|
|
|
-+ break;
|
|
|
-+ case MACH_LEMOTE_ML2F7:
|
|
|
-+ /* Mengloong-2F has a 800x480 screen */
|
|
|
-+ if ((strstr(arcs_cmdline, "vga=")) == NULL)
|
|
|
-+ strcat(arcs_cmdline, " vga=0x313");
|
|
|
-+ break;
|
|
|
-+ default:
|
|
|
-+ break;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ /* copy arcs_cmdline into loongson_cmdline */
|
|
|
-+ strncpy(loongson_cmdline, arcs_cmdline, COMMAND_LINE_SIZE);
|
|
|
- }
|
|
|
-diff -Nur linux-2.6.36.orig/arch/mips/loongson/common/cs5536/cs5536_acc.c linux-2.6.36/arch/mips/loongson/common/cs5536/cs5536_acc.c
|
|
|
|
|
|
-+++ linux-2.6.36/arch/mips/loongson/common/cs5536/cs5536_acc.c 2010-11-18 11:47:59.000000000 +0100
|
|
|
-@@ -18,7 +18,7 @@
|
|
|
-
|
|
|
- void pci_acc_write_reg(int reg, u32 value)
|
|
|
- {
|
|
|
-- u32 hi = 0, lo = value;
|
|
|
-+ u32 hi, lo;
|
|
|
-
|
|
|
- switch (reg) {
|
|
|
- case PCI_COMMAND:
|
|
|
-@@ -66,75 +66,73 @@
|
|
|
- u32 pci_acc_read_reg(int reg)
|
|
|
- {
|
|
|
- u32 hi, lo;
|
|
|
-- u32 conf_data = 0;
|
|
|
-+ u32 cfg = 0;
|
|
|
-
|
|
|
- switch (reg) {
|
|
|
- case PCI_VENDOR_ID:
|
|
|
-- conf_data =
|
|
|
-- CFG_PCI_VENDOR_ID(CS5536_ACC_DEVICE_ID, CS5536_VENDOR_ID);
|
|
|
-+ cfg = CFG_PCI_VENDOR_ID(CS5536_ACC_DEVICE_ID,
|
|
|
-+ CS5536_VENDOR_ID);
|
|
|
- break;
|
|
|
- case PCI_COMMAND:
|
|
|
- _rdmsr(GLIU_MSR_REG(GLIU_IOD_BM1), &hi, &lo);
|
|
|
- if (((lo & 0xfff00000) || (hi & 0x000000ff))
|
|
|
- && ((hi & 0xf0000000) == 0xa0000000))
|
|
|
-- conf_data |= PCI_COMMAND_IO;
|
|
|
-+ cfg |= PCI_COMMAND_IO;
|
|
|
- _rdmsr(GLIU_MSR_REG(GLIU_PAE), &hi, &lo);
|
|
|
- if ((lo & 0x300) == 0x300)
|
|
|
-- conf_data |= PCI_COMMAND_MASTER;
|
|
|
-+ cfg |= PCI_COMMAND_MASTER;
|
|
|
- break;
|
|
|
- case PCI_STATUS:
|
|
|
-- conf_data |= PCI_STATUS_66MHZ;
|
|
|
-- conf_data |= PCI_STATUS_FAST_BACK;
|
|
|
-+ cfg |= PCI_STATUS_66MHZ;
|
|
|
-+ cfg |= PCI_STATUS_FAST_BACK;
|
|
|
- _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo);
|
|
|
- if (lo & SB_PARE_ERR_FLAG)
|
|
|
-- conf_data |= PCI_STATUS_PARITY;
|
|
|
-- conf_data |= PCI_STATUS_DEVSEL_MEDIUM;
|
|
|
-+ cfg |= PCI_STATUS_PARITY;
|
|
|
-+ cfg |= PCI_STATUS_DEVSEL_MEDIUM;
|
|
|
- break;
|
|
|
- case PCI_CLASS_REVISION:
|
|
|
- _rdmsr(ACC_MSR_REG(ACC_CAP), &hi, &lo);
|
|
|
-- conf_data = lo & 0x000000ff;
|
|
|
-- conf_data |= (CS5536_ACC_CLASS_CODE << 8);
|
|
|
-+ cfg = lo & 0x000000ff;
|
|
|
-+ cfg |= (CS5536_ACC_CLASS_CODE << 8);
|
|
|
- break;
|
|
|
- case PCI_CACHE_LINE_SIZE:
|
|
|
-- conf_data =
|
|
|
-- CFG_PCI_CACHE_LINE_SIZE(PCI_NORMAL_HEADER_TYPE,
|
|
|
-- PCI_NORMAL_LATENCY_TIMER);
|
|
|
-+ cfg = CFG_PCI_CACHE_LINE_SIZE(PCI_NORMAL_HEADER_TYPE,
|
|
|
-+ PCI_NORMAL_LATENCY_TIMER);
|
|
|
- break;
|
|
|
- case PCI_BAR0_REG:
|
|
|
- _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo);
|
|
|
- if (lo & SOFT_BAR_ACC_FLAG) {
|
|
|
-- conf_data = CS5536_ACC_RANGE |
|
|
|
-+ cfg = CS5536_ACC_RANGE |
|
|
|
- PCI_BASE_ADDRESS_SPACE_IO;
|
|
|
- lo &= ~SOFT_BAR_ACC_FLAG;
|
|
|
- _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo);
|
|
|
- } else {
|
|
|
- _rdmsr(GLIU_MSR_REG(GLIU_IOD_BM1), &hi, &lo);
|
|
|
-- conf_data = (hi & 0x000000ff) << 12;
|
|
|
-- conf_data |= (lo & 0xfff00000) >> 20;
|
|
|
-- conf_data |= 0x01;
|
|
|
-- conf_data &= ~0x02;
|
|
|
-+ cfg = (hi & 0x000000ff) << 12;
|
|
|
-+ cfg |= (lo & 0xfff00000) >> 20;
|
|
|
-+ cfg |= 0x01;
|
|
|
-+ cfg &= ~0x02;
|
|
|
- }
|
|
|
- break;
|
|
|
- case PCI_CARDBUS_CIS:
|
|
|
-- conf_data = PCI_CARDBUS_CIS_POINTER;
|
|
|
-+ cfg = PCI_CARDBUS_CIS_POINTER;
|
|
|
- break;
|
|
|
- case PCI_SUBSYSTEM_VENDOR_ID:
|
|
|
-- conf_data =
|
|
|
-- CFG_PCI_VENDOR_ID(CS5536_ACC_SUB_ID, CS5536_SUB_VENDOR_ID);
|
|
|
-+ cfg = CFG_PCI_VENDOR_ID(CS5536_ACC_SUB_ID,
|
|
|
-+ CS5536_SUB_VENDOR_ID);
|
|
|
- break;
|
|
|
- case PCI_ROM_ADDRESS:
|
|
|
-- conf_data = PCI_EXPANSION_ROM_BAR;
|
|
|
-+ cfg = PCI_EXPANSION_ROM_BAR;
|
|
|
- break;
|
|
|
- case PCI_CAPABILITY_LIST:
|
|
|
-- conf_data = PCI_CAPLIST_USB_POINTER;
|
|
|
-+ cfg = PCI_CAPLIST_USB_POINTER;
|
|
|
- break;
|
|
|
- case PCI_INTERRUPT_LINE:
|
|
|
-- conf_data =
|
|
|
-- CFG_PCI_INTERRUPT_LINE(PCI_DEFAULT_PIN, CS5536_ACC_INTR);
|
|
|
-+ cfg = CFG_PCI_INTERRUPT_LINE(PCI_DEFAULT_PIN, CS5536_ACC_INTR);
|
|
|
- break;
|
|
|
- default:
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
-- return conf_data;
|
|
|
-+ return cfg;
|
|
|
- }
|
|
|
-diff -Nur linux-2.6.36.orig/arch/mips/loongson/common/cs5536/cs5536_ehci.c linux-2.6.36/arch/mips/loongson/common/cs5536/cs5536_ehci.c
|
|
|
|
|
|
-+++ linux-2.6.36/arch/mips/loongson/common/cs5536/cs5536_ehci.c 2010-11-18 11:47:59.000000000 +0100
|
|
|
-@@ -18,7 +18,7 @@
|
|
|
-
|
|
|
- void pci_ehci_write_reg(int reg, u32 value)
|
|
|
- {
|
|
|
-- u32 hi = 0, lo = value;
|
|
|
-+ u32 hi, lo;
|
|
|
-
|
|
|
- switch (reg) {
|
|
|
- case PCI_COMMAND:
|
|
|
-@@ -78,83 +78,81 @@
|
|
|
-
|
|
|
- u32 pci_ehci_read_reg(int reg)
|
|
|
- {
|
|
|
-- u32 conf_data = 0;
|
|
|
-+ u32 cfg = 0;
|
|
|
- u32 hi, lo;
|
|
|
-
|
|
|
- switch (reg) {
|
|
|
- case PCI_VENDOR_ID:
|
|
|
-- conf_data =
|
|
|
-- CFG_PCI_VENDOR_ID(CS5536_EHCI_DEVICE_ID, CS5536_VENDOR_ID);
|
|
|
-+ cfg = CFG_PCI_VENDOR_ID(CS5536_EHCI_DEVICE_ID,
|
|
|
-+ CS5536_VENDOR_ID);
|
|
|
- break;
|
|
|
- case PCI_COMMAND:
|
|
|
- _rdmsr(USB_MSR_REG(USB_EHCI), &hi, &lo);
|
|
|
- if (hi & PCI_COMMAND_MASTER)
|
|
|
-- conf_data |= PCI_COMMAND_MASTER;
|
|
|
-+ cfg |= PCI_COMMAND_MASTER;
|
|
|
- if (hi & PCI_COMMAND_MEMORY)
|
|
|
-- conf_data |= PCI_COMMAND_MEMORY;
|
|
|
-+ cfg |= PCI_COMMAND_MEMORY;
|
|
|
- break;
|
|
|
- case PCI_STATUS:
|
|
|
-- conf_data |= PCI_STATUS_66MHZ;
|
|
|
-- conf_data |= PCI_STATUS_FAST_BACK;
|
|
|
-+ cfg |= PCI_STATUS_66MHZ;
|
|
|
-+ cfg |= PCI_STATUS_FAST_BACK;
|
|
|
- _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo);
|
|
|
- if (lo & SB_PARE_ERR_FLAG)
|
|
|
-- conf_data |= PCI_STATUS_PARITY;
|
|
|
-- conf_data |= PCI_STATUS_DEVSEL_MEDIUM;
|
|
|
-+ cfg |= PCI_STATUS_PARITY;
|
|
|
-+ cfg |= PCI_STATUS_DEVSEL_MEDIUM;
|
|
|
- break;
|
|
|
- case PCI_CLASS_REVISION:
|
|
|
- _rdmsr(USB_MSR_REG(USB_CAP), &hi, &lo);
|
|
|
-- conf_data = lo & 0x000000ff;
|
|
|
-- conf_data |= (CS5536_EHCI_CLASS_CODE << 8);
|
|
|
-+ cfg = lo & 0x000000ff;
|
|
|
-+ cfg |= (CS5536_EHCI_CLASS_CODE << 8);
|
|
|
- break;
|
|
|
- case PCI_CACHE_LINE_SIZE:
|
|
|
-- conf_data =
|
|
|
-- CFG_PCI_CACHE_LINE_SIZE(PCI_NORMAL_HEADER_TYPE,
|
|
|
-- PCI_NORMAL_LATENCY_TIMER);
|
|
|
-+ cfg = CFG_PCI_CACHE_LINE_SIZE(PCI_NORMAL_HEADER_TYPE,
|
|
|
-+ PCI_NORMAL_LATENCY_TIMER);
|
|
|
- break;
|
|
|
- case PCI_BAR0_REG:
|
|
|
- _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo);
|
|
|
- if (lo & SOFT_BAR_EHCI_FLAG) {
|
|
|
-- conf_data = CS5536_EHCI_RANGE |
|
|
|
-+ cfg = CS5536_EHCI_RANGE |
|
|
|
- PCI_BASE_ADDRESS_SPACE_MEMORY;
|
|
|
- lo &= ~SOFT_BAR_EHCI_FLAG;
|
|
|
- _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo);
|
|
|
- } else {
|
|
|
- _rdmsr(USB_MSR_REG(USB_EHCI), &hi, &lo);
|
|
|
-- conf_data = lo & 0xfffff000;
|
|
|
-+ cfg = lo & 0xfffff000;
|
|
|
- }
|
|
|
- break;
|
|
|
- case PCI_CARDBUS_CIS:
|
|
|
-- conf_data = PCI_CARDBUS_CIS_POINTER;
|
|
|
-+ cfg = PCI_CARDBUS_CIS_POINTER;
|
|
|
- break;
|
|
|
- case PCI_SUBSYSTEM_VENDOR_ID:
|
|
|
-- conf_data =
|
|
|
-- CFG_PCI_VENDOR_ID(CS5536_EHCI_SUB_ID, CS5536_SUB_VENDOR_ID);
|
|
|
-+ cfg = CFG_PCI_VENDOR_ID(CS5536_EHCI_SUB_ID,
|
|
|
-+ CS5536_SUB_VENDOR_ID);
|
|
|
- break;
|
|
|
- case PCI_ROM_ADDRESS:
|
|
|
-- conf_data = PCI_EXPANSION_ROM_BAR;
|
|
|
-+ cfg = PCI_EXPANSION_ROM_BAR;
|
|
|
- break;
|
|
|
- case PCI_CAPABILITY_LIST:
|
|
|
-- conf_data = PCI_CAPLIST_USB_POINTER;
|
|
|
-+ cfg = PCI_CAPLIST_USB_POINTER;
|
|
|
- break;
|
|
|
- case PCI_INTERRUPT_LINE:
|
|
|
-- conf_data =
|
|
|
-- CFG_PCI_INTERRUPT_LINE(PCI_DEFAULT_PIN, CS5536_USB_INTR);
|
|
|
-+ cfg = CFG_PCI_INTERRUPT_LINE(PCI_DEFAULT_PIN, CS5536_USB_INTR);
|
|
|
- break;
|
|
|
- case PCI_EHCI_LEGSMIEN_REG:
|
|
|
- _rdmsr(USB_MSR_REG(USB_EHCI), &hi, &lo);
|
|
|
-- conf_data = (hi & 0x003f0000) >> 16;
|
|
|
-+ cfg = (hi & 0x003f0000) >> 16;
|
|
|
- break;
|
|
|
- case PCI_EHCI_LEGSMISTS_REG:
|
|
|
- _rdmsr(USB_MSR_REG(USB_EHCI), &hi, &lo);
|
|
|
-- conf_data = (hi & 0x3f000000) >> 24;
|
|
|
-+ cfg = (hi & 0x3f000000) >> 24;
|
|
|
- break;
|
|
|
- case PCI_EHCI_FLADJ_REG:
|
|
|
- _rdmsr(USB_MSR_REG(USB_EHCI), &hi, &lo);
|
|
|
-- conf_data = hi & 0x00003f00;
|
|
|
-+ cfg = hi & 0x00003f00;
|
|
|
- break;
|
|
|
- default:
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
-- return conf_data;
|
|
|
-+ return cfg;
|
|
|
- }
|
|
|
-diff -Nur linux-2.6.36.orig/arch/mips/loongson/common/cs5536/cs5536_ide.c linux-2.6.36/arch/mips/loongson/common/cs5536/cs5536_ide.c
|
|
|
|
|
|
-+++ linux-2.6.36/arch/mips/loongson/common/cs5536/cs5536_ide.c 2010-11-18 11:47:59.000000000 +0100
|
|
|
-@@ -18,7 +18,7 @@
|
|
|
-
|
|
|
- void pci_ide_write_reg(int reg, u32 value)
|
|
|
- {
|
|
|
-- u32 hi = 0, lo = value;
|
|
|
-+ u32 hi, lo;
|
|
|
-
|
|
|
- switch (reg) {
|
|
|
- case PCI_COMMAND:
|
|
|
-@@ -72,26 +72,16 @@
|
|
|
- _wrmsr(IDE_MSR_REG(IDE_CFG), hi, lo);
|
|
|
- }
|
|
|
- break;
|
|
|
-- case PCI_IDE_DTC_REG:
|
|
|
-- _rdmsr(IDE_MSR_REG(IDE_DTC), &hi, &lo);
|
|
|
-- lo = value;
|
|
|
-- _wrmsr(IDE_MSR_REG(IDE_DTC), hi, lo);
|
|
|
-- break;
|
|
|
-- case PCI_IDE_CAST_REG:
|
|
|
-- _rdmsr(IDE_MSR_REG(IDE_CAST), &hi, &lo);
|
|
|
-- lo = value;
|
|
|
-- _wrmsr(IDE_MSR_REG(IDE_CAST), hi, lo);
|
|
|
-- break;
|
|
|
-- case PCI_IDE_ETC_REG:
|
|
|
-- _rdmsr(IDE_MSR_REG(IDE_ETC), &hi, &lo);
|
|
|
-- lo = value;
|
|
|
-- _wrmsr(IDE_MSR_REG(IDE_ETC), hi, lo);
|
|
|
-- break;
|
|
|
-- case PCI_IDE_PM_REG:
|
|
|
-- _rdmsr(IDE_MSR_REG(IDE_INTERNAL_PM), &hi, &lo);
|
|
|
-- lo = value;
|
|
|
-- _wrmsr(IDE_MSR_REG(IDE_INTERNAL_PM), hi, lo);
|
|
|
-- break;
|
|
|
-+#define SET_PCI_IDE_REG(r) \
|
|
|
-+ case PCI_IDE_##r##_REG: \
|
|
|
-+ _rdmsr(IDE_MSR_REG(IDE_##r), &hi, &lo); \
|
|
|
-+ lo = value; \
|
|
|
-+ _wrmsr(IDE_MSR_REG(IDE_##r), hi, lo); \
|
|
|
-+ break;
|
|
|
-+ SET_PCI_IDE_REG(DTC)
|
|
|
-+ SET_PCI_IDE_REG(CAST)
|
|
|
-+ SET_PCI_IDE_REG(ETC)
|
|
|
-+ SET_PCI_IDE_REG(PM)
|
|
|
- default:
|
|
|
- break;
|
|
|
- }
|
|
|
-@@ -99,94 +89,82 @@
|
|
|
-
|
|
|
- u32 pci_ide_read_reg(int reg)
|
|
|
- {
|
|
|
-- u32 conf_data = 0;
|
|
|
-+ u32 cfg = 0;
|
|
|
- u32 hi, lo;
|
|
|
-
|
|
|
- switch (reg) {
|
|
|
- case PCI_VENDOR_ID:
|
|
|
-- conf_data =
|
|
|
-- CFG_PCI_VENDOR_ID(CS5536_IDE_DEVICE_ID, CS5536_VENDOR_ID);
|
|
|
-+ cfg = CFG_PCI_VENDOR_ID(CS5536_IDE_DEVICE_ID,
|
|
|
-+ CS5536_VENDOR_ID);
|
|
|
- break;
|
|
|
- case PCI_COMMAND:
|
|
|
- _rdmsr(IDE_MSR_REG(IDE_IO_BAR), &hi, &lo);
|
|
|
- if (lo & 0xfffffff0)
|
|
|
-- conf_data |= PCI_COMMAND_IO;
|
|
|
-+ cfg |= PCI_COMMAND_IO;
|
|
|
- _rdmsr(GLIU_MSR_REG(GLIU_PAE), &hi, &lo);
|
|
|
- if ((lo & 0x30) == 0x30)
|
|
|
-- conf_data |= PCI_COMMAND_MASTER;
|
|
|
-+ cfg |= PCI_COMMAND_MASTER;
|
|
|
- break;
|
|
|
- case PCI_STATUS:
|
|
|
-- conf_data |= PCI_STATUS_66MHZ;
|
|
|
-- conf_data |= PCI_STATUS_FAST_BACK;
|
|
|
-+ cfg |= PCI_STATUS_66MHZ;
|
|
|
-+ cfg |= PCI_STATUS_FAST_BACK;
|
|
|
- _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo);
|
|
|
- if (lo & SB_PARE_ERR_FLAG)
|
|
|
-- conf_data |= PCI_STATUS_PARITY;
|
|
|
-- conf_data |= PCI_STATUS_DEVSEL_MEDIUM;
|
|
|
-+ cfg |= PCI_STATUS_PARITY;
|
|
|
-+ cfg |= PCI_STATUS_DEVSEL_MEDIUM;
|
|
|
- break;
|
|
|
- case PCI_CLASS_REVISION:
|
|
|
- _rdmsr(IDE_MSR_REG(IDE_CAP), &hi, &lo);
|
|
|
-- conf_data = lo & 0x000000ff;
|
|
|
-- conf_data |= (CS5536_IDE_CLASS_CODE << 8);
|
|
|
-+ cfg = lo & 0x000000ff;
|
|
|
-+ cfg |= (CS5536_IDE_CLASS_CODE << 8);
|
|
|
- break;
|
|
|
- case PCI_CACHE_LINE_SIZE:
|
|
|
- _rdmsr(SB_MSR_REG(SB_CTRL), &hi, &lo);
|
|
|
- hi &= 0x000000f8;
|
|
|
-- conf_data = CFG_PCI_CACHE_LINE_SIZE(PCI_NORMAL_HEADER_TYPE, hi);
|
|
|
-+ cfg = CFG_PCI_CACHE_LINE_SIZE(PCI_NORMAL_HEADER_TYPE, hi);
|
|
|
- break;
|
|
|
- case PCI_BAR4_REG:
|
|
|
- _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo);
|
|
|
- if (lo & SOFT_BAR_IDE_FLAG) {
|
|
|
-- conf_data = CS5536_IDE_RANGE |
|
|
|
-+ cfg = CS5536_IDE_RANGE |
|
|
|
- PCI_BASE_ADDRESS_SPACE_IO;
|
|
|
- lo &= ~SOFT_BAR_IDE_FLAG;
|
|
|
- _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo);
|
|
|
- } else {
|
|
|
- _rdmsr(IDE_MSR_REG(IDE_IO_BAR), &hi, &lo);
|
|
|
-- conf_data = lo & 0xfffffff0;
|
|
|
-- conf_data |= 0x01;
|
|
|
-- conf_data &= ~0x02;
|
|
|
-+ cfg = lo & 0xfffffff0;
|
|
|
-+ cfg |= 0x01;
|
|
|
-+ cfg &= ~0x02;
|
|
|
- }
|
|
|
- break;
|
|
|
- case PCI_CARDBUS_CIS:
|
|
|
-- conf_data = PCI_CARDBUS_CIS_POINTER;
|
|
|
-+ cfg = PCI_CARDBUS_CIS_POINTER;
|
|
|
- break;
|
|
|
- case PCI_SUBSYSTEM_VENDOR_ID:
|
|
|
-- conf_data =
|
|
|
-- CFG_PCI_VENDOR_ID(CS5536_IDE_SUB_ID, CS5536_SUB_VENDOR_ID);
|
|
|
-+ cfg = CFG_PCI_VENDOR_ID(CS5536_IDE_SUB_ID,
|
|
|
-+ CS5536_SUB_VENDOR_ID);
|
|
|
- break;
|
|
|
- case PCI_ROM_ADDRESS:
|
|
|
-- conf_data = PCI_EXPANSION_ROM_BAR;
|
|
|
-+ cfg = PCI_EXPANSION_ROM_BAR;
|
|
|
- break;
|
|
|
- case PCI_CAPABILITY_LIST:
|
|
|
-- conf_data = PCI_CAPLIST_POINTER;
|
|
|
-+ cfg = PCI_CAPLIST_POINTER;
|
|
|
- break;
|
|
|
- case PCI_INTERRUPT_LINE:
|
|
|
-- conf_data =
|
|
|
-- CFG_PCI_INTERRUPT_LINE(PCI_DEFAULT_PIN, CS5536_IDE_INTR);
|
|
|
-- break;
|
|
|
-- case PCI_IDE_CFG_REG:
|
|
|
-- _rdmsr(IDE_MSR_REG(IDE_CFG), &hi, &lo);
|
|
|
-- conf_data = lo;
|
|
|
-- break;
|
|
|
-- case PCI_IDE_DTC_REG:
|
|
|
-- _rdmsr(IDE_MSR_REG(IDE_DTC), &hi, &lo);
|
|
|
-- conf_data = lo;
|
|
|
-- break;
|
|
|
-- case PCI_IDE_CAST_REG:
|
|
|
-- _rdmsr(IDE_MSR_REG(IDE_CAST), &hi, &lo);
|
|
|
-- conf_data = lo;
|
|
|
-- break;
|
|
|
-- case PCI_IDE_ETC_REG:
|
|
|
-- _rdmsr(IDE_MSR_REG(IDE_ETC), &hi, &lo);
|
|
|
-- conf_data = lo;
|
|
|
-- break;
|
|
|
-- case PCI_IDE_PM_REG:
|
|
|
-- _rdmsr(IDE_MSR_REG(IDE_INTERNAL_PM), &hi, &lo);
|
|
|
-- conf_data = lo;
|
|
|
-+ cfg = CFG_PCI_INTERRUPT_LINE(PCI_DEFAULT_PIN, CS5536_IDE_INTR);
|
|
|
- break;
|
|
|
-+#define GET_PCI_IDE_REG(r) \
|
|
|
-+ case PCI_IDE_##r##_REG: \
|
|
|
-+ _rdmsr(IDE_MSR_REG(IDE_##r), &hi, &cfg); \
|
|
|
-+ break;
|
|
|
-+ GET_PCI_IDE_REG(CFG)
|
|
|
-+ GET_PCI_IDE_REG(DTC)
|
|
|
-+ GET_PCI_IDE_REG(CAST)
|
|
|
-+ GET_PCI_IDE_REG(ETC)
|
|
|
-+ GET_PCI_IDE_REG(PM)
|
|
|
- default:
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
-- return conf_data;
|
|
|
-+ return cfg;
|
|
|
- }
|
|
|
-diff -Nur linux-2.6.36.orig/arch/mips/loongson/common/cs5536/cs5536_ohci.c linux-2.6.36/arch/mips/loongson/common/cs5536/cs5536_ohci.c
|
|
|
|
|
|
-+++ linux-2.6.36/arch/mips/loongson/common/cs5536/cs5536_ohci.c 2010-11-18 11:47:59.000000000 +0100
|
|
|
-@@ -18,7 +18,7 @@
|
|
|
-
|
|
|
- void pci_ohci_write_reg(int reg, u32 value)
|
|
|
- {
|
|
|
-- u32 hi = 0, lo = value;
|
|
|
-+ u32 hi, lo;
|
|
|
-
|
|
|
- switch (reg) {
|
|
|
- case PCI_COMMAND:
|
|
|
-@@ -73,77 +73,75 @@
|
|
|
-
|
|
|
- u32 pci_ohci_read_reg(int reg)
|
|
|
- {
|
|
|
-- u32 conf_data = 0;
|
|
|
-+ u32 cfg = 0;
|
|
|
- u32 hi, lo;
|
|
|
-
|
|
|
- switch (reg) {
|
|
|
- case PCI_VENDOR_ID:
|
|
|
-- conf_data =
|
|
|
-- CFG_PCI_VENDOR_ID(CS5536_OHCI_DEVICE_ID, CS5536_VENDOR_ID);
|
|
|
-+ cfg = CFG_PCI_VENDOR_ID(CS5536_OHCI_DEVICE_ID,
|
|
|
-+ CS5536_VENDOR_ID);
|
|
|
- break;
|
|
|
- case PCI_COMMAND:
|
|
|
- _rdmsr(USB_MSR_REG(USB_OHCI), &hi, &lo);
|
|
|
- if (hi & PCI_COMMAND_MASTER)
|
|
|
-- conf_data |= PCI_COMMAND_MASTER;
|
|
|
-+ cfg |= PCI_COMMAND_MASTER;
|
|
|
- if (hi & PCI_COMMAND_MEMORY)
|
|
|
-- conf_data |= PCI_COMMAND_MEMORY;
|
|
|
-+ cfg |= PCI_COMMAND_MEMORY;
|
|
|
- break;
|
|
|
- case PCI_STATUS:
|
|
|
-- conf_data |= PCI_STATUS_66MHZ;
|
|
|
-- conf_data |= PCI_STATUS_FAST_BACK;
|
|
|
-+ cfg |= PCI_STATUS_66MHZ;
|
|
|
-+ cfg |= PCI_STATUS_FAST_BACK;
|
|
|
- _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo);
|
|
|
- if (lo & SB_PARE_ERR_FLAG)
|
|
|
-- conf_data |= PCI_STATUS_PARITY;
|
|
|
-- conf_data |= PCI_STATUS_DEVSEL_MEDIUM;
|
|
|
-+ cfg |= PCI_STATUS_PARITY;
|
|
|
-+ cfg |= PCI_STATUS_DEVSEL_MEDIUM;
|
|
|
- break;
|
|
|
- case PCI_CLASS_REVISION:
|
|
|
- _rdmsr(USB_MSR_REG(USB_CAP), &hi, &lo);
|
|
|
-- conf_data = lo & 0x000000ff;
|
|
|
-- conf_data |= (CS5536_OHCI_CLASS_CODE << 8);
|
|
|
-+ cfg = lo & 0x000000ff;
|
|
|
-+ cfg |= (CS5536_OHCI_CLASS_CODE << 8);
|
|
|
- break;
|
|
|
- case PCI_CACHE_LINE_SIZE:
|
|
|
-- conf_data =
|
|
|
-- CFG_PCI_CACHE_LINE_SIZE(PCI_NORMAL_HEADER_TYPE,
|
|
|
-- PCI_NORMAL_LATENCY_TIMER);
|
|
|
-+ cfg = CFG_PCI_CACHE_LINE_SIZE(PCI_NORMAL_HEADER_TYPE,
|
|
|
-+ PCI_NORMAL_LATENCY_TIMER);
|
|
|
- break;
|
|
|
- case PCI_BAR0_REG:
|
|
|
- _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo);
|
|
|
- if (lo & SOFT_BAR_OHCI_FLAG) {
|
|
|
-- conf_data = CS5536_OHCI_RANGE |
|
|
|
-+ cfg = CS5536_OHCI_RANGE |
|
|
|
- PCI_BASE_ADDRESS_SPACE_MEMORY;
|
|
|
- lo &= ~SOFT_BAR_OHCI_FLAG;
|
|
|
- _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo);
|
|
|
- } else {
|
|
|
- _rdmsr(USB_MSR_REG(USB_OHCI), &hi, &lo);
|
|
|
-- conf_data = lo & 0xffffff00;
|
|
|
-- conf_data &= ~0x0000000f; /* 32bit mem */
|
|
|
-+ cfg = lo & 0xffffff00;
|
|
|
-+ cfg &= ~0x0000000f; /* 32bit mem */
|
|
|
- }
|
|
|
- break;
|
|
|
- case PCI_CARDBUS_CIS:
|
|
|
-- conf_data = PCI_CARDBUS_CIS_POINTER;
|
|
|
-+ cfg = PCI_CARDBUS_CIS_POINTER;
|
|
|
- break;
|
|
|
- case PCI_SUBSYSTEM_VENDOR_ID:
|
|
|
-- conf_data =
|
|
|
-- CFG_PCI_VENDOR_ID(CS5536_OHCI_SUB_ID, CS5536_SUB_VENDOR_ID);
|
|
|
-+ cfg = CFG_PCI_VENDOR_ID(CS5536_OHCI_SUB_ID,
|
|
|
-+ CS5536_SUB_VENDOR_ID);
|
|
|
- break;
|
|
|
- case PCI_ROM_ADDRESS:
|
|
|
-- conf_data = PCI_EXPANSION_ROM_BAR;
|
|
|
-+ cfg = PCI_EXPANSION_ROM_BAR;
|
|
|
- break;
|
|
|
- case PCI_CAPABILITY_LIST:
|
|
|
-- conf_data = PCI_CAPLIST_USB_POINTER;
|
|
|
-+ cfg = PCI_CAPLIST_USB_POINTER;
|
|
|
- break;
|
|
|
- case PCI_INTERRUPT_LINE:
|
|
|
-- conf_data =
|
|
|
-- CFG_PCI_INTERRUPT_LINE(PCI_DEFAULT_PIN, CS5536_USB_INTR);
|
|
|
-+ cfg = CFG_PCI_INTERRUPT_LINE(PCI_DEFAULT_PIN, CS5536_USB_INTR);
|
|
|
- break;
|
|
|
- case PCI_OHCI_INT_REG:
|
|
|
- _rdmsr(DIVIL_MSR_REG(PIC_YSEL_LOW), &hi, &lo);
|
|
|
- if ((lo & 0x00000f00) == CS5536_USB_INTR)
|
|
|
-- conf_data = 1;
|
|
|
-+ cfg = 1;
|
|
|
- break;
|
|
|
- default:
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
-- return conf_data;
|
|
|
-+ return cfg;
|
|
|
- }
|
|
|
-diff -Nur linux-2.6.36.orig/arch/mips/loongson/common/mtd.c linux-2.6.36/arch/mips/loongson/common/mtd.c
|
|
|
|
|
|
-+++ linux-2.6.36/arch/mips/loongson/common/mtd.c 2010-11-18 11:47:59.000000000 +0100
|
|
|
-@@ -0,0 +1,91 @@
|
|
|
-+/*
|
|
|
-+ * Driver for flushing/dumping ROM of PMON on loongson family machines
|
|
|
-+ *
|
|
|
-+ * Copyright (C) 2008-2009 Lemote Inc.
|
|
|
-+ * Author: Yan Hua <yanh@lemote.com>
|
|
|
-+ *
|
|
|
-+ * This program is free software; you can redistribute it and/or modify it
|
|
|
-+ * under the terms of the GNU General Public License as published by the
|
|
|
-+ * Free Software Foundation; either version 2 of the License, or (at your
|
|
|
-+ * option) any later version.
|
|
|
-+ */
|
|
|
-+
|
|
|
-+#include <linux/module.h>
|
|
|
-+#include <linux/types.h>
|
|
|
-+#include <linux/kernel.h>
|
|
|
-+#include <linux/init.h>
|
|
|
-+#include <linux/mtd/mtd.h>
|
|
|
-+#include <linux/mtd/map.h>
|
|
|
-+#include <linux/mtd/partitions.h>
|
|
|
-+
|
|
|
-+#include <asm/io.h>
|
|
|
-+
|
|
|
-+#include <loongson.h>
|
|
|
-+
|
|
|
-+#define FLASH_PHYS_ADDR LOONGSON_BOOT_BASE
|
|
|
-+#define FLASH_SIZE 0x080000
|
|
|
-+
|
|
|
-+#define FLASH_PARTITION0_ADDR 0x00000000
|
|
|
-+#define FLASH_PARTITION0_SIZE 0x00080000
|
|
|
-+
|
|
|
-+struct map_info flash_map = {
|
|
|
-+ .name = "flash device",
|
|
|
-+ .size = FLASH_SIZE,
|
|
|
-+ .bankwidth = 1,
|
|
|
-+};
|
|
|
-+
|
|
|
-+struct mtd_partition flash_parts[] = {
|
|
|
-+ {
|
|
|
-+ .name = "Bootloader",
|
|
|
-+ .offset = FLASH_PARTITION0_ADDR,
|
|
|
-+ .size = FLASH_PARTITION0_SIZE},
|
|
|
-+};
|
|
|
-+
|
|
|
-+#define PARTITION_COUNT ARRAY_SIZE(flash_parts)
|
|
|
-+
|
|
|
-+static struct mtd_info *mymtd;
|
|
|
-+
|
|
|
-+int __init init_flash(void)
|
|
|
-+{
|
|
|
-+ printk(KERN_NOTICE "flash device: %x at %x\n",
|
|
|
-+ FLASH_SIZE, FLASH_PHYS_ADDR);
|
|
|
-+
|
|
|
-+ flash_map.phys = FLASH_PHYS_ADDR;
|
|
|
-+ flash_map.virt = ioremap(FLASH_PHYS_ADDR, FLASH_SIZE);
|
|
|
-+
|
|
|
-+ if (!flash_map.virt) {
|
|
|
-+ printk(KERN_NOTICE "Failed to ioremap\n");
|
|
|
-+ return -EIO;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ simple_map_init(&flash_map);
|
|
|
-+
|
|
|
-+ mymtd = do_map_probe("cfi_probe", &flash_map);
|
|
|
-+ if (mymtd) {
|
|
|
-+ add_mtd_partitions(mymtd, flash_parts, PARTITION_COUNT);
|
|
|
-+ printk(KERN_NOTICE "pmon flash device initialized\n");
|
|
|
-+ return 0;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ iounmap((void *)flash_map.virt);
|
|
|
-+ return -ENXIO;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static void __exit cleanup_flash(void)
|
|
|
-+{
|
|
|
-+ if (mymtd) {
|
|
|
-+ del_mtd_partitions(mymtd);
|
|
|
-+ map_destroy(mymtd);
|
|
|
-+ }
|
|
|
-+ if (flash_map.virt) {
|
|
|
-+ iounmap((void *)flash_map.virt);
|
|
|
-+ flash_map.virt = 0;
|
|
|
-+ }
|
|
|
-+}
|
|
|
-+
|
|
|
-+module_init(init_flash);
|
|
|
-+module_exit(cleanup_flash);
|
|
|
-+
|
|
|
-+MODULE_LICENSE("GPL");
|
|
|
-+MODULE_AUTHOR("Yanhua <yanh@lemote.com>");
|
|
|
-+MODULE_DESCRIPTION("MTD driver for pmon flushing/dumping");
|
|
|
-diff -Nur linux-2.6.36.orig/arch/mips/loongson/lemote-2f/Makefile linux-2.6.36/arch/mips/loongson/lemote-2f/Makefile
|
|
|
|
|
|
-+++ linux-2.6.36/arch/mips/loongson/lemote-2f/Makefile 2010-11-18 11:47:59.000000000 +0100
|
|
|
-@@ -2,7 +2,7 @@
|
|
|
- # Makefile for lemote loongson2f family machines
|
|
|
- #
|
|
|
-
|
|
|
--obj-y += machtype.o irq.o reset.o ec_kb3310b.o
|
|
|
-+obj-y += machtype.o irq.o reset.o ec_kb3310b.o platform.o
|
|
|
-
|
|
|
- #
|
|
|
- # Suspend Support
|
|
|
-diff -Nur linux-2.6.36.orig/arch/mips/loongson/lemote-2f/ec_kb3310b.c linux-2.6.36/arch/mips/loongson/lemote-2f/ec_kb3310b.c
|
|
|
|
|
|
-+++ linux-2.6.36/arch/mips/loongson/lemote-2f/ec_kb3310b.c 2010-11-18 11:47:59.000000000 +0100
|
|
|
-@@ -14,7 +14,7 @@
|
|
|
- #include <linux/spinlock.h>
|
|
|
- #include <linux/delay.h>
|
|
|
-
|
|
|
--#include "ec_kb3310b.h"
|
|
|
-+#include <ec_kb3310b.h>
|
|
|
-
|
|
|
- static DEFINE_SPINLOCK(index_access_lock);
|
|
|
- static DEFINE_SPINLOCK(port_access_lock);
|
|
|
-@@ -78,12 +78,9 @@
|
|
|
- spin_unlock_irqrestore(&port_access_lock, flags);
|
|
|
-
|
|
|
- if (timeout <= 0) {
|
|
|
-- printk(KERN_ERR "%s: deadable error : timeout...\n", __func__);
|
|
|
-+ pr_err("%s: deadable error : timeout...\n", __func__);
|
|
|
- ret = -EINVAL;
|
|
|
-- } else
|
|
|
-- printk(KERN_INFO
|
|
|
-- "(%x/%d)ec issued command %d status : 0x%x\n",
|
|
|
-- timeout, EC_CMD_TIMEOUT - timeout, cmd, status);
|
|
|
-+ }
|
|
|
-
|
|
|
- return ret;
|
|
|
- }
|
|
|
-@@ -118,8 +115,7 @@
|
|
|
- udelay(EC_REG_DELAY);
|
|
|
- }
|
|
|
- if (timeout <= 0) {
|
|
|
-- pr_info("%s: get event number timeout.\n", __func__);
|
|
|
--
|
|
|
-+ pr_err("%s: get event number timeout.\n", __func__);
|
|
|
- return -EINVAL;
|
|
|
- }
|
|
|
- value = inb(EC_DAT_PORT);
|
|
|
-diff -Nur linux-2.6.36.orig/arch/mips/loongson/lemote-2f/ec_kb3310b.h linux-2.6.36/arch/mips/loongson/lemote-2f/ec_kb3310b.h
|
|
|
|
|
|
-+++ linux-2.6.36/arch/mips/loongson/lemote-2f/ec_kb3310b.h 1970-01-01 01:00:00.000000000 +0100
|
|
|
-@@ -1,188 +0,0 @@
|
|
|
--/*
|
|
|
-- * KB3310B Embedded Controller
|
|
|
-- *
|
|
|
-- * Copyright (C) 2008 Lemote Inc.
|
|
|
-- * Author: liujl <liujl@lemote.com>, 2008-03-14
|
|
|
-- *
|
|
|
-- * This program is free software; you can redistribute it and/or modify
|
|
|
-- * it under the terms of the GNU General Public License as published by
|
|
|
-- * the Free Software Foundation; either version 2 of the License, or
|
|
|
-- * (at your option) any later version.
|
|
|
-- */
|
|
|
--
|
|
|
--#ifndef _EC_KB3310B_H
|
|
|
--#define _EC_KB3310B_H
|
|
|
--
|
|
|
--extern unsigned char ec_read(unsigned short addr);
|
|
|
--extern void ec_write(unsigned short addr, unsigned char val);
|
|
|
--extern int ec_query_seq(unsigned char cmd);
|
|
|
--extern int ec_query_event_num(void);
|
|
|
--extern int ec_get_event_num(void);
|
|
|
--
|
|
|
--typedef int (*sci_handler) (int status);
|
|
|
--extern sci_handler yeeloong_report_lid_status;
|
|
|
--
|
|
|
--#define SCI_IRQ_NUM 0x0A
|
|
|
--
|
|
|
--/*
|
|
|
-- * The following registers are determined by the EC index configuration.
|
|
|
-- * 1, fill the PORT_HIGH as EC register high part.
|
|
|
-- * 2, fill the PORT_LOW as EC register low part.
|
|
|
-- * 3, fill the PORT_DATA as EC register write data or get the data from it.
|
|
|
-- */
|
|
|
--#define EC_IO_PORT_HIGH 0x0381
|
|
|
--#define EC_IO_PORT_LOW 0x0382
|
|
|
--#define EC_IO_PORT_DATA 0x0383
|
|
|
--
|
|
|
--/*
|
|
|
-- * EC delay time is 500us for register and status access
|
|
|
-- */
|
|
|
--#define EC_REG_DELAY 500 /* unit : us */
|
|
|
--#define EC_CMD_TIMEOUT 0x1000
|
|
|
--
|
|
|
--/*
|
|
|
-- * EC access port for SCI communication
|
|
|
-- */
|
|
|
--#define EC_CMD_PORT 0x66
|
|
|
--#define EC_STS_PORT 0x66
|
|
|
--#define EC_DAT_PORT 0x62
|
|
|
--#define CMD_INIT_IDLE_MODE 0xdd
|
|
|
--#define CMD_EXIT_IDLE_MODE 0xdf
|
|
|
--#define CMD_INIT_RESET_MODE 0xd8
|
|
|
--#define CMD_REBOOT_SYSTEM 0x8c
|
|
|
--#define CMD_GET_EVENT_NUM 0x84
|
|
|
--#define CMD_PROGRAM_PIECE 0xda
|
|
|
--
|
|
|
--/* temperature & fan registers */
|
|
|
--#define REG_TEMPERATURE_VALUE 0xF458
|
|
|
--#define REG_FAN_AUTO_MAN_SWITCH 0xF459
|
|
|
--#define BIT_FAN_AUTO 0
|
|
|
--#define BIT_FAN_MANUAL 1
|
|
|
--#define REG_FAN_CONTROL 0xF4D2
|
|
|
--#define BIT_FAN_CONTROL_ON (1 << 0)
|
|
|
--#define BIT_FAN_CONTROL_OFF (0 << 0)
|
|
|
--#define REG_FAN_STATUS 0xF4DA
|
|
|
--#define BIT_FAN_STATUS_ON (1 << 0)
|
|
|
--#define BIT_FAN_STATUS_OFF (0 << 0)
|
|
|
--#define REG_FAN_SPEED_HIGH 0xFE22
|
|
|
--#define REG_FAN_SPEED_LOW 0xFE23
|
|
|
--#define REG_FAN_SPEED_LEVEL 0xF4CC
|
|
|
--/* fan speed divider */
|
|
|
--#define FAN_SPEED_DIVIDER 480000 /* (60*1000*1000/62.5/2)*/
|
|
|
--
|
|
|
--/* battery registers */
|
|
|
--#define REG_BAT_DESIGN_CAP_HIGH 0xF77D
|
|
|
--#define REG_BAT_DESIGN_CAP_LOW 0xF77E
|
|
|
--#define REG_BAT_FULLCHG_CAP_HIGH 0xF780
|
|
|
--#define REG_BAT_FULLCHG_CAP_LOW 0xF781
|
|
|
--#define REG_BAT_DESIGN_VOL_HIGH 0xF782
|
|
|
--#define REG_BAT_DESIGN_VOL_LOW 0xF783
|
|
|
--#define REG_BAT_CURRENT_HIGH 0xF784
|
|
|
--#define REG_BAT_CURRENT_LOW 0xF785
|
|
|
--#define REG_BAT_VOLTAGE_HIGH 0xF786
|
|
|
--#define REG_BAT_VOLTAGE_LOW 0xF787
|
|
|
--#define REG_BAT_TEMPERATURE_HIGH 0xF788
|
|
|
--#define REG_BAT_TEMPERATURE_LOW 0xF789
|
|
|
--#define REG_BAT_RELATIVE_CAP_HIGH 0xF492
|
|
|
--#define REG_BAT_RELATIVE_CAP_LOW 0xF493
|
|
|
--#define REG_BAT_VENDOR 0xF4C4
|
|
|
--#define FLAG_BAT_VENDOR_SANYO 0x01
|
|
|
--#define FLAG_BAT_VENDOR_SIMPLO 0x02
|
|
|
--#define REG_BAT_CELL_COUNT 0xF4C6
|
|
|
--#define FLAG_BAT_CELL_3S1P 0x03
|
|
|
--#define FLAG_BAT_CELL_3S2P 0x06
|
|
|
--#define REG_BAT_CHARGE 0xF4A2
|
|
|
--#define FLAG_BAT_CHARGE_DISCHARGE 0x01
|
|
|
--#define FLAG_BAT_CHARGE_CHARGE 0x02
|
|
|
--#define FLAG_BAT_CHARGE_ACPOWER 0x00
|
|
|
--#define REG_BAT_STATUS 0xF4B0
|
|
|
--#define BIT_BAT_STATUS_LOW (1 << 5)
|
|
|
--#define BIT_BAT_STATUS_DESTROY (1 << 2)
|
|
|
--#define BIT_BAT_STATUS_FULL (1 << 1)
|
|
|
--#define BIT_BAT_STATUS_IN (1 << 0)
|
|
|
--#define REG_BAT_CHARGE_STATUS 0xF4B1
|
|
|
--#define BIT_BAT_CHARGE_STATUS_OVERTEMP (1 << 2)
|
|
|
--#define BIT_BAT_CHARGE_STATUS_PRECHG (1 << 1)
|
|
|
--#define REG_BAT_STATE 0xF482
|
|
|
--#define BIT_BAT_STATE_CHARGING (1 << 1)
|
|
|
--#define BIT_BAT_STATE_DISCHARGING (1 << 0)
|
|
|
--#define REG_BAT_POWER 0xF440
|
|
|
--#define BIT_BAT_POWER_S3 (1 << 2)
|
|
|
--#define BIT_BAT_POWER_ON (1 << 1)
|
|
|
--#define BIT_BAT_POWER_ACIN (1 << 0)
|
|
|
--
|
|
|
--/* other registers */
|
|
|
--/* Audio: rd/wr */
|
|
|
--#define REG_AUDIO_VOLUME 0xF46C
|
|
|
--#define REG_AUDIO_MUTE 0xF4E7
|
|
|
--#define REG_AUDIO_BEEP 0xF4D0
|
|
|
--/* USB port power or not: rd/wr */
|
|
|
--#define REG_USB0_FLAG 0xF461
|
|
|
--#define REG_USB1_FLAG 0xF462
|
|
|
--#define REG_USB2_FLAG 0xF463
|
|
|
--#define BIT_USB_FLAG_ON 1
|
|
|
--#define BIT_USB_FLAG_OFF 0
|
|
|
--/* LID */
|
|
|
--#define REG_LID_DETECT 0xF4BD
|
|
|
--#define BIT_LID_DETECT_ON 1
|
|
|
--#define BIT_LID_DETECT_OFF 0
|
|
|
--/* CRT */
|
|
|
--#define REG_CRT_DETECT 0xF4AD
|
|
|
--#define BIT_CRT_DETECT_PLUG 1
|
|
|
--#define BIT_CRT_DETECT_UNPLUG 0
|
|
|
--/* LCD backlight brightness adjust: 9 levels */
|
|
|
--#define REG_DISPLAY_BRIGHTNESS 0xF4F5
|
|
|
--/* Black screen Status */
|
|
|
--#define BIT_DISPLAY_LCD_ON 1
|
|
|
--#define BIT_DISPLAY_LCD_OFF 0
|
|
|
--/* LCD backlight control: off/restore */
|
|
|
--#define REG_BACKLIGHT_CTRL 0xF7BD
|
|
|
--#define BIT_BACKLIGHT_ON 1
|
|
|
--#define BIT_BACKLIGHT_OFF 0
|
|
|
--/* Reset the machine auto-clear: rd/wr */
|
|
|
--#define REG_RESET 0xF4EC
|
|
|
--#define BIT_RESET_ON 1
|
|
|
--/* Light the led: rd/wr */
|
|
|
--#define REG_LED 0xF4C8
|
|
|
--#define BIT_LED_RED_POWER (1 << 0)
|
|
|
--#define BIT_LED_ORANGE_POWER (1 << 1)
|
|
|
--#define BIT_LED_GREEN_CHARGE (1 << 2)
|
|
|
--#define BIT_LED_RED_CHARGE (1 << 3)
|
|
|
--#define BIT_LED_NUMLOCK (1 << 4)
|
|
|
--/* Test led mode, all led on/off */
|
|
|
--#define REG_LED_TEST 0xF4C2
|
|
|
--#define BIT_LED_TEST_IN 1
|
|
|
--#define BIT_LED_TEST_OUT 0
|
|
|
--/* Camera on/off */
|
|
|
--#define REG_CAMERA_STATUS 0xF46A
|
|
|
--#define BIT_CAMERA_STATUS_ON 1
|
|
|
--#define BIT_CAMERA_STATUS_OFF 0
|
|
|
--#define REG_CAMERA_CONTROL 0xF7B7
|
|
|
--#define BIT_CAMERA_CONTROL_OFF 0
|
|
|
--#define BIT_CAMERA_CONTROL_ON 1
|
|
|
--/* Wlan Status */
|
|
|
--#define REG_WLAN 0xF4FA
|
|
|
--#define BIT_WLAN_ON 1
|
|
|
--#define BIT_WLAN_OFF 0
|
|
|
--#define REG_DISPLAY_LCD 0xF79F
|
|
|
--
|
|
|
--/* SCI Event Number from EC */
|
|
|
--enum {
|
|
|
-- EVENT_LID = 0x23, /* LID open/close */
|
|
|
-- EVENT_DISPLAY_TOGGLE, /* Fn+F3 for display switch */
|
|
|
-- EVENT_SLEEP, /* Fn+F1 for entering sleep mode */
|
|
|
-- EVENT_OVERTEMP, /* Over-temperature happened */
|
|
|
-- EVENT_CRT_DETECT, /* CRT is connected */
|
|
|
-- EVENT_CAMERA, /* Camera on/off */
|
|
|
-- EVENT_USB_OC2, /* USB2 Over Current occurred */
|
|
|
-- EVENT_USB_OC0, /* USB0 Over Current occurred */
|
|
|
-- EVENT_BLACK_SCREEN, /* Turn on/off backlight */
|
|
|
-- EVENT_AUDIO_MUTE, /* Mute on/off */
|
|
|
-- EVENT_DISPLAY_BRIGHTNESS,/* LCD backlight brightness adjust */
|
|
|
-- EVENT_AC_BAT, /* AC & Battery relative issue */
|
|
|
-- EVENT_AUDIO_VOLUME, /* Volume adjust */
|
|
|
-- EVENT_WLAN, /* Wlan on/off */
|
|
|
-- EVENT_END
|
|
|
--};
|
|
|
--
|
|
|
--#endif /* !_EC_KB3310B_H */
|
|
|
-diff -Nur linux-2.6.36.orig/arch/mips/loongson/lemote-2f/platform.c linux-2.6.36/arch/mips/loongson/lemote-2f/platform.c
|
|
|
|
|
|
-+++ linux-2.6.36/arch/mips/loongson/lemote-2f/platform.c 2010-11-18 11:47:59.000000000 +0100
|
|
|
-@@ -0,0 +1,48 @@
|
|
|
-+/*
|
|
|
-+ * Copyright (C) 2009 Lemote Inc.
|
|
|
-+ * Author: Wu Zhangjin, wuzhangjin@gmail.com
|
|
|
-+ *
|
|
|
-+ * This program is free software; you can redistribute it and/or modify it
|
|
|
-+ * under the terms of the GNU General Public License as published by the
|
|
|
-+ * Free Software Foundation; either version 2 of the License, or (at your
|
|
|
-+ * option) any later version.
|
|
|
-+ */
|
|
|
-+
|
|
|
-+#include <linux/err.h>
|
|
|
-+#include <linux/platform_device.h>
|
|
|
-+
|
|
|
-+#include <asm/bootinfo.h>
|
|
|
-+
|
|
|
-+static struct platform_device yeeloong_pdev = {
|
|
|
-+ .name = "yeeloong_laptop",
|
|
|
-+ .id = -1,
|
|
|
-+};
|
|
|
-+
|
|
|
-+static struct platform_device lynloong_pdev = {
|
|
|
-+ .name = "lynloong_pc",
|
|
|
-+ .id = -1,
|
|
|
-+};
|
|
|
-+
|
|
|
-+static int __init lemote2f_platform_init(void)
|
|
|
-+{
|
|
|
-+ struct platform_device *pdev = NULL;
|
|
|
-+
|
|
|
-+ switch (mips_machtype) {
|
|
|
-+ case MACH_LEMOTE_YL2F89:
|
|
|
-+ pdev = &yeeloong_pdev;
|
|
|
-+ break;
|
|
|
-+ case MACH_LEMOTE_LL2F:
|
|
|
-+ pdev = &lynloong_pdev;
|
|
|
-+ break;
|
|
|
-+ default:
|
|
|
-+ break;
|
|
|
-+
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ if (pdev != NULL)
|
|
|
-+ return platform_device_register(pdev);
|
|
|
-+
|
|
|
-+ return -ENODEV;
|
|
|
-+}
|
|
|
-+
|
|
|
-+arch_initcall(lemote2f_platform_init);
|
|
|
-diff -Nur linux-2.6.36.orig/arch/mips/loongson/lemote-2f/pm.c linux-2.6.36/arch/mips/loongson/lemote-2f/pm.c
|
|
|
|
|
|
-+++ linux-2.6.36/arch/mips/loongson/lemote-2f/pm.c 2010-11-18 11:47:59.000000000 +0100
|
|
|
-@@ -23,7 +23,7 @@
|
|
|
- #include <loongson.h>
|
|
|
-
|
|
|
- #include <cs5536/cs5536_mfgpt.h>
|
|
|
--#include "ec_kb3310b.h"
|
|
|
-+#include <ec_kb3310b.h>
|
|
|
-
|
|
|
- #define I8042_KBD_IRQ 1
|
|
|
- #define I8042_CTR_KBDINT 0x01
|
|
|
-@@ -100,7 +100,7 @@
|
|
|
- if (irq < 0)
|
|
|
- return 0;
|
|
|
-
|
|
|
-- printk(KERN_INFO "%s: irq = %d\n", __func__, irq);
|
|
|
-+ pr_info("%s: irq = %d\n", __func__, irq);
|
|
|
-
|
|
|
- if (irq == I8042_KBD_IRQ)
|
|
|
- return 1;
|
|
|
-diff -Nur linux-2.6.36.orig/arch/mips/loongson/lemote-2f/reset.c linux-2.6.36/arch/mips/loongson/lemote-2f/reset.c
|
|
|
|
|
|
-+++ linux-2.6.36/arch/mips/loongson/lemote-2f/reset.c 2010-11-18 11:47:59.000000000 +0100
|
|
|
-@@ -20,7 +20,7 @@
|
|
|
- #include <loongson.h>
|
|
|
-
|
|
|
- #include <cs5536/cs5536.h>
|
|
|
--#include "ec_kb3310b.h"
|
|
|
-+#include <ec_kb3310b.h>
|
|
|
-
|
|
|
- static void reset_cpu(void)
|
|
|
- {
|
|
|
-diff -Nur linux-2.6.36.orig/arch/mips/mm/dma-default.c linux-2.6.36/arch/mips/mm/dma-default.c
|
|
|
|
|
|
-+++ linux-2.6.36/arch/mips/mm/dma-default.c 2010-11-18 11:47:59.000000000 +0100
|
|
|
-@@ -380,3 +380,16 @@
|
|
|
- }
|
|
|
-
|
|
|
- EXPORT_SYMBOL(dma_cache_sync);
|
|
|
-+
|
|
|
-+int __weak dma_mmap_coherent(struct device *dev, struct vm_area_struct *vma,
|
|
|
-+ void *cpu_addr, dma_addr_t handle, size_t size)
|
|
|
-+{
|
|
|
-+ struct page *pg;
|
|
|
-+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
|
|
|
-+ cpu_addr = (void *)dma_addr_to_virt(dev, handle);
|
|
|
-+ pg = virt_to_page(cpu_addr);
|
|
|
-+ return remap_pfn_range(vma, vma->vm_start,
|
|
|
-+ page_to_pfn(pg) + vma->vm_pgoff,
|
|
|
-+ size, vma->vm_page_prot);
|
|
|
-+}
|
|
|
-+EXPORT_SYMBOL(dma_mmap_coherent);
|
|
|
-diff -Nur linux-2.6.36.orig/drivers/ide/ide-iops.c linux-2.6.36/drivers/ide/ide-iops.c
|
|
|
|
|
|
-+++ linux-2.6.36/drivers/ide/ide-iops.c 2010-11-18 11:47:59.000000000 +0100
|
|
|
-@@ -27,6 +27,8 @@
|
|
|
- #include <asm/uaccess.h>
|
|
|
- #include <asm/io.h>
|
|
|
-
|
|
|
-+#include <asm/bootinfo.h>
|
|
|
-+
|
|
|
- void SELECT_MASK(ide_drive_t *drive, int mask)
|
|
|
- {
|
|
|
- const struct ide_port_ops *port_ops = drive->hwif->port_ops;
|
|
|
-@@ -300,6 +302,9 @@
|
|
|
- {
|
|
|
- const char **list, *m = (char *)&drive->id[ATA_ID_PROD];
|
|
|
-
|
|
|
-+ if (mips_machtype != MACH_LEMOTE_YL2F89)
|
|
|
-+ return;
|
|
|
-+
|
|
|
- for (list = nien_quirk_list; *list != NULL; list++)
|
|
|
- if (strstr(m, *list) != NULL) {
|
|
|
- drive->dev_flags |= IDE_DFLAG_NIEN_QUIRK;
|
|
|
-diff -Nur linux-2.6.36.orig/drivers/platform/Kconfig linux-2.6.36/drivers/platform/Kconfig
|
|
|
|
|
|
-+++ linux-2.6.36/drivers/platform/Kconfig 2010-11-18 11:47:59.000000000 +0100
|
|
|
-@@ -1,3 +1,7 @@
|
|
|
- if X86
|
|
|
- source "drivers/platform/x86/Kconfig"
|
|
|
- endif
|
|
|
-+
|
|
|
-+if MIPS
|
|
|
-+source "drivers/platform/mips/Kconfig"
|
|
|
-+endif
|
|
|
-diff -Nur linux-2.6.36.orig/drivers/platform/Makefile linux-2.6.36/drivers/platform/Makefile
|
|
|
|
|
|
-+++ linux-2.6.36/drivers/platform/Makefile 2010-11-18 11:47:59.000000000 +0100
|
|
|
-@@ -3,3 +3,4 @@
|
|
|
- #
|
|
|
-
|
|
|
- obj-$(CONFIG_X86) += x86/
|
|
|
-+obj-$(CONFIG_MIPS) += mips/
|
|
|
-diff -Nur linux-2.6.36.orig/drivers/platform/mips/Kconfig linux-2.6.36/drivers/platform/mips/Kconfig
|
|
|
|
|
|
-+++ linux-2.6.36/drivers/platform/mips/Kconfig 2010-11-18 11:47:59.000000000 +0100
|
|
|
-@@ -0,0 +1,43 @@
|
|
|
-+#
|
|
|
-+# MIPS Platform Specific Drivers
|
|
|
-+#
|
|
|
-+
|
|
|
-+menuconfig MIPS_PLATFORM_DEVICES
|
|
|
-+ bool "MIPS Platform Specific Device Drivers"
|
|
|
-+ default y
|
|
|
-+ help
|
|
|
-+ Say Y here to get to see options for device drivers of various
|
|
|
-+ MIPS platforms, including vendor-specific netbook/laptop/pc extension
|
|
|
-+ drivers. This option alone does not add any kernel code.
|
|
|
-+
|
|
|
-+ If you say N, all options in this submenu will be skipped and disabled.
|
|
|
-+
|
|
|
-+if MIPS_PLATFORM_DEVICES
|
|
|
-+
|
|
|
-+config LEMOTE_YEELOONG2F
|
|
|
-+ tristate "Lemote YeeLoong Laptop"
|
|
|
-+ depends on LEMOTE_MACH2F
|
|
|
-+ select BACKLIGHT_CLASS_DEVICE
|
|
|
-+ select POWER_SUPPLY
|
|
|
-+ select HWMON
|
|
|
-+ select VIDEO_OUTPUT_CONTROL
|
|
|
-+ select INPUT_SPARSEKMAP
|
|
|
-+ depends on INPUT
|
|
|
-+ help
|
|
|
-+ YeeLoong netbook is a mini laptop made by Lemote, which is basically
|
|
|
-+ compatible to FuLoong2F mini PC, but it has an extra Embedded
|
|
|
-+ Controller(kb3310b) for battery, hotkey, backlight, temperature and
|
|
|
-+ fan management.
|
|
|
-+
|
|
|
-+config LEMOTE_LYNLOONG2F
|
|
|
-+ tristate "Lemote LynLoong PC"
|
|
|
-+ depends on LEMOTE_MACH2F
|
|
|
-+ select BACKLIGHT_CLASS_DEVICE
|
|
|
-+ select VIDEO_OUTPUT_CONTROL
|
|
|
-+ help
|
|
|
-+ LynLoong PC is an AllINONE machine made by Lemote, which is basically
|
|
|
-+ compatible to FuLoong2F Mini PC, the only difference is that it has a
|
|
|
-+ size-fixed screen: 1360x768 with sisfb video driver. and also, it has
|
|
|
-+ its own specific suspend support.
|
|
|
-+
|
|
|
-+endif # MIPS_PLATFORM_DEVICES
|
|
|
-diff -Nur linux-2.6.36.orig/drivers/platform/mips/Makefile linux-2.6.36/drivers/platform/mips/Makefile
|
|
|
|
|
|
-+++ linux-2.6.36/drivers/platform/mips/Makefile 2010-11-18 11:47:59.000000000 +0100
|
|
|
-@@ -0,0 +1,7 @@
|
|
|
-+#
|
|
|
-+# Makefile for MIPS Platform-Specific Drivers
|
|
|
-+#
|
|
|
-+
|
|
|
-+obj-$(CONFIG_LEMOTE_YEELOONG2F) += yeeloong_laptop.o
|
|
|
-+
|
|
|
-+obj-$(CONFIG_LEMOTE_LYNLOONG2F) += lynloong_pc.o
|
|
|
-diff -Nur linux-2.6.36.orig/drivers/platform/mips/lynloong_pc.c linux-2.6.36/drivers/platform/mips/lynloong_pc.c
|
|
|
|
|
|
-+++ linux-2.6.36/drivers/platform/mips/lynloong_pc.c 2010-11-18 11:47:59.000000000 +0100
|
|
|
-@@ -0,0 +1,513 @@
|
|
|
-+/*
|
|
|
-+ * Driver for LynLoong PC extras
|
|
|
-+ *
|
|
|
-+ * Copyright (C) 2009 Lemote Inc.
|
|
|
-+ * Author: Wu Zhangjin <wuzhangjin@gmail.com>, Xiang Yu <xiangy@lemote.com>
|
|
|
-+ *
|
|
|
-+ * This program is free software; you can redistribute it and/or modify
|
|
|
-+ * it under the terms of the GNU General Public License version 2 as
|
|
|
-+ * published by the Free Software Foundation.
|
|
|
-+ */
|
|
|
-+
|
|
|
-+#include <linux/err.h>
|
|
|
-+#include <linux/platform_device.h>
|
|
|
-+#include <linux/backlight.h> /* for backlight subdriver */
|
|
|
-+#include <linux/fb.h>
|
|
|
-+#include <linux/video_output.h> /* for video output subdriver */
|
|
|
-+#include <linux/delay.h> /* for suspend support */
|
|
|
-+
|
|
|
-+#include <cs5536/cs5536.h>
|
|
|
-+#include <cs5536/cs5536_mfgpt.h>
|
|
|
-+
|
|
|
-+#include <loongson.h>
|
|
|
-+
|
|
|
-+static u32 gpio_base, mfgpt_base;
|
|
|
-+
|
|
|
-+static void set_gpio_reg_high(int gpio, int reg)
|
|
|
-+{
|
|
|
-+ u32 val;
|
|
|
-+
|
|
|
-+ val = inl(gpio_base + reg);
|
|
|
-+ val |= (1 << gpio);
|
|
|
-+ val &= ~(1 << (16 + gpio));
|
|
|
-+ outl(val, gpio_base + reg);
|
|
|
-+ mmiowb();
|
|
|
-+}
|
|
|
-+
|
|
|
-+static void set_gpio_reg_low(int gpio, int reg)
|
|
|
-+{
|
|
|
-+ u32 val;
|
|
|
-+
|
|
|
-+ val = inl(gpio_base + reg);
|
|
|
-+ val |= (1 << (16 + gpio));
|
|
|
-+ val &= ~(1 << gpio);
|
|
|
-+ outl(val, gpio_base + reg);
|
|
|
-+ mmiowb();
|
|
|
-+}
|
|
|
-+
|
|
|
-+static void set_gpio_output_low(int gpio)
|
|
|
-+{
|
|
|
-+ set_gpio_reg_high(gpio, GPIOL_OUT_EN);
|
|
|
-+ set_gpio_reg_low(gpio, GPIOL_OUT_VAL);
|
|
|
-+}
|
|
|
-+
|
|
|
-+static void set_gpio_output_high(int gpio)
|
|
|
-+{
|
|
|
-+ set_gpio_reg_high(gpio, GPIOL_OUT_EN);
|
|
|
-+ set_gpio_reg_high(gpio, GPIOL_OUT_VAL);
|
|
|
-+}
|
|
|
-+
|
|
|
-+/* backlight subdriver */
|
|
|
-+
|
|
|
-+#define MAX_BRIGHTNESS 100
|
|
|
-+#define DEFAULT_BRIGHTNESS 50
|
|
|
-+#define MIN_BRIGHTNESS 0
|
|
|
-+static unsigned int level;
|
|
|
-+
|
|
|
-+DEFINE_SPINLOCK(backlight_lock);
|
|
|
-+/* Tune the brightness */
|
|
|
-+static void setup_mfgpt2(void)
|
|
|
-+{
|
|
|
-+ unsigned long flags;
|
|
|
-+
|
|
|
-+ spin_lock_irqsave(&backlight_lock, flags);
|
|
|
-+
|
|
|
-+ /* Set MFGPT2 comparator 1,2 */
|
|
|
-+ outw(MAX_BRIGHTNESS-level, MFGPT2_CMP1);
|
|
|
-+ outw(MAX_BRIGHTNESS, MFGPT2_CMP2);
|
|
|
-+ /* Clear MFGPT2 UP COUNTER */
|
|
|
-+ outw(0, MFGPT2_CNT);
|
|
|
-+ /* Enable counter, compare mode, 32k */
|
|
|
-+ outw(0x8280, MFGPT2_SETUP);
|
|
|
-+
|
|
|
-+ spin_unlock_irqrestore(&backlight_lock, flags);
|
|
|
-+}
|
|
|
-+
|
|
|
-+static int lynloong_set_brightness(struct backlight_device *bd)
|
|
|
-+{
|
|
|
-+ level = (bd->props.fb_blank == FB_BLANK_UNBLANK &&
|
|
|
-+ bd->props.power == FB_BLANK_UNBLANK) ?
|
|
|
-+ bd->props.brightness : 0;
|
|
|
-+
|
|
|
-+ if (level > MAX_BRIGHTNESS)
|
|
|
-+ level = MAX_BRIGHTNESS;
|
|
|
-+ else if (level < MIN_BRIGHTNESS)
|
|
|
-+ level = MIN_BRIGHTNESS;
|
|
|
-+
|
|
|
-+ setup_mfgpt2();
|
|
|
-+
|
|
|
-+ return 0;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static int lynloong_get_brightness(struct backlight_device *bd)
|
|
|
-+{
|
|
|
-+ return level;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static struct backlight_ops backlight_ops = {
|
|
|
-+ .get_brightness = lynloong_get_brightness,
|
|
|
-+ .update_status = lynloong_set_brightness,
|
|
|
-+};
|
|
|
-+
|
|
|
-+static struct backlight_device *lynloong_backlight_dev;
|
|
|
-+
|
|
|
-+static int lynloong_backlight_init(void)
|
|
|
-+{
|
|
|
-+ int ret;
|
|
|
-+ u32 hi;
|
|
|
-+ struct backlight_properties props;
|
|
|
-+
|
|
|
-+ /* Get gpio_base */
|
|
|
-+ _rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_GPIO), &hi, &gpio_base);
|
|
|
-+ /* Get mfgpt_base */
|
|
|
-+ _rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_MFGPT), &hi, &mfgpt_base);
|
|
|
-+ /* Get gpio_base */
|
|
|
-+ _rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_GPIO), &hi, &gpio_base);
|
|
|
-+
|
|
|
-+ /* Select for mfgpt */
|
|
|
-+ set_gpio_reg_high(7, GPIOL_OUT_AUX1_SEL);
|
|
|
-+ /* Enable brightness controlling */
|
|
|
-+ set_gpio_output_high(7);
|
|
|
-+
|
|
|
-+ memset(&props, 0, sizeof(struct backlight_properties));
|
|
|
-+ props.max_brightness = MAX_BRIGHTNESS;
|
|
|
-+ lynloong_backlight_dev = backlight_device_register("backlight0", NULL,
|
|
|
-+ NULL, &backlight_ops, &props);
|
|
|
-+
|
|
|
-+ if (IS_ERR(lynloong_backlight_dev)) {
|
|
|
-+ ret = PTR_ERR(lynloong_backlight_dev);
|
|
|
-+ return ret;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ lynloong_backlight_dev->props.brightness = DEFAULT_BRIGHTNESS;
|
|
|
-+ backlight_update_status(lynloong_backlight_dev);
|
|
|
-+
|
|
|
-+ return 0;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static void lynloong_backlight_exit(void)
|
|
|
-+{
|
|
|
-+ if (lynloong_backlight_dev) {
|
|
|
-+ backlight_device_unregister(lynloong_backlight_dev);
|
|
|
-+ lynloong_backlight_dev = NULL;
|
|
|
-+ }
|
|
|
-+ /* Disable brightness controlling */
|
|
|
-+ set_gpio_output_low(7);
|
|
|
-+}
|
|
|
-+
|
|
|
-+/* video output driver */
|
|
|
-+static int vo_status = 1;
|
|
|
-+
|
|
|
-+static int lcd_video_output_get(struct output_device *od)
|
|
|
-+{
|
|
|
-+ return vo_status;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static int lcd_video_output_set(struct output_device *od)
|
|
|
-+{
|
|
|
-+ int i;
|
|
|
-+ unsigned long status;
|
|
|
-+
|
|
|
-+ status = !!od->request_state;
|
|
|
-+
|
|
|
-+ if (status == 0) {
|
|
|
-+ /* Set the current status as off */
|
|
|
-+ vo_status = 0;
|
|
|
-+ /* Turn off the backlight */
|
|
|
-+ set_gpio_output_low(11);
|
|
|
-+ for (i = 0; i < 0x500; i++)
|
|
|
-+ delay();
|
|
|
-+ /* Turn off the LCD */
|
|
|
-+ set_gpio_output_high(8);
|
|
|
-+ } else {
|
|
|
-+ /* Turn on the LCD */
|
|
|
-+ set_gpio_output_low(8);
|
|
|
-+ for (i = 0; i < 0x500; i++)
|
|
|
-+ delay();
|
|
|
-+ /* Turn on the backlight */
|
|
|
-+ set_gpio_output_high(11);
|
|
|
-+ /* Set the current status as on */
|
|
|
-+ vo_status = 1;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ return 0;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static struct output_properties lcd_output_properties = {
|
|
|
-+ .set_state = lcd_video_output_set,
|
|
|
-+ .get_status = lcd_video_output_get,
|
|
|
-+};
|
|
|
-+
|
|
|
-+static struct output_device *lcd_output_dev;
|
|
|
-+
|
|
|
-+static void lynloong_lcd_vo_set(int status)
|
|
|
-+{
|
|
|
-+ lcd_output_dev->request_state = status;
|
|
|
-+ lcd_video_output_set(lcd_output_dev);
|
|
|
-+}
|
|
|
-+
|
|
|
-+static int lynloong_vo_init(void)
|
|
|
-+{
|
|
|
-+ int ret;
|
|
|
-+
|
|
|
-+ /* Register video output device: lcd */
|
|
|
-+ lcd_output_dev = video_output_register("LCD", NULL, NULL,
|
|
|
-+ &lcd_output_properties);
|
|
|
-+
|
|
|
-+ if (IS_ERR(lcd_output_dev)) {
|
|
|
-+ ret = PTR_ERR(lcd_output_dev);
|
|
|
-+ lcd_output_dev = NULL;
|
|
|
-+ return ret;
|
|
|
-+ }
|
|
|
-+ /* Ensure LCD is on by default */
|
|
|
-+ lynloong_lcd_vo_set(1);
|
|
|
-+
|
|
|
-+ return 0;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static void lynloong_vo_exit(void)
|
|
|
-+{
|
|
|
-+ if (lcd_output_dev) {
|
|
|
-+ video_output_unregister(lcd_output_dev);
|
|
|
-+ lcd_output_dev = NULL;
|
|
|
-+ }
|
|
|
-+}
|
|
|
-+
|
|
|
-+/* suspend support */
|
|
|
-+
|
|
|
-+#ifdef CONFIG_PM
|
|
|
-+
|
|
|
-+static u32 smb_base;
|
|
|
-+
|
|
|
-+/* I2C operations */
|
|
|
-+
|
|
|
-+static int i2c_wait(void)
|
|
|
-+{
|
|
|
-+ char c;
|
|
|
-+ int i;
|
|
|
-+
|
|
|
-+ udelay(1000);
|
|
|
-+ for (i = 0; i < 20; i++) {
|
|
|
-+ c = inb(smb_base | SMB_STS);
|
|
|
-+ if (c & (SMB_STS_BER | SMB_STS_NEGACK))
|
|
|
-+ return -1;
|
|
|
-+ if (c & SMB_STS_SDAST)
|
|
|
-+ return 0;
|
|
|
-+ udelay(100);
|
|
|
-+ }
|
|
|
-+ return -2;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static void i2c_read_single(int addr, int regNo, char *value)
|
|
|
-+{
|
|
|
-+ unsigned char c;
|
|
|
-+
|
|
|
-+ /* Start condition */
|
|
|
-+ c = inb(smb_base | SMB_CTRL1);
|
|
|
-+ outb(c | SMB_CTRL1_START, smb_base | SMB_CTRL1);
|
|
|
-+ i2c_wait();
|
|
|
-+
|
|
|
-+ /* Send slave address */
|
|
|
-+ outb(addr & 0xfe, smb_base | SMB_SDA);
|
|
|
-+ i2c_wait();
|
|
|
-+
|
|
|
-+ /* Acknowledge smbus */
|
|
|
-+ c = inb(smb_base | SMB_CTRL1);
|
|
|
-+ outb(c | SMB_CTRL1_ACK, smb_base | SMB_CTRL1);
|
|
|
-+
|
|
|
-+ /* Send register index */
|
|
|
-+ outb(regNo, smb_base | SMB_SDA);
|
|
|
-+ i2c_wait();
|
|
|
-+
|
|
|
-+ /* Acknowledge smbus */
|
|
|
-+ c = inb(smb_base | SMB_CTRL1);
|
|
|
-+ outb(c | SMB_CTRL1_ACK, smb_base | SMB_CTRL1);
|
|
|
-+
|
|
|
-+ /* Start condition again */
|
|
|
-+ c = inb(smb_base | SMB_CTRL1);
|
|
|
-+ outb(c | SMB_CTRL1_START, smb_base | SMB_CTRL1);
|
|
|
-+ i2c_wait();
|
|
|
-+
|
|
|
-+ /* Send salve address again */
|
|
|
-+ outb(1 | addr, smb_base | SMB_SDA);
|
|
|
-+ i2c_wait();
|
|
|
-+
|
|
|
-+ /* Acknowledge smbus */
|
|
|
-+ c = inb(smb_base | SMB_CTRL1);
|
|
|
-+ outb(c | SMB_CTRL1_ACK, smb_base | SMB_CTRL1);
|
|
|
-+
|
|
|
-+ /* Read data */
|
|
|
-+ *value = inb(smb_base | SMB_SDA);
|
|
|
-+
|
|
|
-+ /* Stop condition */
|
|
|
-+ outb(SMB_CTRL1_STOP, smb_base | SMB_CTRL1);
|
|
|
-+ i2c_wait();
|
|
|
-+}
|
|
|
-+
|
|
|
-+static void i2c_write_single(int addr, int regNo, char value)
|
|
|
-+{
|
|
|
-+ unsigned char c;
|
|
|
-+
|
|
|
-+ /* Start condition */
|
|
|
-+ c = inb(smb_base | SMB_CTRL1);
|
|
|
-+ outb(c | SMB_CTRL1_START, smb_base | SMB_CTRL1);
|
|
|
-+ i2c_wait();
|
|
|
-+ /* Send slave address */
|
|
|
-+ outb(addr & 0xfe, smb_base | SMB_SDA);
|
|
|
-+ i2c_wait();;
|
|
|
-+
|
|
|
-+ /* Send register index */
|
|
|
-+ outb(regNo, smb_base | SMB_SDA);
|
|
|
-+ i2c_wait();
|
|
|
-+
|
|
|
-+ /* Write data */
|
|
|
-+ outb(value, smb_base | SMB_SDA);
|
|
|
-+ i2c_wait();
|
|
|
-+ /* Stop condition */
|
|
|
-+ outb(SMB_CTRL1_STOP, smb_base | SMB_CTRL1);
|
|
|
-+ i2c_wait();
|
|
|
-+}
|
|
|
-+
|
|
|
-+static void stop_clock(int clk_reg, int clk_sel)
|
|
|
-+{
|
|
|
-+ u8 value;
|
|
|
-+
|
|
|
-+ i2c_read_single(0xd3, clk_reg, &value);
|
|
|
-+ value &= ~(1 << clk_sel);
|
|
|
-+ i2c_write_single(0xd2, clk_reg, value);
|
|
|
-+}
|
|
|
-+
|
|
|
-+static void enable_clock(int clk_reg, int clk_sel)
|
|
|
-+{
|
|
|
-+ u8 value;
|
|
|
-+
|
|
|
-+ i2c_read_single(0xd3, clk_reg, &value);
|
|
|
-+ value |= (1 << clk_sel);
|
|
|
-+ i2c_write_single(0xd2, clk_reg, value);
|
|
|
-+}
|
|
|
-+
|
|
|
-+static char cached_clk_freq;
|
|
|
-+static char cached_pci_fixed_freq;
|
|
|
-+
|
|
|
-+static void decrease_clk_freq(void)
|
|
|
-+{
|
|
|
-+ char value;
|
|
|
-+
|
|
|
-+ i2c_read_single(0xd3, 1, &value);
|
|
|
-+ cached_clk_freq = value;
|
|
|
-+
|
|
|
-+ /* Select frequency by software */
|
|
|
-+ value |= (1 << 1);
|
|
|
-+ /* CPU, 3V66, PCI : 100, 66, 33(1) */
|
|
|
-+ value |= (1 << 2);
|
|
|
-+ i2c_write_single(0xd2, 1, value);
|
|
|
-+
|
|
|
-+ /* Cache the pci frequency */
|
|
|
-+ i2c_read_single(0xd3, 14, &value);
|
|
|
-+ cached_pci_fixed_freq = value;
|
|
|
-+
|
|
|
-+ /* Enable PCI fix mode */
|
|
|
-+ value |= (1 << 5);
|
|
|
-+ /* 3V66, PCI : 64MHz, 32MHz */
|
|
|
-+ value |= (1 << 3);
|
|
|
-+ i2c_write_single(0xd2, 14, value);
|
|
|
-+
|
|
|
-+}
|
|
|
-+
|
|
|
-+static void resume_clk_freq(void)
|
|
|
-+{
|
|
|
-+ i2c_write_single(0xd2, 1, cached_clk_freq);
|
|
|
-+ i2c_write_single(0xd2, 14, cached_pci_fixed_freq);
|
|
|
-+}
|
|
|
-+
|
|
|
-+static void stop_clocks(void)
|
|
|
-+{
|
|
|
-+ /* CPU Clock Register */
|
|
|
-+ stop_clock(2, 5); /* not used */
|
|
|
-+ stop_clock(2, 6); /* not used */
|
|
|
-+ stop_clock(2, 7); /* not used */
|
|
|
-+
|
|
|
-+ /* PCI Clock Register */
|
|
|
-+ stop_clock(3, 1); /* 8100 */
|
|
|
-+ stop_clock(3, 5); /* SIS */
|
|
|
-+ stop_clock(3, 0); /* not used */
|
|
|
-+ stop_clock(3, 6); /* not used */
|
|
|
-+
|
|
|
-+ /* PCI 48M Clock Register */
|
|
|
-+ stop_clock(4, 6); /* USB grounding */
|
|
|
-+ stop_clock(4, 5); /* REF(5536_14M) */
|
|
|
-+
|
|
|
-+ /* 3V66 Control Register */
|
|
|
-+ stop_clock(5, 0); /* VCH_CLK..., grounding */
|
|
|
-+}
|
|
|
-+
|
|
|
-+static void enable_clocks(void)
|
|
|
-+{
|
|
|
-+ enable_clock(3, 1); /* 8100 */
|
|
|
-+ enable_clock(3, 5); /* SIS */
|
|
|
-+
|
|
|
-+ enable_clock(4, 6);
|
|
|
-+ enable_clock(4, 5); /* REF(5536_14M) */
|
|
|
-+
|
|
|
-+ enable_clock(5, 0); /* VCH_CLOCK, grounding */
|
|
|
-+}
|
|
|
-+
|
|
|
-+static int lynloong_suspend(struct device *dev)
|
|
|
-+{
|
|
|
-+ /* Disable AMP */
|
|
|
-+ set_gpio_output_high(6);
|
|
|
-+ /* Turn off LCD */
|
|
|
-+ lynloong_lcd_vo_set(0);
|
|
|
-+
|
|
|
-+ /* Stop the clocks of some devices */
|
|
|
-+ stop_clocks();
|
|
|
-+
|
|
|
-+ /* Decrease the external clock frequency */
|
|
|
-+ decrease_clk_freq();
|
|
|
-+
|
|
|
-+ return 0;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static int lynloong_resume(struct device *dev)
|
|
|
-+{
|
|
|
-+ /* Turn on the LCD */
|
|
|
-+ lynloong_lcd_vo_set(1);
|
|
|
-+
|
|
|
-+ /* Resume clock frequency, enable the relative clocks */
|
|
|
-+ resume_clk_freq();
|
|
|
-+ enable_clocks();
|
|
|
-+
|
|
|
-+ /* Enable AMP */
|
|
|
-+ set_gpio_output_low(6);
|
|
|
-+
|
|
|
-+ return 0;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static const SIMPLE_DEV_PM_OPS(lynloong_pm_ops, lynloong_suspend,
|
|
|
-+ lynloong_resume);
|
|
|
-+#endif /* !CONFIG_PM */
|
|
|
-+
|
|
|
-+static struct platform_device_id platform_device_ids[] = {
|
|
|
-+ {
|
|
|
-+ .name = "lynloong_pc",
|
|
|
-+ },
|
|
|
-+ {}
|
|
|
-+};
|
|
|
-+
|
|
|
-+MODULE_DEVICE_TABLE(platform, platform_device_ids);
|
|
|
-+
|
|
|
-+static struct platform_driver platform_driver = {
|
|
|
-+ .driver = {
|
|
|
-+ .name = "lynloong_pc",
|
|
|
-+ .owner = THIS_MODULE,
|
|
|
-+#ifdef CONFIG_PM
|
|
|
-+ .pm = &lynloong_pm_ops,
|
|
|
-+#endif
|
|
|
-+ },
|
|
|
-+ .id_table = platform_device_ids,
|
|
|
-+};
|
|
|
-+
|
|
|
-+static int __init lynloong_init(void)
|
|
|
-+{
|
|
|
-+ int ret;
|
|
|
-+
|
|
|
-+ pr_info("Load LynLoong Platform Specific Driver.\n");
|
|
|
-+
|
|
|
-+ /* Register platform stuff */
|
|
|
-+ ret = platform_driver_register(&platform_driver);
|
|
|
-+ if (ret) {
|
|
|
-+ pr_err("Fail to register lynloong platform driver.\n");
|
|
|
-+ return ret;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ ret = lynloong_backlight_init();
|
|
|
-+ if (ret) {
|
|
|
-+ pr_err("Fail to register lynloong backlight driver.\n");
|
|
|
-+ return ret;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ ret = lynloong_vo_init();
|
|
|
-+ if (ret) {
|
|
|
-+ pr_err("Fail to register lynloong backlight driver.\n");
|
|
|
-+ lynloong_vo_exit();
|
|
|
-+ return ret;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ return 0;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static void __exit lynloong_exit(void)
|
|
|
-+{
|
|
|
-+ lynloong_vo_exit();
|
|
|
-+ lynloong_backlight_exit();
|
|
|
-+ platform_driver_unregister(&platform_driver);
|
|
|
-+
|
|
|
-+ pr_info("Unload LynLoong Platform Specific Driver.\n");
|
|
|
-+}
|
|
|
-+
|
|
|
-+module_init(lynloong_init);
|
|
|
-+module_exit(lynloong_exit);
|
|
|
-+
|
|
|
-+MODULE_AUTHOR("Wu Zhangjin <wuzhangjin@gmail.com>; Xiang Yu <xiangy@lemote.com>");
|
|
|
-+MODULE_DESCRIPTION("LynLoong PC driver");
|
|
|
-+MODULE_LICENSE("GPL");
|
|
|
-diff -Nur linux-2.6.36.orig/drivers/platform/mips/yeeloong_ecrom.c linux-2.6.36/drivers/platform/mips/yeeloong_ecrom.c
|
|
|
|
|
|
-+++ linux-2.6.36/drivers/platform/mips/yeeloong_ecrom.c 2010-11-18 11:47:59.000000000 +0100
|
|
|
-@@ -0,0 +1,943 @@
|
|
|
-+/*
|
|
|
-+ * Driver for flushing/dumping ROM of EC on YeeLoong laptop
|
|
|
-+ *
|
|
|
-+ * Copyright (C) 2009 Lemote Inc.
|
|
|
-+ * Author: liujl <liujl@lemote.com>
|
|
|
-+ *
|
|
|
-+ * NOTE :
|
|
|
-+ * The EC resources accessing and programming are supported.
|
|
|
-+ */
|
|
|
-+
|
|
|
-+#include <linux/proc_fs.h>
|
|
|
-+#include <linux/miscdevice.h>
|
|
|
-+#include <linux/init.h>
|
|
|
-+#include <linux/delay.h>
|
|
|
-+
|
|
|
-+#include <ec_kb3310b.h>
|
|
|
-+
|
|
|
-+#define EC_MISC_DEV "ec_misc"
|
|
|
-+#define EC_IOC_MAGIC 'E'
|
|
|
-+
|
|
|
-+/* ec registers range */
|
|
|
-+#define EC_MAX_REGADDR 0xFFFF
|
|
|
-+#define EC_MIN_REGADDR 0xF000
|
|
|
-+#define EC_RAM_ADDR 0xF800
|
|
|
-+
|
|
|
-+/* version burned address */
|
|
|
-+#define VER_ADDR 0xf7a1
|
|
|
-+#define VER_MAX_SIZE 7
|
|
|
-+#define EC_ROM_MAX_SIZE 0x10000
|
|
|
-+
|
|
|
-+/* ec internal register */
|
|
|
-+#define REG_POWER_MODE 0xF710
|
|
|
-+#define FLAG_NORMAL_MODE 0x00
|
|
|
-+#define FLAG_IDLE_MODE 0x01
|
|
|
-+#define FLAG_RESET_MODE 0x02
|
|
|
-+
|
|
|
-+/* ec update program flag */
|
|
|
-+#define PROGRAM_FLAG_NONE 0x00
|
|
|
-+#define PROGRAM_FLAG_IE 0x01
|
|
|
-+#define PROGRAM_FLAG_ROM 0x02
|
|
|
-+
|
|
|
-+/* XBI relative registers */
|
|
|
-+#define REG_XBISEG0 0xFEA0
|
|
|
-+#define REG_XBISEG1 0xFEA1
|
|
|
-+#define REG_XBIRSV2 0xFEA2
|
|
|
-+#define REG_XBIRSV3 0xFEA3
|
|
|
-+#define REG_XBIRSV4 0xFEA4
|
|
|
-+#define REG_XBICFG 0xFEA5
|
|
|
-+#define REG_XBICS 0xFEA6
|
|
|
-+#define REG_XBIWE 0xFEA7
|
|
|
-+#define REG_XBISPIA0 0xFEA8
|
|
|
-+#define REG_XBISPIA1 0xFEA9
|
|
|
-+#define REG_XBISPIA2 0xFEAA
|
|
|
-+#define REG_XBISPIDAT 0xFEAB
|
|
|
-+#define REG_XBISPICMD 0xFEAC
|
|
|
-+#define REG_XBISPICFG 0xFEAD
|
|
|
-+#define REG_XBISPIDATR 0xFEAE
|
|
|
-+#define REG_XBISPICFG2 0xFEAF
|
|
|
-+
|
|
|
-+/* commands definition for REG_XBISPICMD */
|
|
|
-+#define SPICMD_WRITE_STATUS 0x01
|
|
|
-+#define SPICMD_BYTE_PROGRAM 0x02
|
|
|
-+#define SPICMD_READ_BYTE 0x03
|
|
|
-+#define SPICMD_WRITE_DISABLE 0x04
|
|
|
-+#define SPICMD_READ_STATUS 0x05
|
|
|
-+#define SPICMD_WRITE_ENABLE 0x06
|
|
|
-+#define SPICMD_HIGH_SPEED_READ 0x0B
|
|
|
-+#define SPICMD_POWER_DOWN 0xB9
|
|
|
-+#define SPICMD_SST_EWSR 0x50
|
|
|
-+#define SPICMD_SST_SEC_ERASE 0x20
|
|
|
-+#define SPICMD_SST_BLK_ERASE 0x52
|
|
|
-+#define SPICMD_SST_CHIP_ERASE 0x60
|
|
|
-+#define SPICMD_FRDO 0x3B
|
|
|
-+#define SPICMD_SEC_ERASE 0xD7
|
|
|
-+#define SPICMD_BLK_ERASE 0xD8
|
|
|
-+#define SPICMD_CHIP_ERASE 0xC7
|
|
|
-+
|
|
|
-+/* bits definition for REG_XBISPICFG */
|
|
|
-+#define SPICFG_AUTO_CHECK 0x01
|
|
|
-+#define SPICFG_SPI_BUSY 0x02
|
|
|
-+#define SPICFG_DUMMY_READ 0x04
|
|
|
-+#define SPICFG_EN_SPICMD 0x08
|
|
|
-+#define SPICFG_LOW_SPICS 0x10
|
|
|
-+#define SPICFG_EN_SHORT_READ 0x20
|
|
|
-+#define SPICFG_EN_OFFSET_READ 0x40
|
|
|
-+#define SPICFG_EN_FAST_READ 0x80
|
|
|
-+
|
|
|
-+/* watchdog timer registers */
|
|
|
-+#define REG_WDTCFG 0xfe80
|
|
|
-+#define REG_WDTPF 0xfe81
|
|
|
-+#define REG_WDT 0xfe82
|
|
|
-+
|
|
|
-+/* lpc configure register */
|
|
|
-+#define REG_LPCCFG 0xfe95
|
|
|
-+
|
|
|
-+/* 8051 reg */
|
|
|
-+#define REG_PXCFG 0xff14
|
|
|
-+
|
|
|
-+/* Fan register in KB3310 */
|
|
|
-+#define REG_ECFAN_SPEED_LEVEL 0xf4e4
|
|
|
-+#define REG_ECFAN_SWITCH 0xf4d2
|
|
|
-+
|
|
|
-+/* the ec flash rom id number */
|
|
|
-+#define EC_ROM_PRODUCT_ID_SPANSION 0x01
|
|
|
-+#define EC_ROM_PRODUCT_ID_MXIC 0xC2
|
|
|
-+#define EC_ROM_PRODUCT_ID_AMIC 0x37
|
|
|
-+#define EC_ROM_PRODUCT_ID_EONIC 0x1C
|
|
|
-+
|
|
|
-+/* misc ioctl operations */
|
|
|
-+#define IOCTL_RDREG _IOR(EC_IOC_MAGIC, 1, int)
|
|
|
-+#define IOCTL_WRREG _IOW(EC_IOC_MAGIC, 2, int)
|
|
|
-+#define IOCTL_READ_EC _IOR(EC_IOC_MAGIC, 3, int)
|
|
|
-+#define IOCTL_PROGRAM_IE _IOW(EC_IOC_MAGIC, 4, int)
|
|
|
-+#define IOCTL_PROGRAM_EC _IOW(EC_IOC_MAGIC, 5, int)
|
|
|
-+
|
|
|
-+/* start address for programming of EC content or IE */
|
|
|
-+/* ec running code start address */
|
|
|
-+#define EC_START_ADDR 0x00000000
|
|
|
-+/* ec information element storing address */
|
|
|
-+#define IE_START_ADDR 0x00020000
|
|
|
-+
|
|
|
-+/* EC state */
|
|
|
-+#define EC_STATE_IDLE 0x00 /* ec in idle state */
|
|
|
-+#define EC_STATE_BUSY 0x01 /* ec in busy state */
|
|
|
-+
|
|
|
-+/* timeout value for programming */
|
|
|
-+#define EC_FLASH_TIMEOUT 0x1000 /* ec program timeout */
|
|
|
-+/* command checkout timeout including cmd to port or state flag check */
|
|
|
-+#define EC_CMD_TIMEOUT 0x1000
|
|
|
-+#define EC_SPICMD_STANDARD_TIMEOUT (4 * 1000) /* unit : us */
|
|
|
-+#define EC_MAX_DELAY_UNIT (10) /* every time for polling */
|
|
|
-+#define SPI_FINISH_WAIT_TIME 10
|
|
|
-+/* EC content max size */
|
|
|
-+#define EC_CONTENT_MAX_SIZE (64 * 1024)
|
|
|
-+#define IE_CONTENT_MAX_SIZE (0x100000 - IE_START_ADDR)
|
|
|
-+
|
|
|
-+/* the register operation access struct */
|
|
|
-+struct ec_reg {
|
|
|
-+ u32 addr; /* the address of kb3310 registers */
|
|
|
-+ u8 val; /* the register value */
|
|
|
-+};
|
|
|
-+
|
|
|
-+struct ec_info {
|
|
|
-+ u32 start_addr;
|
|
|
-+ u32 size;
|
|
|
-+ u8 *buf;
|
|
|
-+};
|
|
|
-+
|
|
|
-+/* open for using rom protection action */
|
|
|
-+#define EC_ROM_PROTECTION
|
|
|
-+
|
|
|
-+/* enable the chip reset mode */
|
|
|
-+static int ec_init_reset_mode(void)
|
|
|
-+{
|
|
|
-+ int timeout;
|
|
|
-+ unsigned char status = 0;
|
|
|
-+ int ret = 0;
|
|
|
-+
|
|
|
-+ /* make chip goto reset mode */
|
|
|
-+ ret = ec_query_seq(CMD_INIT_RESET_MODE);
|
|
|
-+ if (ret < 0) {
|
|
|
-+ printk(KERN_ERR "ec init reset mode failed.\n");
|
|
|
-+ goto out;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ /* make the action take active */
|
|
|
-+ timeout = EC_CMD_TIMEOUT;
|
|
|
-+ status = ec_read(REG_POWER_MODE) & FLAG_RESET_MODE;
|
|
|
-+ while (timeout--) {
|
|
|
-+ if (status) {
|
|
|
-+ udelay(EC_REG_DELAY);
|
|
|
-+ break;
|
|
|
-+ }
|
|
|
-+ status = ec_read(REG_POWER_MODE) & FLAG_RESET_MODE;
|
|
|
-+ udelay(EC_REG_DELAY);
|
|
|
-+ }
|
|
|
-+ if (timeout <= 0) {
|
|
|
-+ printk(KERN_ERR "ec rom fixup : can't check reset status.\n");
|
|
|
-+ ret = -EINVAL;
|
|
|
-+ } else
|
|
|
-+ printk(KERN_INFO "(%d/%d)reset 0xf710 : 0x%x\n", timeout,
|
|
|
-+ EC_CMD_TIMEOUT - timeout, status);
|
|
|
-+
|
|
|
-+ /* set MCU to reset mode */
|
|
|
-+ udelay(EC_REG_DELAY);
|
|
|
-+ status = ec_read(REG_PXCFG);
|
|
|
-+ status |= (1 << 0);
|
|
|
-+ ec_write(REG_PXCFG, status);
|
|
|
-+ udelay(EC_REG_DELAY);
|
|
|
-+
|
|
|
-+ /* disable FWH/LPC */
|
|
|
-+ udelay(EC_REG_DELAY);
|
|
|
-+ status = ec_read(REG_LPCCFG);
|
|
|
-+ status &= ~(1 << 7);
|
|
|
-+ ec_write(REG_LPCCFG, status);
|
|
|
-+ udelay(EC_REG_DELAY);
|
|
|
-+
|
|
|
-+ printk(KERN_INFO "entering reset mode ok..............\n");
|
|
|
-+
|
|
|
-+ out:
|
|
|
-+ return ret;
|
|
|
-+}
|
|
|
-+
|
|
|
-+/* make ec exit from reset mode */
|
|
|
-+static void ec_exit_reset_mode(void)
|
|
|
-+{
|
|
|
-+ unsigned char regval;
|
|
|
-+
|
|
|
-+ udelay(EC_REG_DELAY);
|
|
|
-+ regval = ec_read(REG_LPCCFG);
|
|
|
-+ regval |= (1 << 7);
|
|
|
-+ ec_write(REG_LPCCFG, regval);
|
|
|
-+ regval = ec_read(REG_PXCFG);
|
|
|
-+ regval &= ~(1 << 0);
|
|
|
-+ ec_write(REG_PXCFG, regval);
|
|
|
-+ printk(KERN_INFO "exit reset mode ok..................\n");
|
|
|
-+
|
|
|
-+ return;
|
|
|
-+}
|
|
|
-+
|
|
|
-+/* make ec disable WDD */
|
|
|
-+static void ec_disable_WDD(void)
|
|
|
-+{
|
|
|
-+ unsigned char status;
|
|
|
-+
|
|
|
-+ udelay(EC_REG_DELAY);
|
|
|
-+ status = ec_read(REG_WDTCFG);
|
|
|
-+ ec_write(REG_WDTPF, 0x03);
|
|
|
-+ ec_write(REG_WDTCFG, (status & 0x80) | 0x48);
|
|
|
-+ printk(KERN_INFO "Disable WDD ok..................\n");
|
|
|
-+
|
|
|
-+ return;
|
|
|
-+}
|
|
|
-+
|
|
|
-+/* make ec enable WDD */
|
|
|
-+static void ec_enable_WDD(void)
|
|
|
-+{
|
|
|
-+ unsigned char status;
|
|
|
-+
|
|
|
-+ udelay(EC_REG_DELAY);
|
|
|
-+ status = ec_read(REG_WDTCFG);
|
|
|
-+ ec_write(REG_WDT, 0x28); /* set WDT 5sec(0x28) */
|
|
|
-+ ec_write(REG_WDTCFG, (status & 0x80) | 0x03);
|
|
|
-+ printk(KERN_INFO "Enable WDD ok..................\n");
|
|
|
-+
|
|
|
-+ return;
|
|
|
-+}
|
|
|
-+
|
|
|
-+/* make ec goto idle mode */
|
|
|
-+static int ec_init_idle_mode(void)
|
|
|
-+{
|
|
|
-+ int timeout;
|
|
|
-+ unsigned char status = 0;
|
|
|
-+ int ret = 0;
|
|
|
-+
|
|
|
-+ ec_query_seq(CMD_INIT_IDLE_MODE);
|
|
|
-+
|
|
|
-+ /* make the action take active */
|
|
|
-+ timeout = EC_CMD_TIMEOUT;
|
|
|
-+ status = ec_read(REG_POWER_MODE) & FLAG_IDLE_MODE;
|
|
|
-+ while (timeout--) {
|
|
|
-+ if (status) {
|
|
|
-+ udelay(EC_REG_DELAY);
|
|
|
-+ break;
|
|
|
-+ }
|
|
|
-+ status = ec_read(REG_POWER_MODE) & FLAG_IDLE_MODE;
|
|
|
-+ udelay(EC_REG_DELAY);
|
|
|
-+ }
|
|
|
-+ if (timeout <= 0) {
|
|
|
-+ printk(KERN_ERR "ec rom fixup : can't check out the status.\n");
|
|
|
-+ ret = -EINVAL;
|
|
|
-+ } else
|
|
|
-+ printk(KERN_INFO "(%d/%d)0xf710 : 0x%x\n", timeout,
|
|
|
-+ EC_CMD_TIMEOUT - timeout, ec_read(REG_POWER_MODE));
|
|
|
-+
|
|
|
-+ printk(KERN_INFO "entering idle mode ok...................\n");
|
|
|
-+
|
|
|
-+ return ret;
|
|
|
-+}
|
|
|
-+
|
|
|
-+/* make ec exit from idle mode */
|
|
|
-+static int ec_exit_idle_mode(void)
|
|
|
-+{
|
|
|
-+
|
|
|
-+ ec_query_seq(CMD_EXIT_IDLE_MODE);
|
|
|
-+
|
|
|
-+ printk(KERN_INFO "exit idle mode ok...................\n");
|
|
|
-+
|
|
|
-+ return 0;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static int ec_instruction_cycle(void)
|
|
|
-+{
|
|
|
-+ unsigned long timeout;
|
|
|
-+ int ret = 0;
|
|
|
-+
|
|
|
-+ timeout = EC_FLASH_TIMEOUT;
|
|
|
-+ while (timeout-- >= 0) {
|
|
|
-+ if (!(ec_read(REG_XBISPICFG) & SPICFG_SPI_BUSY))
|
|
|
-+ break;
|
|
|
-+ }
|
|
|
-+ if (timeout <= 0) {
|
|
|
-+ printk(KERN_ERR
|
|
|
-+ "EC_INSTRUCTION_CYCLE : timeout for check flag.\n");
|
|
|
-+ ret = -EINVAL;
|
|
|
-+ goto out;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ out:
|
|
|
-+ return ret;
|
|
|
-+}
|
|
|
-+
|
|
|
-+/* To see if the ec is in busy state or not. */
|
|
|
-+static inline int ec_flash_busy(unsigned long timeout)
|
|
|
-+{
|
|
|
-+ /* assurance the first command be going to rom */
|
|
|
-+ if (ec_instruction_cycle() < 0)
|
|
|
-+ return EC_STATE_BUSY;
|
|
|
-+#if 1
|
|
|
-+ timeout = timeout / EC_MAX_DELAY_UNIT;
|
|
|
-+ while (timeout-- > 0) {
|
|
|
-+ /* check the rom's status of busy flag */
|
|
|
-+ ec_write(REG_XBISPICMD, SPICMD_READ_STATUS);
|
|
|
-+ if (ec_instruction_cycle() < 0)
|
|
|
-+ return EC_STATE_BUSY;
|
|
|
-+ if ((ec_read(REG_XBISPIDAT) & 0x01) == 0x00)
|
|
|
-+ return EC_STATE_IDLE;
|
|
|
-+ udelay(EC_MAX_DELAY_UNIT);
|
|
|
-+ }
|
|
|
-+ if (timeout <= 0) {
|
|
|
-+ printk(KERN_ERR
|
|
|
-+ "EC_FLASH_BUSY : timeout for check rom flag.\n");
|
|
|
-+ return EC_STATE_BUSY;
|
|
|
-+ }
|
|
|
-+#else
|
|
|
-+ /* check the rom's status of busy flag */
|
|
|
-+ ec_write(REG_XBISPICMD, SPICMD_READ_STATUS);
|
|
|
-+ if (ec_instruction_cycle() < 0)
|
|
|
-+ return EC_STATE_BUSY;
|
|
|
-+
|
|
|
-+ timeout = timeout / EC_MAX_DELAY_UNIT;
|
|
|
-+ while (timeout-- > 0) {
|
|
|
-+ if ((ec_read(REG_XBISPIDAT) & 0x01) == 0x00)
|
|
|
-+ return EC_STATE_IDLE;
|
|
|
-+ udelay(EC_MAX_DELAY_UNIT);
|
|
|
-+ }
|
|
|
-+ if (timeout <= 0) {
|
|
|
-+ printk(KERN_ERR
|
|
|
-+ "EC_FLASH_BUSY : timeout for check rom flag.\n");
|
|
|
-+ return EC_STATE_BUSY;
|
|
|
-+ }
|
|
|
-+#endif
|
|
|
-+
|
|
|
-+ return EC_STATE_IDLE;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static int rom_instruction_cycle(unsigned char cmd)
|
|
|
-+{
|
|
|
-+ unsigned long timeout = 0;
|
|
|
-+
|
|
|
-+ switch (cmd) {
|
|
|
-+ case SPICMD_READ_STATUS:
|
|
|
-+ case SPICMD_WRITE_ENABLE:
|
|
|
-+ case SPICMD_WRITE_DISABLE:
|
|
|
-+ case SPICMD_READ_BYTE:
|
|
|
-+ case SPICMD_HIGH_SPEED_READ:
|
|
|
-+ timeout = 0;
|
|
|
-+ break;
|
|
|
-+ case SPICMD_WRITE_STATUS:
|
|
|
-+ timeout = 300 * 1000;
|
|
|
-+ break;
|
|
|
-+ case SPICMD_BYTE_PROGRAM:
|
|
|
-+ timeout = 5 * 1000;
|
|
|
-+ break;
|
|
|
-+ case SPICMD_SST_SEC_ERASE:
|
|
|
-+ case SPICMD_SEC_ERASE:
|
|
|
-+ timeout = 1000 * 1000;
|
|
|
-+ break;
|
|
|
-+ case SPICMD_SST_BLK_ERASE:
|
|
|
-+ case SPICMD_BLK_ERASE:
|
|
|
-+ timeout = 3 * 1000 * 1000;
|
|
|
-+ break;
|
|
|
-+ case SPICMD_SST_CHIP_ERASE:
|
|
|
-+ case SPICMD_CHIP_ERASE:
|
|
|
-+ timeout = 20 * 1000 * 1000;
|
|
|
-+ break;
|
|
|
-+ default:
|
|
|
-+ timeout = EC_SPICMD_STANDARD_TIMEOUT;
|
|
|
-+ }
|
|
|
-+ if (timeout == 0)
|
|
|
-+ return ec_instruction_cycle();
|
|
|
-+ if (timeout < EC_SPICMD_STANDARD_TIMEOUT)
|
|
|
-+ timeout = EC_SPICMD_STANDARD_TIMEOUT;
|
|
|
-+
|
|
|
-+ return ec_flash_busy(timeout);
|
|
|
-+}
|
|
|
-+
|
|
|
-+/* delay for start/stop action */
|
|
|
-+static void delay_spi(int n)
|
|
|
-+{
|
|
|
-+ while (n--)
|
|
|
-+ inb(EC_IO_PORT_HIGH);
|
|
|
-+}
|
|
|
-+
|
|
|
-+/* start the action to spi rom function */
|
|
|
-+static void ec_start_spi(void)
|
|
|
-+{
|
|
|
-+ unsigned char val;
|
|
|
-+
|
|
|
-+ delay_spi(SPI_FINISH_WAIT_TIME);
|
|
|
-+ val = ec_read(REG_XBISPICFG) | SPICFG_EN_SPICMD | SPICFG_AUTO_CHECK;
|
|
|
-+ ec_write(REG_XBISPICFG, val);
|
|
|
-+ delay_spi(SPI_FINISH_WAIT_TIME);
|
|
|
-+}
|
|
|
-+
|
|
|
-+/* stop the action to spi rom function */
|
|
|
-+static void ec_stop_spi(void)
|
|
|
-+{
|
|
|
-+ unsigned char val;
|
|
|
-+
|
|
|
-+ delay_spi(SPI_FINISH_WAIT_TIME);
|
|
|
-+ val =
|
|
|
-+ ec_read(REG_XBISPICFG) & (~(SPICFG_EN_SPICMD | SPICFG_AUTO_CHECK));
|
|
|
-+ ec_write(REG_XBISPICFG, val);
|
|
|
-+ delay_spi(SPI_FINISH_WAIT_TIME);
|
|
|
-+}
|
|
|
-+
|
|
|
-+/* read one byte from xbi interface */
|
|
|
-+static int ec_read_byte(unsigned int addr, unsigned char *byte)
|
|
|
-+{
|
|
|
-+ int ret = 0;
|
|
|
-+
|
|
|
-+ /* enable spicmd writing. */
|
|
|
-+ ec_start_spi();
|
|
|
-+
|
|
|
-+ /* enable write spi flash */
|
|
|
-+ ec_write(REG_XBISPICMD, SPICMD_WRITE_ENABLE);
|
|
|
-+ if (rom_instruction_cycle(SPICMD_WRITE_ENABLE) == EC_STATE_BUSY) {
|
|
|
-+ printk(KERN_ERR "EC_READ_BYTE : SPICMD_WRITE_ENABLE failed.\n");
|
|
|
-+ ret = -EINVAL;
|
|
|
-+ goto out;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ /* write the address */
|
|
|
-+ ec_write(REG_XBISPIA2, (addr & 0xff0000) >> 16);
|
|
|
-+ ec_write(REG_XBISPIA1, (addr & 0x00ff00) >> 8);
|
|
|
-+ ec_write(REG_XBISPIA0, (addr & 0x0000ff) >> 0);
|
|
|
-+ /* start action */
|
|
|
-+ ec_write(REG_XBISPICMD, SPICMD_HIGH_SPEED_READ);
|
|
|
-+ if (rom_instruction_cycle(SPICMD_HIGH_SPEED_READ) == EC_STATE_BUSY) {
|
|
|
-+ printk(KERN_ERR
|
|
|
-+ "EC_READ_BYTE : SPICMD_HIGH_SPEED_READ failed.\n");
|
|
|
-+ ret = -EINVAL;
|
|
|
-+ goto out;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ *byte = ec_read(REG_XBISPIDAT);
|
|
|
-+
|
|
|
-+ out:
|
|
|
-+ /* disable spicmd writing. */
|
|
|
-+ ec_stop_spi();
|
|
|
-+
|
|
|
-+ return ret;
|
|
|
-+}
|
|
|
-+
|
|
|
-+/* write one byte to ec rom */
|
|
|
-+static int ec_write_byte(unsigned int addr, unsigned char byte)
|
|
|
-+{
|
|
|
-+ int ret = 0;
|
|
|
-+
|
|
|
-+ /* enable spicmd writing. */
|
|
|
-+ ec_start_spi();
|
|
|
-+
|
|
|
-+ /* enable write spi flash */
|
|
|
-+ ec_write(REG_XBISPICMD, SPICMD_WRITE_ENABLE);
|
|
|
-+ if (rom_instruction_cycle(SPICMD_WRITE_ENABLE) == EC_STATE_BUSY) {
|
|
|
-+ printk(KERN_ERR
|
|
|
-+ "EC_WRITE_BYTE : SPICMD_WRITE_ENABLE failed.\n");
|
|
|
-+ ret = -EINVAL;
|
|
|
-+ goto out;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ /* write the address */
|
|
|
-+ ec_write(REG_XBISPIA2, (addr & 0xff0000) >> 16);
|
|
|
-+ ec_write(REG_XBISPIA1, (addr & 0x00ff00) >> 8);
|
|
|
-+ ec_write(REG_XBISPIA0, (addr & 0x0000ff) >> 0);
|
|
|
-+ ec_write(REG_XBISPIDAT, byte);
|
|
|
-+ /* start action */
|
|
|
-+ ec_write(REG_XBISPICMD, SPICMD_BYTE_PROGRAM);
|
|
|
-+ if (rom_instruction_cycle(SPICMD_BYTE_PROGRAM) == EC_STATE_BUSY) {
|
|
|
-+ printk(KERN_ERR
|
|
|
-+ "EC_WRITE_BYTE : SPICMD_BYTE_PROGRAM failed.\n");
|
|
|
-+ ret = -EINVAL;
|
|
|
-+ goto out;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ out:
|
|
|
-+ /* disable spicmd writing. */
|
|
|
-+ ec_stop_spi();
|
|
|
-+
|
|
|
-+ return ret;
|
|
|
-+}
|
|
|
-+
|
|
|
-+/* unprotect SPI ROM */
|
|
|
-+/* EC_ROM_unprotect function code */
|
|
|
-+static int EC_ROM_unprotect(void)
|
|
|
-+{
|
|
|
-+ unsigned char status;
|
|
|
-+
|
|
|
-+ /* enable write spi flash */
|
|
|
-+ ec_write(REG_XBISPICMD, SPICMD_WRITE_ENABLE);
|
|
|
-+ if (rom_instruction_cycle(SPICMD_WRITE_ENABLE) == EC_STATE_BUSY) {
|
|
|
-+ printk(KERN_ERR
|
|
|
-+ "EC_UNIT_ERASE : SPICMD_WRITE_ENABLE failed.\n");
|
|
|
-+ return 1;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ /* unprotect the status register of rom */
|
|
|
-+ ec_write(REG_XBISPICMD, SPICMD_READ_STATUS);
|
|
|
-+ if (rom_instruction_cycle(SPICMD_READ_STATUS) == EC_STATE_BUSY) {
|
|
|
-+ printk(KERN_ERR "EC_UNIT_ERASE : SPICMD_READ_STATUS failed.\n");
|
|
|
-+ return 1;
|
|
|
-+ }
|
|
|
-+ status = ec_read(REG_XBISPIDAT);
|
|
|
-+ ec_write(REG_XBISPIDAT, status & 0x02);
|
|
|
-+ if (ec_instruction_cycle() < 0) {
|
|
|
-+ printk(KERN_ERR "EC_UNIT_ERASE : write status value failed.\n");
|
|
|
-+ return 1;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ ec_write(REG_XBISPICMD, SPICMD_WRITE_STATUS);
|
|
|
-+ if (rom_instruction_cycle(SPICMD_WRITE_STATUS) == EC_STATE_BUSY) {
|
|
|
-+ printk(KERN_ERR
|
|
|
-+ "EC_UNIT_ERASE : SPICMD_WRITE_STATUS failed.\n");
|
|
|
-+ return 1;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ /* enable write spi flash */
|
|
|
-+ ec_write(REG_XBISPICMD, SPICMD_WRITE_ENABLE);
|
|
|
-+ if (rom_instruction_cycle(SPICMD_WRITE_ENABLE) == EC_STATE_BUSY) {
|
|
|
-+ printk(KERN_ERR
|
|
|
-+ "EC_UNIT_ERASE : SPICMD_WRITE_ENABLE failed.\n");
|
|
|
-+ return 1;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ return 0;
|
|
|
-+}
|
|
|
-+
|
|
|
-+/* erase one block or chip or sector as needed */
|
|
|
-+static int ec_unit_erase(unsigned char erase_cmd, unsigned int addr)
|
|
|
-+{
|
|
|
-+ unsigned char status;
|
|
|
-+ int ret = 0, i = 0;
|
|
|
-+ int unprotect_count = 3;
|
|
|
-+ int check_flag = 0;
|
|
|
-+
|
|
|
-+ /* enable spicmd writing. */
|
|
|
-+ ec_start_spi();
|
|
|
-+
|
|
|
-+#ifdef EC_ROM_PROTECTION
|
|
|
-+ /* added for re-check SPICMD_READ_STATUS */
|
|
|
-+ while (unprotect_count-- > 0) {
|
|
|
-+ if (EC_ROM_unprotect()) {
|
|
|
-+ ret = -EINVAL;
|
|
|
-+ goto out;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ /* first time:500ms --> 5.5sec -->10.5sec */
|
|
|
-+ for (i = 0; i < ((2 - unprotect_count) * 100 + 10); i++)
|
|
|
-+ udelay(50000);
|
|
|
-+ ec_write(REG_XBISPICMD, SPICMD_READ_STATUS);
|
|
|
-+ if (rom_instruction_cycle(SPICMD_READ_STATUS)
|
|
|
-+ == EC_STATE_BUSY) {
|
|
|
-+ printk(KERN_ERR
|
|
|
-+ "EC_PROGRAM_ROM : SPICMD_READ_STATUS failed.\n");
|
|
|
-+ } else {
|
|
|
-+ status = ec_read(REG_XBISPIDAT);
|
|
|
-+ printk(KERN_INFO "Read unprotect status : 0x%x\n",
|
|
|
-+ status);
|
|
|
-+ if ((status & 0x1C) == 0x00) {
|
|
|
-+ printk(KERN_INFO
|
|
|
-+ "Read unprotect status OK1 : 0x%x\n",
|
|
|
-+ status & 0x1C);
|
|
|
-+ check_flag = 1;
|
|
|
-+ break;
|
|
|
-+ }
|
|
|
-+ }
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ if (!check_flag) {
|
|
|
-+ printk(KERN_INFO "SPI ROM unprotect fail.\n");
|
|
|
-+ return 1;
|
|
|
-+ }
|
|
|
-+#endif
|
|
|
-+
|
|
|
-+ /* block address fill */
|
|
|
-+ if (erase_cmd == SPICMD_BLK_ERASE) {
|
|
|
-+ ec_write(REG_XBISPIA2, (addr & 0x00ff0000) >> 16);
|
|
|
-+ ec_write(REG_XBISPIA1, (addr & 0x0000ff00) >> 8);
|
|
|
-+ ec_write(REG_XBISPIA0, (addr & 0x000000ff) >> 0);
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ /* erase the whole chip first */
|
|
|
-+ ec_write(REG_XBISPICMD, erase_cmd);
|
|
|
-+ if (rom_instruction_cycle(erase_cmd) == EC_STATE_BUSY) {
|
|
|
-+ printk(KERN_ERR "EC_UNIT_ERASE : erase failed.\n");
|
|
|
-+ ret = -EINVAL;
|
|
|
-+ goto out;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ out:
|
|
|
-+ /* disable spicmd writing. */
|
|
|
-+ ec_stop_spi();
|
|
|
-+
|
|
|
-+ return ret;
|
|
|
-+}
|
|
|
-+
|
|
|
-+/* update the whole rom content with H/W mode
|
|
|
-+ * PLEASE USING ec_unit_erase() FIRSTLY
|
|
|
-+ */
|
|
|
-+static int ec_program_rom(struct ec_info *info, int flag)
|
|
|
-+{
|
|
|
-+ unsigned int addr = 0;
|
|
|
-+ unsigned long size = 0;
|
|
|
-+ unsigned char *ptr = NULL;
|
|
|
-+ unsigned char data;
|
|
|
-+ unsigned char val = 0;
|
|
|
-+ int ret = 0;
|
|
|
-+ int i, j;
|
|
|
-+ unsigned char status;
|
|
|
-+
|
|
|
-+ /* modify for program serial No.
|
|
|
-+ * set IE_START_ADDR & use idle mode,
|
|
|
-+ * disable WDD
|
|
|
-+ */
|
|
|
-+ if (flag == PROGRAM_FLAG_ROM) {
|
|
|
-+ ret = ec_init_reset_mode();
|
|
|
-+ addr = info->start_addr + EC_START_ADDR;
|
|
|
-+ printk(KERN_INFO "PROGRAM_FLAG_ROM..............\n");
|
|
|
-+ } else if (flag == PROGRAM_FLAG_IE) {
|
|
|
-+ ret = ec_init_idle_mode();
|
|
|
-+ ec_disable_WDD();
|
|
|
-+ addr = info->start_addr + IE_START_ADDR;
|
|
|
-+ printk(KERN_INFO "PROGRAM_FLAG_IE..............\n");
|
|
|
-+ } else {
|
|
|
-+ return 0;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ if (ret < 0) {
|
|
|
-+ if (flag == PROGRAM_FLAG_IE)
|
|
|
-+ ec_enable_WDD();
|
|
|
-+ return ret;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ size = info->size;
|
|
|
-+ ptr = info->buf;
|
|
|
-+ printk(KERN_INFO "starting update ec ROM..............\n");
|
|
|
-+
|
|
|
-+ ret = ec_unit_erase(SPICMD_BLK_ERASE, addr);
|
|
|
-+ if (ret) {
|
|
|
-+ printk(KERN_ERR "program ec : erase block failed.\n");
|
|
|
-+ goto out;
|
|
|
-+ }
|
|
|
-+ printk(KERN_ERR "program ec : erase block OK.\n");
|
|
|
-+
|
|
|
-+ i = 0;
|
|
|
-+ while (i < size) {
|
|
|
-+ data = *(ptr + i);
|
|
|
-+ ec_write_byte(addr, data);
|
|
|
-+ ec_read_byte(addr, &val);
|
|
|
-+ if (val != data) {
|
|
|
-+ ec_write_byte(addr, data);
|
|
|
-+ ec_read_byte(addr, &val);
|
|
|
-+ if (val != data) {
|
|
|
-+ printk(KERN_INFO
|
|
|
-+ "EC : Second flash program failed at:\t");
|
|
|
-+ printk(KERN_INFO
|
|
|
-+ "addr : 0x%x, source : 0x%x, dest: 0x%x\n",
|
|
|
-+ addr, data, val);
|
|
|
-+ printk(KERN_INFO "This should not happen... STOP\n");
|
|
|
-+ break;
|
|
|
-+ }
|
|
|
-+ }
|
|
|
-+ i++;
|
|
|
-+ addr++;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+#ifdef EC_ROM_PROTECTION
|
|
|
-+ /* we should start spi access firstly */
|
|
|
-+ ec_start_spi();
|
|
|
-+
|
|
|
-+ /* enable write spi flash */
|
|
|
-+ ec_write(REG_XBISPICMD, SPICMD_WRITE_ENABLE);
|
|
|
-+ if (rom_instruction_cycle(SPICMD_WRITE_ENABLE) == EC_STATE_BUSY) {
|
|
|
-+ printk(KERN_ERR
|
|
|
-+ "EC_PROGRAM_ROM : SPICMD_WRITE_ENABLE failed.\n");
|
|
|
-+ goto out1;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ /* protect the status register of rom */
|
|
|
-+ ec_write(REG_XBISPICMD, SPICMD_READ_STATUS);
|
|
|
-+ if (rom_instruction_cycle(SPICMD_READ_STATUS) == EC_STATE_BUSY) {
|
|
|
-+ printk(KERN_ERR
|
|
|
-+ "EC_PROGRAM_ROM : SPICMD_READ_STATUS failed.\n");
|
|
|
-+ goto out1;
|
|
|
-+ }
|
|
|
-+ status = ec_read(REG_XBISPIDAT);
|
|
|
-+
|
|
|
-+ ec_write(REG_XBISPIDAT, status | 0x1C);
|
|
|
-+ if (ec_instruction_cycle() < 0) {
|
|
|
-+ printk(KERN_ERR
|
|
|
-+ "EC_PROGRAM_ROM : write status value failed.\n");
|
|
|
-+ goto out1;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ ec_write(REG_XBISPICMD, SPICMD_WRITE_STATUS);
|
|
|
-+ if (rom_instruction_cycle(SPICMD_WRITE_STATUS) == EC_STATE_BUSY) {
|
|
|
-+ printk(KERN_ERR
|
|
|
-+ "EC_PROGRAM_ROM : SPICMD_WRITE_STATUS failed.\n");
|
|
|
-+ goto out1;
|
|
|
-+ }
|
|
|
-+#endif
|
|
|
-+
|
|
|
-+ /* disable the write action to spi rom */
|
|
|
-+ ec_write(REG_XBISPICMD, SPICMD_WRITE_DISABLE);
|
|
|
-+ if (rom_instruction_cycle(SPICMD_WRITE_DISABLE) == EC_STATE_BUSY) {
|
|
|
-+ printk(KERN_ERR
|
|
|
-+ "EC_PROGRAM_ROM : SPICMD_WRITE_DISABLE failed.\n");
|
|
|
-+ goto out1;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ out1:
|
|
|
-+ /* we should stop spi access firstly */
|
|
|
-+ ec_stop_spi();
|
|
|
-+ out:
|
|
|
-+ /* for security */
|
|
|
-+ for (j = 0; j < 2000; j++)
|
|
|
-+ udelay(1000);
|
|
|
-+
|
|
|
-+ /* modify for program serial No.
|
|
|
-+ * after program No exit idle mode
|
|
|
-+ * and enable WDD
|
|
|
-+ */
|
|
|
-+ if (flag == PROGRAM_FLAG_ROM) {
|
|
|
-+ /* exit from the reset mode */
|
|
|
-+ ec_exit_reset_mode();
|
|
|
-+ } else {
|
|
|
-+ /* ec exit from idle mode */
|
|
|
-+ ret = ec_exit_idle_mode();
|
|
|
-+ ec_enable_WDD();
|
|
|
-+ if (ret < 0)
|
|
|
-+ return ret;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ return 0;
|
|
|
-+}
|
|
|
-+
|
|
|
-+/* ioctl */
|
|
|
-+static int misc_ioctl(struct inode *inode, struct file *filp, u_int cmd,
|
|
|
-+ u_long arg)
|
|
|
-+{
|
|
|
-+ struct ec_info ecinfo;
|
|
|
-+ void __user *ptr = (void __user *)arg;
|
|
|
-+ struct ec_reg *ecreg = (struct ec_reg *)(filp->private_data);
|
|
|
-+ int ret = 0;
|
|
|
-+
|
|
|
-+ switch (cmd) {
|
|
|
-+ case IOCTL_RDREG:
|
|
|
-+ ret = copy_from_user(ecreg, ptr, sizeof(struct ec_reg));
|
|
|
-+ if (ret) {
|
|
|
-+ printk(KERN_ERR "reg read : copy from user error.\n");
|
|
|
-+ return -EFAULT;
|
|
|
-+ }
|
|
|
-+ if ((ecreg->addr > EC_MAX_REGADDR)
|
|
|
-+ || (ecreg->addr < EC_MIN_REGADDR)) {
|
|
|
-+ printk(KERN_ERR
|
|
|
-+ "reg read : out of register address range.\n");
|
|
|
-+ return -EINVAL;
|
|
|
-+ }
|
|
|
-+ ecreg->val = ec_read(ecreg->addr);
|
|
|
-+ ret = copy_to_user(ptr, ecreg, sizeof(struct ec_reg));
|
|
|
-+ if (ret) {
|
|
|
-+ printk(KERN_ERR "reg read : copy to user error.\n");
|
|
|
-+ return -EFAULT;
|
|
|
-+ }
|
|
|
-+ break;
|
|
|
-+ case IOCTL_WRREG:
|
|
|
-+ ret = copy_from_user(ecreg, ptr, sizeof(struct ec_reg));
|
|
|
-+ if (ret) {
|
|
|
-+ printk(KERN_ERR "reg write : copy from user error.\n");
|
|
|
-+ return -EFAULT;
|
|
|
-+ }
|
|
|
-+ if ((ecreg->addr > EC_MAX_REGADDR)
|
|
|
-+ || (ecreg->addr < EC_MIN_REGADDR)) {
|
|
|
-+ printk(KERN_ERR
|
|
|
-+ "reg write : out of register address range.\n");
|
|
|
-+ return -EINVAL;
|
|
|
-+ }
|
|
|
-+ ec_write(ecreg->addr, ecreg->val);
|
|
|
-+ break;
|
|
|
-+ case IOCTL_READ_EC:
|
|
|
-+ ret = copy_from_user(ecreg, ptr, sizeof(struct ec_reg));
|
|
|
-+ if (ret) {
|
|
|
-+ printk(KERN_ERR "spi read : copy from user error.\n");
|
|
|
-+ return -EFAULT;
|
|
|
-+ }
|
|
|
-+ if ((ecreg->addr > EC_RAM_ADDR)
|
|
|
-+ && (ecreg->addr < EC_MAX_REGADDR)) {
|
|
|
-+ printk(KERN_ERR
|
|
|
-+ "spi read : out of register address range.\n");
|
|
|
-+ return -EINVAL;
|
|
|
-+ }
|
|
|
-+ ec_read_byte(ecreg->addr, &(ecreg->val));
|
|
|
-+ ret = copy_to_user(ptr, ecreg, sizeof(struct ec_reg));
|
|
|
-+ if (ret) {
|
|
|
-+ printk(KERN_ERR "spi read : copy to user error.\n");
|
|
|
-+ return -EFAULT;
|
|
|
-+ }
|
|
|
-+ break;
|
|
|
-+ case IOCTL_PROGRAM_IE:
|
|
|
-+ ecinfo.start_addr = EC_START_ADDR;
|
|
|
-+ ecinfo.size = EC_CONTENT_MAX_SIZE;
|
|
|
-+ ecinfo.buf = (u8 *) kmalloc(ecinfo.size, GFP_KERNEL);
|
|
|
-+ if (ecinfo.buf == NULL) {
|
|
|
-+ printk(KERN_ERR "program ie : kmalloc failed.\n");
|
|
|
-+ return -ENOMEM;
|
|
|
-+ }
|
|
|
-+ ret = copy_from_user(ecinfo.buf, (u8 *) ptr, ecinfo.size);
|
|
|
-+ if (ret) {
|
|
|
-+ printk(KERN_ERR "program ie : copy from user error.\n");
|
|
|
-+ kfree(ecinfo.buf);
|
|
|
-+ ecinfo.buf = NULL;
|
|
|
-+ return -EFAULT;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ /* use ec_program_rom to write serial No */
|
|
|
-+ ec_program_rom(&ecinfo, PROGRAM_FLAG_IE);
|
|
|
-+
|
|
|
-+ kfree(ecinfo.buf);
|
|
|
-+ ecinfo.buf = NULL;
|
|
|
-+ break;
|
|
|
-+ case IOCTL_PROGRAM_EC:
|
|
|
-+ ecinfo.start_addr = EC_START_ADDR;
|
|
|
-+ if (get_user((ecinfo.size), (u32 *) ptr)) {
|
|
|
-+ printk(KERN_ERR "program ec : get user error.\n");
|
|
|
-+ return -EFAULT;
|
|
|
-+ }
|
|
|
-+ if ((ecinfo.size) > EC_CONTENT_MAX_SIZE) {
|
|
|
-+ printk(KERN_ERR "program ec : size out of limited.\n");
|
|
|
-+ return -EINVAL;
|
|
|
-+ }
|
|
|
-+ ecinfo.buf = (u8 *) kmalloc(ecinfo.size, GFP_KERNEL);
|
|
|
-+ if (ecinfo.buf == NULL) {
|
|
|
-+ printk(KERN_ERR "program ec : kmalloc failed.\n");
|
|
|
-+ return -ENOMEM;
|
|
|
-+ }
|
|
|
-+ ret = copy_from_user(ecinfo.buf, ((u8 *) ptr + 4), ecinfo.size);
|
|
|
-+ if (ret) {
|
|
|
-+ printk(KERN_ERR "program ec : copy from user error.\n");
|
|
|
-+ kfree(ecinfo.buf);
|
|
|
-+ ecinfo.buf = NULL;
|
|
|
-+ return -EFAULT;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ ec_program_rom(&ecinfo, PROGRAM_FLAG_ROM);
|
|
|
-+
|
|
|
-+ kfree(ecinfo.buf);
|
|
|
-+ ecinfo.buf = NULL;
|
|
|
-+ break;
|
|
|
-+
|
|
|
-+ default:
|
|
|
-+ break;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ return 0;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static long misc_compat_ioctl(struct file *file, unsigned int cmd,
|
|
|
-+ unsigned long arg)
|
|
|
-+{
|
|
|
-+ return misc_ioctl(file->f_dentry->d_inode, file, cmd, arg);
|
|
|
-+}
|
|
|
-+
|
|
|
-+static int misc_open(struct inode *inode, struct file *filp)
|
|
|
-+{
|
|
|
-+ struct ec_reg *ecreg = NULL;
|
|
|
-+ ecreg = kmalloc(sizeof(struct ec_reg), GFP_KERNEL);
|
|
|
-+ if (ecreg)
|
|
|
-+ filp->private_data = ecreg;
|
|
|
-+
|
|
|
-+ return ecreg ? 0 : -ENOMEM;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static int misc_release(struct inode *inode, struct file *filp)
|
|
|
-+{
|
|
|
-+ struct ec_reg *ecreg = (struct ec_reg *)(filp->private_data);
|
|
|
-+
|
|
|
-+ filp->private_data = NULL;
|
|
|
-+ kfree(ecreg);
|
|
|
-+
|
|
|
-+ return 0;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static const struct file_operations ecmisc_fops = {
|
|
|
-+ .open = misc_open,
|
|
|
-+ .release = misc_release,
|
|
|
-+ .read = NULL,
|
|
|
-+ .write = NULL,
|
|
|
-+#ifdef CONFIG_64BIT
|
|
|
-+ .compat_ioctl = misc_compat_ioctl,
|
|
|
-+#else
|
|
|
-+ .ioctl = misc_ioctl,
|
|
|
-+#endif
|
|
|
-+};
|
|
|
-+
|
|
|
-+static struct miscdevice ecmisc_device = {
|
|
|
-+ .minor = MISC_DYNAMIC_MINOR,
|
|
|
-+ .name = EC_MISC_DEV,
|
|
|
-+ .fops = &ecmisc_fops
|
|
|
-+};
|
|
|
-+
|
|
|
-+static int __init ecmisc_init(void)
|
|
|
-+{
|
|
|
-+ int ret;
|
|
|
-+
|
|
|
-+ printk(KERN_INFO "EC misc device init.\n");
|
|
|
-+ ret = misc_register(&ecmisc_device);
|
|
|
-+
|
|
|
-+ return ret;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static void __exit ecmisc_exit(void)
|
|
|
-+{
|
|
|
-+ printk(KERN_INFO "EC misc device exit.\n");
|
|
|
-+ misc_deregister(&ecmisc_device);
|
|
|
-+}
|
|
|
-+
|
|
|
-+module_init(ecmisc_init);
|
|
|
-+module_exit(ecmisc_exit);
|
|
|
-+
|
|
|
-+MODULE_AUTHOR("liujl <liujl@lemote.com>");
|
|
|
-+MODULE_DESCRIPTION("Driver for flushing/dumping ROM of EC on YeeLoong laptop");
|
|
|
-+MODULE_LICENSE("GPL");
|
|
|
-diff -Nur linux-2.6.36.orig/drivers/platform/mips/yeeloong_laptop.c linux-2.6.36/drivers/platform/mips/yeeloong_laptop.c
|
|
|
|
|
|
-+++ linux-2.6.36/drivers/platform/mips/yeeloong_laptop.c 2010-11-18 11:47:59.000000000 +0100
|
|
|
-@@ -0,0 +1,1200 @@
|
|
|
-+/*
|
|
|
-+ * Driver for YeeLoong laptop extras
|
|
|
-+ *
|
|
|
-+ * Copyright (C) 2009 Lemote Inc.
|
|
|
-+ * Author: Wu Zhangjin <wuzhangjin@gmail.com>, Liu Junliang <liujl@lemote.com>
|
|
|
-+ *
|
|
|
-+ * This program is free software; you can redistribute it and/or modify
|
|
|
-+ * it under the terms of the GNU General Public License version 2 as
|
|
|
-+ * published by the Free Software Foundation.
|
|
|
-+ */
|
|
|
-+
|
|
|
-+#include <linux/err.h>
|
|
|
-+#include <linux/platform_device.h>
|
|
|
-+#include <linux/backlight.h> /* for backlight subdriver */
|
|
|
-+#include <linux/fb.h>
|
|
|
-+#include <linux/hwmon.h> /* for hwmon subdriver */
|
|
|
-+#include <linux/hwmon-sysfs.h>
|
|
|
-+#include <linux/video_output.h> /* for video output subdriver */
|
|
|
-+#include <linux/input.h> /* for hotkey subdriver */
|
|
|
-+#include <linux/input/sparse-keymap.h>
|
|
|
-+#include <linux/interrupt.h>
|
|
|
-+#include <linux/delay.h>
|
|
|
-+#include <linux/power_supply.h> /* for AC & Battery subdriver */
|
|
|
-+
|
|
|
-+#include <cs5536/cs5536.h>
|
|
|
-+
|
|
|
-+#include <loongson.h> /* for loongson_cmdline */
|
|
|
-+#include <ec_kb3310b.h>
|
|
|
-+
|
|
|
-+/* common function */
|
|
|
-+#define EC_VER_LEN 64
|
|
|
-+
|
|
|
-+static int ec_version_before(char *version)
|
|
|
-+{
|
|
|
-+ char *p, ec_ver[EC_VER_LEN];
|
|
|
-+
|
|
|
-+ p = strstr(loongson_cmdline, "EC_VER=");
|
|
|
-+ if (!p)
|
|
|
-+ memset(ec_ver, 0, EC_VER_LEN);
|
|
|
-+ else {
|
|
|
-+ strncpy(ec_ver, p, EC_VER_LEN);
|
|
|
-+ p = strstr(ec_ver, " ");
|
|
|
-+ if (p)
|
|
|
-+ *p = '\0';
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ return (strncasecmp(ec_ver, version, 64) < 0);
|
|
|
-+}
|
|
|
-+
|
|
|
-+/* backlight subdriver */
|
|
|
-+#define MAX_BRIGHTNESS 8
|
|
|
-+
|
|
|
-+static int yeeloong_set_brightness(struct backlight_device *bd)
|
|
|
-+{
|
|
|
-+ unsigned int level, current_level;
|
|
|
-+ static unsigned int old_level;
|
|
|
-+
|
|
|
-+ level = (bd->props.fb_blank == FB_BLANK_UNBLANK &&
|
|
|
-+ bd->props.power == FB_BLANK_UNBLANK) ?
|
|
|
-+ bd->props.brightness : 0;
|
|
|
-+
|
|
|
-+ level = SENSORS_LIMIT(level, 0, MAX_BRIGHTNESS);
|
|
|
-+
|
|
|
-+ /* Avoid to modify the brightness when EC is tuning it */
|
|
|
-+ if (old_level != level) {
|
|
|
-+ current_level = ec_read(REG_DISPLAY_BRIGHTNESS);
|
|
|
-+ if (old_level == current_level)
|
|
|
-+ ec_write(REG_DISPLAY_BRIGHTNESS, level);
|
|
|
-+ old_level = level;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ return 0;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static int yeeloong_get_brightness(struct backlight_device *bd)
|
|
|
-+{
|
|
|
-+ return ec_read(REG_DISPLAY_BRIGHTNESS);
|
|
|
-+}
|
|
|
-+
|
|
|
-+static struct backlight_ops backlight_ops = {
|
|
|
-+ .get_brightness = yeeloong_get_brightness,
|
|
|
-+ .update_status = yeeloong_set_brightness,
|
|
|
-+};
|
|
|
-+
|
|
|
-+static struct backlight_device *yeeloong_backlight_dev;
|
|
|
-+
|
|
|
-+static int yeeloong_backlight_init(void)
|
|
|
-+{
|
|
|
-+ int ret;
|
|
|
-+ struct backlight_properties props;
|
|
|
-+
|
|
|
-+ memset(&props, 0, sizeof(struct backlight_properties));
|
|
|
-+ props.max_brightness = MAX_BRIGHTNESS;
|
|
|
-+ yeeloong_backlight_dev = backlight_device_register("backlight0", NULL,
|
|
|
-+ NULL, &backlight_ops, &props);
|
|
|
-+
|
|
|
-+ if (IS_ERR(yeeloong_backlight_dev)) {
|
|
|
-+ ret = PTR_ERR(yeeloong_backlight_dev);
|
|
|
-+ yeeloong_backlight_dev = NULL;
|
|
|
-+ return ret;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ yeeloong_backlight_dev->props.brightness =
|
|
|
-+ yeeloong_get_brightness(yeeloong_backlight_dev);
|
|
|
-+ backlight_update_status(yeeloong_backlight_dev);
|
|
|
-+
|
|
|
-+ return 0;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static void yeeloong_backlight_exit(void)
|
|
|
-+{
|
|
|
-+ if (yeeloong_backlight_dev) {
|
|
|
-+ backlight_device_unregister(yeeloong_backlight_dev);
|
|
|
-+ yeeloong_backlight_dev = NULL;
|
|
|
-+ }
|
|
|
-+}
|
|
|
-+
|
|
|
-+/* AC & Battery subdriver */
|
|
|
-+
|
|
|
-+static struct power_supply yeeloong_ac, yeeloong_bat;
|
|
|
-+
|
|
|
-+#define AC_OFFLINE 0
|
|
|
-+#define AC_ONLINE 1
|
|
|
-+
|
|
|
-+static int yeeloong_get_ac_props(struct power_supply *psy,
|
|
|
-+ enum power_supply_property psp,
|
|
|
-+ union power_supply_propval *val)
|
|
|
-+{
|
|
|
-+ switch (psp) {
|
|
|
-+ case POWER_SUPPLY_PROP_ONLINE:
|
|
|
-+ val->intval = ((ec_read(REG_BAT_POWER)) & BIT_BAT_POWER_ACIN) ?
|
|
|
-+ AC_ONLINE : AC_OFFLINE;
|
|
|
-+ break;
|
|
|
-+ default:
|
|
|
-+ return -EINVAL;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ return 0;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static enum power_supply_property yeeloong_ac_props[] = {
|
|
|
-+ POWER_SUPPLY_PROP_ONLINE,
|
|
|
-+};
|
|
|
-+
|
|
|
-+static struct power_supply yeeloong_ac = {
|
|
|
-+ .name = "yeeloong-ac",
|
|
|
-+ .type = POWER_SUPPLY_TYPE_MAINS,
|
|
|
-+ .properties = yeeloong_ac_props,
|
|
|
-+ .num_properties = ARRAY_SIZE(yeeloong_ac_props),
|
|
|
-+ .get_property = yeeloong_get_ac_props,
|
|
|
-+};
|
|
|
-+
|
|
|
-+#define BAT_CAP_CRITICAL 5
|
|
|
-+#define BAT_CAP_HIGH 99
|
|
|
-+
|
|
|
-+#define get_bat_info(type) \
|
|
|
-+ ((ec_read(REG_BAT_##type##_HIGH) << 8) | \
|
|
|
-+ (ec_read(REG_BAT_##type##_LOW)))
|
|
|
-+
|
|
|
-+static int yeeloong_bat_get_ex_property(enum power_supply_property psp,
|
|
|
-+ union power_supply_propval *val)
|
|
|
-+{
|
|
|
-+ int bat_in, curr_cap, cap_level, status, charge, health;
|
|
|
-+
|
|
|
-+ status = ec_read(REG_BAT_STATUS);
|
|
|
-+ bat_in = status & BIT_BAT_STATUS_IN;
|
|
|
-+ curr_cap = get_bat_info(RELATIVE_CAP);
|
|
|
-+ if (status & BIT_BAT_STATUS_FULL)
|
|
|
-+ curr_cap = 100;
|
|
|
-+
|
|
|
-+ switch (psp) {
|
|
|
-+ case POWER_SUPPLY_PROP_PRESENT:
|
|
|
-+ val->intval = bat_in;
|
|
|
-+ break;
|
|
|
-+ case POWER_SUPPLY_PROP_CAPACITY:
|
|
|
-+ val->intval = curr_cap;
|
|
|
-+ break;
|
|
|
-+ case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
|
|
|
-+ cap_level = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
|
|
|
-+ if (status & BIT_BAT_STATUS_LOW) {
|
|
|
-+ cap_level = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
|
|
|
-+ if (curr_cap <= BAT_CAP_CRITICAL)
|
|
|
-+ cap_level =
|
|
|
-+ POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
|
|
|
-+ } else if (status & BIT_BAT_STATUS_FULL) {
|
|
|
-+ cap_level = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
|
|
|
-+ if (curr_cap >= BAT_CAP_HIGH)
|
|
|
-+ cap_level = POWER_SUPPLY_CAPACITY_LEVEL_HIGH;
|
|
|
-+ } else if (status & BIT_BAT_STATUS_DESTROY)
|
|
|
-+ cap_level = POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN;
|
|
|
-+ val->intval = cap_level;
|
|
|
-+ break;
|
|
|
-+ case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:
|
|
|
-+ /* seconds */
|
|
|
-+ val->intval = bat_in ? (curr_cap - 3) * 54 + 142 : 0;
|
|
|
-+ break;
|
|
|
-+ case POWER_SUPPLY_PROP_STATUS:
|
|
|
-+ if (!bat_in)
|
|
|
-+ charge = POWER_SUPPLY_STATUS_UNKNOWN;
|
|
|
-+ else {
|
|
|
-+ if (status & BIT_BAT_STATUS_FULL) {
|
|
|
-+ val->intval = POWER_SUPPLY_STATUS_FULL;
|
|
|
-+ break;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ charge = ec_read(REG_BAT_CHARGE);
|
|
|
-+ if (charge & FLAG_BAT_CHARGE_DISCHARGE)
|
|
|
-+ charge = POWER_SUPPLY_STATUS_DISCHARGING;
|
|
|
-+ else if (charge & FLAG_BAT_CHARGE_CHARGE)
|
|
|
-+ charge = POWER_SUPPLY_STATUS_CHARGING;
|
|
|
-+ else
|
|
|
-+ charge = POWER_SUPPLY_STATUS_NOT_CHARGING;
|
|
|
-+ }
|
|
|
-+ val->intval = charge;
|
|
|
-+ break;
|
|
|
-+ case POWER_SUPPLY_PROP_HEALTH:
|
|
|
-+ if (!bat_in) /* no battery present */
|
|
|
-+ health = POWER_SUPPLY_HEALTH_UNKNOWN;
|
|
|
-+ else { /* Assume it is good */
|
|
|
-+ health = POWER_SUPPLY_HEALTH_GOOD;
|
|
|
-+ if (status &
|
|
|
-+ (BIT_BAT_STATUS_DESTROY | BIT_BAT_STATUS_LOW))
|
|
|
-+ health = POWER_SUPPLY_HEALTH_DEAD;
|
|
|
-+ if (ec_read(REG_BAT_CHARGE_STATUS) &
|
|
|
-+ BIT_BAT_CHARGE_STATUS_OVERTEMP)
|
|
|
-+ health = POWER_SUPPLY_HEALTH_OVERHEAT;
|
|
|
-+ }
|
|
|
-+ val->intval = health;
|
|
|
-+ break;
|
|
|
-+ case POWER_SUPPLY_PROP_CHARGE_NOW: /* 1/100(%)*1000 µAh */
|
|
|
-+ val->intval = curr_cap * get_bat_info(FULLCHG_CAP) * 10;
|
|
|
-+ break;
|
|
|
-+ default:
|
|
|
-+ return -EINVAL;
|
|
|
-+ }
|
|
|
-+ return 0;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static int get_battery_temp(void)
|
|
|
-+{
|
|
|
-+ int value;
|
|
|
-+
|
|
|
-+ value = get_bat_info(TEMPERATURE);
|
|
|
-+
|
|
|
-+ return value * 1000;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static int get_battery_current(void)
|
|
|
-+{
|
|
|
-+ s16 value;
|
|
|
-+
|
|
|
-+ value = get_bat_info(CURRENT);
|
|
|
-+
|
|
|
-+ return -value;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static int get_battery_voltage(void)
|
|
|
-+{
|
|
|
-+ int value;
|
|
|
-+
|
|
|
-+ value = get_bat_info(VOLTAGE);
|
|
|
-+
|
|
|
-+ return value;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static int yeeloong_get_bat_props(struct power_supply *psy,
|
|
|
-+ enum power_supply_property psp,
|
|
|
-+ union power_supply_propval *val)
|
|
|
-+{
|
|
|
-+ switch (psp) {
|
|
|
-+ /* Fixed information */
|
|
|
-+ case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
|
|
|
-+ val->intval = get_bat_info(DESIGN_VOL) * 1000; /* mV -> µV */
|
|
|
-+ break;
|
|
|
-+ case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
|
|
|
-+ val->intval = get_bat_info(DESIGN_CAP) * 1000; /* mAh->µAh */
|
|
|
-+ break;
|
|
|
-+ case POWER_SUPPLY_PROP_CHARGE_FULL:
|
|
|
-+ val->intval = get_bat_info(FULLCHG_CAP) * 1000; /* µAh */
|
|
|
-+ break;
|
|
|
-+ case POWER_SUPPLY_PROP_MANUFACTURER:
|
|
|
-+ val->strval = (ec_read(REG_BAT_VENDOR) ==
|
|
|
-+ FLAG_BAT_VENDOR_SANYO) ? "SANYO" : "SIMPLO";
|
|
|
-+ break;
|
|
|
-+ /* Dynamic information */
|
|
|
-+ case POWER_SUPPLY_PROP_CURRENT_NOW:
|
|
|
-+ val->intval = get_battery_current() * 1000; /* mA -> µA */
|
|
|
-+ break;
|
|
|
-+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
|
|
|
-+ val->intval = get_battery_voltage() * 1000; /* mV -> µV */
|
|
|
-+ break;
|
|
|
-+ case POWER_SUPPLY_PROP_TEMP:
|
|
|
-+ val->intval = get_battery_temp(); /* Celcius */
|
|
|
-+ break;
|
|
|
-+ /* Dynamic but related information */
|
|
|
-+ default:
|
|
|
-+ return yeeloong_bat_get_ex_property(psp, val);
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ return 0;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static enum power_supply_property yeeloong_bat_props[] = {
|
|
|
-+ POWER_SUPPLY_PROP_STATUS,
|
|
|
-+ POWER_SUPPLY_PROP_PRESENT,
|
|
|
-+ POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
|
|
|
-+ POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
|
|
|
-+ POWER_SUPPLY_PROP_CHARGE_FULL,
|
|
|
-+ POWER_SUPPLY_PROP_CHARGE_NOW,
|
|
|
-+ POWER_SUPPLY_PROP_CURRENT_NOW,
|
|
|
-+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
|
|
|
-+ POWER_SUPPLY_PROP_HEALTH,
|
|
|
-+ POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
|
|
|
-+ POWER_SUPPLY_PROP_CAPACITY,
|
|
|
-+ POWER_SUPPLY_PROP_CAPACITY_LEVEL,
|
|
|
-+ POWER_SUPPLY_PROP_TEMP,
|
|
|
-+ POWER_SUPPLY_PROP_MANUFACTURER,
|
|
|
-+};
|
|
|
-+
|
|
|
-+static struct power_supply yeeloong_bat = {
|
|
|
-+ .name = "yeeloong-bat",
|
|
|
-+ .type = POWER_SUPPLY_TYPE_BATTERY,
|
|
|
-+ .properties = yeeloong_bat_props,
|
|
|
-+ .num_properties = ARRAY_SIZE(yeeloong_bat_props),
|
|
|
-+ .get_property = yeeloong_get_bat_props,
|
|
|
-+};
|
|
|
-+
|
|
|
-+static int ac_bat_initialized;
|
|
|
-+
|
|
|
-+static int yeeloong_bat_init(void)
|
|
|
-+{
|
|
|
-+ int ret;
|
|
|
-+
|
|
|
-+ ret = power_supply_register(NULL, &yeeloong_ac);
|
|
|
-+ if (ret)
|
|
|
-+ return ret;
|
|
|
-+ ret = power_supply_register(NULL, &yeeloong_bat);
|
|
|
-+ if (ret) {
|
|
|
-+ power_supply_unregister(&yeeloong_ac);
|
|
|
-+ return ret;
|
|
|
-+ }
|
|
|
-+ ac_bat_initialized = 1;
|
|
|
-+
|
|
|
-+ return 0;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static void yeeloong_bat_exit(void)
|
|
|
-+{
|
|
|
-+ ac_bat_initialized = 0;
|
|
|
-+
|
|
|
-+ power_supply_unregister(&yeeloong_ac);
|
|
|
-+ power_supply_unregister(&yeeloong_bat);
|
|
|
-+}
|
|
|
-+/* hwmon subdriver */
|
|
|
-+
|
|
|
-+#define MIN_FAN_SPEED 0
|
|
|
-+#define MAX_FAN_SPEED 3
|
|
|
-+
|
|
|
-+static int get_fan_pwm_enable(void)
|
|
|
-+{
|
|
|
-+ int level, mode;
|
|
|
-+
|
|
|
-+ level = ec_read(REG_FAN_SPEED_LEVEL);
|
|
|
-+ mode = ec_read(REG_FAN_AUTO_MAN_SWITCH);
|
|
|
-+
|
|
|
-+ if (level == MAX_FAN_SPEED && mode == BIT_FAN_MANUAL)
|
|
|
-+ mode = 0;
|
|
|
-+ else if (mode == BIT_FAN_MANUAL)
|
|
|
-+ mode = 1;
|
|
|
-+ else
|
|
|
-+ mode = 2;
|
|
|
-+
|
|
|
-+ return mode;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static void set_fan_pwm_enable(int mode)
|
|
|
-+{
|
|
|
-+ switch (mode) {
|
|
|
-+ case 0:
|
|
|
-+ /* fullspeed */
|
|
|
-+ ec_write(REG_FAN_AUTO_MAN_SWITCH, BIT_FAN_MANUAL);
|
|
|
-+ ec_write(REG_FAN_SPEED_LEVEL, MAX_FAN_SPEED);
|
|
|
-+ break;
|
|
|
-+ case 1:
|
|
|
-+ ec_write(REG_FAN_AUTO_MAN_SWITCH, BIT_FAN_MANUAL);
|
|
|
-+ break;
|
|
|
-+ case 2:
|
|
|
-+ ec_write(REG_FAN_AUTO_MAN_SWITCH, BIT_FAN_AUTO);
|
|
|
-+ break;
|
|
|
-+ default:
|
|
|
-+ break;
|
|
|
-+ }
|
|
|
-+}
|
|
|
-+
|
|
|
-+static int get_fan_pwm(void)
|
|
|
-+{
|
|
|
-+ return ec_read(REG_FAN_SPEED_LEVEL);
|
|
|
-+}
|
|
|
-+
|
|
|
-+static void set_fan_pwm(int value)
|
|
|
-+{
|
|
|
-+ int mode;
|
|
|
-+
|
|
|
-+ mode = ec_read(REG_FAN_AUTO_MAN_SWITCH);
|
|
|
-+ if (mode != BIT_FAN_MANUAL)
|
|
|
-+ return;
|
|
|
-+
|
|
|
-+ value = SENSORS_LIMIT(value, 0, 3);
|
|
|
-+
|
|
|
-+ /* We must ensure the fan is on */
|
|
|
-+ if (value > 0)
|
|
|
-+ ec_write(REG_FAN_CONTROL, BIT_FAN_CONTROL_ON);
|
|
|
-+
|
|
|
-+ ec_write(REG_FAN_SPEED_LEVEL, value);
|
|
|
-+}
|
|
|
-+
|
|
|
-+static int get_fan_rpm(void)
|
|
|
-+{
|
|
|
-+ int value;
|
|
|
-+
|
|
|
-+ value = FAN_SPEED_DIVIDER /
|
|
|
-+ (((ec_read(REG_FAN_SPEED_HIGH) & 0x0f) << 8) |
|
|
|
-+ ec_read(REG_FAN_SPEED_LOW));
|
|
|
-+
|
|
|
-+ return value;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static int get_cpu_temp(void)
|
|
|
-+{
|
|
|
-+ s8 value;
|
|
|
-+
|
|
|
-+ value = ec_read(REG_TEMPERATURE_VALUE);
|
|
|
-+
|
|
|
-+ return value * 1000;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static int get_cpu_temp_max(void)
|
|
|
-+{
|
|
|
-+ return 60 * 1000;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static int get_battery_temp_alarm(void)
|
|
|
-+{
|
|
|
-+ int status;
|
|
|
-+
|
|
|
-+ status = (ec_read(REG_BAT_CHARGE_STATUS) &
|
|
|
-+ BIT_BAT_CHARGE_STATUS_OVERTEMP);
|
|
|
-+
|
|
|
-+ return !!status;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static ssize_t store_sys_hwmon(void (*set) (int), const char *buf, size_t count)
|
|
|
-+{
|
|
|
-+ int ret;
|
|
|
-+ unsigned long value;
|
|
|
-+
|
|
|
-+ if (!count)
|
|
|
-+ return 0;
|
|
|
-+
|
|
|
-+ ret = strict_strtoul(buf, 10, &value);
|
|
|
-+ if (ret)
|
|
|
-+ return ret;
|
|
|
-+
|
|
|
-+ set(value);
|
|
|
-+
|
|
|
-+ return count;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static ssize_t show_sys_hwmon(int (*get) (void), char *buf)
|
|
|
-+{
|
|
|
-+ return sprintf(buf, "%d\n", get());
|
|
|
-+}
|
|
|
-+
|
|
|
-+#define CREATE_SENSOR_ATTR(_name, _mode, _set, _get) \
|
|
|
-+ static ssize_t show_##_name(struct device *dev, \
|
|
|
-+ struct device_attribute *attr, \
|
|
|
-+ char *buf) \
|
|
|
-+ { \
|
|
|
-+ return show_sys_hwmon(_set, buf); \
|
|
|
-+ } \
|
|
|
-+ static ssize_t store_##_name(struct device *dev, \
|
|
|
-+ struct device_attribute *attr, \
|
|
|
-+ const char *buf, size_t count) \
|
|
|
-+ { \
|
|
|
-+ return store_sys_hwmon(_get, buf, count); \
|
|
|
-+ } \
|
|
|
-+ static SENSOR_DEVICE_ATTR(_name, _mode, show_##_name, store_##_name, 0);
|
|
|
-+
|
|
|
-+CREATE_SENSOR_ATTR(fan1_input, S_IRUGO, get_fan_rpm, NULL);
|
|
|
-+CREATE_SENSOR_ATTR(pwm1, S_IRUGO | S_IWUSR, get_fan_pwm, set_fan_pwm);
|
|
|
-+CREATE_SENSOR_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, get_fan_pwm_enable,
|
|
|
-+ set_fan_pwm_enable);
|
|
|
-+CREATE_SENSOR_ATTR(temp1_input, S_IRUGO, get_cpu_temp, NULL);
|
|
|
-+CREATE_SENSOR_ATTR(temp1_max, S_IRUGO, get_cpu_temp_max, NULL);
|
|
|
-+CREATE_SENSOR_ATTR(temp2_input, S_IRUGO, get_battery_temp, NULL);
|
|
|
-+CREATE_SENSOR_ATTR(temp2_max_alarm, S_IRUGO, get_battery_temp_alarm, NULL);
|
|
|
-+CREATE_SENSOR_ATTR(curr1_input, S_IRUGO, get_battery_current, NULL);
|
|
|
-+CREATE_SENSOR_ATTR(in1_input, S_IRUGO, get_battery_voltage, NULL);
|
|
|
-+
|
|
|
-+static ssize_t
|
|
|
-+show_name(struct device *dev, struct device_attribute *attr, char *buf)
|
|
|
-+{
|
|
|
-+ return sprintf(buf, "yeeloong\n");
|
|
|
-+}
|
|
|
-+
|
|
|
-+static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0);
|
|
|
-+
|
|
|
-+static struct attribute *hwmon_attributes[] = {
|
|
|
-+ &sensor_dev_attr_pwm1.dev_attr.attr,
|
|
|
-+ &sensor_dev_attr_pwm1_enable.dev_attr.attr,
|
|
|
-+ &sensor_dev_attr_fan1_input.dev_attr.attr,
|
|
|
-+ &sensor_dev_attr_temp1_input.dev_attr.attr,
|
|
|
-+ &sensor_dev_attr_temp1_max.dev_attr.attr,
|
|
|
-+ &sensor_dev_attr_temp2_input.dev_attr.attr,
|
|
|
-+ &sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
|
|
|
-+ &sensor_dev_attr_curr1_input.dev_attr.attr,
|
|
|
-+ &sensor_dev_attr_in1_input.dev_attr.attr,
|
|
|
-+ &sensor_dev_attr_name.dev_attr.attr,
|
|
|
-+ NULL
|
|
|
-+};
|
|
|
-+
|
|
|
-+static struct attribute_group hwmon_attribute_group = {
|
|
|
-+ .attrs = hwmon_attributes
|
|
|
-+};
|
|
|
-+
|
|
|
-+static struct device *yeeloong_hwmon_dev;
|
|
|
-+
|
|
|
-+static int yeeloong_hwmon_init(void)
|
|
|
-+{
|
|
|
-+ int ret;
|
|
|
-+
|
|
|
-+ yeeloong_hwmon_dev = hwmon_device_register(NULL);
|
|
|
-+ if (IS_ERR(yeeloong_hwmon_dev)) {
|
|
|
-+ pr_err("Fail to register yeeloong hwmon device\n");
|
|
|
-+ yeeloong_hwmon_dev = NULL;
|
|
|
-+ return PTR_ERR(yeeloong_hwmon_dev);
|
|
|
-+ }
|
|
|
-+ ret = sysfs_create_group(&yeeloong_hwmon_dev->kobj,
|
|
|
-+ &hwmon_attribute_group);
|
|
|
-+ if (ret) {
|
|
|
-+ hwmon_device_unregister(yeeloong_hwmon_dev);
|
|
|
-+ yeeloong_hwmon_dev = NULL;
|
|
|
-+ return ret;
|
|
|
-+ }
|
|
|
-+ /* ensure fan is set to auto mode */
|
|
|
-+ set_fan_pwm_enable(2);
|
|
|
-+
|
|
|
-+ return 0;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static void yeeloong_hwmon_exit(void)
|
|
|
-+{
|
|
|
-+ if (yeeloong_hwmon_dev) {
|
|
|
-+ sysfs_remove_group(&yeeloong_hwmon_dev->kobj,
|
|
|
-+ &hwmon_attribute_group);
|
|
|
-+ hwmon_device_unregister(yeeloong_hwmon_dev);
|
|
|
-+ yeeloong_hwmon_dev = NULL;
|
|
|
-+ }
|
|
|
-+}
|
|
|
-+
|
|
|
-+/* video output subdriver */
|
|
|
-+
|
|
|
-+static int lcd_video_output_get(struct output_device *od)
|
|
|
-+{
|
|
|
-+ return ec_read(REG_DISPLAY_LCD);
|
|
|
-+}
|
|
|
-+
|
|
|
-+#define LCD 0
|
|
|
-+#define CRT 1
|
|
|
-+
|
|
|
-+static void display_vo_set(int display, int on)
|
|
|
-+{
|
|
|
-+ int addr;
|
|
|
-+ unsigned long value;
|
|
|
-+
|
|
|
-+ addr = (display == LCD) ? 0x31 : 0x21;
|
|
|
-+
|
|
|
-+ outb(addr, 0x3c4);
|
|
|
-+ value = inb(0x3c5);
|
|
|
-+
|
|
|
-+ if (display == LCD)
|
|
|
-+ value |= (on ? 0x03 : 0x02);
|
|
|
-+ else {
|
|
|
-+ if (on)
|
|
|
-+ clear_bit(7, &value);
|
|
|
-+ else
|
|
|
-+ set_bit(7, &value);
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ outb(addr, 0x3c4);
|
|
|
-+ outb(value, 0x3c5);
|
|
|
-+}
|
|
|
-+
|
|
|
-+static int lcd_video_output_set(struct output_device *od)
|
|
|
-+{
|
|
|
-+ unsigned long status;
|
|
|
-+
|
|
|
-+ status = !!od->request_state;
|
|
|
-+
|
|
|
-+ display_vo_set(LCD, status);
|
|
|
-+ ec_write(REG_BACKLIGHT_CTRL, status);
|
|
|
-+
|
|
|
-+ return 0;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static struct output_properties lcd_output_properties = {
|
|
|
-+ .set_state = lcd_video_output_set,
|
|
|
-+ .get_status = lcd_video_output_get,
|
|
|
-+};
|
|
|
-+
|
|
|
-+static int crt_video_output_get(struct output_device *od)
|
|
|
-+{
|
|
|
-+ return ec_read(REG_CRT_DETECT);
|
|
|
-+}
|
|
|
-+
|
|
|
-+static int crt_video_output_set(struct output_device *od)
|
|
|
-+{
|
|
|
-+ unsigned long status;
|
|
|
-+
|
|
|
-+ status = !!od->request_state;
|
|
|
-+
|
|
|
-+ if (ec_read(REG_CRT_DETECT) == BIT_CRT_DETECT_PLUG)
|
|
|
-+ display_vo_set(CRT, status);
|
|
|
-+
|
|
|
-+ return 0;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static struct output_properties crt_output_properties = {
|
|
|
-+ .set_state = crt_video_output_set,
|
|
|
-+ .get_status = crt_video_output_get,
|
|
|
-+};
|
|
|
-+
|
|
|
-+static struct output_device *lcd_output_dev, *crt_output_dev;
|
|
|
-+
|
|
|
-+static void yeeloong_lcd_vo_set(int status)
|
|
|
-+{
|
|
|
-+ lcd_output_dev->request_state = status;
|
|
|
-+ lcd_video_output_set(lcd_output_dev);
|
|
|
-+}
|
|
|
-+
|
|
|
-+static void yeeloong_crt_vo_set(int status)
|
|
|
-+{
|
|
|
-+ crt_output_dev->request_state = status;
|
|
|
-+ crt_video_output_set(crt_output_dev);
|
|
|
-+}
|
|
|
-+
|
|
|
-+static int yeeloong_vo_init(void)
|
|
|
-+{
|
|
|
-+ int ret;
|
|
|
-+
|
|
|
-+ /* Register video output device: lcd, crt */
|
|
|
-+ lcd_output_dev = video_output_register("LCD", NULL, NULL,
|
|
|
-+ &lcd_output_properties);
|
|
|
-+
|
|
|
-+ if (IS_ERR(lcd_output_dev)) {
|
|
|
-+ ret = PTR_ERR(lcd_output_dev);
|
|
|
-+ lcd_output_dev = NULL;
|
|
|
-+ return ret;
|
|
|
-+ }
|
|
|
-+ /* Ensure LCD is on by default */
|
|
|
-+ yeeloong_lcd_vo_set(BIT_DISPLAY_LCD_ON);
|
|
|
-+
|
|
|
-+ crt_output_dev = video_output_register("CRT", NULL, NULL,
|
|
|
-+ &crt_output_properties);
|
|
|
-+
|
|
|
-+ if (IS_ERR(crt_output_dev)) {
|
|
|
-+ ret = PTR_ERR(crt_output_dev);
|
|
|
-+ crt_output_dev = NULL;
|
|
|
-+ return ret;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ /* Turn off CRT by default, and will be enabled when the CRT
|
|
|
-+ * connectting event reported by SCI */
|
|
|
-+ yeeloong_crt_vo_set(BIT_CRT_DETECT_UNPLUG);
|
|
|
-+
|
|
|
-+ return 0;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static void yeeloong_vo_exit(void)
|
|
|
-+{
|
|
|
-+ if (lcd_output_dev) {
|
|
|
-+ video_output_unregister(lcd_output_dev);
|
|
|
-+ lcd_output_dev = NULL;
|
|
|
-+ }
|
|
|
-+ if (crt_output_dev) {
|
|
|
-+ video_output_unregister(crt_output_dev);
|
|
|
-+ crt_output_dev = NULL;
|
|
|
-+ }
|
|
|
-+}
|
|
|
-+
|
|
|
-+/* hotkey subdriver */
|
|
|
-+
|
|
|
-+static struct input_dev *yeeloong_hotkey_dev;
|
|
|
-+
|
|
|
-+static const struct key_entry yeeloong_keymap[] = {
|
|
|
-+ {KE_SW, EVENT_LID, { SW_LID } },
|
|
|
-+ {KE_KEY, EVENT_CAMERA, { KEY_CAMERA } }, /* Fn + ESC */
|
|
|
-+ {KE_KEY, EVENT_SLEEP, { KEY_SLEEP } }, /* Fn + F1 */
|
|
|
-+ {KE_KEY, EVENT_DISPLAYTOGGLE, { KEY_DISPLAYTOGGLE } }, /* Fn + F2 */
|
|
|
-+ {KE_KEY, EVENT_SWITCHVIDEOMODE, { KEY_SWITCHVIDEOMODE } }, /* Fn + F3 */
|
|
|
-+ {KE_KEY, EVENT_AUDIO_MUTE, { KEY_MUTE } }, /* Fn + F4 */
|
|
|
-+ {KE_KEY, EVENT_WLAN, { KEY_WLAN } }, /* Fn + F5 */
|
|
|
-+ {KE_KEY, EVENT_DISPLAY_BRIGHTNESS, { KEY_BRIGHTNESSUP } }, /* Fn + up */
|
|
|
-+ {KE_KEY, EVENT_DISPLAY_BRIGHTNESS, { KEY_BRIGHTNESSDOWN } }, /* Fn + down */
|
|
|
-+ {KE_KEY, EVENT_AUDIO_VOLUME, { KEY_VOLUMEUP } }, /* Fn + right */
|
|
|
-+ {KE_KEY, EVENT_AUDIO_VOLUME, { KEY_VOLUMEDOWN } }, /* Fn + left */
|
|
|
-+ {KE_END, 0}
|
|
|
-+};
|
|
|
-+
|
|
|
-+static struct key_entry *get_event_key_entry(int event, int status)
|
|
|
-+{
|
|
|
-+ struct key_entry *ke;
|
|
|
-+ static int old_brightness_status = -1;
|
|
|
-+ static int old_volume_status = -1;
|
|
|
-+
|
|
|
-+ ke = sparse_keymap_entry_from_scancode(yeeloong_hotkey_dev, event);
|
|
|
-+ if (!ke)
|
|
|
-+ return NULL;
|
|
|
-+
|
|
|
-+ switch (event) {
|
|
|
-+ case EVENT_DISPLAY_BRIGHTNESS:
|
|
|
-+ /* current status > old one, means up */
|
|
|
-+ if ((status < old_brightness_status) || (0 == status))
|
|
|
-+ ke++;
|
|
|
-+ old_brightness_status = status;
|
|
|
-+ break;
|
|
|
-+ case EVENT_AUDIO_VOLUME:
|
|
|
-+ if ((status < old_volume_status) || (0 == status))
|
|
|
-+ ke++;
|
|
|
-+ old_volume_status = status;
|
|
|
-+ break;
|
|
|
-+ default:
|
|
|
-+ break;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ return ke;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static int report_lid_switch(int status)
|
|
|
-+{
|
|
|
-+ input_report_switch(yeeloong_hotkey_dev, SW_LID, !status);
|
|
|
-+ input_sync(yeeloong_hotkey_dev);
|
|
|
-+
|
|
|
-+ return status;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static int crt_detect_handler(int status)
|
|
|
-+{
|
|
|
-+ if (status) {
|
|
|
-+ yeeloong_crt_vo_set(BIT_CRT_DETECT_PLUG);
|
|
|
-+ yeeloong_lcd_vo_set(BIT_DISPLAY_LCD_OFF);
|
|
|
-+ } else {
|
|
|
-+ yeeloong_lcd_vo_set(BIT_DISPLAY_LCD_ON);
|
|
|
-+ yeeloong_crt_vo_set(BIT_CRT_DETECT_UNPLUG);
|
|
|
-+ }
|
|
|
-+ return status;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static int displaytoggle_handler(int status)
|
|
|
-+{
|
|
|
-+ /* EC(>=PQ1D26) does this job for us, we can not do it again,
|
|
|
-+ * otherwise, the brightness will not resume to the normal level! */
|
|
|
-+ if (ec_version_before("EC_VER=PQ1D26"))
|
|
|
-+ yeeloong_lcd_vo_set(status);
|
|
|
-+
|
|
|
-+ return status;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static int switchvideomode_handler(int status)
|
|
|
-+{
|
|
|
-+ static int video_output_status;
|
|
|
-+
|
|
|
-+ /* Only enable switch video output button
|
|
|
-+ * when CRT is connected */
|
|
|
-+ if (ec_read(REG_CRT_DETECT) == BIT_CRT_DETECT_UNPLUG)
|
|
|
-+ return 0;
|
|
|
-+ /* 0. no CRT connected: LCD on, CRT off
|
|
|
-+ * 1. BOTH on
|
|
|
-+ * 2. LCD off, CRT on
|
|
|
-+ * 3. BOTH off
|
|
|
-+ * 4. LCD on, CRT off
|
|
|
-+ */
|
|
|
-+ video_output_status++;
|
|
|
-+ if (video_output_status > 4)
|
|
|
-+ video_output_status = 1;
|
|
|
-+
|
|
|
-+ switch (video_output_status) {
|
|
|
-+ case 1:
|
|
|
-+ yeeloong_lcd_vo_set(BIT_DISPLAY_LCD_ON);
|
|
|
-+ yeeloong_crt_vo_set(BIT_CRT_DETECT_PLUG);
|
|
|
-+ break;
|
|
|
-+ case 2:
|
|
|
-+ yeeloong_lcd_vo_set(BIT_DISPLAY_LCD_OFF);
|
|
|
-+ yeeloong_crt_vo_set(BIT_CRT_DETECT_PLUG);
|
|
|
-+ break;
|
|
|
-+ case 3:
|
|
|
-+ yeeloong_lcd_vo_set(BIT_DISPLAY_LCD_OFF);
|
|
|
-+ yeeloong_crt_vo_set(BIT_CRT_DETECT_UNPLUG);
|
|
|
-+ break;
|
|
|
-+ case 4:
|
|
|
-+ yeeloong_lcd_vo_set(BIT_DISPLAY_LCD_ON);
|
|
|
-+ yeeloong_crt_vo_set(BIT_CRT_DETECT_UNPLUG);
|
|
|
-+ break;
|
|
|
-+ default:
|
|
|
-+ /* Ensure LCD is on */
|
|
|
-+ yeeloong_lcd_vo_set(BIT_DISPLAY_LCD_ON);
|
|
|
-+ break;
|
|
|
-+ }
|
|
|
-+ return video_output_status;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static int camera_handler(int status)
|
|
|
-+{
|
|
|
-+ int value;
|
|
|
-+
|
|
|
-+ value = ec_read(REG_CAMERA_CONTROL);
|
|
|
-+ ec_write(REG_CAMERA_CONTROL, value | (1 << 1));
|
|
|
-+
|
|
|
-+ return status;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static int usb2_handler(int status)
|
|
|
-+{
|
|
|
-+ pr_emerg("USB2 Over Current occurred\n");
|
|
|
-+
|
|
|
-+ return status;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static int usb0_handler(int status)
|
|
|
-+{
|
|
|
-+ pr_emerg("USB0 Over Current occurred\n");
|
|
|
-+
|
|
|
-+ return status;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static int ac_bat_handler(int status)
|
|
|
-+{
|
|
|
-+ if (ac_bat_initialized) {
|
|
|
-+ power_supply_changed(&yeeloong_ac);
|
|
|
-+ power_supply_changed(&yeeloong_bat);
|
|
|
-+ }
|
|
|
-+ return status;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static void do_event_action(int event)
|
|
|
-+{
|
|
|
-+ sci_handler handler;
|
|
|
-+ int reg, status;
|
|
|
-+ struct key_entry *ke;
|
|
|
-+
|
|
|
-+ reg = 0;
|
|
|
-+ handler = NULL;
|
|
|
-+
|
|
|
-+ switch (event) {
|
|
|
-+ case EVENT_LID:
|
|
|
-+ reg = REG_LID_DETECT;
|
|
|
-+ break;
|
|
|
-+ case EVENT_SWITCHVIDEOMODE:
|
|
|
-+ handler = switchvideomode_handler;
|
|
|
-+ break;
|
|
|
-+ case EVENT_CRT_DETECT:
|
|
|
-+ reg = REG_CRT_DETECT;
|
|
|
-+ handler = crt_detect_handler;
|
|
|
-+ break;
|
|
|
-+ case EVENT_CAMERA:
|
|
|
-+ reg = REG_CAMERA_STATUS;
|
|
|
-+ handler = camera_handler;
|
|
|
-+ break;
|
|
|
-+ case EVENT_USB_OC2:
|
|
|
-+ reg = REG_USB2_FLAG;
|
|
|
-+ handler = usb2_handler;
|
|
|
-+ break;
|
|
|
-+ case EVENT_USB_OC0:
|
|
|
-+ reg = REG_USB0_FLAG;
|
|
|
-+ handler = usb0_handler;
|
|
|
-+ break;
|
|
|
-+ case EVENT_DISPLAYTOGGLE:
|
|
|
-+ reg = REG_DISPLAY_LCD;
|
|
|
-+ handler = displaytoggle_handler;
|
|
|
-+ break;
|
|
|
-+ case EVENT_AUDIO_MUTE:
|
|
|
-+ reg = REG_AUDIO_MUTE;
|
|
|
-+ break;
|
|
|
-+ case EVENT_DISPLAY_BRIGHTNESS:
|
|
|
-+ reg = REG_DISPLAY_BRIGHTNESS;
|
|
|
-+ break;
|
|
|
-+ case EVENT_AUDIO_VOLUME:
|
|
|
-+ reg = REG_AUDIO_VOLUME;
|
|
|
-+ break;
|
|
|
-+ case EVENT_AC_BAT:
|
|
|
-+ handler = ac_bat_handler;
|
|
|
-+ break;
|
|
|
-+ default:
|
|
|
-+ break;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ if (reg != 0)
|
|
|
-+ status = ec_read(reg);
|
|
|
-+
|
|
|
-+ if (handler != NULL)
|
|
|
-+ status = handler(status);
|
|
|
-+
|
|
|
-+ pr_info("%s: event: %d status: %d\n", __func__, event, status);
|
|
|
-+
|
|
|
-+ /* Report current key to user-space */
|
|
|
-+ ke = get_event_key_entry(event, status);
|
|
|
-+ if (ke) {
|
|
|
-+ if (ke->keycode == SW_LID)
|
|
|
-+ report_lid_switch(status);
|
|
|
-+ else
|
|
|
-+ sparse_keymap_report_entry(yeeloong_hotkey_dev, ke, 1,
|
|
|
-+ true);
|
|
|
-+ }
|
|
|
-+}
|
|
|
-+
|
|
|
-+/*
|
|
|
-+ * SCI(system control interrupt) main interrupt routine
|
|
|
-+ *
|
|
|
-+ * We will do the query and get event number together so the interrupt routine
|
|
|
-+ * should be longer than 120us now at least 3ms elpase for it.
|
|
|
-+ */
|
|
|
-+static irqreturn_t sci_irq_handler(int irq, void *dev_id)
|
|
|
-+{
|
|
|
-+ int ret, event;
|
|
|
-+
|
|
|
-+ if (SCI_IRQ_NUM != irq)
|
|
|
-+ return IRQ_NONE;
|
|
|
-+
|
|
|
-+ /* Query the event number */
|
|
|
-+ ret = ec_query_event_num();
|
|
|
-+ if (ret < 0)
|
|
|
-+ return IRQ_NONE;
|
|
|
-+
|
|
|
-+ event = ec_get_event_num();
|
|
|
-+ if (event < EVENT_START || event > EVENT_END)
|
|
|
-+ return IRQ_NONE;
|
|
|
-+
|
|
|
-+ /* Execute corresponding actions */
|
|
|
-+ do_event_action(event);
|
|
|
-+
|
|
|
-+ return IRQ_HANDLED;
|
|
|
-+}
|
|
|
-+
|
|
|
-+/*
|
|
|
-+ * Config and init some msr and gpio register properly.
|
|
|
-+ */
|
|
|
-+static int sci_irq_init(void)
|
|
|
-+{
|
|
|
-+ u32 hi, lo;
|
|
|
-+ u32 gpio_base;
|
|
|
-+ unsigned long flags;
|
|
|
-+ int ret;
|
|
|
-+
|
|
|
-+ /* Get gpio base */
|
|
|
-+ _rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_GPIO), &hi, &lo);
|
|
|
-+ gpio_base = lo & 0xff00;
|
|
|
-+
|
|
|
-+ /* Filter the former kb3310 interrupt for security */
|
|
|
-+ ret = ec_query_event_num();
|
|
|
-+ if (ret)
|
|
|
-+ return ret;
|
|
|
-+
|
|
|
-+ /* For filtering next number interrupt */
|
|
|
-+ udelay(10000);
|
|
|
-+
|
|
|
-+ /* Set gpio native registers and msrs for GPIO27 SCI EVENT PIN
|
|
|
-+ * gpio :
|
|
|
-+ * input, pull-up, no-invert, event-count and value 0,
|
|
|
-+ * no-filter, no edge mode
|
|
|
-+ * gpio27 map to Virtual gpio0
|
|
|
-+ * msr :
|
|
|
-+ * no primary and lpc
|
|
|
-+ * Unrestricted Z input to IG10 from Virtual gpio 0.
|
|
|
-+ */
|
|
|
-+ local_irq_save(flags);
|
|
|
-+ _rdmsr(0x80000024, &hi, &lo);
|
|
|
-+ lo &= ~(1 << 10);
|
|
|
-+ _wrmsr(0x80000024, hi, lo);
|
|
|
-+ _rdmsr(0x80000025, &hi, &lo);
|
|
|
-+ lo &= ~(1 << 10);
|
|
|
-+ _wrmsr(0x80000025, hi, lo);
|
|
|
-+ _rdmsr(0x80000023, &hi, &lo);
|
|
|
-+ lo |= (0x0a << 0);
|
|
|
-+ _wrmsr(0x80000023, hi, lo);
|
|
|
-+ local_irq_restore(flags);
|
|
|
-+
|
|
|
-+ /* Set gpio27 as sci interrupt
|
|
|
-+ *
|
|
|
-+ * input, pull-up, no-fliter, no-negedge, invert
|
|
|
-+ * the sci event is just about 120us
|
|
|
-+ */
|
|
|
-+ asm(".set noreorder\n");
|
|
|
-+ /* input enable */
|
|
|
-+ outl(0x00000800, (gpio_base | 0xA0));
|
|
|
-+ /* revert the input */
|
|
|
-+ outl(0x00000800, (gpio_base | 0xA4));
|
|
|
-+ /* event-int enable */
|
|
|
-+ outl(0x00000800, (gpio_base | 0xB8));
|
|
|
-+ asm(".set reorder\n");
|
|
|
-+
|
|
|
-+ return 0;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static struct irqaction sci_irqaction = {
|
|
|
-+ .handler = sci_irq_handler,
|
|
|
-+ .name = "sci",
|
|
|
-+ .flags = IRQF_SHARED,
|
|
|
-+};
|
|
|
-+
|
|
|
-+static int yeeloong_hotkey_init(void)
|
|
|
-+{
|
|
|
-+ int ret;
|
|
|
-+
|
|
|
-+ ret = sci_irq_init();
|
|
|
-+ if (ret)
|
|
|
-+ return -EFAULT;
|
|
|
-+
|
|
|
-+ ret = setup_irq(SCI_IRQ_NUM, &sci_irqaction);
|
|
|
-+ if (ret)
|
|
|
-+ return -EFAULT;
|
|
|
-+
|
|
|
-+ yeeloong_hotkey_dev = input_allocate_device();
|
|
|
-+
|
|
|
-+ if (!yeeloong_hotkey_dev) {
|
|
|
-+ remove_irq(SCI_IRQ_NUM, &sci_irqaction);
|
|
|
-+ return -ENOMEM;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ yeeloong_hotkey_dev->name = "HotKeys";
|
|
|
-+ yeeloong_hotkey_dev->phys = "button/input0";
|
|
|
-+ yeeloong_hotkey_dev->id.bustype = BUS_HOST;
|
|
|
-+ yeeloong_hotkey_dev->dev.parent = NULL;
|
|
|
-+
|
|
|
-+ ret = sparse_keymap_setup(yeeloong_hotkey_dev, yeeloong_keymap, NULL);
|
|
|
-+ if (ret) {
|
|
|
-+ pr_err("Fail to setup input device keymap\n");
|
|
|
-+ input_free_device(yeeloong_hotkey_dev);
|
|
|
-+ return ret;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ ret = input_register_device(yeeloong_hotkey_dev);
|
|
|
-+ if (ret) {
|
|
|
-+ sparse_keymap_free(yeeloong_hotkey_dev);
|
|
|
-+ input_free_device(yeeloong_hotkey_dev);
|
|
|
-+ return ret;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ /* Update the current status of LID */
|
|
|
-+ report_lid_switch(BIT_LID_DETECT_ON);
|
|
|
-+
|
|
|
-+#ifdef CONFIG_LOONGSON_SUSPEND
|
|
|
-+ /* Install the real yeeloong_report_lid_status for pm.c */
|
|
|
-+ yeeloong_report_lid_status = report_lid_switch;
|
|
|
-+#endif
|
|
|
-+
|
|
|
-+ return 0;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static void yeeloong_hotkey_exit(void)
|
|
|
-+{
|
|
|
-+ /* Free irq */
|
|
|
-+ remove_irq(SCI_IRQ_NUM, &sci_irqaction);
|
|
|
-+
|
|
|
-+#ifdef CONFIG_LOONGSON_SUSPEND
|
|
|
-+ /* Uninstall yeeloong_report_lid_status for pm.c */
|
|
|
-+ if (yeeloong_report_lid_status == report_lid_switch)
|
|
|
-+ yeeloong_report_lid_status = NULL;
|
|
|
-+#endif
|
|
|
-+
|
|
|
-+ if (yeeloong_hotkey_dev) {
|
|
|
-+ sparse_keymap_free(yeeloong_hotkey_dev);
|
|
|
-+ input_unregister_device(yeeloong_hotkey_dev);
|
|
|
-+ yeeloong_hotkey_dev = NULL;
|
|
|
-+ }
|
|
|
-+}
|
|
|
-+
|
|
|
-+#ifdef CONFIG_PM
|
|
|
-+static void usb_ports_set(int status)
|
|
|
-+{
|
|
|
-+ status = !!status;
|
|
|
-+
|
|
|
-+ ec_write(REG_USB0_FLAG, status);
|
|
|
-+ ec_write(REG_USB1_FLAG, status);
|
|
|
-+ ec_write(REG_USB2_FLAG, status);
|
|
|
-+}
|
|
|
-+
|
|
|
-+static int yeeloong_suspend(struct device *dev)
|
|
|
-+
|
|
|
-+{
|
|
|
-+ if (ec_version_before("EC_VER=PQ1D27"))
|
|
|
-+ yeeloong_lcd_vo_set(BIT_DISPLAY_LCD_OFF);
|
|
|
-+ yeeloong_crt_vo_set(BIT_CRT_DETECT_UNPLUG);
|
|
|
-+ usb_ports_set(BIT_USB_FLAG_OFF);
|
|
|
-+
|
|
|
-+ return 0;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static int yeeloong_resume(struct device *dev)
|
|
|
-+{
|
|
|
-+ if (ec_version_before("EC_VER=PQ1D27"))
|
|
|
-+ yeeloong_lcd_vo_set(BIT_DISPLAY_LCD_ON);
|
|
|
-+ yeeloong_crt_vo_set(BIT_CRT_DETECT_PLUG);
|
|
|
-+ usb_ports_set(BIT_USB_FLAG_ON);
|
|
|
-+
|
|
|
-+ return 0;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static const SIMPLE_DEV_PM_OPS(yeeloong_pm_ops, yeeloong_suspend,
|
|
|
-+ yeeloong_resume);
|
|
|
-+#endif
|
|
|
-+
|
|
|
-+static struct platform_device_id platform_device_ids[] = {
|
|
|
-+ {
|
|
|
-+ .name = "yeeloong_laptop",
|
|
|
-+ },
|
|
|
-+ {}
|
|
|
-+};
|
|
|
-+
|
|
|
-+MODULE_DEVICE_TABLE(platform, platform_device_ids);
|
|
|
-+
|
|
|
-+static struct platform_driver platform_driver = {
|
|
|
-+ .driver = {
|
|
|
-+ .name = "yeeloong_laptop",
|
|
|
-+ .owner = THIS_MODULE,
|
|
|
-+#ifdef CONFIG_PM
|
|
|
-+ .pm = &yeeloong_pm_ops,
|
|
|
-+#endif
|
|
|
-+ },
|
|
|
-+ .id_table = platform_device_ids,
|
|
|
-+};
|
|
|
-+
|
|
|
-+static int __init yeeloong_init(void)
|
|
|
-+{
|
|
|
-+ int ret;
|
|
|
-+
|
|
|
-+ pr_info("Load YeeLoong Laptop Platform Specific Driver.\n");
|
|
|
-+
|
|
|
-+ /* Register platform stuff */
|
|
|
-+ ret = platform_driver_register(&platform_driver);
|
|
|
-+ if (ret) {
|
|
|
-+ pr_err("Fail to register yeeloong platform driver.\n");
|
|
|
-+ return ret;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ ret = yeeloong_backlight_init();
|
|
|
-+ if (ret) {
|
|
|
-+ pr_err("Fail to register yeeloong backlight driver.\n");
|
|
|
-+ yeeloong_backlight_exit();
|
|
|
-+ return ret;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ ret = yeeloong_bat_init();
|
|
|
-+ if (ret) {
|
|
|
-+ pr_err("Fail to register yeeloong battery driver.\n");
|
|
|
-+ yeeloong_bat_exit();
|
|
|
-+ return ret;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ ret = yeeloong_hwmon_init();
|
|
|
-+ if (ret) {
|
|
|
-+ pr_err("Fail to register yeeloong hwmon driver.\n");
|
|
|
-+ yeeloong_hwmon_exit();
|
|
|
-+ return ret;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ ret = yeeloong_vo_init();
|
|
|
-+ if (ret) {
|
|
|
-+ pr_err("Fail to register yeeloong video output driver.\n");
|
|
|
-+ yeeloong_vo_exit();
|
|
|
-+ return ret;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ ret = yeeloong_hotkey_init();
|
|
|
-+ if (ret) {
|
|
|
-+ pr_err("Fail to register yeeloong hotkey driver.\n");
|
|
|
-+ yeeloong_hotkey_exit();
|
|
|
-+ return ret;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ return 0;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static void __exit yeeloong_exit(void)
|
|
|
-+{
|
|
|
-+ yeeloong_hotkey_exit();
|
|
|
-+ yeeloong_vo_exit();
|
|
|
-+ yeeloong_hwmon_exit();
|
|
|
-+ yeeloong_bat_exit();
|
|
|
-+ yeeloong_backlight_exit();
|
|
|
-+ platform_driver_unregister(&platform_driver);
|
|
|
-+
|
|
|
-+ pr_info("Unload YeeLoong Platform Specific Driver.\n");
|
|
|
-+}
|
|
|
-+
|
|
|
-+module_init(yeeloong_init);
|
|
|
-+module_exit(yeeloong_exit);
|
|
|
-+
|
|
|
-+MODULE_AUTHOR("Wu Zhangjin <wuzhangjin@gmail.com>; Liu Junliang <liujl@lemote.com>");
|
|
|
-+MODULE_DESCRIPTION("YeeLoong laptop driver");
|
|
|
-+MODULE_LICENSE("GPL");
|
|
|
-diff -Nur linux-2.6.36.orig/drivers/staging/sm7xx/smtcfb.c linux-2.6.36/drivers/staging/sm7xx/smtcfb.c
|
|
|
|
|
|
-+++ linux-2.6.36/drivers/staging/sm7xx/smtcfb.c 2010-11-18 11:47:59.000000000 +0100
|
|
|
-@@ -12,6 +12,8 @@
|
|
|
- * License. See the file COPYING in the main directory of this archive for
|
|
|
- * more details.
|
|
|
- *
|
|
|
-+ * - Remove the buggy 2D support for Lynx, 2010/01/06, Wu Zhangjin
|
|
|
-+ *
|
|
|
- * Version 0.10.26192.21.01
|
|
|
- * - Add PowerPC/Big endian support
|
|
|
- * - Add 2D support for Lynx
|
|
|
-@@ -107,6 +109,7 @@
|
|
|
- {"0x307", 1280, 1024, 8},
|
|
|
-
|
|
|
- {"0x311", 640, 480, 16},
|
|
|
-+ {"0x313", 800, 480, 16},
|
|
|
- {"0x314", 800, 600, 16},
|
|
|
- {"0x317", 1024, 768, 16},
|
|
|
- {"0x31A", 1280, 1024, 16},
|
|
|
-diff -Nur linux-2.6.36.orig/drivers/usb/host/ohci-hcd.c linux-2.6.36/drivers/usb/host/ohci-hcd.c
|
|
|
|
|
|
-+++ linux-2.6.36/drivers/usb/host/ohci-hcd.c 2010-11-18 11:47:59.000000000 +0100
|
|
|
-@@ -832,9 +832,13 @@
|
|
|
- }
|
|
|
-
|
|
|
- if (ints & OHCI_INTR_WDH) {
|
|
|
-- spin_lock (&ohci->lock);
|
|
|
-- dl_done_list (ohci);
|
|
|
-- spin_unlock (&ohci->lock);
|
|
|
-+ if (ohci->hcca->done_head == 0) {
|
|
|
-+ ints &= ~OHCI_INTR_WDH;
|
|
|
-+ } else {
|
|
|
-+ spin_lock (&ohci->lock);
|
|
|
-+ dl_done_list (ohci);
|
|
|
-+ spin_unlock (&ohci->lock);
|
|
|
-+ }
|
|
|
- }
|
|
|
-
|
|
|
- if (quirk_zfmicro(ohci) && (ints & OHCI_INTR_SF)) {
|
|
|
-diff -Nur linux-2.6.36.orig/net/rfkill/core.c linux-2.6.36/net/rfkill/core.c
|
|
|
|
|
|
-+++ linux-2.6.36/net/rfkill/core.c 2010-11-18 11:48:02.000000000 +0100
|
|
|
-@@ -112,7 +112,7 @@
|
|
|
- static DEFINE_MUTEX(rfkill_global_mutex);
|
|
|
- static LIST_HEAD(rfkill_fds); /* list of open fds of /dev/rfkill */
|
|
|
-
|
|
|
--static unsigned int rfkill_default_state = 1;
|
|
|
-+static unsigned int rfkill_default_state; /* default: 0 = radio off */
|
|
|
- module_param_named(default_state, rfkill_default_state, uint, 0444);
|
|
|
- MODULE_PARM_DESC(default_state,
|
|
|
- "Default initial state for all radio types, 0 = radio off");
|