All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/4] MIPS: Lonngson64: Copy kernel command line from arcs_cmdline Since lemte-2f/marchtype.c need to get cmdline from loongson.h this patch simply copy kernel command line from arcs_cmdline to fix that issue
@ 2017-11-12  6:36 jiaxun.yang
  2017-11-12  6:36 ` [PATCH 2/4] MIPS: Loongson64: lemote-2f move ec_kb3310b.h to include dir and clean up To operate EC from platform driver, this head file need able to be include from anywhere. This patch just move ec_kb3310b.h to include dir and clean up ec_kb3310b.h jiaxun.yang
                   ` (4 more replies)
  0 siblings, 5 replies; 14+ messages in thread
From: jiaxun.yang @ 2017-11-12  6:36 UTC (permalink / raw)
  To: ralf; +Cc: linux-mips, linux-kernel, Jiaxun Yang

From: Jiaxun Yang <jiaxun.yang@flygoat.com>

Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 arch/mips/include/asm/mach-loongson64/loongson.h | 6 ++++++
 arch/mips/loongson64/common/cmdline.c            | 7 +++++++
 2 files changed, 13 insertions(+)

diff --git a/arch/mips/include/asm/mach-loongson64/loongson.h b/arch/mips/include/asm/mach-loongson64/loongson.h
index c68c0cc879c6..1edf3a484e6a 100644
--- a/arch/mips/include/asm/mach-loongson64/loongson.h
+++ b/arch/mips/include/asm/mach-loongson64/loongson.h
@@ -45,6 +45,12 @@ static inline void prom_init_uart_base(void)
 #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 --git a/arch/mips/loongson64/common/cmdline.c b/arch/mips/loongson64/common/cmdline.c
index 01fbed137028..49e172184e15 100644
--- a/arch/mips/loongson64/common/cmdline.c
+++ b/arch/mips/loongson64/common/cmdline.c
@@ -21,6 +21,11 @@
 
 #include <loongson.h>
 
+/* the kernel command line copied from arcs_cmdline */
+#include <linux/export.h>
+char loongson_cmdline[COMMAND_LINE_SIZE];
+EXPORT_SYMBOL(loongson_cmdline);
+
 void __init prom_init_cmdline(void)
 {
 	int prom_argc;
@@ -45,4 +50,6 @@ void __init prom_init_cmdline(void)
 	}
 
 	prom_init_machtype();
+	/* copy arcs_cmdline into loongson_cmdline */
+	strncpy(loongson_cmdline, arcs_cmdline, COMMAND_LINE_SIZE);
 }
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 2/4] MIPS: Loongson64: lemote-2f move ec_kb3310b.h to include dir and clean up To operate EC from platform driver, this head file need able to be include from anywhere. This patch just move ec_kb3310b.h to include dir and clean up ec_kb3310b.h.
  2017-11-12  6:36 [PATCH 1/4] MIPS: Lonngson64: Copy kernel command line from arcs_cmdline Since lemte-2f/marchtype.c need to get cmdline from loongson.h this patch simply copy kernel command line from arcs_cmdline to fix that issue jiaxun.yang
@ 2017-11-12  6:36 ` jiaxun.yang
  2017-11-13 14:27   ` Ralf Baechle
  2017-11-12  6:36 ` [PATCH 3/4] MIPS: Loongson64: Yeeloong add platform driver Yeeloong is a laptop with a MIPS Loongson 2F processor, AMD CS5536 chipset, and KB3310B controller jiaxun.yang
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 14+ messages in thread
From: jiaxun.yang @ 2017-11-12  6:36 UTC (permalink / raw)
  To: ralf; +Cc: linux-mips, linux-kernel, Jiaxun Yang

From: Jiaxun Yang <jiaxun.yang@flygoat.com>

Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 arch/mips/include/asm/mach-loongson64/ec_kb3310b.h | 170 +++++++++++++++++++
 arch/mips/loongson64/lemote-2f/ec_kb3310b.c        |   2 +-
 arch/mips/loongson64/lemote-2f/ec_kb3310b.h        | 188 ---------------------
 arch/mips/loongson64/lemote-2f/pm.c                |   4 +-
 arch/mips/loongson64/lemote-2f/reset.c             |   4 +-
 5 files changed, 175 insertions(+), 193 deletions(-)
 create mode 100644 arch/mips/include/asm/mach-loongson64/ec_kb3310b.h
 delete mode 100644 arch/mips/loongson64/lemote-2f/ec_kb3310b.h

diff --git a/arch/mips/include/asm/mach-loongson64/ec_kb3310b.h b/arch/mips/include/asm/mach-loongson64/ec_kb3310b.h
new file mode 100644
index 000000000000..2e8690532ea5
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson64/ec_kb3310b.h
@@ -0,0 +1,170 @@
+/*
+ * 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 ON	1
+#define OFF	0
+
+#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	REG_FAN_STATUS		0xF4DA
+#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	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
+/* LID */
+#define	REG_LID_DETECT		0xF4BD
+/* CRT */
+#define	REG_CRT_DETECT		0xF4AD
+/* LCD backlight brightness adjust: 9 levels */
+#define	REG_DISPLAY_BRIGHTNESS	0xF4F5
+/* LCD backlight control: off/restore */
+#define	REG_BACKLIGHT_CTRL	0xF7BD
+/* Reset the machine auto-clear: rd/wr */
+#define	REG_RESET		0xF4EC
+/* 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	REG_CAMERA_CONTROL	0xF7B7
+/* Wlan Status */
+#define	REG_WLAN		0xF4FA
+#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 --git a/arch/mips/loongson64/lemote-2f/ec_kb3310b.c b/arch/mips/loongson64/lemote-2f/ec_kb3310b.c
index 321822997e76..6e416d55b42a 100644
--- a/arch/mips/loongson64/lemote-2f/ec_kb3310b.c
+++ b/arch/mips/loongson64/lemote-2f/ec_kb3310b.c
@@ -15,7 +15,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);
diff --git a/arch/mips/loongson64/lemote-2f/ec_kb3310b.h b/arch/mips/loongson64/lemote-2f/ec_kb3310b.h
deleted file mode 100644
index 5a3f1860d4d2..000000000000
--- a/arch/mips/loongson64/lemote-2f/ec_kb3310b.h
+++ /dev/null
@@ -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 --git a/arch/mips/loongson64/lemote-2f/pm.c b/arch/mips/loongson64/lemote-2f/pm.c
index 6859e934862d..0768739155f6 100644
--- a/arch/mips/loongson64/lemote-2f/pm.c
+++ b/arch/mips/loongson64/lemote-2f/pm.c
@@ -88,7 +88,7 @@ EXPORT_SYMBOL(yeeloong_report_lid_status);
 static void yeeloong_lid_update_task(struct work_struct *work)
 {
 	if (yeeloong_report_lid_status)
-		yeeloong_report_lid_status(BIT_LID_DETECT_ON);
+		yeeloong_report_lid_status(ON);
 }
 
 int wakeup_loongson(void)
@@ -118,7 +118,7 @@ int wakeup_loongson(void)
 			/* check the LID status */
 			lid_status = ec_read(REG_LID_DETECT);
 			/* wakeup cpu when people open the LID */
-			if (lid_status == BIT_LID_DETECT_ON) {
+			if (lid_status == ON) {
 				/* If we call it directly here, the WARNING
 				 * will be sent out by getnstimeofday
 				 * via "WARN_ON(timekeeping_suspended);"
diff --git a/arch/mips/loongson64/lemote-2f/reset.c b/arch/mips/loongson64/lemote-2f/reset.c
index a26ca7fcd7e0..2b72b197c51d 100644
--- a/arch/mips/loongson64/lemote-2f/reset.c
+++ b/arch/mips/loongson64/lemote-2f/reset.c
@@ -20,7 +20,7 @@
 #include <loongson.h>
 
 #include <cs5536/cs5536.h>
-#include "ec_kb3310b.h"
+#include <ec_kb3310b.h>
 
 static void reset_cpu(void)
 {
@@ -81,7 +81,7 @@ static void ml2f_reboot(void)
 	reset_cpu();
 
 	/* sending an reset signal to EC(embedded controller) */
-	ec_write(REG_RESET, BIT_RESET_ON);
+	ec_write(REG_RESET, ON);
 }
 
 #define yl2f89_reboot ml2f_reboot
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 3/4] MIPS: Loongson64: Yeeloong add platform driver Yeeloong is a laptop with a MIPS Loongson 2F processor, AMD CS5536 chipset, and KB3310B controller.
  2017-11-12  6:36 [PATCH 1/4] MIPS: Lonngson64: Copy kernel command line from arcs_cmdline Since lemte-2f/marchtype.c need to get cmdline from loongson.h this patch simply copy kernel command line from arcs_cmdline to fix that issue jiaxun.yang
  2017-11-12  6:36 ` [PATCH 2/4] MIPS: Loongson64: lemote-2f move ec_kb3310b.h to include dir and clean up To operate EC from platform driver, this head file need able to be include from anywhere. This patch just move ec_kb3310b.h to include dir and clean up ec_kb3310b.h jiaxun.yang
@ 2017-11-12  6:36 ` jiaxun.yang
  2017-11-14 13:21   ` Ralf Baechle
  2017-11-14 13:35   ` Ralf Baechle
  2017-11-12  6:36 ` [PATCH 4/4] MIPS: Loongson64: Load platform device during boot This patch just add pdev during boot to load the platform driver jiaxun.yang
                   ` (2 subsequent siblings)
  4 siblings, 2 replies; 14+ messages in thread
From: jiaxun.yang @ 2017-11-12  6:36 UTC (permalink / raw)
  To: ralf; +Cc: linux-mips, linux-kernel, Jiaxun Yang

From: Jiaxun Yang <jiaxun.yang@flygoat.com>

This yeeloong_laptop module enables access to sensors, battery,
video camera switch, external video connector event, and some
additional buttons.

This driver was orginally from linux-loongson-community. I Just do
some clean up and port to mainline kernel tree.

Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 drivers/platform/mips/Kconfig           |   18 +
 drivers/platform/mips/Makefile          |    3 +
 drivers/platform/mips/yeeloong_laptop.c | 1143 +++++++++++++++++++++++++++++++
 3 files changed, 1164 insertions(+)
 create mode 100644 drivers/platform/mips/yeeloong_laptop.c

diff --git a/drivers/platform/mips/Kconfig b/drivers/platform/mips/Kconfig
index b3ae30a4c67b..0f054efc26e3 100644
--- a/drivers/platform/mips/Kconfig
+++ b/drivers/platform/mips/Kconfig
@@ -23,4 +23,22 @@ config CPU_HWMON
 	help
 	  Loongson-3A/3B CPU Hwmon (temperature sensor) driver.
 
+config LEMOTE_YEELOONG2F
+	tristate "Lemote YeeLoong Laptop"
+	depends on LEMOTE_MACH2F
+	select BACKLIGHT_LCD_SUPPORT
+	select LCD_CLASS_DEVICE
+	select BACKLIGHT_CLASS_DEVICE
+	select POWER_SUPPLY
+	select HWMON
+	select INPUT_SPARSEKMAP
+	select INPUT_EVDEV
+	depends on INPUT
+	default m
+	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.
+
 endif # MIPS_PLATFORM_DEVICES
diff --git a/drivers/platform/mips/Makefile b/drivers/platform/mips/Makefile
index 8dfd03924c37..b3172b081a2f 100644
--- a/drivers/platform/mips/Makefile
+++ b/drivers/platform/mips/Makefile
@@ -1 +1,4 @@
 obj-$(CONFIG_CPU_HWMON) += cpu_hwmon.o
+
+obj-$(CONFIG_LEMOTE_YEELOONG2F)	+= yeeloong_laptop.o
+CFLAGS_yeeloong_laptop.o = -I$(srctree)/arch/mips/loongson/lemote-2f
diff --git a/drivers/platform/mips/yeeloong_laptop.c b/drivers/platform/mips/yeeloong_laptop.c
new file mode 100644
index 000000000000..280f2044858b
--- /dev/null
+++ b/drivers/platform/mips/yeeloong_laptop.c
@@ -0,0 +1,1143 @@
+/*
+ * Driver for YeeLoong laptop extras
+ *
+ *  Copyright (C) 2017 Jiaxun Yang.
+ *  Author: Jiaxun Yang <jiaxun.yang@flygoat.com>
+ *
+ *  Copyright (C) 2009 Lemote Inc.
+ *  Author: Wu Zhangjin <wuzhangjin@gmail.com>, Liu Junliang <liujl@lemote.com>
+ *
+ *  Fixes: Petr Pisar <petr.pisar@atlas.cz>, 2012, 2013, 2014, 2015.
+ *
+ *  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/kernel.h>   /* for clamp_val() */
+#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 <linux/module.h>   /* For MODULE_DEVICE_TABLE() */
+
+#include <asm/bootinfo.h>
+
+#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 = clamp_val(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);
+}
+
+const 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.type = BACKLIGHT_RAW;
+	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 RET (val->intval)
+
+static inline bool is_ac_in(void)
+{
+	return !!(ec_read(REG_BAT_POWER) & BIT_BAT_POWER_ACIN);
+}
+
+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:
+		RET = is_ac_in();
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static enum power_supply_property yeeloong_ac_props[] = {
+	POWER_SUPPLY_PROP_ONLINE,
+};
+
+static const struct power_supply_desc yeeloong_ac_desc = {
+	.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     95
+
+#define get_bat_info(type) \
+	((ec_read(REG_BAT_##type##_HIGH) << 8) | \
+	 (ec_read(REG_BAT_##type##_LOW)))
+
+static inline bool is_bat_in(void)
+{
+	return !!(ec_read(REG_BAT_STATUS) & BIT_BAT_STATUS_IN);
+}
+
+static inline int get_bat_status(void)
+{
+	return ec_read(REG_BAT_STATUS);
+}
+
+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 inline char *get_manufacturer(void)
+{
+	return (ec_read(REG_BAT_VENDOR) == FLAG_BAT_VENDOR_SANYO) ? "SANYO" :
+		"SIMPLO";
+}
+
+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:
+		/* mV -> µV */
+		RET = get_bat_info(DESIGN_VOL) * 1000;
+		break;
+	case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
+		/* mAh->µAh */
+		RET = get_bat_info(DESIGN_CAP) * 1000;
+		break;
+	case POWER_SUPPLY_PROP_CHARGE_FULL:
+		/* µAh */
+		RET = get_bat_info(FULLCHG_CAP) * 1000;
+		break;
+	case POWER_SUPPLY_PROP_MANUFACTURER:
+		val->strval = get_manufacturer();
+		break;
+	/* Dynamic information */
+	case POWER_SUPPLY_PROP_PRESENT:
+		RET = is_bat_in();
+		break;
+	case POWER_SUPPLY_PROP_CURRENT_NOW:
+		/* mA -> µA */
+		RET = is_bat_in() ? get_battery_current() * 1000 : 0;
+		break;
+	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+		/* mV -> µV */
+		RET = is_bat_in() ? get_battery_voltage() * 1000 : 0;
+		break;
+	case POWER_SUPPLY_PROP_TEMP:
+		/* Celcius */
+		RET = is_bat_in() ? get_battery_temp() : 0;
+		break;
+	case POWER_SUPPLY_PROP_CAPACITY:
+		RET = is_bat_in() ? get_bat_info(RELATIVE_CAP) : 0;
+		break;
+	case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
+		{
+		int status;
+
+		if (!is_bat_in()) {
+			RET = POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN;
+			break;
+		}
+
+		status = get_bat_status();
+		RET = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
+
+		if (unlikely(status & BIT_BAT_STATUS_DESTROY)) {
+			RET = POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN;
+			break;
+		}
+
+		if (status & BIT_BAT_STATUS_LOW)
+			RET = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
+		else if (status & BIT_BAT_STATUS_FULL)
+			RET = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
+		else {
+			int curr_cap;
+
+			curr_cap = get_bat_info(RELATIVE_CAP);
+
+			if (curr_cap >= BAT_CAP_HIGH)
+				RET = POWER_SUPPLY_CAPACITY_LEVEL_HIGH;
+			else if (curr_cap <= BAT_CAP_CRITICAL)
+				RET = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
+		}
+
+		} break;
+	case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:
+		/* seconds */
+		RET = is_bat_in() ?
+			(get_bat_info(RELATIVE_CAP) - 3) * 54 + 142
+			: 0;
+		break;
+	case POWER_SUPPLY_PROP_STATUS:
+		{
+			int charge = ec_read(REG_BAT_CHARGE);
+
+			if (charge & FLAG_BAT_CHARGE_DISCHARGE)
+				RET = POWER_SUPPLY_STATUS_DISCHARGING;
+			else if (charge & FLAG_BAT_CHARGE_CHARGE)
+				RET = POWER_SUPPLY_STATUS_CHARGING;
+			else
+				RET = POWER_SUPPLY_STATUS_NOT_CHARGING;
+		}
+		break;
+	case POWER_SUPPLY_PROP_HEALTH:
+		{
+			int status;
+
+			if (!is_bat_in()) {
+				RET = POWER_SUPPLY_HEALTH_UNKNOWN;
+				break;
+			}
+
+			status = get_bat_status();
+
+			RET = POWER_SUPPLY_HEALTH_GOOD;
+			if (status & (BIT_BAT_STATUS_DESTROY |
+						BIT_BAT_STATUS_LOW))
+				RET = POWER_SUPPLY_HEALTH_DEAD;
+			if (ec_read(REG_BAT_CHARGE_STATUS) &
+					BIT_BAT_CHARGE_STATUS_OVERTEMP)
+				RET = POWER_SUPPLY_HEALTH_OVERHEAT;
+		}
+		break;
+	case POWER_SUPPLY_PROP_CHARGE_NOW:	/* 1/100(%)*1000 µAh */
+		RET = get_bat_info(RELATIVE_CAP) *
+			get_bat_info(FULLCHG_CAP) * 10;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+#undef RET
+
+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 const struct power_supply_desc yeeloong_bat_desc = {
+	.name = "yeeloongbattery",
+	.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)
+{
+	yeeloong_ac = power_supply_register(NULL, &yeeloong_ac_desc, NULL);
+	if (IS_ERR(yeeloong_ac))
+		return PTR_ERR(yeeloong_ac);
+	yeeloong_bat = power_supply_register(NULL, &yeeloong_bat_desc, NULL);
+	if (IS_ERR(yeeloong_bat)) {
+		power_supply_unregister(yeeloong_ac);
+		return PTR_ERR(yeeloong_bat);
+	}
+	ac_bat_initialized = 1;
+
+	return 0;
+}
+
+static void yeeloong_bat_exit(void)
+{
+	if (ac_bat_initialized) {
+		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 = clamp_val(value, 0, 3);
+
+	/* We must ensure the fan is on */
+	if (value > 0)
+		ec_write(REG_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 = kstrtoul(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, 0444, get_fan_rpm, NULL);
+CREATE_SENSOR_ATTR(pwm1, 0444 | 0644, get_fan_pwm, set_fan_pwm);
+CREATE_SENSOR_ATTR(pwm1_enable, 0444 | 0644, get_fan_pwm_enable,
+		set_fan_pwm_enable);
+CREATE_SENSOR_ATTR(temp1_input, 0444, get_cpu_temp, NULL);
+CREATE_SENSOR_ATTR(temp1_max, 0444, get_cpu_temp_max, NULL);
+CREATE_SENSOR_ATTR(temp2_input, 0444, get_battery_temp, NULL);
+CREATE_SENSOR_ATTR(temp2_max_alarm, 0444, get_battery_temp_alarm, NULL);
+CREATE_SENSOR_ATTR(curr1_input, 0444, get_battery_current, NULL);
+CREATE_SENSOR_ATTR(in1_input, 0444, 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, 0444, 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 controller */
+
+
+#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);
+}
+
+
+
+/* hotkey subdriver */
+
+static struct input_dev *yeeloong_hotkey_dev;
+
+static const struct key_entry yeeloong_keymap[] = {
+	{KE_SW, EVENT_LID, {SW_LID} },
+	/* Fn + ESC */
+	{KE_KEY, EVENT_CAMERA, {KEY_CAMERA} },
+	/* Fn + F1 */
+	{KE_KEY, EVENT_SLEEP, {KEY_SLEEP} },
+	/* Fn + F2 */
+	{KE_KEY, EVENT_DISPLAYTOGGLE, {KEY_DISPLAYTOGGLE} },
+	/* Fn + F3 */
+	{KE_KEY, EVENT_SWITCHVIDEOMODE, {KEY_SWITCHVIDEOMODE} },
+	/* Fn + F4 */
+	{KE_KEY, EVENT_AUDIO_MUTE, {KEY_MUTE} },
+	/* Fn + F5 */
+	{KE_KEY, EVENT_WLAN, {KEY_WLAN} },
+	/* Fn + up */
+	{KE_KEY, EVENT_DISPLAY_BRIGHTNESS, {KEY_BRIGHTNESSUP} },
+	/* Fn + down */
+	{KE_KEY, EVENT_DISPLAY_BRIGHTNESS, {KEY_BRIGHTNESSDOWN} },
+	/* Fn + right */
+	{KE_KEY, EVENT_AUDIO_VOLUME, {KEY_VOLUMEUP} },
+	/* Fn + left */
+	{KE_KEY, EVENT_AUDIO_VOLUME, {KEY_VOLUMEDOWN} },
+	{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 == 0) || (status < old_brightness_status))
+			ke++;
+		old_brightness_status = status;
+		break;
+	case EVENT_AUDIO_VOLUME:
+		if ((status == 0) || (status < old_volume_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 void yeeloong_vo_set(int lcd_status, int crt_status)
+{
+	display_vo_set(LCD, lcd_status);
+	display_vo_set(CRT, crt_status);
+}
+
+static int crt_detect_handler(int status)
+{
+	if (status)
+		yeeloong_vo_set(ON, ON);
+	else
+		yeeloong_vo_set(ON, OFF);
+
+	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"))
+		display_vo_set(LCD, 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) == OFF)
+		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_vo_set(ON, ON);
+		break;
+	case 2:
+		yeeloong_vo_set(OFF, ON);
+		break;
+	case 3:
+		yeeloong_vo_set(OFF, OFF);
+		break;
+	case 4:
+		yeeloong_vo_set(ON, OFF);
+		break;
+	default:
+		/* Ensure LCD is on */
+		display_vo_set(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;
+	status = 0;
+
+	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_debug("%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 (irq != SCI_IRQ_NUM)
+		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 */
+	mdelay(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 int yeeloong_hotkey_init(void)
+{
+	int ret;
+
+	ret = sci_irq_init();
+	if (ret)
+		return -EFAULT;
+
+	ret = request_threaded_irq(SCI_IRQ_NUM, NULL, &sci_irq_handler,
+			IRQF_ONESHOT, "sci", NULL);
+	if (ret)
+		return -EFAULT;
+
+	yeeloong_hotkey_dev = input_allocate_device();
+
+	if (!yeeloong_hotkey_dev) {
+		free_irq(SCI_IRQ_NUM, NULL);
+		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) {
+		input_free_device(yeeloong_hotkey_dev);
+		return ret;
+	}
+
+	/* Update the current status of LID */
+	report_lid_switch(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 */
+	free_irq(SCI_IRQ_NUM, NULL);
+
+#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) {
+		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"))
+		display_vo_set(LCD, OFF);
+	display_vo_set(CRT, OFF);
+	usb_ports_set(OFF);
+
+	return 0;
+}
+
+static int yeeloong_resume(struct device *dev)
+{
+	int ret;
+
+	if (ec_version_before("EC_VER=PQ1D27"))
+		display_vo_set(LCD, ON);
+	display_vo_set(CRT, ON);
+	usb_ports_set(ON);
+
+	ret = sci_irq_init();
+	if (ret)
+		return -EFAULT;
+
+	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;
+
+	if (mips_machtype != MACH_LEMOTE_YL2F89) {
+		pr_err("Unsupported system.\n");
+		return -ENODEV;
+	}
+
+	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_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_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");
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 4/4] MIPS: Loongson64: Load platform device during boot This patch just add pdev during boot to load the platform driver
  2017-11-12  6:36 [PATCH 1/4] MIPS: Lonngson64: Copy kernel command line from arcs_cmdline Since lemte-2f/marchtype.c need to get cmdline from loongson.h this patch simply copy kernel command line from arcs_cmdline to fix that issue jiaxun.yang
  2017-11-12  6:36 ` [PATCH 2/4] MIPS: Loongson64: lemote-2f move ec_kb3310b.h to include dir and clean up To operate EC from platform driver, this head file need able to be include from anywhere. This patch just move ec_kb3310b.h to include dir and clean up ec_kb3310b.h jiaxun.yang
  2017-11-12  6:36 ` [PATCH 3/4] MIPS: Loongson64: Yeeloong add platform driver Yeeloong is a laptop with a MIPS Loongson 2F processor, AMD CS5536 chipset, and KB3310B controller jiaxun.yang
@ 2017-11-12  6:36 ` jiaxun.yang
  2017-11-14 13:29   ` Ralf Baechle
  2017-11-13 14:21 ` [PATCH 1/4] MIPS: Lonngson64: Copy kernel command line from arcs_cmdline Since lemte-2f/marchtype.c need to get cmdline from loongson.h this patch simply copy kernel command line from arcs_cmdline to fix that issue Ralf Baechle
  2017-11-15  3:11 ` [PATCH v3 1/4] MIPS: Lonngson64: Copy kernel command line from arcs_cmdline Jiaxun Yang
  4 siblings, 1 reply; 14+ messages in thread
From: jiaxun.yang @ 2017-11-12  6:36 UTC (permalink / raw)
  To: ralf; +Cc: linux-mips, linux-kernel, Jiaxun Yang

From: Jiaxun Yang <jiaxun.yang@flygoat.com>

Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 arch/mips/loongson64/lemote-2f/Makefile   |  2 +-
 arch/mips/loongson64/lemote-2f/platform.c | 45 +++++++++++++++++++++++++++++++
 2 files changed, 46 insertions(+), 1 deletion(-)
 create mode 100644 arch/mips/loongson64/lemote-2f/platform.c

diff --git a/arch/mips/loongson64/lemote-2f/Makefile b/arch/mips/loongson64/lemote-2f/Makefile
index 08b8abcbfef5..31c90737b98c 100644
--- a/arch/mips/loongson64/lemote-2f/Makefile
+++ b/arch/mips/loongson64/lemote-2f/Makefile
@@ -2,7 +2,7 @@
 # Makefile for lemote loongson2f family machines
 #
 
-obj-y += clock.o machtype.o irq.o reset.o ec_kb3310b.o
+obj-y += clock.o machtype.o irq.o reset.o ec_kb3310b.o platform.o
 
 #
 # Suspend Support
diff --git a/arch/mips/loongson64/lemote-2f/platform.c b/arch/mips/loongson64/lemote-2f/platform.c
new file mode 100644
index 000000000000..c36efcccb9a9
--- /dev/null
+++ b/arch/mips/loongson64/lemote-2f/platform.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2017 Jiaxun Yang.
+ * Author: Jiaxun Yang, jiaxun.yang@flygoat.com
+
+ * 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 int __init lemote2f_platform_init(void)
+{
+	struct platform_device *pdev = NULL;
+
+	switch (mips_machtype) {
+	case MACH_LEMOTE_YL2F89:
+		pdev = &yeeloong_pdev;
+		break;
+
+	default:
+		break;
+
+	}
+
+	if (pdev != NULL)
+		return platform_device_register(pdev);
+
+	return -ENODEV;
+}
+
+arch_initcall(lemote2f_platform_init);
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/4] MIPS: Lonngson64: Copy kernel command line from arcs_cmdline Since lemte-2f/marchtype.c need to get cmdline from loongson.h this patch simply copy kernel command line from arcs_cmdline to fix that issue
  2017-11-12  6:36 [PATCH 1/4] MIPS: Lonngson64: Copy kernel command line from arcs_cmdline Since lemte-2f/marchtype.c need to get cmdline from loongson.h this patch simply copy kernel command line from arcs_cmdline to fix that issue jiaxun.yang
                   ` (2 preceding siblings ...)
  2017-11-12  6:36 ` [PATCH 4/4] MIPS: Loongson64: Load platform device during boot This patch just add pdev during boot to load the platform driver jiaxun.yang
@ 2017-11-13 14:21 ` Ralf Baechle
  2017-11-15  3:11 ` [PATCH v3 1/4] MIPS: Lonngson64: Copy kernel command line from arcs_cmdline Jiaxun Yang
  4 siblings, 0 replies; 14+ messages in thread
From: Ralf Baechle @ 2017-11-13 14:21 UTC (permalink / raw)
  To: jiaxun.yang; +Cc: linux-mips, linux-kernel

On Sun, Nov 12, 2017 at 02:36:14PM +0800, jiaxun.yang@flygoat.com wrote:
> Date:   Sun, 12 Nov 2017 14:36:14 +0800
> From: jiaxun.yang@flygoat.com
> To: ralf@linux-mips.org
> Cc: linux-mips@linux-mips.org, linux-kernel@vger.kernel.org, Jiaxun Yang
>  <jiaxun.yang@flygoat.com>
> Subject: [PATCH 1/4] MIPS: Lonngson64: Copy kernel command line from
>  arcs_cmdline Since lemte-2f/marchtype.c need to get cmdline from
>  loongson.h this patch simply copy kernel command line from arcs_cmdline to
>  fix that issue

Please don't cram the entire commit message into the subject line.  The
standard for commit messages to keep lines only so long that when you
look at them in "git log" in a 80 column terminal they don't get line
wrapped or truncated.

And what is "lemte-2f/marchtype.c"?  Maybe you meant lemote-2f/machtype.c?

> From: Jiaxun Yang <jiaxun.yang@flygoat.com>
> 
> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> ---
>  arch/mips/include/asm/mach-loongson64/loongson.h | 6 ++++++
>  arch/mips/loongson64/common/cmdline.c            | 7 +++++++
>  2 files changed, 13 insertions(+)
> 
> diff --git a/arch/mips/include/asm/mach-loongson64/loongson.h b/arch/mips/include/asm/mach-loongson64/loongson.h
> index c68c0cc879c6..1edf3a484e6a 100644
> --- a/arch/mips/include/asm/mach-loongson64/loongson.h
> +++ b/arch/mips/include/asm/mach-loongson64/loongson.h
> @@ -45,6 +45,12 @@ static inline void prom_init_uart_base(void)
>  #endif
>  }
>  
> +/*
> + * Copy kernel command line from arcs_cmdline
> + */
> +#include <asm/setup.h>

Please group #include lines at the top of the file.

> +extern char loongson_cmdline[COMMAND_LINE_SIZE];
> +
>  /* irq operation functions */
>  extern void bonito_irqdispatch(void);
>  extern void __init bonito_irq_init(void);
> diff --git a/arch/mips/loongson64/common/cmdline.c b/arch/mips/loongson64/common/cmdline.c
> index 01fbed137028..49e172184e15 100644
> --- a/arch/mips/loongson64/common/cmdline.c
> +++ b/arch/mips/loongson64/common/cmdline.c
> @@ -21,6 +21,11 @@
>  
>  #include <loongson.h>
>  
> +/* the kernel command line copied from arcs_cmdline */
> +#include <linux/export.h>
> +char loongson_cmdline[COMMAND_LINE_SIZE];
> +EXPORT_SYMBOL(loongson_cmdline);
> +
>  void __init prom_init_cmdline(void)
>  {
>  	int prom_argc;
> @@ -45,4 +50,6 @@ void __init prom_init_cmdline(void)
>  	}
>  
>  	prom_init_machtype();
> +	/* copy arcs_cmdline into loongson_cmdline */
> +	strncpy(loongson_cmdline, arcs_cmdline, COMMAND_LINE_SIZE);
>  }

  Ralf

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 2/4] MIPS: Loongson64: lemote-2f move ec_kb3310b.h to include dir and clean up To operate EC from platform driver, this head file need able to be include from anywhere. This patch just move ec_kb3310b.h to include dir and clean up ec_kb3310b.h.
  2017-11-12  6:36 ` [PATCH 2/4] MIPS: Loongson64: lemote-2f move ec_kb3310b.h to include dir and clean up To operate EC from platform driver, this head file need able to be include from anywhere. This patch just move ec_kb3310b.h to include dir and clean up ec_kb3310b.h jiaxun.yang
@ 2017-11-13 14:27   ` Ralf Baechle
  0 siblings, 0 replies; 14+ messages in thread
From: Ralf Baechle @ 2017-11-13 14:27 UTC (permalink / raw)
  To: jiaxun.yang; +Cc: linux-mips, linux-kernel

On Sun, Nov 12, 2017 at 02:36:15PM +0800, jiaxun.yang@flygoat.com wrote:
> Date:   Sun, 12 Nov 2017 14:36:15 +0800
> From: jiaxun.yang@flygoat.com
> To: ralf@linux-mips.org
> Cc: linux-mips@linux-mips.org, linux-kernel@vger.kernel.org, Jiaxun Yang
>  <jiaxun.yang@flygoat.com>
> Subject: [PATCH 2/4] MIPS: Loongson64: lemote-2f move ec_kb3310b.h to
>  include dir and clean up To operate EC from platform driver, this head
>  file need able to be include from anywhere. This patch just move
>  ec_kb3310b.h to include dir and clean up ec_kb3310b.h.

Some comment as for the previous patch:

Please don't cram the entire commit message into the subject line.  The
standard for commit messages to keep lines only so long that when you
look at them in "git log" in a 80 column terminal they don't get line
wrapped or truncated.

> From: Jiaxun Yang <jiaxun.yang@flygoat.com>
> 
> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> ---
>  arch/mips/include/asm/mach-loongson64/ec_kb3310b.h | 170 +++++++++++++++++++
>  arch/mips/loongson64/lemote-2f/ec_kb3310b.c        |   2 +-
>  arch/mips/loongson64/lemote-2f/ec_kb3310b.h        | 188 ---------------------
>  arch/mips/loongson64/lemote-2f/pm.c                |   4 +-
>  arch/mips/loongson64/lemote-2f/reset.c             |   4 +-
>  5 files changed, 175 insertions(+), 193 deletions(-)
>  create mode 100644 arch/mips/include/asm/mach-loongson64/ec_kb3310b.h
>  delete mode 100644 arch/mips/loongson64/lemote-2f/ec_kb3310b.h

When preparing patches for submission please use the git diff option -M
which will make git-diff detect files being moved around and produce a much
smaller, easier to review diff file.

> diff --git a/arch/mips/include/asm/mach-loongson64/ec_kb3310b.h b/arch/mips/include/asm/mach-loongson64/ec_kb3310b.h
> new file mode 100644
> index 000000000000..2e8690532ea5
> --- /dev/null
> +++ b/arch/mips/include/asm/mach-loongson64/ec_kb3310b.h
> @@ -0,0 +1,170 @@
> +/*
> + * 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 ON	1
> +#define OFF	0
> +
> +#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	REG_FAN_STATUS		0xF4DA
> +#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	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
> +/* LID */
> +#define	REG_LID_DETECT		0xF4BD
> +/* CRT */
> +#define	REG_CRT_DETECT		0xF4AD
> +/* LCD backlight brightness adjust: 9 levels */
> +#define	REG_DISPLAY_BRIGHTNESS	0xF4F5
> +/* LCD backlight control: off/restore */
> +#define	REG_BACKLIGHT_CTRL	0xF7BD
> +/* Reset the machine auto-clear: rd/wr */
> +#define	REG_RESET		0xF4EC
> +/* 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	REG_CAMERA_CONTROL	0xF7B7
> +/* Wlan Status */
> +#define	REG_WLAN		0xF4FA
> +#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 --git a/arch/mips/loongson64/lemote-2f/ec_kb3310b.c b/arch/mips/loongson64/lemote-2f/ec_kb3310b.c
> index 321822997e76..6e416d55b42a 100644
> --- a/arch/mips/loongson64/lemote-2f/ec_kb3310b.c
> +++ b/arch/mips/loongson64/lemote-2f/ec_kb3310b.c
> @@ -15,7 +15,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);
> diff --git a/arch/mips/loongson64/lemote-2f/ec_kb3310b.h b/arch/mips/loongson64/lemote-2f/ec_kb3310b.h
> deleted file mode 100644
> index 5a3f1860d4d2..000000000000
> --- a/arch/mips/loongson64/lemote-2f/ec_kb3310b.h
> +++ /dev/null
> @@ -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 --git a/arch/mips/loongson64/lemote-2f/pm.c b/arch/mips/loongson64/lemote-2f/pm.c
> index 6859e934862d..0768739155f6 100644
> --- a/arch/mips/loongson64/lemote-2f/pm.c
> +++ b/arch/mips/loongson64/lemote-2f/pm.c
> @@ -88,7 +88,7 @@ EXPORT_SYMBOL(yeeloong_report_lid_status);
>  static void yeeloong_lid_update_task(struct work_struct *work)
>  {
>  	if (yeeloong_report_lid_status)
> -		yeeloong_report_lid_status(BIT_LID_DETECT_ON);
> +		yeeloong_report_lid_status(ON);
>  }
>  
>  int wakeup_loongson(void)
> @@ -118,7 +118,7 @@ int wakeup_loongson(void)
>  			/* check the LID status */
>  			lid_status = ec_read(REG_LID_DETECT);
>  			/* wakeup cpu when people open the LID */
> -			if (lid_status == BIT_LID_DETECT_ON) {
> +			if (lid_status == ON) {
>  				/* If we call it directly here, the WARNING
>  				 * will be sent out by getnstimeofday
>  				 * via "WARN_ON(timekeeping_suspended);"
> diff --git a/arch/mips/loongson64/lemote-2f/reset.c b/arch/mips/loongson64/lemote-2f/reset.c
> index a26ca7fcd7e0..2b72b197c51d 100644
> --- a/arch/mips/loongson64/lemote-2f/reset.c
> +++ b/arch/mips/loongson64/lemote-2f/reset.c
> @@ -20,7 +20,7 @@
>  #include <loongson.h>
>  
>  #include <cs5536/cs5536.h>
> -#include "ec_kb3310b.h"
> +#include <ec_kb3310b.h>
>  
>  static void reset_cpu(void)
>  {
> @@ -81,7 +81,7 @@ static void ml2f_reboot(void)
>  	reset_cpu();
>  
>  	/* sending an reset signal to EC(embedded controller) */
> -	ec_write(REG_RESET, BIT_RESET_ON);
> +	ec_write(REG_RESET, ON);
>  }
>  
>  #define yl2f89_reboot ml2f_reboot

  Ralf

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 3/4] MIPS: Loongson64: Yeeloong add platform driver Yeeloong is a laptop with a MIPS Loongson 2F processor, AMD CS5536 chipset, and KB3310B controller.
  2017-11-12  6:36 ` [PATCH 3/4] MIPS: Loongson64: Yeeloong add platform driver Yeeloong is a laptop with a MIPS Loongson 2F processor, AMD CS5536 chipset, and KB3310B controller jiaxun.yang
@ 2017-11-14 13:21   ` Ralf Baechle
  2017-11-14 13:35   ` Ralf Baechle
  1 sibling, 0 replies; 14+ messages in thread
From: Ralf Baechle @ 2017-11-14 13:21 UTC (permalink / raw)
  To: jiaxun.yang; +Cc: linux-mips, linux-kernel

On Sun, Nov 12, 2017 at 02:36:16PM +0800, jiaxun.yang@flygoat.com wrote:
> Date:   Sun, 12 Nov 2017 14:36:16 +0800
> From: jiaxun.yang@flygoat.com
> To: ralf@linux-mips.org
> Cc: linux-mips@linux-mips.org, linux-kernel@vger.kernel.org, Jiaxun Yang
>  <jiaxun.yang@flygoat.com>
> Subject: [PATCH 3/4] MIPS: Loongson64: Yeeloong add platform driver
>  Yeeloong is a laptop with a MIPS Loongson 2F processor, AMD CS5536
>  chipset, and KB3310B controller.
> Content-Type: text/plain; charset=UTF-8

Some comment as for the previous patch:

Please don't cram the entire commit message into the subject line.  The
standard for commit messages to keep lines only so long that when you
look at them in "git log" in a 80 column terminal they don't get line
wrapped or truncated.

> From: Jiaxun Yang <jiaxun.yang@flygoat.com>
> 
> This yeeloong_laptop module enables access to sensors, battery,
> video camera switch, external video connector event, and some
> additional buttons.
> 
> This driver was orginally from linux-loongson-community. I Just do
> some clean up and port to mainline kernel tree.
> 
> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> ---
>  drivers/platform/mips/Kconfig           |   18 +
>  drivers/platform/mips/Makefile          |    3 +
>  drivers/platform/mips/yeeloong_laptop.c | 1143 +++++++++++++++++++++++++++++++
>  3 files changed, 1164 insertions(+)
>  create mode 100644 drivers/platform/mips/yeeloong_laptop.c
> 
> diff --git a/drivers/platform/mips/Kconfig b/drivers/platform/mips/Kconfig
> index b3ae30a4c67b..0f054efc26e3 100644
> --- a/drivers/platform/mips/Kconfig
> +++ b/drivers/platform/mips/Kconfig
> @@ -23,4 +23,22 @@ config CPU_HWMON
>  	help
>  	  Loongson-3A/3B CPU Hwmon (temperature sensor) driver.
>  
> +config LEMOTE_YEELOONG2F
> +	tristate "Lemote YeeLoong Laptop"
> +	depends on LEMOTE_MACH2F
> +	select BACKLIGHT_LCD_SUPPORT
> +	select LCD_CLASS_DEVICE
> +	select BACKLIGHT_CLASS_DEVICE
> +	select POWER_SUPPLY
> +	select HWMON
> +	select INPUT_SPARSEKMAP
> +	select INPUT_EVDEV
> +	depends on INPUT
> +	default m
> +	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.

Please don't depend on INPUT, it's going to drive users crazy because
mortals less familiar with the configuration process for this platform
almost certainly won't know that INPUT needs to be enabled so
LEMOTE_YEELOONG2F can be selected.

This will require further changes because you can't force INPUT_SPARSEKMAP
and INPUT_EVDEV on if you don't know INPUT is selected.

It also looks as if your Kconfig changes won't work properly if INPUT_MISC
has not been selected manually.

>  endif # MIPS_PLATFORM_DEVICES
> diff --git a/drivers/platform/mips/Makefile b/drivers/platform/mips/Makefile
> index 8dfd03924c37..b3172b081a2f 100644
> --- a/drivers/platform/mips/Makefile
> +++ b/drivers/platform/mips/Makefile
> @@ -1 +1,4 @@
>  obj-$(CONFIG_CPU_HWMON) += cpu_hwmon.o
> +
> +obj-$(CONFIG_LEMOTE_YEELOONG2F)	+= yeeloong_laptop.o
> +CFLAGS_yeeloong_laptop.o = -I$(srctree)/arch/mips/loongson/lemote-2f
> diff --git a/drivers/platform/mips/yeeloong_laptop.c b/drivers/platform/mips/yeeloong_laptop.c
> new file mode 100644
> index 000000000000..280f2044858b
> --- /dev/null
> +++ b/drivers/platform/mips/yeeloong_laptop.c
> @@ -0,0 +1,1143 @@
> +/*
> + * Driver for YeeLoong laptop extras
> + *
> + *  Copyright (C) 2017 Jiaxun Yang.
> + *  Author: Jiaxun Yang <jiaxun.yang@flygoat.com>
> + *
> + *  Copyright (C) 2009 Lemote Inc.
> + *  Author: Wu Zhangjin <wuzhangjin@gmail.com>, Liu Junliang <liujl@lemote.com>
> + *
> + *  Fixes: Petr Pisar <petr.pisar@atlas.cz>, 2012, 2013, 2014, 2015.
> + *
> + *  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/kernel.h>   /* for clamp_val() */
> +#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 <linux/module.h>   /* For MODULE_DEVICE_TABLE() */
> +
> +#include <asm/bootinfo.h>
> +
> +#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 = clamp_val(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);
> +}
> +
> +const 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.type = BACKLIGHT_RAW;
> +	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 RET (val->intval)
> +
> +static inline bool is_ac_in(void)
> +{
> +	return !!(ec_read(REG_BAT_POWER) & BIT_BAT_POWER_ACIN);
> +}
> +
> +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:
> +		RET = is_ac_in();
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static enum power_supply_property yeeloong_ac_props[] = {
> +	POWER_SUPPLY_PROP_ONLINE,
> +};
> +
> +static const struct power_supply_desc yeeloong_ac_desc = {
> +	.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     95
> +
> +#define get_bat_info(type) \
> +	((ec_read(REG_BAT_##type##_HIGH) << 8) | \
> +	 (ec_read(REG_BAT_##type##_LOW)))
> +
> +static inline bool is_bat_in(void)
> +{
> +	return !!(ec_read(REG_BAT_STATUS) & BIT_BAT_STATUS_IN);
> +}
> +
> +static inline int get_bat_status(void)
> +{
> +	return ec_read(REG_BAT_STATUS);
> +}
> +
> +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 inline char *get_manufacturer(void)
> +{
> +	return (ec_read(REG_BAT_VENDOR) == FLAG_BAT_VENDOR_SANYO) ? "SANYO" :
> +		"SIMPLO";
> +}
> +
> +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:
> +		/* mV -> µV */
> +		RET = get_bat_info(DESIGN_VOL) * 1000;
> +		break;
> +	case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
> +		/* mAh->µAh */
> +		RET = get_bat_info(DESIGN_CAP) * 1000;
> +		break;
> +	case POWER_SUPPLY_PROP_CHARGE_FULL:
> +		/* µAh */
> +		RET = get_bat_info(FULLCHG_CAP) * 1000;
> +		break;
> +	case POWER_SUPPLY_PROP_MANUFACTURER:
> +		val->strval = get_manufacturer();
> +		break;
> +	/* Dynamic information */
> +	case POWER_SUPPLY_PROP_PRESENT:
> +		RET = is_bat_in();
> +		break;
> +	case POWER_SUPPLY_PROP_CURRENT_NOW:
> +		/* mA -> µA */
> +		RET = is_bat_in() ? get_battery_current() * 1000 : 0;
> +		break;
> +	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
> +		/* mV -> µV */
> +		RET = is_bat_in() ? get_battery_voltage() * 1000 : 0;
> +		break;
> +	case POWER_SUPPLY_PROP_TEMP:
> +		/* Celcius */
> +		RET = is_bat_in() ? get_battery_temp() : 0;
> +		break;
> +	case POWER_SUPPLY_PROP_CAPACITY:
> +		RET = is_bat_in() ? get_bat_info(RELATIVE_CAP) : 0;
> +		break;
> +	case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
> +		{
> +		int status;
> +
> +		if (!is_bat_in()) {
> +			RET = POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN;
> +			break;
> +		}
> +
> +		status = get_bat_status();
> +		RET = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
> +
> +		if (unlikely(status & BIT_BAT_STATUS_DESTROY)) {
> +			RET = POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN;
> +			break;
> +		}
> +
> +		if (status & BIT_BAT_STATUS_LOW)
> +			RET = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
> +		else if (status & BIT_BAT_STATUS_FULL)
> +			RET = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
> +		else {
> +			int curr_cap;
> +
> +			curr_cap = get_bat_info(RELATIVE_CAP);
> +
> +			if (curr_cap >= BAT_CAP_HIGH)
> +				RET = POWER_SUPPLY_CAPACITY_LEVEL_HIGH;
> +			else if (curr_cap <= BAT_CAP_CRITICAL)
> +				RET = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
> +		}
> +
> +		} break;
> +	case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:
> +		/* seconds */
> +		RET = is_bat_in() ?
> +			(get_bat_info(RELATIVE_CAP) - 3) * 54 + 142
> +			: 0;
> +		break;
> +	case POWER_SUPPLY_PROP_STATUS:
> +		{
> +			int charge = ec_read(REG_BAT_CHARGE);
> +
> +			if (charge & FLAG_BAT_CHARGE_DISCHARGE)
> +				RET = POWER_SUPPLY_STATUS_DISCHARGING;
> +			else if (charge & FLAG_BAT_CHARGE_CHARGE)
> +				RET = POWER_SUPPLY_STATUS_CHARGING;
> +			else
> +				RET = POWER_SUPPLY_STATUS_NOT_CHARGING;
> +		}
> +		break;
> +	case POWER_SUPPLY_PROP_HEALTH:
> +		{
> +			int status;
> +
> +			if (!is_bat_in()) {
> +				RET = POWER_SUPPLY_HEALTH_UNKNOWN;
> +				break;
> +			}
> +
> +			status = get_bat_status();
> +
> +			RET = POWER_SUPPLY_HEALTH_GOOD;
> +			if (status & (BIT_BAT_STATUS_DESTROY |
> +						BIT_BAT_STATUS_LOW))
> +				RET = POWER_SUPPLY_HEALTH_DEAD;
> +			if (ec_read(REG_BAT_CHARGE_STATUS) &
> +					BIT_BAT_CHARGE_STATUS_OVERTEMP)
> +				RET = POWER_SUPPLY_HEALTH_OVERHEAT;
> +		}
> +		break;
> +	case POWER_SUPPLY_PROP_CHARGE_NOW:	/* 1/100(%)*1000 µAh */
> +		RET = get_bat_info(RELATIVE_CAP) *
> +			get_bat_info(FULLCHG_CAP) * 10;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +	return 0;
> +}
> +#undef RET
> +
> +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 const struct power_supply_desc yeeloong_bat_desc = {
> +	.name = "yeeloongbattery",
> +	.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)
> +{
> +	yeeloong_ac = power_supply_register(NULL, &yeeloong_ac_desc, NULL);
> +	if (IS_ERR(yeeloong_ac))
> +		return PTR_ERR(yeeloong_ac);
> +	yeeloong_bat = power_supply_register(NULL, &yeeloong_bat_desc, NULL);
> +	if (IS_ERR(yeeloong_bat)) {
> +		power_supply_unregister(yeeloong_ac);
> +		return PTR_ERR(yeeloong_bat);
> +	}
> +	ac_bat_initialized = 1;
> +
> +	return 0;
> +}
> +
> +static void yeeloong_bat_exit(void)
> +{
> +	if (ac_bat_initialized) {
> +		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 = clamp_val(value, 0, 3);
> +
> +	/* We must ensure the fan is on */
> +	if (value > 0)
> +		ec_write(REG_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 = kstrtoul(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, 0444, get_fan_rpm, NULL);
> +CREATE_SENSOR_ATTR(pwm1, 0444 | 0644, get_fan_pwm, set_fan_pwm);
> +CREATE_SENSOR_ATTR(pwm1_enable, 0444 | 0644, get_fan_pwm_enable,
> +		set_fan_pwm_enable);
> +CREATE_SENSOR_ATTR(temp1_input, 0444, get_cpu_temp, NULL);
> +CREATE_SENSOR_ATTR(temp1_max, 0444, get_cpu_temp_max, NULL);
> +CREATE_SENSOR_ATTR(temp2_input, 0444, get_battery_temp, NULL);
> +CREATE_SENSOR_ATTR(temp2_max_alarm, 0444, get_battery_temp_alarm, NULL);
> +CREATE_SENSOR_ATTR(curr1_input, 0444, get_battery_current, NULL);
> +CREATE_SENSOR_ATTR(in1_input, 0444, 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, 0444, 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 controller */
> +
> +
> +#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);
> +}
> +
> +
> +
> +/* hotkey subdriver */
> +
> +static struct input_dev *yeeloong_hotkey_dev;
> +
> +static const struct key_entry yeeloong_keymap[] = {
> +	{KE_SW, EVENT_LID, {SW_LID} },
> +	/* Fn + ESC */
> +	{KE_KEY, EVENT_CAMERA, {KEY_CAMERA} },
> +	/* Fn + F1 */
> +	{KE_KEY, EVENT_SLEEP, {KEY_SLEEP} },
> +	/* Fn + F2 */
> +	{KE_KEY, EVENT_DISPLAYTOGGLE, {KEY_DISPLAYTOGGLE} },
> +	/* Fn + F3 */
> +	{KE_KEY, EVENT_SWITCHVIDEOMODE, {KEY_SWITCHVIDEOMODE} },
> +	/* Fn + F4 */
> +	{KE_KEY, EVENT_AUDIO_MUTE, {KEY_MUTE} },
> +	/* Fn + F5 */
> +	{KE_KEY, EVENT_WLAN, {KEY_WLAN} },
> +	/* Fn + up */
> +	{KE_KEY, EVENT_DISPLAY_BRIGHTNESS, {KEY_BRIGHTNESSUP} },
> +	/* Fn + down */
> +	{KE_KEY, EVENT_DISPLAY_BRIGHTNESS, {KEY_BRIGHTNESSDOWN} },
> +	/* Fn + right */
> +	{KE_KEY, EVENT_AUDIO_VOLUME, {KEY_VOLUMEUP} },
> +	/* Fn + left */
> +	{KE_KEY, EVENT_AUDIO_VOLUME, {KEY_VOLUMEDOWN} },
> +	{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 == 0) || (status < old_brightness_status))
> +			ke++;
> +		old_brightness_status = status;
> +		break;
> +	case EVENT_AUDIO_VOLUME:
> +		if ((status == 0) || (status < old_volume_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 void yeeloong_vo_set(int lcd_status, int crt_status)
> +{
> +	display_vo_set(LCD, lcd_status);
> +	display_vo_set(CRT, crt_status);
> +}
> +
> +static int crt_detect_handler(int status)
> +{
> +	if (status)
> +		yeeloong_vo_set(ON, ON);
> +	else
> +		yeeloong_vo_set(ON, OFF);
> +
> +	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"))
> +		display_vo_set(LCD, 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) == OFF)
> +		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_vo_set(ON, ON);
> +		break;
> +	case 2:
> +		yeeloong_vo_set(OFF, ON);
> +		break;
> +	case 3:
> +		yeeloong_vo_set(OFF, OFF);
> +		break;
> +	case 4:
> +		yeeloong_vo_set(ON, OFF);
> +		break;
> +	default:
> +		/* Ensure LCD is on */
> +		display_vo_set(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;
> +	status = 0;
> +
> +	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_debug("%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 (irq != SCI_IRQ_NUM)
> +		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 */
> +	mdelay(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 int yeeloong_hotkey_init(void)
> +{
> +	int ret;
> +
> +	ret = sci_irq_init();
> +	if (ret)
> +		return -EFAULT;
> +
> +	ret = request_threaded_irq(SCI_IRQ_NUM, NULL, &sci_irq_handler,
> +			IRQF_ONESHOT, "sci", NULL);
> +	if (ret)
> +		return -EFAULT;
> +
> +	yeeloong_hotkey_dev = input_allocate_device();
> +
> +	if (!yeeloong_hotkey_dev) {
> +		free_irq(SCI_IRQ_NUM, NULL);
> +		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) {
> +		input_free_device(yeeloong_hotkey_dev);
> +		return ret;
> +	}
> +
> +	/* Update the current status of LID */
> +	report_lid_switch(ON);
> +
> +#ifdef CONFIG_LOONGSON_SUSPEND
> +	/* Install the real yeeloong_report_lid_status for pm.c */
> +	yeeloong_report_lid_status = report_lid_switch;
> +#endif

CONFIG_LOONGSON_SUSPEND was removed by 5361832704d3 ("MIPS: Loongson:
Cleanup CONFIG_LOONGSON_SUSPEND.") on 2017-10-07.  So while probably
replacing CONFIG_LOONGSON_SUSPEND with CONFIG_SUSPEND appears to be the
right thing I'm wondering if code that is not being built since two
years is still needed or can be considered tested ...

> +
> +	return 0;
> +}
> +
> +static void yeeloong_hotkey_exit(void)
> +{
> +	/* Free irq */
> +	free_irq(SCI_IRQ_NUM, NULL);
> +
> +#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

Ditto.

> +
> +	if (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"))
> +		display_vo_set(LCD, OFF);
> +	display_vo_set(CRT, OFF);
> +	usb_ports_set(OFF);
> +
> +	return 0;
> +}
> +
> +static int yeeloong_resume(struct device *dev)
> +{
> +	int ret;
> +
> +	if (ec_version_before("EC_VER=PQ1D27"))
> +		display_vo_set(LCD, ON);
> +	display_vo_set(CRT, ON);
> +	usb_ports_set(ON);
> +
> +	ret = sci_irq_init();
> +	if (ret)
> +		return -EFAULT;
> +
> +	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;
> +
> +	if (mips_machtype != MACH_LEMOTE_YL2F89) {
> +		pr_err("Unsupported system.\n");
> +		return -ENODEV;
> +	}
> +
> +	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_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_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");

  Ralf

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 4/4] MIPS: Loongson64: Load platform device during boot This patch just add pdev during boot to load the platform driver
  2017-11-12  6:36 ` [PATCH 4/4] MIPS: Loongson64: Load platform device during boot This patch just add pdev during boot to load the platform driver jiaxun.yang
@ 2017-11-14 13:29   ` Ralf Baechle
  0 siblings, 0 replies; 14+ messages in thread
From: Ralf Baechle @ 2017-11-14 13:29 UTC (permalink / raw)
  To: jiaxun.yang; +Cc: linux-mips, linux-kernel

On Sun, Nov 12, 2017 at 02:36:17PM +0800, jiaxun.yang@flygoat.com wrote:

> From: Jiaxun Yang <jiaxun.yang@flygoat.com>
> 
> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> ---
>  arch/mips/loongson64/lemote-2f/Makefile   |  2 +-
>  arch/mips/loongson64/lemote-2f/platform.c | 45 +++++++++++++++++++++++++++++++
>  2 files changed, 46 insertions(+), 1 deletion(-)
>  create mode 100644 arch/mips/loongson64/lemote-2f/platform.c
> 
> diff --git a/arch/mips/loongson64/lemote-2f/Makefile b/arch/mips/loongson64/lemote-2f/Makefile
> index 08b8abcbfef5..31c90737b98c 100644
> --- a/arch/mips/loongson64/lemote-2f/Makefile
> +++ b/arch/mips/loongson64/lemote-2f/Makefile
> @@ -2,7 +2,7 @@
>  # Makefile for lemote loongson2f family machines
>  #
>  
> -obj-y += clock.o machtype.o irq.o reset.o ec_kb3310b.o
> +obj-y += clock.o machtype.o irq.o reset.o ec_kb3310b.o platform.o
>  
>  #
>  # Suspend Support
> diff --git a/arch/mips/loongson64/lemote-2f/platform.c b/arch/mips/loongson64/lemote-2f/platform.c
> new file mode 100644
> index 000000000000..c36efcccb9a9
> --- /dev/null
> +++ b/arch/mips/loongson64/lemote-2f/platform.c
> @@ -0,0 +1,45 @@
> +/*
> + * Copyright (C) 2017 Jiaxun Yang.
> + * Author: Jiaxun Yang, jiaxun.yang@flygoat.com
> +
> + * 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 int __init lemote2f_platform_init(void)
> +{
> +	struct platform_device *pdev = NULL;
> +
> +	switch (mips_machtype) {
> +	case MACH_LEMOTE_YL2F89:
> +		pdev = &yeeloong_pdev;
> +		break;
> +
> +	default:
> +		break;
> +
> +	}
> +
> +	if (pdev != NULL)
> +		return platform_device_register(pdev);
> +
> +	return -ENODEV;
> +}
> +
> +arch_initcall(lemote2f_platform_init);

Looks like you can simplify this by using something like:

> +static int __init lemote2f_platform_init(void)
> +{
> +     struct platform_device *pdev = NULL;
> +
> +     switch (mips_machtype) {
> +     case MACH_LEMOTE_YL2F89:
> +             pdev = &yeeloong_pdev;
> +             break;
> +
> +     default:
> +             break;
> +
> +     }
> +
> +     if (pdev != NULL)
> +             return platform_device_register(pdev);
> +
> +     return -ENODEV;
> +}

Looks like this can be simplified to:

static int __init lemote2f_platform_init(void)
{
	if (mips_machtype != MACH_LEMOTE_YL2F89)
		return -ENODEV;

	return platform_device_register_simple("yeeloong_laptop", -1, NULL, 0);
}


  Ralf

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 3/4] MIPS: Loongson64: Yeeloong add platform driver Yeeloong is a laptop with a MIPS Loongson 2F processor, AMD CS5536 chipset, and KB3310B controller.
  2017-11-12  6:36 ` [PATCH 3/4] MIPS: Loongson64: Yeeloong add platform driver Yeeloong is a laptop with a MIPS Loongson 2F processor, AMD CS5536 chipset, and KB3310B controller jiaxun.yang
  2017-11-14 13:21   ` Ralf Baechle
@ 2017-11-14 13:35   ` Ralf Baechle
  1 sibling, 0 replies; 14+ messages in thread
From: Ralf Baechle @ 2017-11-14 13:35 UTC (permalink / raw)
  To: jiaxun.yang; +Cc: linux-mips, linux-kernel

On Sun, Nov 12, 2017 at 02:36:16PM +0800, jiaxun.yang@flygoat.com wrote:

> +     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");

I forgot to comment on this .set noreorder thing.  GCC expects gas to be
in reorder mode at the end of every bit of inline assembler, so above
code is at the mercy of GCC.

Not sure what the intent was here, was it to avoid GCC from reordering
the outl() calls?  These are already marked volatlile and should not be
reordered by GCC.  .set (no)reorder on the other hand is a directive
to GAS and GCC won't be influenced at all by it.

Cheers,

  Ralf

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v3 1/4] MIPS: Lonngson64: Copy kernel command line from arcs_cmdline
  2017-11-12  6:36 [PATCH 1/4] MIPS: Lonngson64: Copy kernel command line from arcs_cmdline Since lemte-2f/marchtype.c need to get cmdline from loongson.h this patch simply copy kernel command line from arcs_cmdline to fix that issue jiaxun.yang
                   ` (3 preceding siblings ...)
  2017-11-13 14:21 ` [PATCH 1/4] MIPS: Lonngson64: Copy kernel command line from arcs_cmdline Since lemte-2f/marchtype.c need to get cmdline from loongson.h this patch simply copy kernel command line from arcs_cmdline to fix that issue Ralf Baechle
@ 2017-11-15  3:11 ` Jiaxun Yang
  2017-11-15  3:11   ` [PATCH v3 2/4] MIPS: Loongson64: lemote-2f move ec_kb3310b.h to include dir and clean up Jiaxun Yang
                     ` (3 more replies)
  4 siblings, 4 replies; 14+ messages in thread
From: Jiaxun Yang @ 2017-11-15  3:11 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips, linux-kernel, Jiaxun Yang

Since lemote-2f/marchtype.c need to get cmdline from loongson.h
this patch simply copy kernel command line from arcs_cmdline
to fix that issue.

Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 arch/mips/include/asm/mach-loongson64/loongson.h | 6 ++++++
 arch/mips/loongson64/common/cmdline.c            | 7 +++++++
 2 files changed, 13 insertions(+)

diff --git a/arch/mips/include/asm/mach-loongson64/loongson.h b/arch/mips/include/asm/mach-loongson64/loongson.h
index c68c0cc879c6..1edf3a484e6a 100644
--- a/arch/mips/include/asm/mach-loongson64/loongson.h
+++ b/arch/mips/include/asm/mach-loongson64/loongson.h
@@ -45,6 +45,12 @@ static inline void prom_init_uart_base(void)
 #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 --git a/arch/mips/loongson64/common/cmdline.c b/arch/mips/loongson64/common/cmdline.c
index 01fbed137028..49e172184e15 100644
--- a/arch/mips/loongson64/common/cmdline.c
+++ b/arch/mips/loongson64/common/cmdline.c
@@ -21,6 +21,11 @@
 
 #include <loongson.h>
 
+/* the kernel command line copied from arcs_cmdline */
+#include <linux/export.h>
+char loongson_cmdline[COMMAND_LINE_SIZE];
+EXPORT_SYMBOL(loongson_cmdline);
+
 void __init prom_init_cmdline(void)
 {
 	int prom_argc;
@@ -45,4 +50,6 @@ void __init prom_init_cmdline(void)
 	}
 
 	prom_init_machtype();
+	/* copy arcs_cmdline into loongson_cmdline */
+	strncpy(loongson_cmdline, arcs_cmdline, COMMAND_LINE_SIZE);
 }
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v3 2/4] MIPS: Loongson64: lemote-2f move ec_kb3310b.h to include dir and clean up
  2017-11-15  3:11 ` [PATCH v3 1/4] MIPS: Lonngson64: Copy kernel command line from arcs_cmdline Jiaxun Yang
@ 2017-11-15  3:11   ` Jiaxun Yang
  2017-11-15  3:11   ` [PATCH v3 3/4] MIPS: Loongson64: Yeeloong add platform driver Jiaxun Yang
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 14+ messages in thread
From: Jiaxun Yang @ 2017-11-15  3:11 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips, linux-kernel, Jiaxun Yang

To operate EC from platform driver, this head file need able to be include
from anywhere. This patch just move ec_kb3310b.h to include dir and
clean up ec_kb3310b.h.

Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 arch/mips/include/asm/mach-loongson64/ec_kb3310b.h | 170 +++++++++++++++++++
 arch/mips/loongson64/lemote-2f/ec_kb3310b.c        |   2 +-
 arch/mips/loongson64/lemote-2f/ec_kb3310b.h        | 188 ---------------------
 arch/mips/loongson64/lemote-2f/pm.c                |   4 +-
 arch/mips/loongson64/lemote-2f/reset.c             |   4 +-
 5 files changed, 175 insertions(+), 193 deletions(-)
 create mode 100644 arch/mips/include/asm/mach-loongson64/ec_kb3310b.h
 delete mode 100644 arch/mips/loongson64/lemote-2f/ec_kb3310b.h

diff --git a/arch/mips/include/asm/mach-loongson64/ec_kb3310b.h b/arch/mips/include/asm/mach-loongson64/ec_kb3310b.h
new file mode 100644
index 000000000000..2e8690532ea5
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson64/ec_kb3310b.h
@@ -0,0 +1,170 @@
+/*
+ * 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 ON	1
+#define OFF	0
+
+#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	REG_FAN_STATUS		0xF4DA
+#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	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
+/* LID */
+#define	REG_LID_DETECT		0xF4BD
+/* CRT */
+#define	REG_CRT_DETECT		0xF4AD
+/* LCD backlight brightness adjust: 9 levels */
+#define	REG_DISPLAY_BRIGHTNESS	0xF4F5
+/* LCD backlight control: off/restore */
+#define	REG_BACKLIGHT_CTRL	0xF7BD
+/* Reset the machine auto-clear: rd/wr */
+#define	REG_RESET		0xF4EC
+/* 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	REG_CAMERA_CONTROL	0xF7B7
+/* Wlan Status */
+#define	REG_WLAN		0xF4FA
+#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 --git a/arch/mips/loongson64/lemote-2f/ec_kb3310b.c b/arch/mips/loongson64/lemote-2f/ec_kb3310b.c
index 321822997e76..6e416d55b42a 100644
--- a/arch/mips/loongson64/lemote-2f/ec_kb3310b.c
+++ b/arch/mips/loongson64/lemote-2f/ec_kb3310b.c
@@ -15,7 +15,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);
diff --git a/arch/mips/loongson64/lemote-2f/ec_kb3310b.h b/arch/mips/loongson64/lemote-2f/ec_kb3310b.h
deleted file mode 100644
index 5a3f1860d4d2..000000000000
--- a/arch/mips/loongson64/lemote-2f/ec_kb3310b.h
+++ /dev/null
@@ -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 --git a/arch/mips/loongson64/lemote-2f/pm.c b/arch/mips/loongson64/lemote-2f/pm.c
index 6859e934862d..0768739155f6 100644
--- a/arch/mips/loongson64/lemote-2f/pm.c
+++ b/arch/mips/loongson64/lemote-2f/pm.c
@@ -88,7 +88,7 @@ EXPORT_SYMBOL(yeeloong_report_lid_status);
 static void yeeloong_lid_update_task(struct work_struct *work)
 {
 	if (yeeloong_report_lid_status)
-		yeeloong_report_lid_status(BIT_LID_DETECT_ON);
+		yeeloong_report_lid_status(ON);
 }
 
 int wakeup_loongson(void)
@@ -118,7 +118,7 @@ int wakeup_loongson(void)
 			/* check the LID status */
 			lid_status = ec_read(REG_LID_DETECT);
 			/* wakeup cpu when people open the LID */
-			if (lid_status == BIT_LID_DETECT_ON) {
+			if (lid_status == ON) {
 				/* If we call it directly here, the WARNING
 				 * will be sent out by getnstimeofday
 				 * via "WARN_ON(timekeeping_suspended);"
diff --git a/arch/mips/loongson64/lemote-2f/reset.c b/arch/mips/loongson64/lemote-2f/reset.c
index a26ca7fcd7e0..2b72b197c51d 100644
--- a/arch/mips/loongson64/lemote-2f/reset.c
+++ b/arch/mips/loongson64/lemote-2f/reset.c
@@ -20,7 +20,7 @@
 #include <loongson.h>
 
 #include <cs5536/cs5536.h>
-#include "ec_kb3310b.h"
+#include <ec_kb3310b.h>
 
 static void reset_cpu(void)
 {
@@ -81,7 +81,7 @@ static void ml2f_reboot(void)
 	reset_cpu();
 
 	/* sending an reset signal to EC(embedded controller) */
-	ec_write(REG_RESET, BIT_RESET_ON);
+	ec_write(REG_RESET, ON);
 }
 
 #define yl2f89_reboot ml2f_reboot
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v3 3/4] MIPS: Loongson64: Yeeloong add platform driver
  2017-11-15  3:11 ` [PATCH v3 1/4] MIPS: Lonngson64: Copy kernel command line from arcs_cmdline Jiaxun Yang
  2017-11-15  3:11   ` [PATCH v3 2/4] MIPS: Loongson64: lemote-2f move ec_kb3310b.h to include dir and clean up Jiaxun Yang
@ 2017-11-15  3:11   ` Jiaxun Yang
  2017-11-15  3:11   ` [PATCH v3 4/4] MIPS: Loongson64: Load platform device during boot Jiaxun Yang
  2017-11-16  4:22   ` [PATCH v3 1/4] MIPS: Lonngson64: Copy kernel command line from arcs_cmdline Huacai Chen
  3 siblings, 0 replies; 14+ messages in thread
From: Jiaxun Yang @ 2017-11-15  3:11 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips, linux-kernel, Jiaxun Yang

Yeeloong is a laptop with a MIPS Loongson 2F processor, AMD CS5536
chipset, and KB3310B controller.

This yeeloong_laptop module enables access to sensors, battery,
video camera switch, external video connector event, and some
additional buttons.

This driver was orginally from linux-loongson-community. I Just do
some clean up and port to mainline kernel tree.

Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 drivers/platform/mips/Kconfig           |   19 +
 drivers/platform/mips/Makefile          |    3 +
 drivers/platform/mips/yeeloong_laptop.c | 1142 +++++++++++++++++++++++++++++++
 3 files changed, 1164 insertions(+)
 create mode 100644 drivers/platform/mips/yeeloong_laptop.c

diff --git a/drivers/platform/mips/Kconfig b/drivers/platform/mips/Kconfig
index b3ae30a4c67b..acd27e36710b 100644
--- a/drivers/platform/mips/Kconfig
+++ b/drivers/platform/mips/Kconfig
@@ -23,4 +23,23 @@ config CPU_HWMON
 	help
 	  Loongson-3A/3B CPU Hwmon (temperature sensor) driver.
 
+config LEMOTE_YEELOONG2F
+	tristate "Lemote YeeLoong Laptop"
+	depends on LEMOTE_MACH2F
+	select BACKLIGHT_LCD_SUPPORT
+	select LCD_CLASS_DEVICE
+	select BACKLIGHT_CLASS_DEVICE
+	select POWER_SUPPLY
+	select HWMON
+	select INPUT
+	select INPUT_MISC
+	select INPUT_SPARSEKMAP
+	select INPUT_EVDEV
+	default m
+	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.
+
 endif # MIPS_PLATFORM_DEVICES
diff --git a/drivers/platform/mips/Makefile b/drivers/platform/mips/Makefile
index 8dfd03924c37..b3172b081a2f 100644
--- a/drivers/platform/mips/Makefile
+++ b/drivers/platform/mips/Makefile
@@ -1 +1,4 @@
 obj-$(CONFIG_CPU_HWMON) += cpu_hwmon.o
+
+obj-$(CONFIG_LEMOTE_YEELOONG2F)	+= yeeloong_laptop.o
+CFLAGS_yeeloong_laptop.o = -I$(srctree)/arch/mips/loongson/lemote-2f
diff --git a/drivers/platform/mips/yeeloong_laptop.c b/drivers/platform/mips/yeeloong_laptop.c
new file mode 100644
index 000000000000..61353c3e894c
--- /dev/null
+++ b/drivers/platform/mips/yeeloong_laptop.c
@@ -0,0 +1,1142 @@
+/*
+ * Driver for YeeLoong laptop extras
+ *
+ *  Copyright (C) 2017 Jiaxun Yang.
+ *  Author: Jiaxun Yang <jiaxun.yang@flygoat.com>
+ *
+ *  Copyright (C) 2009 Lemote Inc.
+ *  Author: Wu Zhangjin <wuzhangjin@gmail.com>, Liu Junliang <liujl@lemote.com>
+ *
+ *  Fixes: Petr Pisar <petr.pisar@atlas.cz>, 2012, 2013, 2014, 2015.
+ *
+ *  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/kernel.h>   /* for clamp_val() */
+#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 <linux/module.h>   /* For MODULE_DEVICE_TABLE() */
+
+#include <asm/bootinfo.h>
+
+#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 = clamp_val(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);
+}
+
+const 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.type = BACKLIGHT_RAW;
+	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 RET (val->intval)
+
+static inline bool is_ac_in(void)
+{
+	return !!(ec_read(REG_BAT_POWER) & BIT_BAT_POWER_ACIN);
+}
+
+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:
+		RET = is_ac_in();
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static enum power_supply_property yeeloong_ac_props[] = {
+	POWER_SUPPLY_PROP_ONLINE,
+};
+
+static const struct power_supply_desc yeeloong_ac_desc = {
+	.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     95
+
+#define get_bat_info(type) \
+	((ec_read(REG_BAT_##type##_HIGH) << 8) | \
+	 (ec_read(REG_BAT_##type##_LOW)))
+
+static inline bool is_bat_in(void)
+{
+	return !!(ec_read(REG_BAT_STATUS) & BIT_BAT_STATUS_IN);
+}
+
+static inline int get_bat_status(void)
+{
+	return ec_read(REG_BAT_STATUS);
+}
+
+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 inline char *get_manufacturer(void)
+{
+	return (ec_read(REG_BAT_VENDOR) == FLAG_BAT_VENDOR_SANYO) ? "SANYO" :
+		"SIMPLO";
+}
+
+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:
+		/* mV -> µV */
+		RET = get_bat_info(DESIGN_VOL) * 1000;
+		break;
+	case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
+		/* mAh->µAh */
+		RET = get_bat_info(DESIGN_CAP) * 1000;
+		break;
+	case POWER_SUPPLY_PROP_CHARGE_FULL:
+		/* µAh */
+		RET = get_bat_info(FULLCHG_CAP) * 1000;
+		break;
+	case POWER_SUPPLY_PROP_MANUFACTURER:
+		val->strval = get_manufacturer();
+		break;
+	/* Dynamic information */
+	case POWER_SUPPLY_PROP_PRESENT:
+		RET = is_bat_in();
+		break;
+	case POWER_SUPPLY_PROP_CURRENT_NOW:
+		/* mA -> µA */
+		RET = is_bat_in() ? get_battery_current() * 1000 : 0;
+		break;
+	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+		/* mV -> µV */
+		RET = is_bat_in() ? get_battery_voltage() * 1000 : 0;
+		break;
+	case POWER_SUPPLY_PROP_TEMP:
+		/* Celcius */
+		RET = is_bat_in() ? get_battery_temp() : 0;
+		break;
+	case POWER_SUPPLY_PROP_CAPACITY:
+		RET = is_bat_in() ? get_bat_info(RELATIVE_CAP) : 0;
+		break;
+	case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
+		{
+		int status;
+
+		if (!is_bat_in()) {
+			RET = POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN;
+			break;
+		}
+
+		status = get_bat_status();
+		RET = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
+
+		if (unlikely(status & BIT_BAT_STATUS_DESTROY)) {
+			RET = POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN;
+			break;
+		}
+
+		if (status & BIT_BAT_STATUS_LOW)
+			RET = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
+		else if (status & BIT_BAT_STATUS_FULL)
+			RET = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
+		else {
+			int curr_cap;
+
+			curr_cap = get_bat_info(RELATIVE_CAP);
+
+			if (curr_cap >= BAT_CAP_HIGH)
+				RET = POWER_SUPPLY_CAPACITY_LEVEL_HIGH;
+			else if (curr_cap <= BAT_CAP_CRITICAL)
+				RET = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
+		}
+
+		} break;
+	case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:
+		/* seconds */
+		RET = is_bat_in() ?
+			(get_bat_info(RELATIVE_CAP) - 3) * 54 + 142
+			: 0;
+		break;
+	case POWER_SUPPLY_PROP_STATUS:
+		{
+			int charge = ec_read(REG_BAT_CHARGE);
+
+			if (charge & FLAG_BAT_CHARGE_DISCHARGE)
+				RET = POWER_SUPPLY_STATUS_DISCHARGING;
+			else if (charge & FLAG_BAT_CHARGE_CHARGE)
+				RET = POWER_SUPPLY_STATUS_CHARGING;
+			else
+				RET = POWER_SUPPLY_STATUS_NOT_CHARGING;
+		}
+		break;
+	case POWER_SUPPLY_PROP_HEALTH:
+		{
+			int status;
+
+			if (!is_bat_in()) {
+				RET = POWER_SUPPLY_HEALTH_UNKNOWN;
+				break;
+			}
+
+			status = get_bat_status();
+
+			RET = POWER_SUPPLY_HEALTH_GOOD;
+			if (status & (BIT_BAT_STATUS_DESTROY |
+						BIT_BAT_STATUS_LOW))
+				RET = POWER_SUPPLY_HEALTH_DEAD;
+			if (ec_read(REG_BAT_CHARGE_STATUS) &
+					BIT_BAT_CHARGE_STATUS_OVERTEMP)
+				RET = POWER_SUPPLY_HEALTH_OVERHEAT;
+		}
+		break;
+	case POWER_SUPPLY_PROP_CHARGE_NOW:	/* 1/100(%)*1000 µAh */
+		RET = get_bat_info(RELATIVE_CAP) *
+			get_bat_info(FULLCHG_CAP) * 10;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+#undef RET
+
+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 const struct power_supply_desc yeeloong_bat_desc = {
+	.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)
+{
+	yeeloong_ac = power_supply_register(NULL, &yeeloong_ac_desc, NULL);
+	if (IS_ERR(yeeloong_ac))
+		return PTR_ERR(yeeloong_ac);
+	yeeloong_bat = power_supply_register(NULL, &yeeloong_bat_desc, NULL);
+	if (IS_ERR(yeeloong_bat)) {
+		power_supply_unregister(yeeloong_ac);
+		return PTR_ERR(yeeloong_bat);
+	}
+	ac_bat_initialized = 1;
+
+	return 0;
+}
+
+static void yeeloong_bat_exit(void)
+{
+	if (ac_bat_initialized) {
+		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 = clamp_val(value, 0, 3);
+
+	/* We must ensure the fan is on */
+	if (value > 0)
+		ec_write(REG_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 = kstrtoul(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, 0444, get_fan_rpm, NULL);
+CREATE_SENSOR_ATTR(pwm1, 0444 | 0644, get_fan_pwm, set_fan_pwm);
+CREATE_SENSOR_ATTR(pwm1_enable, 0444 | 0644, get_fan_pwm_enable,
+		set_fan_pwm_enable);
+CREATE_SENSOR_ATTR(temp1_input, 0444, get_cpu_temp, NULL);
+CREATE_SENSOR_ATTR(temp1_max, 0444, get_cpu_temp_max, NULL);
+CREATE_SENSOR_ATTR(temp2_input, 0444, get_battery_temp, NULL);
+CREATE_SENSOR_ATTR(temp2_max_alarm, 0444, get_battery_temp_alarm, NULL);
+CREATE_SENSOR_ATTR(curr1_input, 0444, get_battery_current, NULL);
+CREATE_SENSOR_ATTR(in1_input, 0444, 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, 0444, 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 controller */
+
+
+#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);
+}
+
+
+
+/* hotkey subdriver */
+
+static struct input_dev *yeeloong_hotkey_dev;
+
+static const struct key_entry yeeloong_keymap[] = {
+	{KE_SW, EVENT_LID, {SW_LID} },
+	/* Fn + ESC */
+	{KE_KEY, EVENT_CAMERA, {KEY_CAMERA} },
+	/* Fn + F1 */
+	{KE_KEY, EVENT_SLEEP, {KEY_SLEEP} },
+	/* Fn + F2 */
+	{KE_KEY, EVENT_DISPLAYTOGGLE, {KEY_DISPLAYTOGGLE} },
+	/* Fn + F3 */
+	{KE_KEY, EVENT_SWITCHVIDEOMODE, {KEY_SWITCHVIDEOMODE} },
+	/* Fn + F4 */
+	{KE_KEY, EVENT_AUDIO_MUTE, {KEY_MUTE} },
+	/* Fn + F5 */
+	{KE_KEY, EVENT_WLAN, {KEY_WLAN} },
+	/* Fn + up */
+	{KE_KEY, EVENT_DISPLAY_BRIGHTNESS, {KEY_BRIGHTNESSUP} },
+	/* Fn + down */
+	{KE_KEY, EVENT_DISPLAY_BRIGHTNESS, {KEY_BRIGHTNESSDOWN} },
+	/* Fn + right */
+	{KE_KEY, EVENT_AUDIO_VOLUME, {KEY_VOLUMEUP} },
+	/* Fn + left */
+	{KE_KEY, EVENT_AUDIO_VOLUME, {KEY_VOLUMEDOWN} },
+	{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 == 0) || (status < old_brightness_status))
+			ke++;
+		old_brightness_status = status;
+		break;
+	case EVENT_AUDIO_VOLUME:
+		if ((status == 0) || (status < old_volume_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 void yeeloong_vo_set(int lcd_status, int crt_status)
+{
+	display_vo_set(LCD, lcd_status);
+	display_vo_set(CRT, crt_status);
+}
+
+static int crt_detect_handler(int status)
+{
+	if (status)
+		yeeloong_vo_set(ON, ON);
+	else
+		yeeloong_vo_set(ON, OFF);
+
+	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"))
+		display_vo_set(LCD, 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) == OFF)
+		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_vo_set(ON, ON);
+		break;
+	case 2:
+		yeeloong_vo_set(OFF, ON);
+		break;
+	case 3:
+		yeeloong_vo_set(OFF, OFF);
+		break;
+	case 4:
+		yeeloong_vo_set(ON, OFF);
+		break;
+	default:
+		/* Ensure LCD is on */
+		display_vo_set(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;
+	status = 0;
+
+	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_debug("%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 (irq != SCI_IRQ_NUM)
+		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 */
+	mdelay(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
+	 */
+
+	/*  input enable */
+	outl(0x00000800, (gpio_base | 0xA0));
+	/*  revert the input */
+	outl(0x00000800, (gpio_base | 0xA4));
+	/*  event-int enable */
+	outl(0x00000800, (gpio_base | 0xB8));
+
+	return 0;
+}
+
+static int yeeloong_hotkey_init(void)
+{
+	int ret;
+
+	ret = sci_irq_init();
+	if (ret)
+		return -EFAULT;
+
+	ret = request_threaded_irq(SCI_IRQ_NUM, NULL, &sci_irq_handler,
+			IRQF_ONESHOT, "sci", NULL);
+	if (ret)
+		return -EFAULT;
+
+	yeeloong_hotkey_dev = input_allocate_device();
+
+	if (!yeeloong_hotkey_dev) {
+		free_irq(SCI_IRQ_NUM, NULL);
+		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) {
+		input_free_device(yeeloong_hotkey_dev);
+		return ret;
+	}
+
+	/* Update the current status of LID */
+	report_lid_switch(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 */
+	free_irq(SCI_IRQ_NUM, NULL);
+
+#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) {
+		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"))
+		display_vo_set(LCD, OFF);
+	display_vo_set(CRT, OFF);
+	usb_ports_set(OFF);
+
+	return 0;
+}
+
+static int yeeloong_resume(struct device *dev)
+{
+	int ret;
+
+	if (ec_version_before("EC_VER=PQ1D27"))
+		display_vo_set(LCD, ON);
+	display_vo_set(CRT, ON);
+	usb_ports_set(ON);
+
+	ret = sci_irq_init();
+	if (ret)
+		return -EFAULT;
+
+	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;
+
+	if (mips_machtype != MACH_LEMOTE_YL2F89) {
+		pr_err("Unsupported system.\n");
+		return -ENODEV;
+	}
+
+	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_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_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>; Jiaxun Yang <jiaxun.yang@flygoat.com>");
+MODULE_DESCRIPTION("YeeLoong laptop driver");
+MODULE_LICENSE("GPL");
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v3 4/4] MIPS: Loongson64: Load platform device during boot
  2017-11-15  3:11 ` [PATCH v3 1/4] MIPS: Lonngson64: Copy kernel command line from arcs_cmdline Jiaxun Yang
  2017-11-15  3:11   ` [PATCH v3 2/4] MIPS: Loongson64: lemote-2f move ec_kb3310b.h to include dir and clean up Jiaxun Yang
  2017-11-15  3:11   ` [PATCH v3 3/4] MIPS: Loongson64: Yeeloong add platform driver Jiaxun Yang
@ 2017-11-15  3:11   ` Jiaxun Yang
  2017-11-16  4:22   ` [PATCH v3 1/4] MIPS: Lonngson64: Copy kernel command line from arcs_cmdline Huacai Chen
  3 siblings, 0 replies; 14+ messages in thread
From: Jiaxun Yang @ 2017-11-15  3:11 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips, linux-kernel, Jiaxun Yang

This patch just add pdev during boot to load the platform driver

Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 arch/mips/loongson64/lemote-2f/Makefile   |  2 +-
 arch/mips/loongson64/lemote-2f/platform.c | 27 +++++++++++++++++++++++++++
 2 files changed, 28 insertions(+), 1 deletion(-)
 create mode 100644 arch/mips/loongson64/lemote-2f/platform.c

diff --git a/arch/mips/loongson64/lemote-2f/Makefile b/arch/mips/loongson64/lemote-2f/Makefile
index 08b8abcbfef5..31c90737b98c 100644
--- a/arch/mips/loongson64/lemote-2f/Makefile
+++ b/arch/mips/loongson64/lemote-2f/Makefile
@@ -2,7 +2,7 @@
 # Makefile for lemote loongson2f family machines
 #
 
-obj-y += clock.o machtype.o irq.o reset.o ec_kb3310b.o
+obj-y += clock.o machtype.o irq.o reset.o ec_kb3310b.o platform.o
 
 #
 # Suspend Support
diff --git a/arch/mips/loongson64/lemote-2f/platform.c b/arch/mips/loongson64/lemote-2f/platform.c
new file mode 100644
index 000000000000..46922f730a64
--- /dev/null
+++ b/arch/mips/loongson64/lemote-2f/platform.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2017 Jiaxun Yang.
+ * Author: Jiaxun Yang, jiaxun.yang@flygoat.com
+
+ * 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 int __init lemote2f_platform_init(void)
+{
+	if (mips_machtype != MACH_LEMOTE_YL2F89)
+		return -ENODEV;
+
+	return platform_device_register_simple("yeeloong_laptop", -1, NULL, 0);
+}
+
+arch_initcall(lemote2f_platform_init);
\ No newline at end of file
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH v3 1/4] MIPS: Lonngson64: Copy kernel command line from arcs_cmdline
  2017-11-15  3:11 ` [PATCH v3 1/4] MIPS: Lonngson64: Copy kernel command line from arcs_cmdline Jiaxun Yang
                     ` (2 preceding siblings ...)
  2017-11-15  3:11   ` [PATCH v3 4/4] MIPS: Loongson64: Load platform device during boot Jiaxun Yang
@ 2017-11-16  4:22   ` Huacai Chen
  3 siblings, 0 replies; 14+ messages in thread
From: Huacai Chen @ 2017-11-16  4:22 UTC (permalink / raw)
  To: Jiaxun Yang; +Cc: Ralf Baechle, Linux MIPS Mailing List, linux-kernel

Hi, Ralf and James,

Why xxx@lemote.com is always denied by mail.linux-mips.org?

Huacai

On Wed, Nov 15, 2017 at 11:11 AM, Jiaxun Yang <jiaxun.yang@flygoat.com> wrote:
> Since lemote-2f/marchtype.c need to get cmdline from loongson.h
> this patch simply copy kernel command line from arcs_cmdline
> to fix that issue.
>
> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> ---
>  arch/mips/include/asm/mach-loongson64/loongson.h | 6 ++++++
>  arch/mips/loongson64/common/cmdline.c            | 7 +++++++
>  2 files changed, 13 insertions(+)
>
> diff --git a/arch/mips/include/asm/mach-loongson64/loongson.h b/arch/mips/include/asm/mach-loongson64/loongson.h
> index c68c0cc879c6..1edf3a484e6a 100644
> --- a/arch/mips/include/asm/mach-loongson64/loongson.h
> +++ b/arch/mips/include/asm/mach-loongson64/loongson.h
> @@ -45,6 +45,12 @@ static inline void prom_init_uart_base(void)
>  #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 --git a/arch/mips/loongson64/common/cmdline.c b/arch/mips/loongson64/common/cmdline.c
> index 01fbed137028..49e172184e15 100644
> --- a/arch/mips/loongson64/common/cmdline.c
> +++ b/arch/mips/loongson64/common/cmdline.c
> @@ -21,6 +21,11 @@
>
>  #include <loongson.h>
>
> +/* the kernel command line copied from arcs_cmdline */
> +#include <linux/export.h>
> +char loongson_cmdline[COMMAND_LINE_SIZE];
> +EXPORT_SYMBOL(loongson_cmdline);
> +
>  void __init prom_init_cmdline(void)
>  {
>         int prom_argc;
> @@ -45,4 +50,6 @@ void __init prom_init_cmdline(void)
>         }
>
>         prom_init_machtype();
> +       /* copy arcs_cmdline into loongson_cmdline */
> +       strncpy(loongson_cmdline, arcs_cmdline, COMMAND_LINE_SIZE);
>  }
> --
> 2.14.1
>
>

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2017-11-16  4:22 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-11-12  6:36 [PATCH 1/4] MIPS: Lonngson64: Copy kernel command line from arcs_cmdline Since lemte-2f/marchtype.c need to get cmdline from loongson.h this patch simply copy kernel command line from arcs_cmdline to fix that issue jiaxun.yang
2017-11-12  6:36 ` [PATCH 2/4] MIPS: Loongson64: lemote-2f move ec_kb3310b.h to include dir and clean up To operate EC from platform driver, this head file need able to be include from anywhere. This patch just move ec_kb3310b.h to include dir and clean up ec_kb3310b.h jiaxun.yang
2017-11-13 14:27   ` Ralf Baechle
2017-11-12  6:36 ` [PATCH 3/4] MIPS: Loongson64: Yeeloong add platform driver Yeeloong is a laptop with a MIPS Loongson 2F processor, AMD CS5536 chipset, and KB3310B controller jiaxun.yang
2017-11-14 13:21   ` Ralf Baechle
2017-11-14 13:35   ` Ralf Baechle
2017-11-12  6:36 ` [PATCH 4/4] MIPS: Loongson64: Load platform device during boot This patch just add pdev during boot to load the platform driver jiaxun.yang
2017-11-14 13:29   ` Ralf Baechle
2017-11-13 14:21 ` [PATCH 1/4] MIPS: Lonngson64: Copy kernel command line from arcs_cmdline Since lemte-2f/marchtype.c need to get cmdline from loongson.h this patch simply copy kernel command line from arcs_cmdline to fix that issue Ralf Baechle
2017-11-15  3:11 ` [PATCH v3 1/4] MIPS: Lonngson64: Copy kernel command line from arcs_cmdline Jiaxun Yang
2017-11-15  3:11   ` [PATCH v3 2/4] MIPS: Loongson64: lemote-2f move ec_kb3310b.h to include dir and clean up Jiaxun Yang
2017-11-15  3:11   ` [PATCH v3 3/4] MIPS: Loongson64: Yeeloong add platform driver Jiaxun Yang
2017-11-15  3:11   ` [PATCH v3 4/4] MIPS: Loongson64: Load platform device during boot Jiaxun Yang
2017-11-16  4:22   ` [PATCH v3 1/4] MIPS: Lonngson64: Copy kernel command line from arcs_cmdline Huacai Chen

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.