linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Add YeeLoong support v6
@ 2017-12-26  3:25 Jiaxun Yang
  2017-12-26  3:25 ` [PATCH v6 1/4] MIPS: Loongson64: lemote-2f move ec_kb3310b.h to include dir and clean up Jiaxun Yang
                   ` (3 more replies)
  0 siblings, 4 replies; 8+ messages in thread
From: Jiaxun Yang @ 2017-12-26  3:25 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: James Hogan, Huacai CHen, linux-mips, linux-kernel

Change since v5:
Use arcs_cmdline instead of loongson_cmdline
Fix GPL copyright issues


Change since v4:
Use SPDX ids copyright header

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

* [PATCH v6 1/4] MIPS: Loongson64: lemote-2f move ec_kb3310b.h to include dir and clean up
  2017-12-26  3:25 Add YeeLoong support v6 Jiaxun Yang
@ 2017-12-26  3:25 ` Jiaxun Yang
  2018-01-24 11:49   ` James Hogan
  2017-12-26  3:26 ` [PATCH v6 2/4] MIPS: Loongson64: Yeeloong add platform driver Jiaxun Yang
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 8+ messages in thread
From: Jiaxun Yang @ 2017-12-26  3:25 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: James Hogan, Huacai CHen, 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.15.1

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

* [PATCH v6 2/4] MIPS: Loongson64: Yeeloong add platform driver
  2017-12-26  3:25 Add YeeLoong support v6 Jiaxun Yang
  2017-12-26  3:25 ` [PATCH v6 1/4] MIPS: Loongson64: lemote-2f move ec_kb3310b.h to include dir and clean up Jiaxun Yang
@ 2017-12-26  3:26 ` Jiaxun Yang
  2018-01-24 11:58   ` James Hogan
  2017-12-26  3:26 ` [PATCH v6 3/4] MIPS: Loongson64: Load platform device during boot Jiaxun Yang
  2017-12-26  3:26 ` [PATCH v6 4/4] MAINTAINERS: Add entry for Lemote YeeLoong Extra Driver Jiaxun Yang
  3 siblings, 1 reply; 8+ messages in thread
From: Jiaxun Yang @ 2017-12-26  3:26 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: James Hogan, Huacai CHen, 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 | 1141 +++++++++++++++++++++++++++++++
 3 files changed, 1163 insertions(+)
 create mode 100755 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 100755
index 000000000000..dc2189e1df26
--- /dev/null
+++ b/drivers/platform/mips/yeeloong_laptop.c
@@ -0,0 +1,1141 @@
+/* SPDX-License-Identifier: GPL */
+
+/*
+ * Driver for YeeLoong laptop extras
+ *
+ *  Copyright (C) 2017 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.
+ *
+ */
+
+#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 <asm/setup.h>		/* for arcs_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(arcs_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.15.1

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

* [PATCH v6 3/4] MIPS: Loongson64: Load platform device during boot
  2017-12-26  3:25 Add YeeLoong support v6 Jiaxun Yang
  2017-12-26  3:25 ` [PATCH v6 1/4] MIPS: Loongson64: lemote-2f move ec_kb3310b.h to include dir and clean up Jiaxun Yang
  2017-12-26  3:26 ` [PATCH v6 2/4] MIPS: Loongson64: Yeeloong add platform driver Jiaxun Yang
@ 2017-12-26  3:26 ` Jiaxun Yang
  2018-01-24 13:18   ` James Hogan
  2017-12-26  3:26 ` [PATCH v6 4/4] MAINTAINERS: Add entry for Lemote YeeLoong Extra Driver Jiaxun Yang
  3 siblings, 1 reply; 8+ messages in thread
From: Jiaxun Yang @ 2017-12-26  3:26 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: James Hogan, Huacai CHen, 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 | 25 +++++++++++++++++++++++++
 2 files changed, 26 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..e0007f6c456a
--- /dev/null
+++ b/arch/mips/loongson64/lemote-2f/platform.c
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* 
+* Copyright (C) 2017 Jiaxun Yang <jiaxun.yang@flygoat.com>
+*
+*/
+
+#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)
+{
+	if (mips_machtype != MACH_LEMOTE_YL2F89)
+		return -ENODEV;
+
+	return platform_device_register(&yeeloong_pdev);
+}
+
+arch_initcall(lemote2f_platform_init);
-- 
2.15.1

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

* [PATCH v6 4/4] MAINTAINERS: Add entry for Lemote YeeLoong Extra Driver
  2017-12-26  3:25 Add YeeLoong support v6 Jiaxun Yang
                   ` (2 preceding siblings ...)
  2017-12-26  3:26 ` [PATCH v6 3/4] MIPS: Loongson64: Load platform device during boot Jiaxun Yang
@ 2017-12-26  3:26 ` Jiaxun Yang
  3 siblings, 0 replies; 8+ messages in thread
From: Jiaxun Yang @ 2017-12-26  3:26 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: James Hogan, Huacai CHen, linux-mips, linux-kernel, Jiaxun Yang

Add myself as a maintainer of Lemote YeeLoong Extra driver

Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 MAINTAINERS | 6 ++++++
 1 file changed, 6 insertions(+)
 mode change 100644 => 100755 MAINTAINERS

diff --git a/MAINTAINERS b/MAINTAINERS
old mode 100644
new mode 100755
index a6e86e20761e..5a7c0d4b233a
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7873,6 +7873,12 @@ W:	http://legousb.sourceforge.net/
 S:	Maintained
 F:	drivers/usb/misc/legousbtower.c
 
+Lemote YeeLoong EXTRAS DRIVER
+M:	Jiaxun Yang <jiaxun.yang@flygoat.com>
+L:	linux-mips@linux-mips.org
+S:	Maintained
+F:	drivers/platform/mips/yeeloong_laptop.c
+
 LG2160 MEDIA DRIVER
 M:	Michael Krufky <mkrufky@linuxtv.org>
 L:	linux-media@vger.kernel.org
-- 
2.15.1

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

* Re: [PATCH v6 1/4] MIPS: Loongson64: lemote-2f move ec_kb3310b.h to include dir and clean up
  2017-12-26  3:25 ` [PATCH v6 1/4] MIPS: Loongson64: lemote-2f move ec_kb3310b.h to include dir and clean up Jiaxun Yang
@ 2018-01-24 11:49   ` James Hogan
  0 siblings, 0 replies; 8+ messages in thread
From: James Hogan @ 2018-01-24 11:49 UTC (permalink / raw)
  To: Jiaxun Yang; +Cc: Ralf Baechle, Huacai CHen, linux-mips, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 16731 bytes --]

On Tue, Dec 26, 2017 at 11:25:59AM +0800, Jiaxun Yang wrote:
> 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.

The grammar could be improved, and also please avoid referring to the
patch, just say what the patch does, e.g.

To operate the EC from its platform driver, the ec_kb3310b.h header
needs to be able to be included from outside of the loongson64
directory. Move ec_kb3310b.h to asm/mach-loongson64 and clean it up by
doing X, Y and Z.

> 
> 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 ---------------------

For review purposes please separate moving the file from cleaning it up.

Cheers
James

>  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.15.1
> 

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v6 2/4] MIPS: Loongson64: Yeeloong add platform driver
  2017-12-26  3:26 ` [PATCH v6 2/4] MIPS: Loongson64: Yeeloong add platform driver Jiaxun Yang
@ 2018-01-24 11:58   ` James Hogan
  0 siblings, 0 replies; 8+ messages in thread
From: James Hogan @ 2018-01-24 11:58 UTC (permalink / raw)
  To: Jiaxun Yang; +Cc: Ralf Baechle, Huacai CHen, linux-mips, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 2026 bytes --]

On Tue, Dec 26, 2017 at 11:26:00AM +0800, Jiaxun Yang wrote:
> diff --git a/drivers/platform/mips/yeeloong_laptop.c b/drivers/platform/mips/yeeloong_laptop.c
> new file mode 100755

Checkpatch complains about having the execute permission set on this
file.

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

I can't help thinking it would be better to separate this into separate
drivers for each part (backlight, power supply etc), and move them into
the appropriate driver directories (drivers/power/supply,
drivers/video/backlight etc). That way each part would get proper review
from the appropriate maintainers (or at least they should be Cc'd).

Is there a particular reason for it to be a single driver?

Cheers
James

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v6 3/4] MIPS: Loongson64: Load platform device during boot
  2017-12-26  3:26 ` [PATCH v6 3/4] MIPS: Loongson64: Load platform device during boot Jiaxun Yang
@ 2018-01-24 13:18   ` James Hogan
  0 siblings, 0 replies; 8+ messages in thread
From: James Hogan @ 2018-01-24 13:18 UTC (permalink / raw)
  To: Jiaxun Yang; +Cc: Ralf Baechle, Huacai CHen, linux-mips, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 1935 bytes --]

On Tue, Dec 26, 2017 at 11:26:01AM +0800, Jiaxun Yang wrote:
> 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 | 25 +++++++++++++++++++++++++
>  2 files changed, 26 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..e0007f6c456a
> --- /dev/null
> +++ b/arch/mips/loongson64/lemote-2f/platform.c
> @@ -0,0 +1,25 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/* 

Trailing whitespace

> +* Copyright (C) 2017 Jiaxun Yang <jiaxun.yang@flygoat.com>
> +*
> +*/

Checkpatch complains about missing spaces to align the '*' on each line
of this block comment.

Cheers
James

> +
> +#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)
> +{
> +	if (mips_machtype != MACH_LEMOTE_YL2F89)
> +		return -ENODEV;
> +
> +	return platform_device_register(&yeeloong_pdev);
> +}
> +
> +arch_initcall(lemote2f_platform_init);
> -- 
> 2.15.1
> 

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

end of thread, other threads:[~2018-01-24 13:19 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-12-26  3:25 Add YeeLoong support v6 Jiaxun Yang
2017-12-26  3:25 ` [PATCH v6 1/4] MIPS: Loongson64: lemote-2f move ec_kb3310b.h to include dir and clean up Jiaxun Yang
2018-01-24 11:49   ` James Hogan
2017-12-26  3:26 ` [PATCH v6 2/4] MIPS: Loongson64: Yeeloong add platform driver Jiaxun Yang
2018-01-24 11:58   ` James Hogan
2017-12-26  3:26 ` [PATCH v6 3/4] MIPS: Loongson64: Load platform device during boot Jiaxun Yang
2018-01-24 13:18   ` James Hogan
2017-12-26  3:26 ` [PATCH v6 4/4] MAINTAINERS: Add entry for Lemote YeeLoong Extra Driver Jiaxun Yang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).