From 9877848b92b8829cb88d8aa611bc1ba764c25102 Mon Sep 17 00:00:00 2001 From: Wentao Guan Date: Fri, 3 Jul 2026 21:27:28 +0800 Subject: [PATCH 1/5] ACPI: EC: workaround EC not work in phytium deepin inclusion category: bugfix ACPI: EC: remove clean up handlers on probe failure in acpi_ec_setup Signed-off-by: huangbibo Signed-off-by: Wentao Guan --- drivers/acpi/ec.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index f94cddbbb55ac..10a30e9e7c1f1 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -1653,7 +1653,12 @@ static int acpi_ec_setup(struct acpi_ec *ec, struct acpi_device *device, bool ca ret = ec_install_handlers(ec, device, call_reg); if (ret) { +#ifdef CONFIG_ARCH_PHYTIUM + if (read_cpuid_implementor() != ARM_CPU_IMP_PHYTIUM) + ec_remove_handlers(ec); +#else ec_remove_handlers(ec); +#endif if (ec == first_ec) first_ec = NULL; From 4fcf003372fd438ac8d4f921c6405b5a7d47e672 Mon Sep 17 00:00:00 2001 From: Wentao Guan Date: Fri, 3 Jul 2026 21:27:28 +0800 Subject: [PATCH 2/5] uos: phytium: ec: integrate EC/laptop driver over PIO port uos inclusion category: feature Bring back the IT8528 EC and laptop platform support, switching the EC transport from the removed Phytium LPC path to the Phytium PIO path. This provides battery, AC, lid, hotkey, backlight and hwmon support for Phytium laptop platforms. based on these commits: commit 4c3ee4f195ca7 uos: phyt/ec_it8528: replace readb/writeb with inb/outb [T381729] commit 9953278324c81 uos: phytium/lpc: Calc iobase and offsets in one function [T381729] commit 7bca99aa60b9b phytium/lpc: Support various lpc address/offset [T366853] commit ba88c0d55b8f3 uos: phyt: port UOS_PHYTIUM_DESKTOP_SUPPORT to V25 [T366853] Assisted-by: kimi-cli:kimi-k2.7 code # reformat patch Signed-off-by: huangbibo Signed-off-by: hmy Signed-off-by: wenlunpeng Signed-off-by: Wentao Guan --- MAINTAINERS | 7 + .../configs/deepin_arm64_desktop_defconfig | 4 + drivers/Kconfig | 2 + drivers/Makefile | 2 + drivers/uos/Kconfig | 5 + drivers/uos/Makefile | 3 + drivers/uos/phyt/Kconfig | 35 + drivers/uos/phyt/Makefile | 6 + drivers/uos/phyt/ec/Makefile | 7 + drivers/uos/phyt/ec/ec_it8528.c | 355 +++++ drivers/uos/phyt/ec/ec_it8528.h | 367 +++++ drivers/uos/phyt/ec/ec_sensor.c | 145 ++ drivers/uos/phyt/ec/phyt_laptop.c | 1363 +++++++++++++++++ include/linux/classtypes.h | 5 + lib/classtypes.c | 52 + 15 files changed, 2358 insertions(+) create mode 100644 drivers/uos/Kconfig create mode 100644 drivers/uos/Makefile create mode 100644 drivers/uos/phyt/Kconfig create mode 100644 drivers/uos/phyt/Makefile create mode 100644 drivers/uos/phyt/ec/Makefile create mode 100644 drivers/uos/phyt/ec/ec_it8528.c create mode 100644 drivers/uos/phyt/ec/ec_it8528.h create mode 100644 drivers/uos/phyt/ec/ec_sensor.c create mode 100644 drivers/uos/phyt/ec/phyt_laptop.c diff --git a/MAINTAINERS b/MAINTAINERS index 7b2018963ae38..76115232115b0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -17570,6 +17570,13 @@ F: drivers/usb/phytium/phytium_usb_v2* F: drivers/usb/typec/role-switch-phytium.c F: arch/arm64/boot/dts/phytium/* F: drivers/gpio/gpio-phytium* +F: drivers/uos/* +F: drivers/uos/phyt/* +F: drivers/uos/phyt/ec/* +F: include/linux/classtypes.h +F: include/linux/cputypes.h +F: lib/classtypes.c +F: lib/cputypes.c QAT DRIVER M: Giovanni Cabiddu diff --git a/arch/arm64/configs/deepin_arm64_desktop_defconfig b/arch/arm64/configs/deepin_arm64_desktop_defconfig index c599bd3208499..f3c423a5faf48 100644 --- a/arch/arm64/configs/deepin_arm64_desktop_defconfig +++ b/arch/arm64/configs/deepin_arm64_desktop_defconfig @@ -818,6 +818,10 @@ CONFIG_MOXTET=m CONFIG_HISILICON_LPC=y CONFIG_IMX_WEIM=y CONFIG_PHYTIUM_PIO=y +CONFIG_UOS_PHYTIUM_DESKTOP_SUPPORT=y +CONFIG_PHYTIUM_EC=y +CONFIG_PHYTIUM_LAPTOP=y +CONFIG_SERIO_I8042=y CONFIG_QCOM_SSC_BLOCK_BUS=y CONFIG_SUNXI_RSB=m CONFIG_TEGRA_ACONNECT=m diff --git a/drivers/Kconfig b/drivers/Kconfig index 83ff63c256b71..0d6284e2bc485 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -245,4 +245,6 @@ source "drivers/cdx/Kconfig" source "drivers/cpuinspect/Kconfig" +source "drivers/uos/Kconfig" + endmenu diff --git a/drivers/Makefile b/drivers/Makefile index 99dbd33629138..c9c59f091565a 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -199,4 +199,6 @@ obj-$(CONFIG_HTE) += hte/ obj-$(CONFIG_DRM_ACCEL) += accel/ obj-$(CONFIG_CDX_BUS) += cdx/ +obj-y += uos/ + obj-$(CONFIG_S390) += s390/ diff --git a/drivers/uos/Kconfig b/drivers/uos/Kconfig new file mode 100644 index 0000000000000..5d7eb0ce07a52 --- /dev/null +++ b/drivers/uos/Kconfig @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0 +menu "UOS Driver config" + +source "drivers/uos/phyt/Kconfig" +endmenu diff --git a/drivers/uos/Makefile b/drivers/uos/Makefile new file mode 100644 index 0000000000000..bf91eeaf69a90 --- /dev/null +++ b/drivers/uos/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 + +obj-$(CONFIG_UOS_PHYTIUM_DESKTOP_SUPPORT) += phyt/ diff --git a/drivers/uos/phyt/Kconfig b/drivers/uos/phyt/Kconfig new file mode 100644 index 0000000000000..2ed2832b0f5bf --- /dev/null +++ b/drivers/uos/phyt/Kconfig @@ -0,0 +1,35 @@ +menuconfig UOS_PHYTIUM_DESKTOP_SUPPORT + bool "phytium desktop drivers/fixups provided by UOS" + default n + help + This option enables a collection of UOS-supplied drivers and + quirks for Phytium desktop and laptop platforms. These drivers + are not part of the standard upstream kernel and should only be + enabled when running on supported Phytium systems. + +if UOS_PHYTIUM_DESKTOP_SUPPORT + +config PHYTIUM_EC + bool "phytium ec support" + depends on PHYTIUM_PIO + default n + help + Enable support for the IT8528 Embedded Controller found on some + Phytium laptop platforms. This driver communicates with the EC + over the Phytium PIO (Programmed I/O) path and is required by the + Phytium laptop driver for battery, lid and hotkey support. + +config PHYTIUM_LAPTOP + bool "phytium laptop support" + depends on PHYTIUM_EC + select POWER_SUPPLY + select BACKLIGHT_CLASS_DEVICE + select INPUT_SPARSEKMAP + select HWMON + help + Enable laptop-specific support for Phytium platforms. This + provides power-supply reporting (AC and battery), backlight + control, lid status and Fn hotkey handling through the IT8528 + embedded controller. + +endif diff --git a/drivers/uos/phyt/Makefile b/drivers/uos/phyt/Makefile new file mode 100644 index 0000000000000..f07f83de9ed38 --- /dev/null +++ b/drivers/uos/phyt/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Makefile for the Phytium notebook EC/laptop drivers. +# + +obj-$(CONFIG_UOS_PHYTIUM_DESKTOP_SUPPORT) += ec/ diff --git a/drivers/uos/phyt/ec/Makefile b/drivers/uos/phyt/ec/Makefile new file mode 100644 index 0000000000000..99be4fe85b370 --- /dev/null +++ b/drivers/uos/phyt/ec/Makefile @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Makefile for the Phytium notebook EC/laptop drivers. +# + +obj-$(CONFIG_PHYTIUM_EC) += ec_it8528.o +obj-$(CONFIG_PHYTIUM_LAPTOP) += phyt_laptop.o ec_sensor.o diff --git a/drivers/uos/phyt/ec/ec_it8528.c b/drivers/uos/phyt/ec/ec_it8528.c new file mode 100644 index 0000000000000..6bdb606071e9d --- /dev/null +++ b/drivers/uos/phyt/ec/ec_it8528.c @@ -0,0 +1,355 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * EC (Embedded Controller) for phytium platform + * + * 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 +#include +#include +#include +#include "ec_it8528.h" + +/* This spinlock is dedicated for 62&66 ports and super io port access. */ +DEFINE_SPINLOCK(index_access_lock); + +static int send_ec_command(unsigned char command) +{ + int timeout, ret = 0; + + timeout = EC_SEND_TIMEOUT; + while ((inb(EC_STS_PORT) & EC_IBF) && --timeout) + udelay(1); + if (!timeout) { + pr_err("Timeout while sending command 0x%02x to EC!\n", command); + ret = -1; + goto out; + } + + outb(command, EC_CMD_PORT); + +out: + return ret; +} + +static int send_ec_data(unsigned char data) +{ + int timeout, ret = 0; + + timeout = EC_SEND_TIMEOUT; + while ((inb(EC_STS_PORT) & EC_IBF) && --timeout) + udelay(1); + if (!timeout) { + pr_err("Timeout while sending data 0x%02x to EC!\n", data); + ret = -1; + goto out; + } + + outb(data, EC_DAT_PORT); + +out: + return ret; +} + +static unsigned char recv_ec_data(void) +{ + int timeout; + unsigned char data; + + timeout = EC_RECV_TIMEOUT; + while (!(inb(EC_STS_PORT) & EC_OBF) && --timeout) + udelay(1); + if (!timeout) { + pr_err("Timeout while receiving data from EC! status 0x%x.\n", inb(EC_STS_PORT)); + data = 0; + goto skip_data; + } + + data = inb(EC_DAT_PORT); + +skip_data: + return data; +} + +unsigned char it8528_read(unsigned char index) +{ + unsigned char value = 0; + unsigned long flags; + int ret = 0; + + spin_lock_irqsave(&index_access_lock, flags); + ret = send_ec_command(CMD_READ_EC); + if (ret < 0) { + pr_err("Send command fail!\n"); + value = 0; + goto out; + } + ret = send_ec_data(index); + if (ret < 0) { + pr_err("Send data fail!\n"); + value = 0; + goto out; + } + value = recv_ec_data(); +out: + spin_unlock_irqrestore(&index_access_lock, flags); + + return value; +} +EXPORT_SYMBOL(it8528_read); + +unsigned char it8528_read_all(unsigned char command, unsigned char index) +{ + unsigned char value = 0; + unsigned long flags; + int ret = 0; + + spin_lock_irqsave(&index_access_lock, flags); + ret = send_ec_command(command); + if (ret < 0) { + pr_err("Send command fail!\n"); + goto out; + } + ret = send_ec_data(index); + if (ret < 0) { + pr_err("Send data fail!\n"); + goto out; + } + value = recv_ec_data(); +out: + spin_unlock_irqrestore(&index_access_lock, flags); + + return value; +} +EXPORT_SYMBOL(it8528_read_all); + +unsigned char it8528_read_noindex(unsigned char command) +{ + unsigned char value = 0; + unsigned long flags; + int ret = 0; + + spin_lock_irqsave(&index_access_lock, flags); + ret = send_ec_command(command); + if (ret < 0) { + pr_err("Send command fail!\n"); + goto out; + } + value = recv_ec_data(); +out: + spin_unlock_irqrestore(&index_access_lock, flags); + + return value; +} +EXPORT_SYMBOL(it8528_read_noindex); + +int it8528_write(unsigned char index, unsigned char data) +{ + int ret = 0; + unsigned long flags; + + spin_lock_irqsave(&index_access_lock, flags); + ret = send_ec_command(CMD_WRITE_EC); + if (ret < 0) { + pr_err("Send command 0x81 fail!\n"); + goto out; + } + ret = send_ec_data(index); + if (ret < 0) { + pr_err("Send index 0x%x fail!\n", index); + goto out; + } + + ret = send_ec_data(data); + if (ret < 0) + pr_err("Send data 0x%x fail!\n", data); +out: + spin_unlock_irqrestore(&index_access_lock, flags); + + return ret; +} +EXPORT_SYMBOL(it8528_write); + +int it8528_write_all(unsigned char command, unsigned char index, unsigned char data) +{ + unsigned long flags; + + spin_lock_irqsave(&index_access_lock, flags); + send_ec_command(command); + send_ec_data(index); + send_ec_data(data); + spin_unlock_irqrestore(&index_access_lock, flags); + + return 0; +} +EXPORT_SYMBOL(it8528_write_all); + +int it8528_write_noindex(unsigned char command, unsigned char data) +{ + unsigned long flags; + + spin_lock_irqsave(&index_access_lock, flags); + send_ec_command(command); + send_ec_data(data); + spin_unlock_irqrestore(&index_access_lock, flags); + + return 0; +} +EXPORT_SYMBOL(it8528_write_noindex); + +bool it8528_get_ec_ibf_flags(void) +{ + return !!(inb(EC_STS_PORT) & EC_IBF); +} +EXPORT_SYMBOL(it8528_get_ec_ibf_flags); + +bool it8528_get_ec_obf_flags(void) +{ + return !!(inb(EC_STS_PORT) & EC_OBF); +} +EXPORT_SYMBOL(it8528_get_ec_obf_flags); + +bool it8528_get_ec_evt_flags(void) +{ + return !!(inb(EC_STS_PORT) & EC_SCI_EVT); +} +EXPORT_SYMBOL(it8528_get_ec_evt_flags); + +int it8528_query_get_event_num(void) +{ + unsigned char value = 0; + unsigned long flags; + int ret = 0; + unsigned int timeout; + + spin_lock_irqsave(&index_access_lock, flags); + ret = send_ec_command(CMD_GET_EVENT_NUM); + if (ret < 0) { + pr_err("Send command fail!\n"); + goto out; + } + + /* check if the command is received by ec */ + timeout = EC_CMD_TIMEOUT; + while ((inb(EC_STS_PORT) & EC_IBF) && timeout--) + udelay(1); + if (timeout <= 0) { + pr_err("EC QUERY SEQ: deadable error : timeout...\n"); + ret = -EINVAL; + goto out; + } + + value = recv_ec_data(); + spin_unlock_irqrestore(&index_access_lock, flags); + return value; +out: + spin_unlock_irqrestore(&index_access_lock, flags); + return ret; +} +EXPORT_SYMBOL(it8528_query_get_event_num); + +int it8528_query_clean_event(void) +{ + int ret; + + while (inb(EC_STS_PORT) & EC_SCI_EVT) { + ret = it8528_query_get_event_num(); + if (ret <= 0) { + pr_info("Clean sci event done!\n"); + return ret; + } + } + + return 0; +} +EXPORT_SYMBOL(it8528_query_clean_event); + +void it8528_ec_event_int_enable(void) +{ + unsigned long flags; + int ret = 0; + unsigned int timeout; + + spin_lock_irqsave(&index_access_lock, flags); + + ret = send_ec_command(CMD_ENABLE_EVENT_EC); + if (ret < 0) { + pr_err("Send command fail!\n"); + goto out; + } + + /* check if the command is received by ec */ + timeout = EC_CMD_TIMEOUT; + while ((inb(EC_STS_PORT) & EC_IBF) && timeout--) + udelay(1); + if (timeout <= 0) { + pr_err("EC ENABLE EVENT INTERRUPT: deadable error : timeout...\n"); + ret = -EINVAL; + goto out; + } +out: + spin_unlock_irqrestore(&index_access_lock, flags); +} +EXPORT_SYMBOL(it8528_ec_event_int_enable); + +void it8528_ec_event_int_disable(void) +{ + unsigned long flags; + int ret = 0; + unsigned int timeout; + + spin_lock_irqsave(&index_access_lock, flags); + + ret = send_ec_command(CMD_DISABLE_EVENT_EC); + if (ret < 0) { + pr_err("Send command fail!\n"); + goto out; + } + + /* check if the command is received by ec */ + timeout = EC_CMD_TIMEOUT; + while ((inb(EC_STS_PORT) & EC_IBF) && timeout--) + udelay(1); + + if (timeout <= 0) { + pr_err("EC ENABLE EVENT INTERRUPT: deadable error : timeout...\n"); + ret = -EINVAL; + goto out; + } + +out: + spin_unlock_irqrestore(&index_access_lock, flags); +} +EXPORT_SYMBOL(it8528_ec_event_int_disable); + +int it8528_init(void) +{ + if (unlikely(!check_cpu_type())) { + pr_err("Stop init on non-Phytium CPU!\n"); + return -ENODEV; + } + return 0; +} +EXPORT_SYMBOL(it8528_init); + +int lpc_ec_interrupt_occurs(void) +{ + int data; + + data = phytium_pio_get_int_status(); + + if (data & EC_EVENT_BIT) + return 1; + return 0; +} +EXPORT_SYMBOL(lpc_ec_interrupt_occurs); + +void lpc_interrupt_clear_all(void) +{ + phytium_pio_clear_interrupt(0); +} +EXPORT_SYMBOL(lpc_interrupt_clear_all); diff --git a/drivers/uos/phyt/ec/ec_it8528.h b/drivers/uos/phyt/ec/ec_it8528.h new file mode 100644 index 0000000000000..bb2dd53a7d9ee --- /dev/null +++ b/drivers/uos/phyt/ec/ec_it8528.h @@ -0,0 +1,367 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * EC (Embedded Controller) IT8528 device driver header for phytium czc B20 + * + * EC relative header file. All the EC registers should be defined here. + * + * 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 you option) and later version. + */ + +#ifndef __EC_IT8528_H__ +#define __EC_IT8528_H__ +#include +#include "../../../bus/phytium_pio.h" + +#define EC_VERSION "1.0" + + +#define EC_EVENT_BIT (1 << 11) +#define I8042_KEY_BIT (1 << 1) +#define I8042_TOUCH_BIT (1 << 12) + +extern u32 phytium_pio_get_int_status(void); + +/* This spinlock is dedicated for 62&66 ports and super io port access. */ +extern spinlock_t i8042_lock; +extern spinlock_t index_access_lock; + +/* + * The following registers are determined by the EC index configureation. + * 1. fill the PORT_INDEX as EC register. + * 2. fill the PORT_DATA as EC register write data or get the data from it. + */ +/* base address for io access for Notebook platform */ +#define SIO_INDEX_PORT 0x4E +#define SIO_DATA_PORT 0x4F + +/* + * EC delay time 500us for register and status access + * Unit : us + */ +#define EC_REG_DELAY 30000 +#define EC_CMD_TIMEOUT 0x1000 +#define EC_SEND_TIMEOUT 0xffff +#define EC_RECV_TIMEOUT 0xffff + +/* + * EC access port for with Host communication. + */ +#define EC_CMD_PORT 0x66 +#define EC_STS_PORT 0x66 +#define EC_DAT_PORT 0x62 + +/* + * ACPI legacy commands. + */ +#define CMD_READ_EC 0x80 /* Read EC command. */ +#define CMD_WRITE_EC 0x81 /* Write EC command. */ +#define CMD_GET_EVENT_NUM 0x84 /* Query EC command, for get ec event number. */ +#define CMD_ENABLE_EVENT_EC 0x86 /* Enable EC event interrupt. */ +#define CMD_DISABLE_EVENT_EC 0x87 /* Disable EC event interrupt. */ + +/* + * ACPI OEM commands. + */ + /* Reset and poweroff the machine auto-clear: rd/wr */ +#define CMD_RESET 0x4E +enum { + RESET_OFF = 0, + RESET_ON, + PWROFF_ON, + STR_ON, + STANDBY_ON +}; + +#define CMD_EC_VERSION 0x4F /* EC Version OEM command: 36 Bytes */ + +/* + * Used ACPI legacy command 80h to do active. + */ +/* >>> Read/Write temperature & fan index for ACPI 80h/81h command. */ + /* Current CPU temperature value, Read and Write(81h command). */ +#define INDEX_CPU_TEMP_VALUE 0x98 + /* Current GPU temperature value, Read and Write(81h command). */ +#define INDEX_GPU_TEMP_VALUE 0x9A + + /* Fan speed maxinum levels supported. Defaut is 6. */ +#define INDEX_FAN_MAXSPEED_LEVEL 0x5B +#define INDEX_FAN_SPEED_LEVEL 0x5C /* FAn speed level. [0,5] or [0x06, 0x38]*/ + /* Fan control mode, 0 = by EC, 1 = by Host.*/ +#define INDEX_FAN_CTRLMOD 0x5D +enum { + FAN_CTRL_BYEC = 0, + FAN_CTRL_BYHOST +}; +#define INDEX_FAN_STSCTRL 0x5E /* Fan status/control, 0 = stop, 1 = run. */ +enum { + FAN_STSCTRL_OFF = 0, + FAN_STSCTRL_ON +}; + /* Fan error status, 0 = no error, 1 = has error. */ +#define INDEX_FAN_ERRSTS 0x5F +enum { + FAN_ERRSTS_NO = 0, + FAN_ERRSTS_HAS +}; + +#define INDEX_CPU_FAN_SPEED_LOW 0xF2 /* Fan speed low byte.*/ +#define INDEX_CPU_FAN_SPEED_HIGH 0xF3 /* Fan speed high byte. */ +#define INDEX_GPU_FAN_SPEED_LOW 0xF4 /* Fan speed low byte.*/ +#define INDEX_GPU_FAN_SPEED_HIGH 0xF5 /* Fan speed high byte. */ +/* <<< End Temp & Fan */ + +/* >>> Read/Write LCD backlight information/control index for ACPI 80h/81h command. */ + /* LCD backlight control mode: 0 = by EC, 1 = by HOST */ +#define INDEX_BACKLIGHT_CTRLMODE 0x57 +enum { + BACKLIGHT_CTRL_BYEC = 0, + BACKLIGHT_CTRL_BYHOST +}; + /* LCD backlight status or control: 0 = turn off, 1 = turn on */ +#define INDEX_BACKLIGHT_STSCTRL 0x58 +enum { + BACKLIGHT_OFF = 0, + BACKLIGHT_ON +}; +#define INDEX_DISPLAY_MAXBRIGHTNESS_LEVEL 0x59 /* LCD backlight brightness max level */ + /* 10 stages (0~9) LCD backlight brightness adjust */ +#define INDEX_DISPLAY_BRIGHTNESS_SET 0x0E + /* 10 stages (0~9) LCD backlight brightness adjust */ +#define INDEX_DISPLAY_BRIGHTNESS_GET 0x0F + +enum { + FLAG_DISPLAY_BRIGHTNESS_LEVEL_0 = 0, /* This level is backlight turn off. */ + FLAG_DISPLAY_BRIGHTNESS_LEVEL_1, + FLAG_DISPLAY_BRIGHTNESS_LEVEL_2, + FLAG_DISPLAY_BRIGHTNESS_LEVEL_3, + FLAG_DISPLAY_BRIGHTNESS_LEVEL_4, + FLAG_DISPLAY_BRIGHTNESS_LEVEL_5, + FLAG_DISPLAY_BRIGHTNESS_LEVEL_6, + FLAG_DISPLAY_BRIGHTNESS_LEVEL_7, + FLAG_DISPLAY_BRIGHTNESS_LEVEL_8, + FLAG_DISPLAY_BRIGHTNESS_LEVEL_9, + FLAG_DISPLAY_BRIGHTNESS_LEVEL_10 +}; +/* <<< End Backlight */ + +/* >>> Read battery index command */ +/* + * The reported battery die temperature. + * The temperature is expressed in units of 0.25 seconds and is updated every 2.56 seconds. + * The equation to calculate reported pack temperature is: + * Temperature = 0.1 * (256 * TEMPH + TEMPL) Kelvin + * Temperature -= 273 Degrees Celsius + * The host system has read-only access to this register pair. + */ +#define INDEX_BATTERY_VOL_LOW 0x2A /* Battery Voltage Low byte. */ +#define INDEX_BATTERY_VOL_HIGH 0x2B /* Battery Voltage High byte. */ +#define INDEX_BATTERY_CURRENT_LOW 0x2C /* Battery Current Low byte. */ +#define INDEX_BATTERY_CURRENT_HIGH 0x2D /* Battery Current High byte. */ +#define INDEX_BATTERY_AC_LOW 0x2E /* Battery AverageCurrent Low byte. */ +#define INDEX_BATTERY_AC_HIGH 0x2F /* Battery AverageCurrent High byte. */ +#define INDEX_BATTERY_CAPACITY 0x21 /* Battery RemainingCapacity percent. */ +#define INDEX_BATTERY_STATUS_LOW 0x3C /* Battery Status low byte. */ + +enum { + BIT_BATTERY_STATUS_FD = 4, /* Battery Fully Discharged Notify. 1 = Fully Discharged */ + BIT_BATTERY_STATUS_FC, /* Battery Fully Charged Notify. 1 = Fully Charged. */ + /* + * Battery Discharging mode. 0 = in charging mode, 1 = in discharging mode, + * relaxation mode, or valid charge termination has occurred. + */ + BIT_BATTERY_STATUS_DSG, + BIT_BATTERY_STATUS_INIT /* Battery Initialization. 1 = Initialization */ +}; +#define INDEX_BATTERY_STATUS 0x3C /* Battery Status byte. */ +enum { + BIT_POWER_BATEMPTY = 4, /* Battery in empty status. */ + BIT_POWER_BATFCHG = 5, /* Battery in fully charging status. */ + BIT_POWER_BATCHG = 6, /* Battery in charging status. */ +}; + +#define INDEX_BATTERY_CAP_LOW 0x24 /* Battery Capacity Low byte. */ +#define INDEX_BATTERY_CAP_HIGH 0x25 /* Battery Capacity High byte. */ +#define INDEX_BATTERY_RC_LOW 0x26 /* Battery RemainingCapacity Low byte. */ +#define INDEX_BATTERY_RC_HIGH 0x27 /* Battery RemainingCapacity High byte. */ +#define INDEX_BATTERY_ATTE_LOW 0x9C /* Battery AverageTimeToEmpty Low byte. */ +#define INDEX_BATTERY_ATTE_HIGH 0x9D /* Battery AverageTimeToEmpty High byte. */ +#define INDEX_BATTERY_ATTF_LOW 0xA4 /* Battery AverageTimeToFull Low byte. */ +#define INDEX_BATTERY_ATTF_HIGH 0xA5 /* Battery AverageTimeToFull High byte. */ +#define INDEX_BATTERY_FCC_LOW 0x24 /* Battery FullChargeCapacity Low byte. */ +#define INDEX_BATTERY_FCC_HIGH 0x25 /* Battery FullChargeCapacity High byte. */ +#define INDEX_BATTERY_CC_LOW 0xAC /* Battery ChargingCurrent Low byte. */ +#define INDEX_BATTERY_CC_HIGH 0xAD /* Battery ChargingCurrent High byte. */ +#define INDEX_BATTERY_CV_LOW 0xAA /* Battery ChargingVoltage Low byte. */ +#define INDEX_BATTERY_CV_HIGH 0xAB /* Battery ChargingVoltage High byte. */ +#define INDEX_BATTERY_TEMP_LOW 0x28 /* Battery temperature low byte. */ +#define INDEX_BATTERY_TEMP_HIGH 0x29 /* Battery temperature high byte. */ +#define INDEX_BATTERY_CYCLECNT_LOW 0xA8 /* Battery CycleCount Low byte. */ +#define INDEX_BATTERY_CYCLECNT_HIGH 0xA9 /* Battery CycleCount High byte. */ + +/* Battery static information. */ +#define INDEX_BATTERY_DC_LOW 0x38 /* Battery DesignCapacity Low byte. */ +#define INDEX_BATTERY_DC_HIGH 0x39 /* Battery DesignCapacity High byte. */ +#define INDEX_BATTERY_DV_LOW 0x3A /* Battery DesignVoltage Low byte. */ +#define INDEX_BATTERY_DV_HIGH 0x3B /* Battery DesignVoltage High byte. */ +#define INDEX_BATTERY_SN_LOW 0x3E /* Battery SerialNumber Low byte. */ +#define INDEX_BATTERY_SN_HIGH 0x3F /* Battery SerialNumber High byte. */ +/* <<< End Battery */ + +/* Phytium S3 timeout information */ +#define INDEX_POWERON_TYPE 0x0B /* Phytium EC Poweron type. */ +#define INDEX_S3_TIMEOUT_LO 0x0C /* Phytium S3 timeout Low byte. */ +#define INDEX_S3_TIMEOUT_HI 0x0D /* Phytium S3 timeout High byte. */ + +#define PHYTIUM_S3_TIMEOUT_DEFAULT 10 /* bxc timeout default 10 min */ +#define PHYTIUM_S3_TIMEOUT_FOREVER 0x0 + +#define PHYTIUM_S3_TIMEOUT_TYPE 0xAA +#define PHYTIUM_S3_NORMAL_WAKEUP_TYPE 0x55 +/* <<< End Phytium S3 */ + +#define MASK(x) (1 << x) + +#define INDEX_POWER_STATUS 0xB0 /* Read current power status. */ +enum { + BIT_POWER_ACPRES, /* AC present. */ + BIT_POWER_BATPRES, /* ZW000B Master Battery present. */ +}; + +#define INDEX_DEVICE_STATUS 0x81 /* Read Current Device Status */ +enum { + BIT_DEVICE_TP = 0, /* TouchPad status: 0 = close, 1 = open */ + BIT_DEVICE_WLAN, /* WLAN status: 0 = close, 1 = open */ + BIT_DEVICE_3G, /* 3G status: 0 = close, 1 = open */ + BIT_DEVICE_CAM, /* Camera status: 0 = close, 1 = open */ + BIT_DEVICE_MUTE, /* Mute status: 0 = close, 1 = open */ + BIT_DEVICE_LID, /* LID status: 0 = close, 1 = open */ + BIT_DEVICE_BKLIGHT, /* BackLight status: 0 = close, 1 = open */ + BIT_DEVICE_SIM /* SIM Card status: 0 = pull out, 1 = insert */ +}; + +#define INDEX_SHUTDOWN_ID 0x82 /* Read Shutdown ID */ +enum { + BIT_SHUTDNID_S45 = 0, /* in S4 or S5 */ + BIT_SHUTDNID_BATDEAD, /* Battery Dead */ + BIT_SHUTDNID_OVERHEAT, /* Over Heat */ + BIT_SHUTDNID_SYSCMD, /* System command */ + BIT_SHUTDNID_LPRESSPWN, /* Long press power button */ + BIT_SHUTDNID_PWRUNDER9V, /* Battery voltage low under 9V */ + BIT_SHUTDNID_S3, /* Entry S3 state */ + BIT_SHUTDNID_S1 /* Entry S1 state */ +}; + +#define INDEX_SYSTEM_CFG 0x82 /* Read System config */ +#define BIT_SYSCFG_TPSWITCH (1 << 0) /* TouchPad switch */ +#define BIT_SYSCFG_WLANPRES (1 << 1) /* WLAN present */ +#define BIT_SYSCFG_NB3GPRES (1 << 2) /* 3G present */ +#define BIT_SYSCFG_CAMERAPRES (1 << 3) /* Camera Present */ +#define BIT_SYSCFG_VOLCTRLEC (1 << 4) /* Volume control by EC */ +#define BIT_SYSCFG_BLCTRLEC (1 << 5) /* Backlight control by EC */ +#define BIT_SYSCFG_AUTOBRIGHT (1 << 7) /* Auto brightness */ + +#define INDEX_VOLUME_LEVEL 0xA6 /* Read Volume Level command */ +#define INDEX_VOLUME_MAXLEVEL 0xA7 /* Volume MaxLevel */ +#define VOLUME_MAX_LEVEL 0x0A /* Volume level max is 11 */ +enum { + FLAG_VOLUME_LEVEL_0 = 0, + FLAG_VOLUME_LEVEL_1, + FLAG_VOLUME_LEVEL_2, + FLAG_VOLUME_LEVEL_3, + FLAG_VOLUME_LEVEL_4, + FLAG_VOLUME_LEVEL_5, + FLAG_VOLUME_LEVEL_6, + FLAG_VOLUME_LEVEL_7, + FLAG_VOLUME_LEVEL_8, + FLAG_VOLUME_LEVEL_9, + FLAG_VOLUME_LEVEL_10 +}; + +/* Camera control */ +#define INDEX_CAM_STSCTRL 0xAA +enum { + CAM_STSCTRL_OFF = 0, + CAM_STSCTRL_ON +}; + +#define INDEX_CPU_TEMP 0x1E /* Read CPU temperature */ +#define INDEX_GPU_TEMP 0x10 /* Read GPU temperature */ + +/* EC_SC input */ +/* EC Status query, by direct read 66h port. */ +#define EC_SMI_EVT (1 << 6) /* 1 = SMI event padding */ +#define EC_SCI_EVT (1 << 5) /* 1 = SCI event padding */ +#define EC_BURST (1 << 4) /* 1 = Controller is in burst mode */ +#define EC_CMD (1 << 3) /* 1 = Byte in data register is command */ + +#define EC_IBF (1 << 1) /* 1 = Input buffer full (data ready for ec) */ +#define EC_OBF (1 << 0) /* 1 = Output buffer full (data ready for host) */ + +/* LPC Event Number from EC */ +enum { + EC_EVENT_NUM_BAT = 0xB3, /* BAT in/out */ + EC_EVENT_NUM_AC = 0xB4, /* AC in/out */ + EC_EVENT_NUM_POWERBTN = 0xB5, /* power button */ + EC_EVENT_NUM_LID = 0xD0, /* press the lid or not */ + EC_EVENT_NUM_RES1 = 0xD1, /* reserve event1 */ + EC_EVENT_NUM_RES2 = 0xD2, /* reserve event2 */ + EC_EVENT_NUM_SLEEP = 0x40, /* 0x40, Fn+F4 for entering sleep mode */ + EC_EVENT_NUM_WLAN = 0x35, /* 0x41, Fn+F6, Wlan is on or off */ + EC_EVENT_NUM_TP, /* 0x43, Fn+F5, TouchPad is on */ + EC_EVENT_NUM_SCREENLOCK, /* 0x43, Fn+F5, ScreenLock */ + /* 0x44, Fn+F3, LCD backlight brightness on or off */ + EC_EVENT_NUM_BRIGHTNESS_OFF, + /* 0x45, Fn+F1, LCD backlight brightness down adjust */ + EC_EVENT_NUM_BRIGHTNESS_DN, + /* 0x46, Fn+F2, LCD backlight brightness up adjust */ + EC_EVENT_NUM_BRIGHTNESS_UP, + EC_EVENT_NUM_DISPLAY_TOGGLE, /* 0x47, Fn+F7, Video switch(LCD/HDMI...)*/ + EC_EVENT_NUM_MICMUTE, /* 0xc2, microphone mute */ + EC_EVENT_NUM_CPU_TEMP, /* 0x3b, read out cpu temperature*/ + EC_EVENT_NUM_RFKILL /* 0xbd, airplane mode switch */ +}; + +#define EC_EVENT_NUM_MIN EC_EVENT_NUM_BAT +#define EC_EVENT_NUM_MAX EC_EVENT_NUM_RES2 +#define EC_EVENT_NUM_GSENSOR EC_EVENT_NUM_RES2 + +#define INDEX_LID_STATUS 0x46 /* Lid status register */ +#define LID_STATUS_BIT (1 << 0) /* Lid status BIT0 1: Closed, 0: Open */ + +typedef int (*ec_handler)(int status); + +extern bool it8528_get_ec_ibf_flags(void); +extern bool it8528_get_ec_obf_flags(void); +extern bool it8528_get_ec_evt_flags(void); + +/* The general ec index-io port read action */ +extern void clean_it8528_event_status(void); +extern unsigned char it8528_read(unsigned char index); +extern unsigned char it8528_read_all(unsigned char command, unsigned char index); +extern unsigned char it8528_read_noindex(unsigned char command); + +/* The general ec index-io port write action */ +extern int it8528_write(unsigned char index, unsigned char data); +extern int it8528_write_all(unsigned char command, unsigned char index, unsigned char data); +extern int it8528_write_noindex(unsigned char command, unsigned char data); + +/* Query sequence of 62/66 port access routine. */ +extern int it8528_query_seq(unsigned char command); +extern int it8528_get_event_num(void); +extern int it8528_query_get_event_num(void); +extern void it8528_ec_event_int_enable(void); +extern void it8528_ec_event_int_disable(void); +extern int it8528_query_clean_event(void); + +/* The ec interrupt functions */ +extern int it8528_init(void); +extern int lpc_ec_interrupt_occurs(void); +extern void lpc_interrupt_clear_all(void); + +/* EC sensor/hwmon registration */ +extern void ec_sensors_register(struct platform_device *pdev); + +#endif /* __EC_IT8528_H__ */ diff --git a/drivers/uos/phyt/ec/ec_sensor.c b/drivers/uos/phyt/ec/ec_sensor.c new file mode 100644 index 0000000000000..c2eb2f632b9ab --- /dev/null +++ b/drivers/uos/phyt/ec/ec_sensor.c @@ -0,0 +1,145 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include "ec_it8528.h" + +/*----------------------------------------------------------------------*/ + +#if IS_REACHABLE(CONFIG_HWMON) + +/* + * Temperature and Fan support form ec devices. + */ +static ssize_t ec_bat_temp_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int temp = 0; + + temp = (it8528_read(INDEX_BATTERY_TEMP_HIGH) << 8) | it8528_read(INDEX_BATTERY_TEMP_LOW); + + temp = temp - 2730; + + return sprintf(buf, "%d.%d\n", temp/10, temp%10); +} + +static ssize_t ec_gpu_temp_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + char temp = 0; + + temp = it8528_read(INDEX_GPU_TEMP_VALUE); + + return sprintf(buf, "%d\n", temp); +} + +static ssize_t ec_cpu_fan_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int speed = 0; + + speed = (it8528_read(INDEX_CPU_FAN_SPEED_HIGH) << 8) | it8528_read(INDEX_CPU_FAN_SPEED_LOW); + + return sprintf(buf, "%d\n", speed); +} + +static ssize_t ec_gpu_fan_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int speed = 0; + + speed = (it8528_read(INDEX_GPU_FAN_SPEED_HIGH) << 8) | it8528_read(INDEX_GPU_FAN_SPEED_LOW); + + return sprintf(buf, "%d\n", speed); +} + +static SENSOR_DEVICE_ATTR(ec_bat_temp, 0444, ec_bat_temp_show, + NULL, 0); +static SENSOR_DEVICE_ATTR(ec_gpu_temp, 0444, ec_gpu_temp_show, + NULL, 0); +static SENSOR_DEVICE_ATTR(ec_cpu_fan, 0444, ec_cpu_fan_show, + NULL, 0); +static SENSOR_DEVICE_ATTR(ec_gpu_fan, 0444, ec_gpu_fan_show, + NULL, 0); + +static struct attribute *ec_bat_temp_hwmon_attrs[] = { + &sensor_dev_attr_ec_bat_temp.dev_attr.attr, + NULL, +}; +static struct attribute *ec_gpu_temp_hwmon_attrs[] = { + &sensor_dev_attr_ec_gpu_temp.dev_attr.attr, + NULL, +}; +static struct attribute *ec_cpu_fan_hwmon_attrs[] = { + &sensor_dev_attr_ec_cpu_fan.dev_attr.attr, + NULL, +}; +static struct attribute *ec_gpu_fan_hwmon_attrs[] = { + &sensor_dev_attr_ec_gpu_fan.dev_attr.attr, + NULL, +}; + +ATTRIBUTE_GROUPS(ec_bat_temp_hwmon); +ATTRIBUTE_GROUPS(ec_gpu_temp_hwmon); +ATTRIBUTE_GROUPS(ec_cpu_fan_hwmon); +ATTRIBUTE_GROUPS(ec_gpu_fan_hwmon); + +void ec_sensors_register(struct platform_device *pdev) +{ + struct device *hwmon_dev; + + char *bat_temp_data, *gpu_temp_data, *cpu_fan_data, *gpu_fan_data; + + /* register bat temp hwmon device */ + bat_temp_data = kzalloc(0x10, GFP_KERNEL); + + hwmon_dev = devm_hwmon_device_register_with_groups(&pdev->dev, "EC_BAT_TEMP", + bat_temp_data, + ec_bat_temp_hwmon_groups); + if (IS_ERR(hwmon_dev)) { + dev_err(&pdev->dev, "unable to register hwmon device %ld\n", + PTR_ERR(hwmon_dev)); + } + + /* register gpu temp hwmon device */ + gpu_temp_data = kzalloc(0x10, GFP_KERNEL); + + hwmon_dev = devm_hwmon_device_register_with_groups(&pdev->dev, "EC_GPU_TEMP", + gpu_temp_data, + ec_gpu_temp_hwmon_groups); + if (IS_ERR(hwmon_dev)) { + dev_err(&pdev->dev, "unable to register hwmon device %ld\n", + PTR_ERR(hwmon_dev)); + } + + /* register cpu fan hwmon device */ + cpu_fan_data = kzalloc(0x10, GFP_KERNEL); + + hwmon_dev = devm_hwmon_device_register_with_groups(&pdev->dev, "EC_CPU_FAN", + cpu_fan_data, + ec_cpu_fan_hwmon_groups); + if (IS_ERR(hwmon_dev)) { + dev_err(&pdev->dev, "unable to register hwmon device %ld\n", + PTR_ERR(hwmon_dev)); + } + + /* register cpu fan hwmon device */ + gpu_fan_data = kzalloc(0x10, GFP_KERNEL); + + hwmon_dev = devm_hwmon_device_register_with_groups(&pdev->dev, "EC_GPU_FAN", + gpu_fan_data, + ec_gpu_fan_hwmon_groups); + if (IS_ERR(hwmon_dev)) { + dev_err(&pdev->dev, "unable to register hwmon device %ld\n", + PTR_ERR(hwmon_dev)); + } + +} + +#else + +void ec_sensors_register(struct platform_device *pdev) +{ +} + +#endif /* IS_REACHABLE(CONFIG_HWMON) */ diff --git a/drivers/uos/phyt/ec/phyt_laptop.c b/drivers/uos/phyt/ec/phyt_laptop.c new file mode 100644 index 0000000000000..193ae8254bc3f --- /dev/null +++ b/drivers/uos/phyt/ec/phyt_laptop.c @@ -0,0 +1,1363 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ec_it8528.h" +#include +#include +#include +#include +#include +#include +#include + +static inline u16 ec_read16(u8 high, u8 low) +{ + return (it8528_read(high) << 8) | it8528_read(low); +} + + +static bool ft_display_state = true; +static unsigned int ft_display_level; +static int ft_set_display_on(bool on); + +extern struct kset *devices_kset; + +#define EC_LPC_DEV "ec" + + +/* Power supply */ +enum { + APM_AC_OFFLINE = 0, + APM_AC_ONLINE, + APM_AC_BACKUP, + APM_AC_UNKNOWN = 0xff +}; + +enum { + APM_BAT_STATUS_HIGH = 0, + APM_BAT_STATUS_LOW, + APM_BAT_STATUS_CRITICAL, + APM_BAT_STATUS_CHARGING, + APM_BAT_STATUS_NOT_PRESENT, + APM_BAT_STATUS_UNKNOWN = 0xff +}; + +enum /* bat_reg_flag */ +{ + BAT_REG_TEMP_FLAG = 1, + BAT_REG_VOLTAGE_FLAG, + BAT_REG_CURRENT_FLAG, + BAT_REG_AC_FLAG, + BAT_REG_RC_FLAG, + BAT_REG_FCC_FLAG, + BAT_REG_ATTE_FLAG, + BAT_REG_ATTF_FLAG, + BAT_REG_RSOC_FLAG, + BAT_REG_CYCLCNT_FLAG +}; + +/* Power info cached timeout */ +#define POWER_INFO_CACHED_TIMEOUT 100 /* jiffies */ + +/* Backlight */ +#define MAX_BRIGHTNESS 100 + +/* Screen rotation */ +#define EC_GSENSOR_X_HIGH 0X63 +#define EC_GSENSOR_X_LOW 0X64 +#define EC_GSENSOR_Y_HIGH 0X65 +#define EC_GSENSOR_Y_LOW 0X66 +#define EC_GSENSOR_Z_HIGH 0X67 +#define EC_GSENSOR_Z_LOW 0X68 + +/* Power information structure */ +struct ft_power_info { + /* AC insert or not */ + unsigned int ac_in; + /* Battery insert or not */ + unsigned int bat_in; + unsigned int health; + + /* Battery designed capacity */ + unsigned int design_capacity; + /* Battery designed voltage */ + unsigned int design_voltage; + /* Battery capacity after full charged */ + unsigned int full_charged_capacity; + /* Battery Manufacture Date */ + unsigned char manufacture_date[11]; + /* Battery Serial number */ + unsigned char serial_number[8]; + /* Battery Manufacturer Name, max 11 + 1(length) bytes */ + unsigned char manufacturer_name[12]; + /* Battery Device Name, max 7 + 1(length) bytes */ + unsigned char device_name[8]; + /* Battery Technology */ + unsigned int technology; + /* Battery cell count */ + unsigned char cell_count; + + /* Battery dynamic charge/discharge voltage */ + unsigned int voltage_now; + /* Battery dynamic charge/discharge average current */ + int current_now; + int current_sign; + int current_average; + /* Battery current remaining capacity */ + unsigned int remain_capacity; + /* Battery current remaining capacity percent */ + unsigned int remain_capacity_percent; + /* Battery current temperature */ + unsigned int temperature; + /* Battery current remaining time (AverageTimeToEmpty) */ + unsigned int remain_time; + /* Battery current full charging time (averageTimeToFull) */ + unsigned int fullchg_time; + /* Battery Status */ + unsigned int charge_status; + /* Battery current cycle count (CycleCount) */ + unsigned int cycle_count; +}; + +/* LPC device structure */ +struct lpc_device { + /* The lpc number get from ec */ + unsigned char number; + /* count */ + unsigned char parameter; + /* Irq relative */ + unsigned char irq; + unsigned char irq_data; + /* Device name */ + unsigned char name[10]; +}; + + +/* LPC device object */ +static struct lpc_device *ft_lpc_device; +static struct lpc_device *ft_gpio_device; +static int ft_lpc_event_probe(struct platform_device *); + +static int ft_get_brightness(struct backlight_device *); +static int ft_set_brightness(struct backlight_device *); + +/* >>>Power management operation */ +/* Update battery information handle function. */ +static void ft_power_battery_info_update(unsigned char bat_reg_flag); +/* Clear battery static information. */ +static void ft_power_info_battery_static_clear(void); +/* Get battery static information. */ +static void ft_power_info_battery_static_update(void); +/* Update power_status value */ +static void ft_power_info_power_status_update(void); +static void ft_bat_get_string(unsigned char index, unsigned char *bat_string); +/* Power supply Battery get property handler */ +static int ft_bat_get_property(struct power_supply *pws, + enum power_supply_property psp, union power_supply_propval *val); +/* Power supply AC get property handler */ +static int ft_ac_get_property(struct power_supply *pws, + enum power_supply_property psp, union power_supply_propval *val); +/* LPC device AC event handler */ +static int ft_ac_handler(int status); +/* LPC device Battery event handler */ +static int ft_bat_handler(int status); + +/* <<code); + input_report_key(dev, ke->keycode, value); + input_sync(dev); + if (value && autorelease) { + input_report_key(dev, ke->keycode, 0); + input_sync(dev); + } +} + +void ft_ec_bl_dn_event(void) +{ + const struct key_entry *key = &ft_keymap[4]; + + sparse_keymap_report_entry(ft_hotkey_dev, key, 1, true); +} +EXPORT_SYMBOL(ft_ec_bl_dn_event); + +void ft_ec_bl_up_event(void) +{ + const struct key_entry *key = &ft_keymap[5]; + + sparse_keymap_report_entry(ft_hotkey_dev, key, 1, true); +} +EXPORT_SYMBOL(ft_ec_bl_up_event); + +void ft_ec_lid_event(void) +{ + const struct key_entry *key = &ft_keymap[0]; + + __clear_bit(SW_LID, ft_hotkey_dev->sw); + input_report_switch(ft_hotkey_dev, key->sw.code, 1); + input_sync(ft_hotkey_dev); + +} +EXPORT_SYMBOL(ft_ec_lid_event); + +void ft_ec_display_off(void) +{ + const struct key_entry *key = &ft_keymap[3]; + + sparse_keymap_report_entry(ft_hotkey_dev, key, 1, true); + ft_set_display_on(!ft_display_state); +} +EXPORT_SYMBOL(ft_ec_display_off); + +void ft_ec_display_event(void) +{ + const struct key_entry *key = &ft_keymap[6]; + + sparse_keymap_report_entry(ft_hotkey_dev, key, 1, true); +} +EXPORT_SYMBOL(ft_ec_display_event); + +void ft_ec_wifi_event(void) +{ + const struct key_entry *key = &ft_keymap[7]; + + sparse_keymap_report_entry(ft_hotkey_dev, key, 1, true); +} +EXPORT_SYMBOL(ft_ec_wifi_event); + +void ft_ec_micmute_event(void) +{ + const struct key_entry *key = &ft_keymap[10]; + + sparse_keymap_report_entry(ft_hotkey_dev, key, 1, true); +} +EXPORT_SYMBOL(ft_ec_micmute_event); + +void ft_ec_airplane_event(void) +{ + const struct key_entry *key = &ft_keymap[11]; + + sparse_keymap_report_entry(ft_hotkey_dev, key, 1, true); +} + +void ft_ec_screen_lock_event(void) +{ + const struct key_entry *key = &ft_keymap[9]; + + sparse_keymap_report_entry(ft_hotkey_dev, key, 1, true); +} +EXPORT_SYMBOL(ft_ec_screen_lock_event); + +void ft_ec_tp_event(void) +{ + const struct key_entry *key = &ft_keymap[2]; + + sparse_keymap_report_entry(ft_hotkey_dev, key, 1, true); +} +EXPORT_SYMBOL(ft_ec_tp_event); + +void ft_ec_screenlock_event(void) +{ + const struct key_entry *key = &ft_keymap[9]; + + sparse_keymap_report_entry(ft_hotkey_dev, key, 1, true); +} +EXPORT_SYMBOL(ft_ec_screenlock_event); + +void ft_sleep_event(void) +{ + const struct key_entry *key = &ft_keymap[1]; + + sparse_keymap_report_entry(ft_hotkey_dev, key, 1, true); +} +EXPORT_SYMBOL(ft_sleep_event); + +void ft_ec_powerbtn_event(void) +{ + const struct key_entry *key = &ft_keymap[8]; + + sparse_keymap_report_entry(ft_hotkey_dev, key, 1, true); +} +EXPORT_SYMBOL(ft_ec_powerbtn_event); + +void ft_ec_screen_rotation_event(void) +{ + int x_val = 0, y_val = 0, z_val = 0; + + x_val = (it8528_read(EC_GSENSOR_X_HIGH) << 8) | it8528_read(EC_GSENSOR_X_LOW); + y_val = (it8528_read(EC_GSENSOR_Y_HIGH) << 8) | it8528_read(EC_GSENSOR_Y_LOW); + z_val = (it8528_read(EC_GSENSOR_Z_HIGH) << 8) | it8528_read(EC_GSENSOR_Z_LOW); + + input_event(ec_gsensor_dev, EV_ABS, ABS_X, x_val); + input_event(ec_gsensor_dev, EV_ABS, ABS_Y, y_val); + input_event(ec_gsensor_dev, EV_ABS, ABS_Z, z_val); + input_sync(ec_gsensor_dev); +} + +/* LPC device event handler */ +void ft_ec_event_handler(int event) +{ + switch (event) { + case EC_EVENT_NUM_LID: + ft_lid_handler(event); + break; + + case EC_EVENT_NUM_AC: + ft_ac_handler(event); + break; + + case EC_EVENT_NUM_BAT: + ft_bat_handler(event); + break; + + case EC_EVENT_NUM_POWERBTN: + ft_ec_powerbtn_event(); + break; + + case EC_EVENT_NUM_GSENSOR: + ft_ec_screen_rotation_event(); + break; + + default: + break; + } + +} + + +static irqreturn_t ft_ec_int_routine(int irq, void *dev_id) +{ + int event; + unsigned long flags; + + spin_lock_irqsave(&i8042_lock, flags); + + /* if not ec irq */ + if (!lpc_ec_interrupt_occurs()) { + spin_unlock_irqrestore(&i8042_lock, flags); + return IRQ_NONE; + } + + /* Clean lpc irq */ + lpc_interrupt_clear_all(); + + event = it8528_query_get_event_num(); + + + if ((event < EC_EVENT_NUM_MIN) || (event > EC_EVENT_NUM_MAX)) + goto exit_event_action; + + ft_ec_event_handler(event); + spin_unlock_irqrestore(&i8042_lock, flags); + return IRQ_HANDLED; + +exit_event_action: + spin_unlock_irqrestore(&i8042_lock, flags); + return IRQ_HANDLED; +} + +irqreturn_t ft_ec_irq_hanlde(void) +{ + int event = 0; + + ft_ac_handler(event); + return IRQ_HANDLED; +} +EXPORT_SYMBOL(ft_ec_irq_hanlde); + +/* LPC driver init */ +static int lpc_int_init(void) +{ + int ret = -EIO; + + pr_debug("phytium: lpc init.\n"); + + ft_lpc_device = kmalloc(sizeof(struct lpc_device), GFP_KERNEL); + if (!ft_lpc_device) + return -ENOMEM; + + ft_lpc_device->irq = 0x25; + ft_lpc_device->irq_data = 0x00; + ft_lpc_device->number = 0x00; + ft_lpc_device->parameter = 0x00; + strscpy(ft_lpc_device->name, EC_LPC_DEV, sizeof(ft_lpc_device->name)); + + /* get lpc irq */ + ft_lpc_device->irq = phytium_pio_get_irq(); + if (ft_lpc_device->irq < 0) + goto out_pdev; + + + /* clear all interrupt status */ + lpc_interrupt_clear_all(); + + /* Regist pci irq */ + ret = request_irq(ft_lpc_device->irq, ft_ec_int_routine, + IRQF_SHARED, ft_lpc_device->name, ft_lpc_device); + if (ret) { + pr_err("phytium ec: Request irq fail.\n"); + ret = -EFAULT; + goto out_irq; + } + + ret = 0; + pr_debug("phytium: LPC init successful.\n"); + + return ret; + +out_irq: +out_pdev: + kfree(ft_lpc_device); + return ret; +} + +/* ec driver interrupt init handler */ +static int lpc_driver_init(void) +{ + int ret; + + ret = lpc_int_init(); + if (ret) { + pr_err("phytium: Register lpc driver fail.\n"); + return ret; + } + pr_debug("phytium: register lpc driver done.\n"); + return ret; +} + +int ec_event_int_error; + +static void ec_int_routine_func(struct work_struct *work) +{ + int event; + unsigned long flags; + + spin_lock_irqsave(&i8042_lock, flags); + event = it8528_query_get_event_num(); + if ((event < EC_EVENT_NUM_MIN) || (event > EC_EVENT_NUM_MAX)) { + pr_err("ec_int_gpio_routine handle event = 0x%x.\r\n", event); + ec_event_int_error = true; + spin_unlock_irqrestore(&i8042_lock, flags); + return; + } + ft_ec_event_handler(event); + spin_unlock_irqrestore(&i8042_lock, flags); +} +DECLARE_WORK(ec_int_routine_wq, ec_int_routine_func); + +static irqreturn_t ft_ec_int_gpio_routine(int irq, void *dev_id) +{ + unsigned long flags; + + spin_lock_irqsave(&i8042_lock, flags); + disable_irq_nosync(irq); + if (ec_event_int_error && !it8528_get_ec_evt_flags()) { /*sci_evt flags*/ + goto event_error; + } + + schedule_work(&ec_int_routine_wq); +event_error: + enable_irq(irq); + spin_unlock_irqrestore(&i8042_lock, flags); + return IRQ_HANDLED; +} + +static int set_func_to_gpio(void) +{ + int reg; + int pin_mul_contrl_base = 0x28180000; + void __iomem *gpio_func_ioremap = NULL; + + gpio_func_ioremap = ioremap(pin_mul_contrl_base, 0x1000); + if (!gpio_func_ioremap) { + pr_err("Could not ioreamp pin_mul_contrl_base!\n"); + return -ENOMEM; + } + + reg = readl(gpio_func_ioremap + 0x204); + + reg |= BIT(31); + reg &= ~BIT(30); + + reg &= ~BIT(29); + reg |= BIT(28); + + writel(reg, gpio_func_ioremap + 0x204); + + iounmap(gpio_func_ioremap); + return 0; +} + +static int gpio_driver_init(int irq) +{ + int ret; + + ft_gpio_device = kmalloc(sizeof(struct lpc_device), GFP_KERNEL); + if (!ft_gpio_device) + return -ENOMEM; + + /* Get GPIO7 soft irq*/ + ft_gpio_device->irq = irq; + strscpy(ft_gpio_device->name, "ec_gpio", sizeof(ft_gpio_device->name)); + + /* Configure GPIO pin function */ + + ret = set_func_to_gpio(); + if (ret) { + pr_err("set gpio func failed.\n"); + return -ENOMEM; + } + + /* Set GPIO related configuration */ + irq_set_irq_type(ft_gpio_device->irq, IRQ_TYPE_EDGE_RISING); + ret = request_irq(ft_gpio_device->irq, ft_ec_int_gpio_routine, + IRQF_TRIGGER_RISING, ft_gpio_device->name, ft_gpio_device); + if (ret) { + pr_err("phytium: Request irq fail.\n"); + return -EFAULT; + } + return ret; +} + +static int ft_set_display_on(bool on) +{ + if (!chassis_types_is_laptop()) + return 0; + + if (on) { + ft_display_state = true; + it8528_write(INDEX_DISPLAY_BRIGHTNESS_SET, ft_display_level); + } else { + ft_display_state = false; + ft_display_level = it8528_read(INDEX_DISPLAY_BRIGHTNESS_GET); + it8528_write(INDEX_DISPLAY_BRIGHTNESS_SET, 0); + } + return 0; +} + +/* Backlight device set brightness handler */ +static int ft_set_brightness(struct backlight_device *pdev) +{ + unsigned int level = 0; + + if (!chassis_types_is_laptop() && !chassis_types_is_allinone()) + return 0; + + if (!ft_display_state) + return 0; + + level = ((pdev->props.fb_blank == FB_BLANK_UNBLANK) && + (pdev->props.power == FB_BLANK_UNBLANK)) ? + pdev->props.brightness : 0; + + if (level > MAX_BRIGHTNESS) + level = MAX_BRIGHTNESS; + else if (level <= 0) + level = 1; + + it8528_write(INDEX_DISPLAY_BRIGHTNESS_SET, level); + + return 0; +} + +/* Backlight device get brightness handler */ +static int ft_get_brightness(struct backlight_device *pdev) +{ + if (!chassis_types_is_laptop() && !chassis_types_is_allinone()) + return 0; + + /* Read level from ec */ + return it8528_read(INDEX_DISPLAY_BRIGHTNESS_GET); +} + +/* Update battery information handle function. */ +static void ft_power_battery_info_update(unsigned char bat_reg_flag) +{ + short bat_info_value = 0, bat_info_value_ac = 0; + + switch (bat_reg_flag) { + /* Update power_info->temperature value */ + case BAT_REG_TEMP_FLAG: + ft_power_info_power_status_update(); + bat_info_value = ec_read16(INDEX_BATTERY_TEMP_HIGH, INDEX_BATTERY_TEMP_LOW); + power_info->temperature = power_info->bat_in ? + (bat_info_value - 2730) : 0; + break; + /* Update power_info->voltage value */ + case BAT_REG_VOLTAGE_FLAG: + bat_info_value = ec_read16(INDEX_BATTERY_VOL_HIGH, INDEX_BATTERY_VOL_LOW); + power_info->voltage_now = (power_info->bat_in) ? bat_info_value : 0; + break; + /* Update power_info->current_now value */ + case BAT_REG_CURRENT_FLAG: + bat_info_value = + ec_read16(INDEX_BATTERY_CURRENT_HIGH, INDEX_BATTERY_CURRENT_LOW); + power_info->current_now = (power_info->bat_in) ? bat_info_value : 0; + break; + /* Update power_info->current_avg value */ + case BAT_REG_AC_FLAG: + ft_power_info_power_status_update(); + bat_info_value = ec_read16(INDEX_BATTERY_AC_HIGH, INDEX_BATTERY_AC_LOW); + power_info->current_average = (power_info->bat_in) ? bat_info_value : 0; + break; + /* Update power_info->remain_capacity value */ + case BAT_REG_RC_FLAG: + power_info->remain_capacity = + ec_read16(INDEX_BATTERY_RC_HIGH, INDEX_BATTERY_RC_LOW); + break; + /* Update power_info->full_charged_capacity value */ + case BAT_REG_FCC_FLAG: + power_info->full_charged_capacity = + ec_read16(INDEX_BATTERY_FCC_HIGH, INDEX_BATTERY_FCC_LOW); + break; + /* Update power_info->remain_time value */ + case BAT_REG_ATTE_FLAG: + bat_info_value = ec_read16(INDEX_BATTERY_AC_HIGH, INDEX_BATTERY_AC_LOW); + bat_info_value = bat_info_value > 0 ? bat_info_value : (-bat_info_value); + if (bat_info_value) + power_info->remain_time = 60 * + ec_read16(INDEX_BATTERY_RC_HIGH, INDEX_BATTERY_RC_LOW) / + bat_info_value; + break; + /* Update power_info->fullchg_time value */ + case BAT_REG_ATTF_FLAG: + bat_info_value = ec_read16(INDEX_BATTERY_CAP_HIGH, INDEX_BATTERY_CAP_LOW); + bat_info_value -= ec_read16(INDEX_BATTERY_RC_HIGH, INDEX_BATTERY_RC_LOW); + bat_info_value_ac = + ec_read16(INDEX_BATTERY_AC_HIGH, INDEX_BATTERY_AC_LOW); + if (bat_info_value_ac > 0) + power_info->fullchg_time = 60 * bat_info_value / bat_info_value_ac; + break; + /* Update power_info->curr_cap value */ + case BAT_REG_RSOC_FLAG: + power_info->remain_capacity_percent = it8528_read(INDEX_BATTERY_CAPACITY); + break; + /* Update power_info->cycle_count value */ + case BAT_REG_CYCLCNT_FLAG: + power_info->cycle_count = + ec_read16(INDEX_BATTERY_CYCLECNT_HIGH, INDEX_BATTERY_CYCLECNT_LOW); + break; + + default: + break; + } +} + +/* Update battery information handle function. */ +static void ft_power_battery_info_init(void) +{ + int flag; + + pr_debug("%s: start ...\r\n", __func__); + + + for (flag = BAT_REG_TEMP_FLAG; flag <= BAT_REG_CYCLCNT_FLAG; flag++) + ft_power_battery_info_update(flag); + + pr_debug("%s: end ...\r\n", __func__); +} + +/* Clear battery static information. */ +static void ft_power_info_battery_static_clear(void) +{ + strscpy(power_info->manufacturer_name, "Unknown", sizeof(power_info->manufacturer_name)); + strscpy(power_info->device_name, "Unknown", sizeof(power_info->device_name)); + power_info->technology = POWER_SUPPLY_TECHNOLOGY_UNKNOWN; + strscpy(power_info->serial_number, "Unknown", sizeof(power_info->serial_number)); + strscpy(power_info->manufacture_date, "Unknown", sizeof(power_info->manufacture_date)); + power_info->cell_count = 0; + power_info->design_capacity = 0; + power_info->design_voltage = 0; +} + +/* Get battery static information. */ +static void ft_power_info_battery_static_update(void) +{ + unsigned int bat_serial_number; + + power_info->technology = POWER_SUPPLY_TECHNOLOGY_LION; + + bat_serial_number = ec_read16(INDEX_BATTERY_SN_HIGH, INDEX_BATTERY_SN_LOW); + snprintf(power_info->serial_number, 8, "%x", bat_serial_number); + + power_info->cell_count = ec_read16(INDEX_BATTERY_CV_HIGH, INDEX_BATTERY_CV_LOW) / 4200; + + power_info->design_capacity = ec_read16(INDEX_BATTERY_DC_HIGH, INDEX_BATTERY_DC_LOW); + power_info->design_voltage = ec_read16(INDEX_BATTERY_DV_HIGH, INDEX_BATTERY_DV_LOW); + power_info->full_charged_capacity = + ec_read16(INDEX_BATTERY_FCC_HIGH, INDEX_BATTERY_FCC_LOW); + pr_debug("DesignCapacity: %dmAh, DesignVoltage: %dmV, FullChargeCapacity: %dmAh\n", + power_info->design_capacity, + power_info->design_voltage, + power_info->full_charged_capacity); +} + +/* Update power_status value */ +static void ft_power_info_power_status_update(void) +{ + unsigned int power_status = 0; + + power_status = it8528_read(INDEX_POWER_STATUS); + + power_info->ac_in = (power_status & MASK(BIT_POWER_ACPRES)) ? + APM_AC_ONLINE : APM_AC_OFFLINE; + + power_info->bat_in = (power_status & MASK(BIT_POWER_BATPRES)) ? 1 : 0; + if (power_info->bat_in && + ec_read16(INDEX_BATTERY_DC_HIGH, INDEX_BATTERY_DC_LOW) == 0) + power_info->bat_in = 0; + + power_info->health = power_info->bat_in ? + POWER_SUPPLY_HEALTH_GOOD : + POWER_SUPPLY_HEALTH_UNKNOWN; + if (!power_info->bat_in) { + power_info->charge_status = POWER_SUPPLY_STATUS_UNKNOWN; + } else { + power_status = it8528_read(INDEX_BATTERY_STATUS); + + if (!(power_status & MASK(BIT_POWER_BATCHG))) + power_info->charge_status = POWER_SUPPLY_STATUS_CHARGING; + else if ((power_status & MASK(BIT_POWER_BATFCHG)) && + power_info->ac_in == APM_AC_ONLINE) + power_info->charge_status = POWER_SUPPLY_STATUS_FULL; + else + power_info->charge_status = POWER_SUPPLY_STATUS_DISCHARGING; + } +} + +/* Get battery static information string */ +static void __maybe_unused ft_bat_get_string(unsigned char index, unsigned char *bat_string) +{ + unsigned char length, i; + + length = it8528_read(index); + for (i = 0; i < length; i++) + *bat_string++ = it8528_read(++index); + *bat_string = '\0'; +} + +/* Power supply Battery get property handler */ +static int ft_bat_get_property(struct power_supply *pws, + enum power_supply_property psp, union power_supply_propval *val) +{ + unsigned long flags; + + spin_lock_irqsave(&i8042_lock, flags); + switch (psp) { + /* Get battery static information. */ + case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: + val->intval = power_info->design_voltage * 1000; /* mV -> uV */ + break; + case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: + val->intval = power_info->design_capacity * 1000; /* mAh -> uAh */ + break; + case POWER_SUPPLY_PROP_MODEL_NAME: + val->strval = power_info->device_name; + break; + case POWER_SUPPLY_PROP_MANUFACTURER: + val->strval = power_info->manufacturer_name; + break; + case POWER_SUPPLY_PROP_SERIAL_NUMBER: + val->strval = power_info->serial_number; + break; + case POWER_SUPPLY_PROP_TECHNOLOGY: + val->intval = power_info->technology; + break; + /* Get battery dynamic information. */ + case POWER_SUPPLY_PROP_STATUS: + ft_power_info_power_status_update(); + val->intval = power_info->charge_status; + break; + case POWER_SUPPLY_PROP_PRESENT: + ft_power_info_power_status_update(); + val->intval = power_info->bat_in; + break; + case POWER_SUPPLY_PROP_HEALTH: + ft_power_info_power_status_update(); + val->intval = power_info->health; + break; + case POWER_SUPPLY_PROP_CURRENT_NOW: + ft_power_battery_info_update(BAT_REG_CURRENT_FLAG); + val->intval = power_info->current_now * 1000; /* mA -> uA */ + break; + case POWER_SUPPLY_PROP_CURRENT_AVG: + ft_power_battery_info_update(BAT_REG_AC_FLAG); + val->intval = power_info->current_average * 1000; /* mA -> uA */ + break; + case POWER_SUPPLY_PROP_VOLTAGE_NOW: + ft_power_battery_info_update(BAT_REG_VOLTAGE_FLAG); + val->intval = power_info->voltage_now * 1000; /* mV -> uV */ + break; + case POWER_SUPPLY_PROP_CHARGE_NOW: + ft_power_battery_info_update(BAT_REG_RC_FLAG); + val->intval = power_info->remain_capacity * 1000; /* mAh -> uAh */ + break; + case POWER_SUPPLY_PROP_CAPACITY: + ft_power_battery_info_update(BAT_REG_RSOC_FLAG); + val->intval = power_info->remain_capacity_percent; /* Percentage */ + break; + case POWER_SUPPLY_PROP_TEMP: + ft_power_battery_info_update(BAT_REG_TEMP_FLAG); + val->intval = power_info->temperature; /* Celcius */ + break; + case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG: + ft_power_battery_info_update(BAT_REG_ATTE_FLAG); + if (power_info->remain_time == 0xFFFF) + power_info->remain_time = 0; + val->intval = power_info->remain_time * 60; /* seconds */ + break; + case POWER_SUPPLY_PROP_TIME_TO_FULL_AVG: + ft_power_battery_info_update(BAT_REG_ATTF_FLAG); + if (power_info->fullchg_time == 0xFFFF) + power_info->fullchg_time = 0; + val->intval = power_info->fullchg_time * 60; /* seconds */ + break; + case POWER_SUPPLY_PROP_CHARGE_FULL: + ft_power_battery_info_update(BAT_REG_FCC_FLAG); + val->intval = power_info->full_charged_capacity * 1000;/* mAh -> uAh */ + break; + case POWER_SUPPLY_PROP_CYCLE_COUNT: + ft_power_battery_info_update(BAT_REG_CYCLCNT_FLAG); + val->intval = power_info->cycle_count; + break; + default: + spin_unlock_irqrestore(&i8042_lock, flags); + return -EINVAL; + } + spin_unlock_irqrestore(&i8042_lock, flags); + return 0; +} + +/* Power supply AC get property handler */ +static int ft_ac_get_property(struct power_supply *pws, + enum power_supply_property psp, union power_supply_propval *val) +{ + unsigned long flags; + + spin_lock_irqsave(&i8042_lock, flags); + + switch (psp) { + case POWER_SUPPLY_PROP_ONLINE: + ft_power_info_power_status_update(); + val->intval = power_info->ac_in; + break; + default: + spin_unlock_irqrestore(&i8042_lock, flags); + return -EINVAL; + } + spin_unlock_irqrestore(&i8042_lock, flags); + return 0; +} + +/* EC device AC event handler */ +static int ft_ac_handler(int status) +{ + /* Report status changed */ + power_supply_changed(ec_ac); + + return 0; +} + +/* EC device AC event handler */ +int ft_ac_handler_test(void) +{ + /* Report status changed */ + power_supply_changed(ec_ac); + + return 0; +} +EXPORT_SYMBOL(ft_ac_handler_test); + +/* LPC device Battery event handler */ +static int ft_bat_handler(int status) +{ + /* Battery insert/pull-out to handle battery static information. */ + if (status & MASK(BIT_POWER_BATPRES)) { + /* If battery is insert, get battery static information. */ + ft_power_info_battery_static_update(); + } else { + /* Else if battery is pull-out, clear battery static information. */ + ft_power_info_battery_static_clear(); + } + /* Report status changed */ + power_supply_changed(ec_bat); + + return 0; +} + +/* LPC device LID event handler */ +static int ft_lid_handler(int status) +{ + ft_ec_lid_event(); + return 1; +} + +/* Hotkey device init */ +int ft_hotkey_init(void) +{ + int ret; + + if (ft_hotkey_dev) + return 0; + + ft_hotkey_dev = input_allocate_device(); + if (!ft_hotkey_dev) + return -ENOMEM; + + ft_hotkey_dev->name = "phytium Laptop Hotkeys"; + ft_hotkey_dev->phys = "button/input0"; + ft_hotkey_dev->id.bustype = BUS_HOST; + ft_hotkey_dev->dev.parent = NULL; + set_bit(EV_KEY, ft_hotkey_dev->evbit); + set_bit(EV_SW, ft_hotkey_dev->evbit); + set_bit(KEY_POWER, ft_hotkey_dev->keybit); + set_bit(SW_LID, ft_hotkey_dev->swbit); + + + ret = sparse_keymap_setup(ft_hotkey_dev, ft_keymap, NULL); + if (ret) { + pr_err("phytium Laptop Platform Driver: Fail to setup input device keymap\n"); + input_free_device(ft_hotkey_dev); + + return ret; + } + + ret = input_register_device(ft_hotkey_dev); + if (ret) { + input_free_device(ft_hotkey_dev); + + return ret; + } + return 0; +} +EXPORT_SYMBOL(ft_hotkey_init); + +/* Hotkey device exit */ +static void ft_hotkey_exit(void) +{ + if (ft_hotkey_dev) { + input_unregister_device(ft_hotkey_dev); + ft_hotkey_dev = NULL; + } +} + +static ssize_t gsensor_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + int x_val = 0; + + x_val = (it8528_read(EC_GSENSOR_X_HIGH) << 8) | it8528_read(EC_GSENSOR_X_LOW); + return sprintf(buf, "%d\n", x_val); +} + +static struct kobj_attribute gsensor_attr = + __ATTR(value_x, 0644, gsensor_show, NULL); + +static struct attribute *gsensor_attrs[] = { + &gsensor_attr.attr, + NULL, +}; + +static struct attribute_group gsensor_attr_group = { + .attrs = gsensor_attrs, +}; + +static struct kobject *gsensor_kobj; + +/* Gsensor device init */ +int ec_gsonsor_init(void) +{ + int ret; + + if (ec_gsensor_dev) + return 0; + + ec_gsensor_dev = input_allocate_device(); + if (!ec_gsensor_dev) + return -ENOMEM; + + ec_gsensor_dev->name = "EC_Gsensor"; + ec_gsensor_dev->uniq = "EC_Gsensor"; + ec_gsensor_dev->id.bustype = BUS_HOST; + + set_bit(EV_SYN, ec_gsensor_dev->evbit); + set_bit(EV_ABS, ec_gsensor_dev->evbit); + set_bit(ABS_X, ec_gsensor_dev->absbit); + set_bit(ABS_Y, ec_gsensor_dev->absbit); + set_bit(ABS_Z, ec_gsensor_dev->absbit); + + input_set_capability(ec_gsensor_dev, EV_ABS, ABS_X); + input_set_capability(ec_gsensor_dev, EV_ABS, ABS_Y); + input_set_capability(ec_gsensor_dev, EV_ABS, ABS_Z); + input_set_abs_params(ec_gsensor_dev, ABS_X, 0, 0xFFFF, 0, 0); + input_set_abs_params(ec_gsensor_dev, ABS_Y, 0, 0xFFFF, 0, 0); + input_set_abs_params(ec_gsensor_dev, ABS_Z, 0, 0xFFFF, 0, 0); + + ret = input_register_device(ec_gsensor_dev); + if (ret) { + input_free_device(ec_gsensor_dev); + return ret; + } + + gsensor_kobj = kobject_create_and_add("gsensor", &devices_kset->kobj); + if (!gsensor_kobj) + return -ENOMEM; + ret = sysfs_create_group(gsensor_kobj, &gsensor_attr_group); + if (ret) { + kobject_put(gsensor_kobj); + return ret; + } + + return 0; +} + +/* Gsensor device exit */ +static void ec_gsensor_exit(void) +{ + if (ec_gsensor_dev) { + input_unregister_device(ec_gsensor_dev); + ec_gsensor_dev = NULL; + } +} + +#ifdef CONFIG_PM + +static int ft_laptop_suspend(struct device *dev) +{ + if (ft_gpio_device) + disable_irq_nosync(ft_gpio_device->irq); + it8528_ec_event_int_disable(); + return 0; +} + +static int ft_laptop_resume(struct device *dev) +{ + int ret; + + if (ft_gpio_device) { + /* Configure GPIO pin function */ + ret = set_func_to_gpio(); + if (ret) { + pr_err("set gpio func failed.\n"); + return -ENOMEM; + } + /*Set GPIO related configuration*/ + irq_set_irq_type(ft_gpio_device->irq, IRQ_TYPE_EDGE_RISING); + it8528_ec_event_int_enable(); + /* clean ec evnet queue*/ + ret = it8528_query_clean_event(); + if (ret) { + pr_err("EC clean event fail.\n"); + return -EINVAL; + } + } + + if (ft_gpio_device) + enable_irq(ft_gpio_device->irq); + /* enable ec event interrupt */ + it8528_ec_event_int_enable(); + + if (chassis_types_is_laptop()) { /* chassis is laptop */ + ft_power_info_power_status_update(); + if (power_info->bat_in) { + /* Get battery static information. */ + ft_power_info_battery_static_update(); + + /* Report status changed */ + power_supply_changed(ec_ac); + } + + input_report_switch(ft_hotkey_dev, SW_LID, 0); + input_sync(ft_hotkey_dev); + } + + return 0; +} +#endif + + +static int ft_lpc_event_probe(struct platform_device *dev) +{ + int ret = 0; + int gpio_irq; + int brightness_default; + + pr_debug("phytium ec: in probe!\n"); + + if (read_cpuid_implementor() != ARM_CPU_IMP_PHYTIUM) + return ret; + + ret = it8528_init(); + if (ret) { + pr_info("laptop_init: ec chip not found!\n"); + return ret; + } + + /* Regist backlight */ + if (chassis_types_is_laptop() || chassis_types_is_allinone()) { + ft_backlight_dev = backlight_device_register("phytium", NULL, NULL, + &ft_backlight_ops, NULL); + if (IS_ERR(ft_backlight_dev)) { + ret = PTR_ERR(ft_backlight_dev); + goto fail_backlight_device_register; + } + ft_backlight_dev->props.max_brightness = 100; + + brightness_default = it8528_read(INDEX_DISPLAY_BRIGHTNESS_GET); + if (brightness_default == 0) { + ft_backlight_dev->props.brightness = ft_backlight_dev->props.max_brightness; + it8528_write(INDEX_DISPLAY_BRIGHTNESS_SET, + ft_backlight_dev->props.max_brightness); + } else { + ft_backlight_dev->props.brightness = brightness_default; + } + + backlight_update_status(ft_backlight_dev); + } + + ret = ft_hotkey_init(); + if (ret) { + pr_err("phytium Platform Driver: Hotkey init fail.\n"); + goto fail_hotkey_init; + } + + ret = ec_gsonsor_init(); + if (ret) { + pr_err("phytium Platform Driver: Gsensor init fail.\n"); + goto fail_gsensor_init; + } + + + /* Register power supply START */ + power_info = kzalloc(sizeof(struct ft_power_info), GFP_KERNEL); + if (!power_info) { + ret = -ENOMEM; + goto fail_power_info_alloc; + } + + ft_power_battery_info_init(); + + ft_power_info_power_status_update(); + if (power_info->bat_in) { + /* Get battery static information. */ + ft_power_info_battery_static_update(); + } else { + pr_info("phytium Platform Driver: The battery does not exist!!\n"); + } + + if (chassis_types_is_laptop() && power_info->bat_in) { + ec_bat = power_supply_register(NULL, &ft_bat, NULL); + if (IS_ERR(ec_bat)) { + ret = -ENOMEM; + goto fail_bat_power_supply_register; + } + + ec_ac = power_supply_register(NULL, &ft_ac, NULL); + if (IS_ERR(ec_ac)) { + ret = -ENOMEM; + goto fail_ac_power_supply_register; + } + } + /* Register power supply END */ + + /* Register Temp and Fan hwmon */ + ec_sensors_register(dev); + + gpio_irq = acpi_dev_gpio_irq_get(ACPI_COMPANION(&(dev->dev)), 0); + if (gpio_irq > 0) { + /* GPIO Driver Init Start */ + ret = gpio_driver_init(gpio_irq); + if (ret) { + pr_err("phytium ec: gpio driver init fail.\n"); + goto fail_gpio_pci_driver_init; + } + } else { + /* LPC Driver Init Start */ + ret = lpc_driver_init(); + if (ret) { + pr_err("phytium: LPC driver init fail.\n"); + goto fail_lpc_pci_driver_init; + } + } + + + + /* clean ec evnet queue*/ + ret = it8528_query_clean_event(); + if (ret) { + pr_err("EC clean event fail.\n"); + goto fail_lpc_pci_driver_init; + } + + /* enable ec event interrupt */ + it8528_ec_event_int_enable(); + + pr_debug("phytium: ec event driver init done...\n"); + + return 0; +fail_gsensor_init: + ec_gsensor_exit(); +fail_hotkey_init: +fail_lpc_pci_driver_init: +fail_gpio_pci_driver_init: + ft_hotkey_exit(); +fail_ac_power_supply_register: + power_supply_unregister(ec_bat); +fail_bat_power_supply_register: + kfree(power_info); +fail_power_info_alloc: + backlight_device_unregister(ft_backlight_dev); +fail_backlight_device_register: + platform_driver_unregister(&ft_ec_pdriver); + return ret; +} + +module_platform_driver(ft_ec_pdriver); + +MODULE_DESCRIPTION("phytium Laptop Driver"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/classtypes.h b/include/linux/classtypes.h index 0e5eef81f2dfd..dd74fb4bcb661 100644 --- a/include/linux/classtypes.h +++ b/include/linux/classtypes.h @@ -2,6 +2,11 @@ #ifndef _LIB_CLASS_TYPE_H #define _LIB_CLASS_TYPE_H +#include + char *get_cpu_name(void); +unsigned long get_chassis_types(void); +bool chassis_types_is_laptop(void); +bool chassis_types_is_allinone(void); #endif diff --git a/lib/classtypes.c b/lib/classtypes.c index f209fdf2b2fad..5932f35e677a8 100644 --- a/lib/classtypes.c +++ b/lib/classtypes.c @@ -3,6 +3,7 @@ #include #include #include +#include static char cpu_name[256]; static bool get_cpu_flag; @@ -60,3 +61,54 @@ char *get_cpu_name(void) return cpu_name; } EXPORT_SYMBOL(get_cpu_name); + +static unsigned long chassis_type; + +unsigned long get_chassis_types(void) +{ + const char *chassis_type_str = NULL; + + if (chassis_type) + return chassis_type; + + chassis_type_str = dmi_get_system_info(DMI_CHASSIS_TYPE); + if (!chassis_type_str) + return 0; + + if (kstrtoul(chassis_type_str, 10, &chassis_type) != 0) + return 0; + + return chassis_type; +} +EXPORT_SYMBOL(get_chassis_types); + +bool chassis_types_is_laptop(void) +{ + unsigned long type; + + type = get_chassis_types(); + + switch (type) { + case 0x09: /* Laptop */ + case 0x0A: /* Notebook */ + return true; + } + + return false; +} +EXPORT_SYMBOL(chassis_types_is_laptop); + +bool chassis_types_is_allinone(void) +{ + unsigned long type; + + type = get_chassis_types(); + + switch (type) { + case 0x0D: /* All in One */ + return true; + } + + return false; +} +EXPORT_SYMBOL(chassis_types_is_allinone); From dd845faa22f5fafaec58b748f227f100d077ac06 Mon Sep 17 00:00:00 2001 From: Wentao Guan Date: Sat, 4 Jul 2026 03:15:46 +0800 Subject: [PATCH 3/5] phytium: ec: simplify EC core and laptop event/battery handling deepin inclusion category: feature Refactor the IT8528 EC driver to reduce duplication and boilerplate: - Replace the six nearly-identical read/write helpers with a single it8528_transaction() routine, mirroring the transaction model used by drivers/acpi/ec.c. - Table-drive battery state updates instead of a large switch/case. - Table-drive EC event dispatch and make the three legacy handlers return void, since their return values were never used. - Remove the unused ft_ec_irq_hanlde() export. Assisted-by: kimi-cli:kimi-k2.7 code Signed-off-by: Wentao Guan --- drivers/uos/phyt/ec/ec_it8528.c | 241 ++++++++++-------------------- drivers/uos/phyt/ec/phyt_laptop.c | 236 +++++++++++++++-------------- 2 files changed, 209 insertions(+), 268 deletions(-) diff --git a/drivers/uos/phyt/ec/ec_it8528.c b/drivers/uos/phyt/ec/ec_it8528.c index 6bdb606071e9d..57bebd53f7b80 100644 --- a/drivers/uos/phyt/ec/ec_it8528.c +++ b/drivers/uos/phyt/ec/ec_it8528.c @@ -17,187 +17,127 @@ /* This spinlock is dedicated for 62&66 ports and super io port access. */ DEFINE_SPINLOCK(index_access_lock); -static int send_ec_command(unsigned char command) +static int ec_wait_ibf_clear(void) { - int timeout, ret = 0; + unsigned int timeout = EC_SEND_TIMEOUT; - timeout = EC_SEND_TIMEOUT; while ((inb(EC_STS_PORT) & EC_IBF) && --timeout) udelay(1); if (!timeout) { - pr_err("Timeout while sending command 0x%02x to EC!\n", command); - ret = -1; - goto out; + pr_err("Timeout waiting for EC IBF clear (status 0x%x)\n", + inb(EC_STS_PORT)); + return -ETIMEDOUT; } - - outb(command, EC_CMD_PORT); - -out: - return ret; + return 0; } -static int send_ec_data(unsigned char data) +static int ec_wait_obf_set(u8 *data) { - int timeout, ret = 0; + unsigned int timeout = EC_RECV_TIMEOUT; - timeout = EC_SEND_TIMEOUT; - while ((inb(EC_STS_PORT) & EC_IBF) && --timeout) + while (!(inb(EC_STS_PORT) & EC_OBF) && --timeout) udelay(1); if (!timeout) { - pr_err("Timeout while sending data 0x%02x to EC!\n", data); - ret = -1; - goto out; + pr_err("Timeout waiting for EC OBF set (status 0x%x)\n", + inb(EC_STS_PORT)); + return -ETIMEDOUT; } - - outb(data, EC_DAT_PORT); - -out: - return ret; + *data = inb(EC_DAT_PORT); + return 0; } -static unsigned char recv_ec_data(void) +static int ec_send_byte(u8 byte, u16 port) { - int timeout; - unsigned char data; + int ret = ec_wait_ibf_clear(); - timeout = EC_RECV_TIMEOUT; - while (!(inb(EC_STS_PORT) & EC_OBF) && --timeout) - udelay(1); - if (!timeout) { - pr_err("Timeout while receiving data from EC! status 0x%x.\n", inb(EC_STS_PORT)); - data = 0; - goto skip_data; - } - - data = inb(EC_DAT_PORT); - -skip_data: - return data; + if (ret) + return ret; + outb(byte, port); + return 0; } -unsigned char it8528_read(unsigned char index) +/* + * One EC transaction: command + optional write data + optional read data. + * The whole sequence is protected by index_access_lock. + */ +static int it8528_transaction(u8 command, const u8 *wdata, int wlen, + u8 *rdata, int rlen) { - unsigned char value = 0; unsigned long flags; - int ret = 0; + int i, ret; + u8 val; spin_lock_irqsave(&index_access_lock, flags); - ret = send_ec_command(CMD_READ_EC); - if (ret < 0) { - pr_err("Send command fail!\n"); - value = 0; + + ret = ec_send_byte(command, EC_CMD_PORT); + if (ret) goto out; + + for (i = 0; i < wlen; i++) { + ret = ec_send_byte(wdata[i], EC_DAT_PORT); + if (ret) + goto out; } - ret = send_ec_data(index); - if (ret < 0) { - pr_err("Send data fail!\n"); - value = 0; - goto out; + + for (i = 0; i < rlen; i++) { + ret = ec_wait_obf_set(&val); + if (ret) + goto out; + rdata[i] = val; } - value = recv_ec_data(); + out: spin_unlock_irqrestore(&index_access_lock, flags); + return ret; +} + +unsigned char it8528_read(unsigned char index) +{ + u8 value = 0; + it8528_transaction(CMD_READ_EC, &index, 1, &value, 1); return value; } EXPORT_SYMBOL(it8528_read); unsigned char it8528_read_all(unsigned char command, unsigned char index) { - unsigned char value = 0; - unsigned long flags; - int ret = 0; - - spin_lock_irqsave(&index_access_lock, flags); - ret = send_ec_command(command); - if (ret < 0) { - pr_err("Send command fail!\n"); - goto out; - } - ret = send_ec_data(index); - if (ret < 0) { - pr_err("Send data fail!\n"); - goto out; - } - value = recv_ec_data(); -out: - spin_unlock_irqrestore(&index_access_lock, flags); + u8 value = 0; + it8528_transaction(command, &index, 1, &value, 1); return value; } EXPORT_SYMBOL(it8528_read_all); unsigned char it8528_read_noindex(unsigned char command) { - unsigned char value = 0; - unsigned long flags; - int ret = 0; - - spin_lock_irqsave(&index_access_lock, flags); - ret = send_ec_command(command); - if (ret < 0) { - pr_err("Send command fail!\n"); - goto out; - } - value = recv_ec_data(); -out: - spin_unlock_irqrestore(&index_access_lock, flags); + u8 value = 0; + it8528_transaction(command, NULL, 0, &value, 1); return value; } EXPORT_SYMBOL(it8528_read_noindex); int it8528_write(unsigned char index, unsigned char data) { - int ret = 0; - unsigned long flags; - - spin_lock_irqsave(&index_access_lock, flags); - ret = send_ec_command(CMD_WRITE_EC); - if (ret < 0) { - pr_err("Send command 0x81 fail!\n"); - goto out; - } - ret = send_ec_data(index); - if (ret < 0) { - pr_err("Send index 0x%x fail!\n", index); - goto out; - } - - ret = send_ec_data(data); - if (ret < 0) - pr_err("Send data 0x%x fail!\n", data); -out: - spin_unlock_irqrestore(&index_access_lock, flags); + u8 wdata[2] = { index, data }; - return ret; + return it8528_transaction(CMD_WRITE_EC, wdata, 2, NULL, 0); } EXPORT_SYMBOL(it8528_write); -int it8528_write_all(unsigned char command, unsigned char index, unsigned char data) +int it8528_write_all(unsigned char command, unsigned char index, + unsigned char data) { - unsigned long flags; + u8 wdata[2] = { index, data }; - spin_lock_irqsave(&index_access_lock, flags); - send_ec_command(command); - send_ec_data(index); - send_ec_data(data); - spin_unlock_irqrestore(&index_access_lock, flags); - - return 0; + return it8528_transaction(command, wdata, 2, NULL, 0); } EXPORT_SYMBOL(it8528_write_all); int it8528_write_noindex(unsigned char command, unsigned char data) { - unsigned long flags; - - spin_lock_irqsave(&index_access_lock, flags); - send_ec_command(command); - send_ec_data(data); - spin_unlock_irqrestore(&index_access_lock, flags); - - return 0; + return it8528_transaction(command, &data, 1, NULL, 0); } EXPORT_SYMBOL(it8528_write_noindex); @@ -221,34 +161,31 @@ EXPORT_SYMBOL(it8528_get_ec_evt_flags); int it8528_query_get_event_num(void) { - unsigned char value = 0; unsigned long flags; - int ret = 0; unsigned int timeout; + u8 value = 0; + int ret; spin_lock_irqsave(&index_access_lock, flags); - ret = send_ec_command(CMD_GET_EVENT_NUM); - if (ret < 0) { - pr_err("Send command fail!\n"); + + ret = ec_send_byte(CMD_GET_EVENT_NUM, EC_CMD_PORT); + if (ret) goto out; - } - /* check if the command is received by ec */ + /* Give the EC a moment to consume the command. */ timeout = EC_CMD_TIMEOUT; while ((inb(EC_STS_PORT) & EC_IBF) && timeout--) udelay(1); - if (timeout <= 0) { - pr_err("EC QUERY SEQ: deadable error : timeout...\n"); - ret = -EINVAL; + if (!timeout) { + pr_err("EC QUERY SEQ: timeout\n"); + ret = -ETIMEDOUT; goto out; } - value = recv_ec_data(); - spin_unlock_irqrestore(&index_access_lock, flags); - return value; + ret = ec_wait_obf_set(&value); out: spin_unlock_irqrestore(&index_access_lock, flags); - return ret; + return ret ? ret : value; } EXPORT_SYMBOL(it8528_query_get_event_num); @@ -271,26 +208,21 @@ EXPORT_SYMBOL(it8528_query_clean_event); void it8528_ec_event_int_enable(void) { unsigned long flags; - int ret = 0; unsigned int timeout; + int ret; spin_lock_irqsave(&index_access_lock, flags); - ret = send_ec_command(CMD_ENABLE_EVENT_EC); - if (ret < 0) { - pr_err("Send command fail!\n"); + ret = ec_send_byte(CMD_ENABLE_EVENT_EC, EC_CMD_PORT); + if (ret) goto out; - } - /* check if the command is received by ec */ timeout = EC_CMD_TIMEOUT; while ((inb(EC_STS_PORT) & EC_IBF) && timeout--) udelay(1); - if (timeout <= 0) { - pr_err("EC ENABLE EVENT INTERRUPT: deadable error : timeout...\n"); - ret = -EINVAL; - goto out; - } + if (!timeout) + pr_err("EC ENABLE EVENT INTERRUPT: timeout\n"); + out: spin_unlock_irqrestore(&index_access_lock, flags); } @@ -299,27 +231,20 @@ EXPORT_SYMBOL(it8528_ec_event_int_enable); void it8528_ec_event_int_disable(void) { unsigned long flags; - int ret = 0; unsigned int timeout; + int ret; spin_lock_irqsave(&index_access_lock, flags); - ret = send_ec_command(CMD_DISABLE_EVENT_EC); - if (ret < 0) { - pr_err("Send command fail!\n"); + ret = ec_send_byte(CMD_DISABLE_EVENT_EC, EC_CMD_PORT); + if (ret) goto out; - } - /* check if the command is received by ec */ timeout = EC_CMD_TIMEOUT; while ((inb(EC_STS_PORT) & EC_IBF) && timeout--) udelay(1); - - if (timeout <= 0) { - pr_err("EC ENABLE EVENT INTERRUPT: deadable error : timeout...\n"); - ret = -EINVAL; - goto out; - } + if (!timeout) + pr_err("EC DISABLE EVENT INTERRUPT: timeout\n"); out: spin_unlock_irqrestore(&index_access_lock, flags); diff --git a/drivers/uos/phyt/ec/phyt_laptop.c b/drivers/uos/phyt/ec/phyt_laptop.c index 193ae8254bc3f..841255f4e737f 100644 --- a/drivers/uos/phyt/ec/phyt_laptop.c +++ b/drivers/uos/phyt/ec/phyt_laptop.c @@ -172,14 +172,14 @@ static int ft_bat_get_property(struct power_supply *pws, static int ft_ac_get_property(struct power_supply *pws, enum power_supply_property psp, union power_supply_propval *val); /* LPC device AC event handler */ -static int ft_ac_handler(int status); +static void ft_ac_handler(int status); /* LPC device Battery event handler */ -static int ft_bat_handler(int status); +static void ft_bat_handler(int status); /* <<temperature value */ - case BAT_REG_TEMP_FLAG: - ft_power_info_power_status_update(); - bat_info_value = ec_read16(INDEX_BATTERY_TEMP_HIGH, INDEX_BATTERY_TEMP_LOW); - power_info->temperature = power_info->bat_in ? - (bat_info_value - 2730) : 0; - break; - /* Update power_info->voltage value */ - case BAT_REG_VOLTAGE_FLAG: - bat_info_value = ec_read16(INDEX_BATTERY_VOL_HIGH, INDEX_BATTERY_VOL_LOW); - power_info->voltage_now = (power_info->bat_in) ? bat_info_value : 0; - break; - /* Update power_info->current_now value */ - case BAT_REG_CURRENT_FLAG: - bat_info_value = - ec_read16(INDEX_BATTERY_CURRENT_HIGH, INDEX_BATTERY_CURRENT_LOW); - power_info->current_now = (power_info->bat_in) ? bat_info_value : 0; - break; - /* Update power_info->current_avg value */ - case BAT_REG_AC_FLAG: - ft_power_info_power_status_update(); - bat_info_value = ec_read16(INDEX_BATTERY_AC_HIGH, INDEX_BATTERY_AC_LOW); - power_info->current_average = (power_info->bat_in) ? bat_info_value : 0; - break; - /* Update power_info->remain_capacity value */ - case BAT_REG_RC_FLAG: - power_info->remain_capacity = - ec_read16(INDEX_BATTERY_RC_HIGH, INDEX_BATTERY_RC_LOW); - break; - /* Update power_info->full_charged_capacity value */ - case BAT_REG_FCC_FLAG: - power_info->full_charged_capacity = - ec_read16(INDEX_BATTERY_FCC_HIGH, INDEX_BATTERY_FCC_LOW); - break; - /* Update power_info->remain_time value */ - case BAT_REG_ATTE_FLAG: - bat_info_value = ec_read16(INDEX_BATTERY_AC_HIGH, INDEX_BATTERY_AC_LOW); - bat_info_value = bat_info_value > 0 ? bat_info_value : (-bat_info_value); - if (bat_info_value) - power_info->remain_time = 60 * - ec_read16(INDEX_BATTERY_RC_HIGH, INDEX_BATTERY_RC_LOW) / - bat_info_value; - break; - /* Update power_info->fullchg_time value */ - case BAT_REG_ATTF_FLAG: - bat_info_value = ec_read16(INDEX_BATTERY_CAP_HIGH, INDEX_BATTERY_CAP_LOW); - bat_info_value -= ec_read16(INDEX_BATTERY_RC_HIGH, INDEX_BATTERY_RC_LOW); - bat_info_value_ac = - ec_read16(INDEX_BATTERY_AC_HIGH, INDEX_BATTERY_AC_LOW); - if (bat_info_value_ac > 0) - power_info->fullchg_time = 60 * bat_info_value / bat_info_value_ac; - break; - /* Update power_info->curr_cap value */ - case BAT_REG_RSOC_FLAG: - power_info->remain_capacity_percent = it8528_read(INDEX_BATTERY_CAPACITY); - break; - /* Update power_info->cycle_count value */ - case BAT_REG_CYCLCNT_FLAG: - power_info->cycle_count = - ec_read16(INDEX_BATTERY_CYCLECNT_HIGH, INDEX_BATTERY_CYCLECNT_LOW); - break; + ft_power_info_power_status_update(); + bat_info_value = ec_read16(INDEX_BATTERY_TEMP_HIGH, INDEX_BATTERY_TEMP_LOW); + power_info->temperature = power_info->bat_in ? (bat_info_value - 2730) : 0; +} - default: - break; - } +static void ft_bat_update_voltage(void) +{ + int bat_info_value = ec_read16(INDEX_BATTERY_VOL_HIGH, INDEX_BATTERY_VOL_LOW); + + power_info->voltage_now = power_info->bat_in ? bat_info_value : 0; +} + +static void ft_bat_update_current(void) +{ + int bat_info_value = + ec_read16(INDEX_BATTERY_CURRENT_HIGH, INDEX_BATTERY_CURRENT_LOW); + + power_info->current_now = power_info->bat_in ? bat_info_value : 0; +} + +static void ft_bat_update_ac(void) +{ + int bat_info_value = ec_read16(INDEX_BATTERY_AC_HIGH, INDEX_BATTERY_AC_LOW); + + ft_power_info_power_status_update(); + power_info->current_average = power_info->bat_in ? bat_info_value : 0; +} + +static void ft_bat_update_rc(void) +{ + power_info->remain_capacity = + ec_read16(INDEX_BATTERY_RC_HIGH, INDEX_BATTERY_RC_LOW); +} + +static void ft_bat_update_fcc(void) +{ + power_info->full_charged_capacity = + ec_read16(INDEX_BATTERY_FCC_HIGH, INDEX_BATTERY_FCC_LOW); +} + +static void ft_bat_update_atte(void) +{ + int bat_info_value = ec_read16(INDEX_BATTERY_AC_HIGH, INDEX_BATTERY_AC_LOW); + + bat_info_value = bat_info_value > 0 ? bat_info_value : -bat_info_value; + if (bat_info_value) + power_info->remain_time = 60 * + ec_read16(INDEX_BATTERY_RC_HIGH, INDEX_BATTERY_RC_LOW) / + bat_info_value; +} + +static void ft_bat_update_attf(void) +{ + int bat_info_value = + ec_read16(INDEX_BATTERY_CAP_HIGH, INDEX_BATTERY_CAP_LOW) - + ec_read16(INDEX_BATTERY_RC_HIGH, INDEX_BATTERY_RC_LOW); + int bat_info_value_ac = + ec_read16(INDEX_BATTERY_AC_HIGH, INDEX_BATTERY_AC_LOW); + + if (bat_info_value_ac > 0) + power_info->fullchg_time = 60 * bat_info_value / bat_info_value_ac; +} + +static void ft_bat_update_rsoc(void) +{ + power_info->remain_capacity_percent = it8528_read(INDEX_BATTERY_CAPACITY); +} + +static void ft_bat_update_cyclcnt(void) +{ + power_info->cycle_count = + ec_read16(INDEX_BATTERY_CYCLECNT_HIGH, INDEX_BATTERY_CYCLECNT_LOW); +} + +static void (* const bat_update_table[])(void) = { + ft_bat_update_temp, + ft_bat_update_voltage, + ft_bat_update_current, + ft_bat_update_ac, + ft_bat_update_rc, + ft_bat_update_fcc, + ft_bat_update_atte, + ft_bat_update_attf, + ft_bat_update_rsoc, + ft_bat_update_cyclcnt, +}; + +/* Update battery information handle function. */ +static void ft_power_battery_info_update(unsigned char bat_reg_flag) +{ + if (bat_reg_flag < BAT_REG_TEMP_FLAG || bat_reg_flag > BAT_REG_CYCLCNT_FLAG) + return; + bat_update_table[bat_reg_flag - 1](); } /* Update battery information handle function. */ @@ -995,12 +1016,10 @@ static int ft_ac_get_property(struct power_supply *pws, } /* EC device AC event handler */ -static int ft_ac_handler(int status) +static void ft_ac_handler(int status) { /* Report status changed */ power_supply_changed(ec_ac); - - return 0; } /* EC device AC event handler */ @@ -1014,7 +1033,7 @@ int ft_ac_handler_test(void) EXPORT_SYMBOL(ft_ac_handler_test); /* LPC device Battery event handler */ -static int ft_bat_handler(int status) +static void ft_bat_handler(int status) { /* Battery insert/pull-out to handle battery static information. */ if (status & MASK(BIT_POWER_BATPRES)) { @@ -1026,15 +1045,12 @@ static int ft_bat_handler(int status) } /* Report status changed */ power_supply_changed(ec_bat); - - return 0; } /* LPC device LID event handler */ -static int ft_lid_handler(int status) +static void ft_lid_handler(int status) { ft_ec_lid_event(); - return 1; } /* Hotkey device init */ From 8e663d3a5d5c70f87170dd312c557b66838d520c Mon Sep 17 00:00:00 2001 From: Wentao Guan Date: Sat, 4 Jul 2026 03:29:35 +0800 Subject: [PATCH 4/5] phytium: ec: use devm helpers and platform device parent for gsensor deepin inclusion category: feature Simplify probe error handling and remove the last checkpatch warning: - Make ec_gsonsor_init() take the platform_device and create the gsensor sysfs group under &dev->dev.kobj instead of the private devices_kset. This eliminates the extern struct kset *devices_kset declaration. - Switch power_info, backlight and power_supply registrations to devm_* variants so most probe resources are auto-released on failure. - Collapse the long goto chain in ft_lpc_event_probe() to a single fail_after_gsensor cleanup path. - Remove the bogus platform_driver_unregister() call from probe's error path. Assisted-by: kimi-cli:kimi-k2.7 code Signed-off-by: Wentao Guan --- drivers/uos/phyt/ec/phyt_laptop.c | 56 ++++++++++++------------------- 1 file changed, 22 insertions(+), 34 deletions(-) diff --git a/drivers/uos/phyt/ec/phyt_laptop.c b/drivers/uos/phyt/ec/phyt_laptop.c index 841255f4e737f..de8f395e0c2fe 100644 --- a/drivers/uos/phyt/ec/phyt_laptop.c +++ b/drivers/uos/phyt/ec/phyt_laptop.c @@ -33,8 +33,7 @@ static inline u16 ec_read16(u8 high, u8 low) static bool ft_display_state = true; static unsigned int ft_display_level; static int ft_set_display_on(bool on); - -extern struct kset *devices_kset; +static int ec_gsonsor_init(struct platform_device *pdev); #define EC_LPC_DEV "ec" @@ -1126,7 +1125,7 @@ static struct attribute_group gsensor_attr_group = { static struct kobject *gsensor_kobj; /* Gsensor device init */ -int ec_gsonsor_init(void) +int ec_gsonsor_init(struct platform_device *pdev) { int ret; @@ -1140,6 +1139,7 @@ int ec_gsonsor_init(void) ec_gsensor_dev->name = "EC_Gsensor"; ec_gsensor_dev->uniq = "EC_Gsensor"; ec_gsensor_dev->id.bustype = BUS_HOST; + ec_gsensor_dev->dev.parent = &pdev->dev; set_bit(EV_SYN, ec_gsensor_dev->evbit); set_bit(EV_ABS, ec_gsensor_dev->evbit); @@ -1160,7 +1160,7 @@ int ec_gsonsor_init(void) return ret; } - gsensor_kobj = kobject_create_and_add("gsensor", &devices_kset->kobj); + gsensor_kobj = kobject_create_and_add("gsensor", &pdev->dev.kobj); if (!gsensor_kobj) return -ENOMEM; ret = sysfs_create_group(gsensor_kobj, &gsensor_attr_group); @@ -1256,11 +1256,11 @@ static int ft_lpc_event_probe(struct platform_device *dev) /* Regist backlight */ if (chassis_types_is_laptop() || chassis_types_is_allinone()) { - ft_backlight_dev = backlight_device_register("phytium", NULL, NULL, - &ft_backlight_ops, NULL); + ft_backlight_dev = devm_backlight_device_register(&dev->dev, "phytium", + &dev->dev, NULL, &ft_backlight_ops, NULL); if (IS_ERR(ft_backlight_dev)) { ret = PTR_ERR(ft_backlight_dev); - goto fail_backlight_device_register; + return ret; } ft_backlight_dev->props.max_brightness = 100; @@ -1279,21 +1279,21 @@ static int ft_lpc_event_probe(struct platform_device *dev) ret = ft_hotkey_init(); if (ret) { pr_err("phytium Platform Driver: Hotkey init fail.\n"); - goto fail_hotkey_init; + return ret; } - ret = ec_gsonsor_init(); + ret = ec_gsonsor_init(dev); if (ret) { pr_err("phytium Platform Driver: Gsensor init fail.\n"); - goto fail_gsensor_init; + ft_hotkey_exit(); + return ret; } - /* Register power supply START */ - power_info = kzalloc(sizeof(struct ft_power_info), GFP_KERNEL); + power_info = devm_kzalloc(&dev->dev, sizeof(struct ft_power_info), GFP_KERNEL); if (!power_info) { ret = -ENOMEM; - goto fail_power_info_alloc; + goto fail_after_gsensor; } ft_power_battery_info_init(); @@ -1307,16 +1307,16 @@ static int ft_lpc_event_probe(struct platform_device *dev) } if (chassis_types_is_laptop() && power_info->bat_in) { - ec_bat = power_supply_register(NULL, &ft_bat, NULL); + ec_bat = devm_power_supply_register(&dev->dev, &ft_bat, NULL); if (IS_ERR(ec_bat)) { ret = -ENOMEM; - goto fail_bat_power_supply_register; + goto fail_after_gsensor; } - ec_ac = power_supply_register(NULL, &ft_ac, NULL); + ec_ac = devm_power_supply_register(&dev->dev, &ft_ac, NULL); if (IS_ERR(ec_ac)) { ret = -ENOMEM; - goto fail_ac_power_supply_register; + goto fail_after_gsensor; } } /* Register power supply END */ @@ -1330,24 +1330,22 @@ static int ft_lpc_event_probe(struct platform_device *dev) ret = gpio_driver_init(gpio_irq); if (ret) { pr_err("phytium ec: gpio driver init fail.\n"); - goto fail_gpio_pci_driver_init; + goto fail_after_gsensor; } } else { /* LPC Driver Init Start */ ret = lpc_driver_init(); if (ret) { pr_err("phytium: LPC driver init fail.\n"); - goto fail_lpc_pci_driver_init; + goto fail_after_gsensor; } } - - /* clean ec evnet queue*/ ret = it8528_query_clean_event(); if (ret) { pr_err("EC clean event fail.\n"); - goto fail_lpc_pci_driver_init; + goto fail_after_gsensor; } /* enable ec event interrupt */ @@ -1356,20 +1354,10 @@ static int ft_lpc_event_probe(struct platform_device *dev) pr_debug("phytium: ec event driver init done...\n"); return 0; -fail_gsensor_init: + +fail_after_gsensor: ec_gsensor_exit(); -fail_hotkey_init: -fail_lpc_pci_driver_init: -fail_gpio_pci_driver_init: ft_hotkey_exit(); -fail_ac_power_supply_register: - power_supply_unregister(ec_bat); -fail_bat_power_supply_register: - kfree(power_info); -fail_power_info_alloc: - backlight_device_unregister(ft_backlight_dev); -fail_backlight_device_register: - platform_driver_unregister(&ft_ec_pdriver); return ret; } From 16e19a7aec37b9b917c6a8fde3fd0962ec1e26a7 Mon Sep 17 00:00:00 2001 From: Wentao Guan Date: Sat, 4 Jul 2026 03:49:08 +0800 Subject: [PATCH 5/5] platform: arm64: phytium: move ec driver to platform directory Relocate the Phytium EC/laptop drivers from the vendor-specific UOS directory tree to drivers/platform/arm64/phytium, following the upstream convention of architecture-specific platform driver directories (e.g. drivers/platform/x86, drivers/platform/loongarch). - Add ARM64_PLATFORM_DEVICES menuconfig under drivers/platform/arm64. - Drop the UOS_PHYTIUM_DESKTOP_SUPPORT indirection and the drivers/uos/ tree entirely. - Update MAINTAINERS and the defconfig accordingly. Assisted-by: kimi-cli:kimi-k2.7 code Signed-off-by: Wentao Guan --- MAINTAINERS | 5 ++- .../configs/deepin_arm64_desktop_defconfig | 7 ++-- drivers/Kconfig | 2 -- drivers/Makefile | 2 -- drivers/platform/Kconfig | 2 ++ drivers/platform/Makefile | 2 ++ drivers/platform/arm64/Kconfig | 36 +++++++++++++++++++ drivers/platform/arm64/Makefile | 3 ++ .../ec => platform/arm64/phytium}/Makefile | 2 +- .../ec => platform/arm64/phytium}/ec_it8528.c | 0 .../ec => platform/arm64/phytium}/ec_it8528.h | 0 .../ec => platform/arm64/phytium}/ec_sensor.c | 0 .../arm64/phytium}/phyt_laptop.c | 0 drivers/uos/Kconfig | 5 --- drivers/uos/Makefile | 3 -- drivers/uos/phyt/Kconfig | 35 ------------------ drivers/uos/phyt/Makefile | 6 ---- 17 files changed, 49 insertions(+), 61 deletions(-) create mode 100644 drivers/platform/arm64/Kconfig create mode 100644 drivers/platform/arm64/Makefile rename drivers/{uos/phyt/ec => platform/arm64/phytium}/Makefile (71%) rename drivers/{uos/phyt/ec => platform/arm64/phytium}/ec_it8528.c (100%) rename drivers/{uos/phyt/ec => platform/arm64/phytium}/ec_it8528.h (100%) rename drivers/{uos/phyt/ec => platform/arm64/phytium}/ec_sensor.c (100%) rename drivers/{uos/phyt/ec => platform/arm64/phytium}/phyt_laptop.c (100%) delete mode 100644 drivers/uos/Kconfig delete mode 100644 drivers/uos/Makefile delete mode 100644 drivers/uos/phyt/Kconfig delete mode 100644 drivers/uos/phyt/Makefile diff --git a/MAINTAINERS b/MAINTAINERS index 76115232115b0..2c32b42327730 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -17570,9 +17570,8 @@ F: drivers/usb/phytium/phytium_usb_v2* F: drivers/usb/typec/role-switch-phytium.c F: arch/arm64/boot/dts/phytium/* F: drivers/gpio/gpio-phytium* -F: drivers/uos/* -F: drivers/uos/phyt/* -F: drivers/uos/phyt/ec/* +F: drivers/platform/arm64/ +F: drivers/platform/arm64/phytium/* F: include/linux/classtypes.h F: include/linux/cputypes.h F: lib/classtypes.c diff --git a/arch/arm64/configs/deepin_arm64_desktop_defconfig b/arch/arm64/configs/deepin_arm64_desktop_defconfig index f3c423a5faf48..f249c15a5c53c 100644 --- a/arch/arm64/configs/deepin_arm64_desktop_defconfig +++ b/arch/arm64/configs/deepin_arm64_desktop_defconfig @@ -818,10 +818,6 @@ CONFIG_MOXTET=m CONFIG_HISILICON_LPC=y CONFIG_IMX_WEIM=y CONFIG_PHYTIUM_PIO=y -CONFIG_UOS_PHYTIUM_DESKTOP_SUPPORT=y -CONFIG_PHYTIUM_EC=y -CONFIG_PHYTIUM_LAPTOP=y -CONFIG_SERIO_I8042=y CONFIG_QCOM_SSC_BLOCK_BUS=y CONFIG_SUNXI_RSB=m CONFIG_TEGRA_ACONNECT=m @@ -4026,6 +4022,9 @@ CONFIG_QLGE=m CONFIG_PHYTIUM_NPU=m CONFIG_NPU_PLATFORM=m CONFIG_PHYTIUM_NPU_PCI=m +CONFIG_ARM64_PLATFORM_DEVICES=y +CONFIG_PHYTIUM_EC=y +CONFIG_PHYTIUM_LAPTOP=y CONFIG_GOLDFISH=y CONFIG_CHROME_PLATFORMS=y CONFIG_MELLANOX_PLATFORM=y diff --git a/drivers/Kconfig b/drivers/Kconfig index 0d6284e2bc485..83ff63c256b71 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -245,6 +245,4 @@ source "drivers/cdx/Kconfig" source "drivers/cpuinspect/Kconfig" -source "drivers/uos/Kconfig" - endmenu diff --git a/drivers/Makefile b/drivers/Makefile index c9c59f091565a..99dbd33629138 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -199,6 +199,4 @@ obj-$(CONFIG_HTE) += hte/ obj-$(CONFIG_DRM_ACCEL) += accel/ obj-$(CONFIG_CDX_BUS) += cdx/ -obj-y += uos/ - obj-$(CONFIG_S390) += s390/ diff --git a/drivers/platform/Kconfig b/drivers/platform/Kconfig index 868b20361769c..db244cbd362fd 100644 --- a/drivers/platform/Kconfig +++ b/drivers/platform/Kconfig @@ -1,4 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only +source "drivers/platform/arm64/Kconfig" + source "drivers/platform/mips/Kconfig" source "drivers/platform/loongarch/Kconfig" diff --git a/drivers/platform/Makefile b/drivers/platform/Makefile index 8296d4c41eb77..4c2bf61715f4d 100644 --- a/drivers/platform/Makefile +++ b/drivers/platform/Makefile @@ -3,6 +3,8 @@ # Makefile for linux/drivers/platform # +obj-$(CONFIG_ARM64) += arm64/ + obj-$(CONFIG_X86) += x86/ obj-$(CONFIG_LOONGARCH) += loongarch/ obj-$(CONFIG_SW64) += sw64/ diff --git a/drivers/platform/arm64/Kconfig b/drivers/platform/arm64/Kconfig new file mode 100644 index 0000000000000..b94fdbefaf247 --- /dev/null +++ b/drivers/platform/arm64/Kconfig @@ -0,0 +1,36 @@ +# SPDX-License-Identifier: GPL-2.0-only + +menuconfig ARM64_PLATFORM_DEVICES + bool "ARM64 platform devices" + depends on ARM64 + help + Say Y here to enable platform-specific drivers for ARM64 systems. + These drivers provide support for vendor-specific hardware that is + not covered by standard subsystem drivers, such as embedded + controllers, laptop hotkeys, backlight and power supply controls. + +if ARM64_PLATFORM_DEVICES + +config PHYTIUM_EC + bool "Phytium IT8528 Embedded Controller support" + depends on PHYTIUM_PIO + help + Enable support for the IT8528 Embedded Controller found on some + Phytium laptop platforms. This driver communicates with the EC + over the Phytium PIO (Programmed I/O) path and is required by the + Phytium laptop driver for battery, lid and hotkey support. + +config PHYTIUM_LAPTOP + bool "Phytium laptop platform support" + depends on PHYTIUM_EC + select POWER_SUPPLY + select BACKLIGHT_CLASS_DEVICE + select INPUT_SPARSEKMAP + select HWMON + help + Enable laptop-specific support for Phytium platforms. This + provides power-supply reporting (AC and battery), backlight + control, lid status and Fn hotkey handling through the IT8528 + embedded controller. + +endif diff --git a/drivers/platform/arm64/Makefile b/drivers/platform/arm64/Makefile new file mode 100644 index 0000000000000..6f23139ddf7b1 --- /dev/null +++ b/drivers/platform/arm64/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 + +obj-$(CONFIG_ARM64_PLATFORM_DEVICES) += phytium/ diff --git a/drivers/uos/phyt/ec/Makefile b/drivers/platform/arm64/phytium/Makefile similarity index 71% rename from drivers/uos/phyt/ec/Makefile rename to drivers/platform/arm64/phytium/Makefile index 99be4fe85b370..75a5271c8a7b5 100644 --- a/drivers/uos/phyt/ec/Makefile +++ b/drivers/platform/arm64/phytium/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 # -# Makefile for the Phytium notebook EC/laptop drivers. +# Makefile for Phytium platform drivers. # obj-$(CONFIG_PHYTIUM_EC) += ec_it8528.o diff --git a/drivers/uos/phyt/ec/ec_it8528.c b/drivers/platform/arm64/phytium/ec_it8528.c similarity index 100% rename from drivers/uos/phyt/ec/ec_it8528.c rename to drivers/platform/arm64/phytium/ec_it8528.c diff --git a/drivers/uos/phyt/ec/ec_it8528.h b/drivers/platform/arm64/phytium/ec_it8528.h similarity index 100% rename from drivers/uos/phyt/ec/ec_it8528.h rename to drivers/platform/arm64/phytium/ec_it8528.h diff --git a/drivers/uos/phyt/ec/ec_sensor.c b/drivers/platform/arm64/phytium/ec_sensor.c similarity index 100% rename from drivers/uos/phyt/ec/ec_sensor.c rename to drivers/platform/arm64/phytium/ec_sensor.c diff --git a/drivers/uos/phyt/ec/phyt_laptop.c b/drivers/platform/arm64/phytium/phyt_laptop.c similarity index 100% rename from drivers/uos/phyt/ec/phyt_laptop.c rename to drivers/platform/arm64/phytium/phyt_laptop.c diff --git a/drivers/uos/Kconfig b/drivers/uos/Kconfig deleted file mode 100644 index 5d7eb0ce07a52..0000000000000 --- a/drivers/uos/Kconfig +++ /dev/null @@ -1,5 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -menu "UOS Driver config" - -source "drivers/uos/phyt/Kconfig" -endmenu diff --git a/drivers/uos/Makefile b/drivers/uos/Makefile deleted file mode 100644 index bf91eeaf69a90..0000000000000 --- a/drivers/uos/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 - -obj-$(CONFIG_UOS_PHYTIUM_DESKTOP_SUPPORT) += phyt/ diff --git a/drivers/uos/phyt/Kconfig b/drivers/uos/phyt/Kconfig deleted file mode 100644 index 2ed2832b0f5bf..0000000000000 --- a/drivers/uos/phyt/Kconfig +++ /dev/null @@ -1,35 +0,0 @@ -menuconfig UOS_PHYTIUM_DESKTOP_SUPPORT - bool "phytium desktop drivers/fixups provided by UOS" - default n - help - This option enables a collection of UOS-supplied drivers and - quirks for Phytium desktop and laptop platforms. These drivers - are not part of the standard upstream kernel and should only be - enabled when running on supported Phytium systems. - -if UOS_PHYTIUM_DESKTOP_SUPPORT - -config PHYTIUM_EC - bool "phytium ec support" - depends on PHYTIUM_PIO - default n - help - Enable support for the IT8528 Embedded Controller found on some - Phytium laptop platforms. This driver communicates with the EC - over the Phytium PIO (Programmed I/O) path and is required by the - Phytium laptop driver for battery, lid and hotkey support. - -config PHYTIUM_LAPTOP - bool "phytium laptop support" - depends on PHYTIUM_EC - select POWER_SUPPLY - select BACKLIGHT_CLASS_DEVICE - select INPUT_SPARSEKMAP - select HWMON - help - Enable laptop-specific support for Phytium platforms. This - provides power-supply reporting (AC and battery), backlight - control, lid status and Fn hotkey handling through the IT8528 - embedded controller. - -endif diff --git a/drivers/uos/phyt/Makefile b/drivers/uos/phyt/Makefile deleted file mode 100644 index f07f83de9ed38..0000000000000 --- a/drivers/uos/phyt/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# -# Makefile for the Phytium notebook EC/laptop drivers. -# - -obj-$(CONFIG_UOS_PHYTIUM_DESKTOP_SUPPORT) += ec/