Merge commit '043518cce67dbcdf345684faacb9aedc54784bda'

* commit '043518cce67dbcdf345684faacb9aedc54784bda': (28 commits)
  ASoC: rockchip: multi-dais: Add legacy_dai_naming flag
  arm64: dts: rockchip: rk3588 boards: fix maximum-speed for usbdp node
  dt-bindings: opp: rockchip: Document rockchip,pvtpll
  soc: rockchip: opp_select: Add support to parse rockchip,pvtpll
  soc: rockchip: opp_select: Add support to parse cci grf
  dt-bindings: opp: rockchip: Document CCI GRF
  soc: rockchip: opp_select: Fix clk error for normal pll clk
  soc: rockchip: opp_select: Add support to set regulator helper
  init: Add CONFIG_ROCKCHIP_THUNDER_BOOT_DEFER_FREE_MEMBLOCK
  mm: memblock: fix only first memblock be freed.
  arm64: dts: rockchip: AMP memory use reserved-memory
  media: i2c: rk628: add hdmirx extcon
  drm/panel: panel-simple: Don't init gpio value at probe
  ASoC: rockchip: multicodec: Fix err path for adc-key
  ASoC: rockchip: spdifrx: Add legacy_dai_naming flag
  spi: spidev-rkslv: Fix compiler error
  media: i2c: ov8865: add camera driver
  media: i2c: add vcm driver ces6301
  media: i2c: s5k3l8xx: adjust power sequence to suit spec
  media: i2c: gc05a2: adjust power sequence to suit spec
  ...

Change-Id: I50aa93e3b8048e85dd446acd4922518652c05a1c
This commit is contained in:
Tao Huang
2024-03-01 18:51:27 +08:00
87 changed files with 25842 additions and 3143 deletions

View File

@@ -51,6 +51,7 @@ In 'operating-points-v2' table:
- rockchip,grf: The phandle of the syscon node for GRF register.
- rockchip,dsu-grf: the phandle of the syscon node for DSU GRF register.
- rockchip,cci-grf: the phandle of the syscon node for CCI GRF register.
- rockchip,opp-clocks: List of clocks for accessing pvtpll and read margin.
- volt-mem-read-margin: The property is an array of 2-tuples items, and
each item consists voltage an memory read margin like
@@ -61,6 +62,7 @@ In 'operating-points-v2' table:
target frequency less than the threshold frequency,
there may be no need to set intermediate rate.
- rockchip,pvtpll: The phandle of the syscon node for PVTPLL register.
- rockchip,pvtpll-table: The property is an array of 5-tuples items, and
each item consists frequency and pvtpll config like
<freq_khz ring length low_temp_ring low_temp_length>,

View File

@@ -10,10 +10,15 @@
#include "rk3562-amp.dtsi"
/ {
memory {
device_type = "memory";
reg = <0x0 0x02000000 0x0 0x06400000>,
<0x0 0x0a200000 0x0 0xf1e00000>;
reserved-memory {
#address-cells = <2>;
#size-cells = <2>;
ranges;
amp_reserved: amp@800000 {
reg = <0x0 0x00800000 0x0 0x01800000>;
no-map;
};
};
};

View File

@@ -11,10 +11,15 @@
#include "rk3562-amp.dtsi"
/ {
memory {
device_type = "memory";
reg = <0x0 0x02000000 0x0 0x04b80000>,
<0x0 0x0a200000 0x0 0x75e00000>;
reserved-memory {
#address-cells = <2>;
#size-cells = <2>;
ranges;
amp_reserved: amp@800000 {
reg = <0x0 0x00800000 0x0 0x01800000>;
no-map;
};
};
};

View File

@@ -14,7 +14,7 @@
model = "Rockchip RK3566 EVB MIPITEST V10 Board";
compatible = "rockchip,rk3566-evb-mipitest-v10", "rockchip,rk3566";
vcc3v3_pcie: gpio-regulator {
vcc3v3_pcie: vcc3v3-pcie {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_pcie";
regulator-min-microvolt = <3300000>;

View File

@@ -14,7 +14,7 @@
model = "Rockchip RK3566 EVB1 DDR4 V10 Board";
compatible = "rockchip,rk3566-evb1-ddr4-v10", "rockchip,rk3566";
vcc3v3_pcie: gpio-regulator {
vcc3v3_pcie: vcc3v3-pcie {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_pcie";
regulator-min-microvolt = <3300000>;

View File

@@ -27,7 +27,7 @@
regulator-boot-on;
};
vcc3v3_pcie: gpio-regulator {
vcc3v3_pcie: vcc3v3-pcie {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_pcie";
regulator-min-microvolt = <3300000>;

View File

@@ -14,7 +14,7 @@
model = "Rockchip RK3566 EVB5 LP4X V10 Board";
compatible = "rockchip,rk3566-evb5-lp4x-v10", "rockchip,rk3566";
vcc3v3_pcie: gpio-regulator {
vcc3v3_pcie: vcc3v3-pcie {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_pcie";
regulator-min-microvolt = <3300000>;

View File

@@ -27,7 +27,7 @@
regulator-boot-on;
};
vcc3v3_pcie: gpio-regulator {
vcc3v3_pcie: vcc3v3-pcie {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_pcie";
regulator-min-microvolt = <3300000>;

View File

@@ -8,10 +8,15 @@
#include "rk3568-amp.dtsi"
/ {
memory {
device_type = "memory";
reg = <0x0 0x03880000 0x0 0x04b80000>,
<0x0 0x0a200000 0x0 0x75e00000>;
reserved-memory {
#address-cells = <2>;
#size-cells = <2>;
ranges;
amp_reserved: amp@1800000 {
reg = <0x0 0x01800000 0x0 0x01800000>;
no-map;
};
};
};

View File

@@ -55,7 +55,7 @@
vin-supply = <&vcc3v3_sys>;
};
vcc3v3_pcie: gpio-regulator {
vcc3v3_pcie: vcc3v3-pcie {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_pcie";
regulator-min-microvolt = <3300000>;

View File

@@ -32,7 +32,7 @@
vin-supply = <&vcc3v3_sys>;
};
vcc3v3_pcie: gpio-regulator {
vcc3v3_pcie: vcc3v3-pcie {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_pcie";
regulator-min-microvolt = <3300000>;
@@ -43,7 +43,7 @@
vin-supply = <&dc_12v>;
};
qsgmii_3v3: gpio-regulator {
qsgmii_3v3: qsgmii-3v3 {
compatible = "regulator-gpio";
regulator-name = "qsgmii_3v3";
regulator-min-microvolt = <0100000>;

View File

@@ -52,7 +52,7 @@
vin-supply = <&vcc3v3_sys>;
};
vcc3v3_pcie: gpio-regulator {
vcc3v3_pcie: vcc3v3-pcie {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_pcie";
regulator-min-microvolt = <3300000>;

View File

@@ -20,7 +20,7 @@
pinctrl-0 = <&hp_det>;
};
vcc3v3_pcie: gpio-regulator {
vcc3v3_pcie: vcc3v3-pcie {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_pcie";
regulator-min-microvolt = <3300000>;

View File

@@ -54,7 +54,7 @@
vin-supply = <&vcc3v3_sys>;
};
vcc3v3_pcie: gpio-regulator {
vcc3v3_pcie: vcc3v3-pcie {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_pcie";
regulator-min-microvolt = <3300000>;

View File

@@ -94,7 +94,7 @@
status = "okay";
};
vcc3v3_pcie: gpio-regulator {
vcc3v3_pcie: vcc3v3-pcie {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_pcie";
regulator-min-microvolt = <3300000>;

View File

@@ -51,7 +51,7 @@
vin-supply = <&vcc3v3_sys>;
};
pcie30_3v3: gpio-regulator {
pcie30_3v3: pcie30-3v3 {
compatible = "regulator-gpio";
regulator-name = "pcie30_3v3";
regulator-min-microvolt = <100000>;
@@ -80,7 +80,7 @@
vin-supply = <&vcc3v3_sys>;
};
vcc3v3_pcie: gpio-regulator {
vcc3v3_pcie: vcc3v3-pcie {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_pcie";
regulator-min-microvolt = <3300000>;

View File

@@ -66,7 +66,7 @@
};
};
pcie20_3v3: gpio-regulator {
pcie20_3v3: pcie20-3v3 {
compatible = "regulator-gpio";
regulator-name = "pcie20_3v3";
regulator-min-microvolt = <100000>;
@@ -97,7 +97,7 @@
vin-supply = <&vcc3v3_sys>;
};
pcie30_3v3: gpio-regulator {
pcie30_3v3: pcie30-3v3 {
compatible = "regulator-gpio";
regulator-name = "pcie30_3v3";
regulator-min-microvolt = <100000>;

View File

@@ -23,12 +23,15 @@
};
};
memory {
device_type = "memory";
reg = <0x0 0x02000000 0x0 0x06400000>,
<0x0 0x09400000 0x0 0xe6c00000>,
<0x1 0x00000000 0x1 0x00000000>,
<0x2 0xf0000000 0x0 0x10000000>;
reserved-memory {
#address-cells = <2>;
#size-cells = <2>;
ranges;
amp_reserved: amp@800000 {
reg = <0x0 0x00800000 0x0 0x01800000>;
no-map;
};
};
};

View File

@@ -828,6 +828,7 @@
};
&usbdp_phy1 {
maximum-speed = "high-speed";
rockchip,dp-lane-mux = <3 2 1 0>;
status = "okay";
};
@@ -837,7 +838,6 @@
};
&usbdp_phy1_u3 {
maximum-speed = "high-speed";
status = "okay";
};

View File

@@ -795,6 +795,7 @@
};
&usbdp_phy1 {
maximum-speed = "high-speed";
rockchip,dp-lane-mux = < 0 1 2 3 >;
status = "okay";
};
@@ -804,7 +805,6 @@
};
&usbdp_phy1_u3 {
maximum-speed = "high-speed";
status = "okay";
};

View File

@@ -368,6 +368,7 @@
};
&usbdp_phy1 {
maximum-speed = "high-speed";
rockchip,dp-lane-mux = <3 2 1 0>;
status = "okay";
};
@@ -377,7 +378,6 @@
};
&usbdp_phy1_u3 {
maximum-speed = "high-speed";
status = "okay";
};

View File

@@ -388,6 +388,7 @@
};
&usbdp_phy1 {
maximum-speed = "high-speed";
rockchip,dp-lane-mux = <3 2 1 0>;
status = "okay";
};
@@ -397,7 +398,6 @@
};
&usbdp_phy1_u3 {
maximum-speed = "high-speed";
status = "okay";
};

View File

@@ -647,6 +647,7 @@
};
&usbdp_phy1 {
maximum-speed = "high-speed";
rockchip,dp-lane-mux = <3 2 1 0>;
status = "okay";
};
@@ -656,7 +657,6 @@
};
&usbdp_phy1_u3 {
maximum-speed = "high-speed";
status = "okay";
};

View File

@@ -224,6 +224,7 @@
};
&usbdp_phy1 {
maximum-speed = "high-speed";
rockchip,dp-lane-mux = <3 2 1 0>;
status = "disabled";
};
@@ -233,7 +234,6 @@
};
&usbdp_phy1_u3 {
maximum-speed = "high-speed";
status = "okay";
};

View File

@@ -585,8 +585,8 @@ static int panel_simple_suspend(struct device *dev)
}
}
gpiod_set_value_cansleep(p->reset_gpio, 1);
gpiod_set_value_cansleep(p->enable_gpio, 0);
gpiod_direction_output(p->reset_gpio, 1);
gpiod_direction_output(p->enable_gpio, 0);
panel_simple_regulator_disable(p);
@@ -630,7 +630,7 @@ static int panel_simple_resume(struct device *dev)
return err;
}
gpiod_set_value_cansleep(p->enable_gpio, 1);
gpiod_direction_output(p->enable_gpio, 1);
if (p->desc->delay.prepare)
panel_simple_msleep(p->desc->delay.prepare);
@@ -642,12 +642,12 @@ static int panel_simple_resume(struct device *dev)
return 0;
}
gpiod_set_value_cansleep(p->reset_gpio, 1);
gpiod_direction_output(p->reset_gpio, 1);
if (p->desc->delay.reset)
panel_simple_msleep(p->desc->delay.reset);
gpiod_set_value_cansleep(p->reset_gpio, 0);
gpiod_direction_output(p->reset_gpio, 0);
if (p->desc->delay.init)
panel_simple_msleep(p->desc->delay.init);

View File

@@ -198,6 +198,8 @@ config TOUCHSCREEN_CHIPONE_ICN8505
To compile this driver as a module, choose M here: the
module will be called chipone_icn8505.
source "drivers/input/touchscreen/chipone_tddi/Kconfig"
config TOUCHSCREEN_CY8CTMA140
tristate "cy8ctma140 touchscreen"
depends on I2C

View File

@@ -22,6 +22,7 @@ obj-$(CONFIG_TOUCHSCREEN_BU21013) += bu21013_ts.o
obj-$(CONFIG_TOUCHSCREEN_BU21029) += bu21029_ts.o
obj-$(CONFIG_TOUCHSCREEN_CHIPONE_ICN8318) += chipone_icn8318.o
obj-$(CONFIG_TOUCHSCREEN_CHIPONE_ICN8505) += chipone_icn8505.o
obj-$(CONFIG_TOUCHSCREEN_CHIPONE_9551R) += chipone_tddi/
obj-$(CONFIG_TOUCHSCREEN_CY8CTMA140) += cy8ctma140.o
obj-$(CONFIG_TOUCHSCREEN_CY8CTMG110) += cy8ctmg110_ts.o
obj-$(CONFIG_TOUCHSCREEN_CYTTSP_CORE) += cyttsp_core.o

View File

@@ -0,0 +1,12 @@
# SPDX-License-Identifier: GPL-2.0-or-later
#
# chipone Touchscreen driver configuration
#
config TOUCHSCREEN_CHIPONE_9551R
tristate "chipone Touchscreen"
depends on I2C
default n
help
Say Y here if you have chipone touch panel.
If unsure, say N.

View File

@@ -0,0 +1,17 @@
# SPDX-License-Identifier: GPL-2.0-or-later
obj-$(CONFIG_TOUCHSCREEN_CHIPONE_9551R) += chipone-ts.o
chipone-ts-y += cts_driver.o
chipone-ts-y += cts_core.o
chipone-ts-y += cts_sfctrlv2.o
chipone-ts-y += cts_spi_flash.o
chipone-ts-y += cts_firmware.o
chipone-ts-y += cts_test.o
chipone-ts-y += cts_charger_detect.o
chipone-ts-y += cts_earjack_detect.o
chipone-ts-y += cts_tcs.o
chipone-ts-y += cts_platform.o
chipone-ts-y += cts_tool.o
chipone-ts-y += cts_sysfs.o
chipone-ts-y += cts_strerror.o
chipone-ts-y += cts_oem.o

View File

@@ -0,0 +1,25 @@
// SPDX-License-Identifier: GPL-2.0-or-later
static u8 icnl9951_driver_builtin_firmware[] = {
};
static u8 icnl9951r_driver_builtin_firmware[] = {
};
static struct cts_firmware cts_driver_builtin_firmwares[] = {
{
.name = "OEM-Project", /* MUST set non-NULL */
.hwid = CTS_DEV_HWID_ICNL9951,
.fwid = CTS_DEV_FWID_ICNL9951,
.data = icnl9951_driver_builtin_firmware,
.size = ARRAY_SIZE(icnl9951_driver_builtin_firmware),
},
{
.name = "OEM-Project", /* MUST set non-NULL */
.hwid = CTS_DEV_HWID_ICNL9951R,
.fwid = CTS_DEV_FWID_ICNL9951R,
.data = icnl9951r_driver_builtin_firmware,
.size = ARRAY_SIZE(icnl9951r_driver_builtin_firmware),
},
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,45 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#ifndef CTS_CHARGER_DETECT_H
#define CTS_CHARGER_DETECT_H
#include "cts_config.h"
struct chipone_ts_data;
#ifdef CONFIG_CTS_CHARGER_DETECT
extern int cts_charger_detect_init(struct chipone_ts_data *cts_data);
extern int cts_charger_detect_deinit(struct chipone_ts_data *cts_data);
extern int cts_start_charger_detect(struct chipone_ts_data *cts_data);
extern int cts_stop_charger_detect(struct chipone_ts_data *cts_data);
extern int cts_is_charger_attached(struct chipone_ts_data *cts_data,
bool *attached);
#else /* CONFIG_CTS_CHARGER_DETECT */
static inline int cts_charger_detect_init(struct chipone_ts_data *cts_data)
{
return -ENOTSUPP;
}
static inline int cts_charger_detect_deinit(struct chipone_ts_data *cts_data)
{
return -ENOTSUPP;
}
static inline int cts_start_charger_detect(struct chipone_ts_data *cts_data)
{
return -ENODEV;
}
static inline int cts_stop_charger_detect(struct chipone_ts_data *cts_data)
{
return -ENODEV;
}
static inline int cts_is_charger_attached(struct chipone_ts_data *cts_data,
bool *attached)
{
return -ENODEV;
}
#endif /* CONFIG_CTS_CHARGER_DETECT */
#endif /* CTS_CHARGER_DETECT_H */

View File

@@ -0,0 +1,242 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#ifndef CTS_CONFIG_H
#define CTS_CONFIG_H
/** Driver version */
#define CFG_CTS_DRIVER_MAJOR_VERSION 3
#define CFG_CTS_DRIVER_MINOR_VERSION 6
#define CFG_CTS_DRIVER_PATCH_VERSION 3
#define CFG_CTS_DRIVER_VERSION "v3.6.3"
/* Support Mediatek TPD arch */
/* #define CFG_CTS_PLATFORM_MTK_TPD_SUPPORTED */
/* Support Spreadtrum platform */
#define CFG_CTS_PLATFORM_SPRD_SUPPORTED
/* Support cascade application */
//#define CFG_CTS_CASCADE_SUPPORTED
/* Support RK dsi extcon notifier for suspend and resume */
#define CONFIG_PM_DSI_EXTCON_NOTIFIER
/* Support both finger and stylus protocol, 11 */
// #define CFG_CTS_FINGER_STYLUS_SUPPORTED
/* #define CFG_CTS_STYLUS_BTN_SUPPORTED */
#define CONFIG_CTS_I2C_HOST
/* For Goole Security */
#define CFG_CTS_FOR_GKI
/** Whether reset pin is used */
#define CFG_CTS_HAS_RESET_PIN
#ifndef CONFIG_CTS_I2C_HOST
#ifndef CFG_CTS_HAS_RESET_PIN
#define CFG_CTS_HAS_RESET_PIN
#endif
#define CFG_CTS_SPI_SPEED_KHZ 9600
#endif /* CONFIG_CTS_I2C_HOST */
/* #define CFG_CTS_FORCE_UP */
/* #define CFG_CTS_HEARTBEAT_MECHANISM */
/* #define CFG_CTS_PALM_DETECT */
#ifdef CFG_CTS_PALM_DETECT
#define CFG_CTS_PALM_EVENT 240
#define CFG_CTS_PALM_ID 0x80
#endif
#define CONFIG_GENERIC_HARDIRQS
/** Whether force download firmware to chip */
/* #define CFG_CTS_FIRMWARE_FORCE_UPDATE */
/** Use build in firmware or firmware file in fs*/
#define CFG_CTS_DRIVER_BUILTIN_FIRMWARE
#define CFG_CTS_FIRMWARE_IN_FS
#ifdef CFG_CTS_FIRMWARE_IN_FS
/* #define CFG_CTS_FW_UPDATE_SYS */
#define CFG_CTS_FIRMWARE_FILENAME "chipone_firmware.bin"
#endif /* CFG_CTS_FIRMWARE_IN_FS */
#define CFG_CTS_FIRMWARE_SIZE (120 * 1024)
#define CFG_CTS_FACTORY_LIMIT_FILENAME "chipone_limit.bin"
/* IC type support */
#define CFG_CTS_CHIP_NAME "CHIPONE-TDDI"
#ifdef CONFIG_PROC_FS
/* Proc FS for backward compatibility for APK tool com.ICN85xx */
#define CONFIG_CTS_LEGACY_TOOL
#endif /* CONFIG_PROC_FS */
#ifdef CONFIG_SYSFS
/* Sys FS for gesture report, debug feature etc. */
#define CONFIG_CTS_SYSFS
#endif /* CONFIG_SYSFS */
#define CFG_CTS_MAX_TOUCH_NUM (10)
#define CFG_CTS_MAX_STYLUS_NUM (4)
/* Virtual key support */
/* #define CONFIG_CTS_VIRTUALKEY */
#ifdef CONFIG_CTS_VIRTUALKEY
#define CFG_CTS_MAX_VKEY_NUM (4)
#define CFG_CTS_NUM_VKEY (3)
#define CFG_CTS_VKEY_KEYCODES {KEY_BACK, KEY_HOME, KEY_MENU}
#endif /* CONFIG_CTS_VIRTUALKEY */
/* Gesture wakeup */
#define CFG_CTS_GESTURE
#ifdef CFG_CTS_GESTURE
#define GESTURE_UP 0x11
#define GESTURE_C 0x12
#define GESTURE_O 0x13
#define GESTURE_M 0x14
#define GESTURE_W 0x15
#define GESTURE_E 0x16
#define GESTURE_S 0x17
#define GESTURE_Z 0x1d
#define GESTURE_V 0x1e
#define GESTURE_D_TAP 0x50
#define GESTURE_DOWN 0x22
#define GESTURE_LEFT 0x23
#define GESTURE_RIGHT 0x24
#define GESTURE_TAP 0x7f
#define CFG_CTS_NUM_GESTURE (14u)
#define CFG_CTS_GESTURE_REPORT_KEY
#define CFG_CTS_GESTURE_KEYMAP \
{ \
{ GESTURE_C, KEY_C,}, \
{ GESTURE_W, KEY_W,}, \
{ GESTURE_V, KEY_V,}, \
{ GESTURE_D_TAP, KEY_F1,}, \
{ GESTURE_Z, KEY_Z,}, \
{ GESTURE_M, KEY_M,}, \
{ GESTURE_O, KEY_O,}, \
{ GESTURE_E, KEY_E,}, \
{ GESTURE_S, KEY_S,}, \
{ GESTURE_UP, KEY_UP,}, \
{ GESTURE_DOWN, KEY_DOWN,}, \
{ GESTURE_LEFT, KEY_LEFT,}, \
{ GESTURE_RIGHT, KEY_RIGHT,}, \
{ GESTURE_TAP, KEY_F2,}, \
}
#define CFG_CTS_GESTURE_REPORT_TRACE 0
#endif /* CFG_CTS_GESTURE */
#define CONFIG_CTS_GLOVE
//#define CONFIG_CTS_EARJACK_DETECT
//#define CONFIG_CTS_CHARGER_DETECT
/* #define CONFIG_CTS_TP_PROXIMITY */
/* ESD protection */
//#define CONFIG_CTS_ESD_PROTECTION
#ifdef CONFIG_CTS_ESD_PROTECTION
#define CFG_CTS_ESD_PROTECTION_CHECK_PERIOD (2 * HZ)
#define CFG_CTS_ESD_FAILED_CONFIRM_CNT 3
#endif /* CONFIG_CTS_ESD_PROTECTION */
/* Use slot protocol (protocol B), comment it if use protocol A. */
#define CONFIG_CTS_SLOTPROTOCOL
/* #define CTS_CONFIG_MKDIR_FOR_CTS_TEST */
#ifdef CONFIG_CTS_LEGACY_TOOL
#define CFG_CTS_TOOL_PROC_FILENAME "cts_tool"
#endif /* CONFIG_CTS_LEGACY_TOOL */
#define CFG_CTS_UPDATE_CRCCHECK
#ifdef CONFIG_OF
#define CONFIG_CTS_OF
#endif
#ifdef CFG_CTS_PLATFORM_MTK_TPD_SUPPORTED
/****************************************************************************
* MTK Platform configurations
****************************************************************************/
#ifdef CONFIG_MTK_I2C_EXTENSION
#define TPD_SUPPORT_I2C_DMA
#define CFG_CTS_MAX_I2C_XFER_SIZE (250)
#define CFG_CTS_MAX_I2C_FIFO_XFER_SIZE (8)
#else
#define CFG_CTS_MAX_I2C_XFER_SIZE (128)
#endif /* CONFIG_MTK_I2C_EXTENSION */
#define CFG_CTS_MAX_I2C_READ_SIZE (8192u)
#define CFG_CTS_MAX_SPI_XFER_SIZE (8192u)
#define CFG_CTS_INT_DATA_MAX_SIZE (8192u)
#define CTS_FW_LOG_REDIRECT_SIGN 0x60
#define CTS_FW_LOG_BUF_LEN 128
//#define CFG_MTK_LEGEND_PLATFORM
#define CFG_CTS_DEVICE_NAME TPD_DEVICE
#define CFG_CTS_DRIVER_NAME "chipone-tddi"
#ifdef CONFIG_CTS_OF
#define CFG_CTS_OF_DEVICE_ID_NAME "mediatek,cap_touch"
#endif /* CONFIG_CTS_OF */
#else /* CFG_CTS_PLATFORM_MTK_TPD_SUPPORTED */
/****************************************************************************
* QCOM Platform configurations
****************************************************************************/
#ifndef CFG_CTS_PLATFORM_SPRD_SUPPORTED
#define CONFIG_CTS_PM_FB_NOTIFIER
#endif
#ifdef CONFIG_CTS_PM_FB_NOTIFIER
#ifdef CONFIG_DRM
#define CFG_CTS_DRM_NOTIFIER
#endif /*CONFIG_DRM */
#else /*CONFIG_CTS_PM_FB_NOTIFIER */
#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PM_SUSPEND)
/* #define CONFIG_CTS_PM_GENERIC */
#endif /* CONFIG_PM_SLEEP */
#ifndef CONFIG_CTS_PM_GENERIC
#define CONFIG_CTS_PM_LEGACY
#endif /*CONFIG_CTS_PM_GENERIC */
#endif /*CONFIG_CTS_PM_FB_NOTIFIER */
#define CFG_CTS_MAX_I2C_XFER_SIZE (48u)
#define CFG_CTS_MAX_I2C_READ_SIZE (8192u)
#define CFG_CTS_MAX_SPI_XFER_SIZE (8192u)
#define CFG_CTS_INT_DATA_MAX_SIZE (8192u)
#define CTS_FW_LOG_REDIRECT_SIGN 0x60
#define CTS_FW_LOG_BUF_LEN 128
#define CFG_CTS_DEVICE_NAME "chipone-tddi"
#define CFG_CTS_DRIVER_NAME "chipone-tddi"
#ifdef CONFIG_CTS_OF
#define CFG_CTS_OF_DEVICE_ID_NAME "chipone-tddi"
#define CFG_CTS_OF_INT_GPIO_NAME "chipone,irq-gpio"
#define CFG_CTS_OF_RST_GPIO_NAME "chipone,rst-gpio"
#ifdef CFG_CTS_MANUAL_CS
#define CFG_CTS_OF_CS_GPIO_NAME "chipone,cs-gpio"
#endif
#define CFG_CTS_OF_X_RESOLUTION_NAME "chipone,x-res"
#define CFG_CTS_OF_Y_RESOLUTION_NAME "chipone,y-res"
#ifdef CFG_CTS_FW_UPDATE_SYS
#define CFG_CTS_OF_PANEL_SUPPLIER "chipone,panel-supplier"
#endif
#endif /* CONFIG_CTS_OF */
#endif /* CFG_CTS_PLATFORM_MTK_TPD_SUPPORTED */
#endif /* CTS_CONFIG_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,988 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#ifndef CTS_CORE_H
#define CTS_CORE_H
#include "cts_config.h"
enum cts_dev_hw_reg {
CTS_DEV_HW_REG_HARDWARE_ID = 0x70000u,
CTS_DEV_HW_REG_CLOCK_GATING = 0x70004u,
CTS_DEV_HW_REG_RESET_CONFIG = 0x70008u,
CTS_DEV_HW_REG_SW_RST_CTRL = 0x7000Au,
CTS_DEV_HW_REG_BOOT_MODE = 0x70010u,
CTS_DEV_HW_REG_CURRENT_MODE = 0x70011u,
CTS_DEV_HW_REG_DDI_REG_CTRL = 0x7002Cu,
CTS_DEV_HW_REG_CLK_DIV_CFG = 0x70033u,
CTS_DEV_HW_REG_HPPROG = 0x70074u,
CTS_DEV_HW_REG_SET_RESET = 0x700F8u,
CTS_DEV_HW_REG_HW_STATUS = 0x7401Bu,
CTS_DEV_HW_REG_I2C_CFG = 0x77001u,
CTS_DEV_HW_REG_SPI_CFG = 0x78438u,
};
enum cts_dev_boot_mode {
CTS_DEV_BOOT_MODE_IDLE = 0,
CTS_DEV_BOOT_MODE_FLASH = 1,
CTS_DEV_BOOT_MODE_I2C_PRG_9911C = 2,
CTS_DEV_BOOT_MODE_TCH_PRG_9916 = 2,
CTS_DEV_BOOT_MODE_SRAM = 3,
CTS_DEV_BOOT_MODE_DDI_PRG = 4,
CTS_DEV_BOOT_MODE_SPI_PRG_9911C = 5,
CTS_DEV_BOOT_MODE_MASK = 7,
};
/* ICNL9951/ICNL9951R */
#define CTS_PWR_MODE_ACTIVE (0x00)
#define CTS_PWR_MODE_MNT (0x01)
#define CTS_PWR_MODE_HIBERNATE (0x02)
#define CTS_PWR_MODE_GSTR_WAKEUP (0x03)
#define CTS_PWR_MODE_MNT_DBG (0x04)
#define CTS_PWR_MODE_GSTR_DBG (0x05)
#define CTS_PWR_MODE_WAIT_TO_HIBERNATE (0x06)
#define CTS_PWR_MODE_WAIT_TO_GSTR (0x07)
//Krang work mode value
#define CTS_KRANG_NORMAL_MODE (0x00)
#define CTS_KRANG_STY_DBG_MODE (0x01)
#define CTS_KRANG_FIN_DBG_MODE (0x02)
#define CTS_KRANG_MNT_DBG_MODE (0x03)
#define CTS_KRANG_GS_DBG_MODE (0x04)
#define CTS_KRANG_OPEN_SHORT_DET_MODE (0x05)
#define CTS_KRANG_CFG_MODE (0x06)
#define CTS_KRANG_TEST_MODE (0x07)
#define CTS_KRANG_DEF_MODE (0x08)
/** I2C addresses(7bits), transfer size and bitrate */
#define CTS_DEV_NORMAL_MODE_I2CADDR (0x48)
#define CTS_DEV_PROGRAM_MODE_I2CADDR (0x30)
#define CTS_DEV_NORMAL_MODE_ADDR_WIDTH (2)
#define CTS_DEV_PROGRAM_MODE_ADDR_WIDTH (3)
#define CTS_DEV_NORMAL_MODE_SPIADDR (0xF0)
#define CTS_DEV_PROGRAM_MODE_SPIADDR (0x60)
/** Chipone firmware register addresses under normal mode */
enum cts_device_fw_reg {
CTS_DEVICE_FW_REG_WORK_MODE = 0x0000,
CTS_DEVICE_FW_REG_SYS_BUSY = 0x0001,
CTS_DEVICE_FW_REG_DATA_READY = 0x0002,
CTS_DEVICE_FW_REG_CMD = 0x0004,
CTS_DEVICE_FW_REG_POWER_MODE = 0x0005,
CTS_DEVICE_FW_REG_FW_LIB_MAIN_VERSION = 0x0009,
CTS_DEVICE_FW_REG_CHIP_TYPE = 0x000A,
CTS_DEVICE_FW_REG_VERSION = 0x000C,
CTS_DEVICE_FW_REG_DDI_VERSION = 0x0010,
CTS_DEVICE_FW_REG_GET_WORK_MODE = 0x003F,
CTS_DEVICE_FW_REG_FW_LIB_SUB_VERSION = 0x0047,
CTS_DEVICE_FW_REG_COMPENSATE_CAP_READY = 0x004E,
CTS_DEVICE_FW_REG_TOUCH_INFO = 0x1000,
CTS_DEVICE_FW_REG_RAW_DATA = 0x2000,
CTS_DEVICE_FW_REG_DIFF_DATA = 0x3000,
CTS_DEVICE_FW_REG_GESTURE_INFO = 0x7000,
CTS_DEVICE_FW_REG_PANEL_PARAM = 0x8000,
CTS_DEVICE_FW_REG_NUM_TX = 0x8007,
CTS_DEVICE_FW_REG_NUM_RX = 0x8008,
CTS_DEVICE_FW_REG_INT_KEEP_TIME = 0x8047,
CTS_DEVICE_FW_REG_RAWDATA_TARGET = 0x8049,
CTS_DEVICE_FW_REG_X_RESOLUTION = 0x8090,
CTS_DEVICE_FW_REG_Y_RESOLUTION = 0x8092,
CTS_DEVICE_FW_REG_SWAP_AXES = 0x8094,
CTS_DEVICE_FW_REG_GLOVE_MODE = 0x8095,
CTS_DEVICE_FW_REG_TEST_WITH_DISPLAY_ON = 0x80A3,
CTS_DEVICE_FW_REG_INT_MODE = 0x80D8,
CTS_DEVICE_FW_REG_EARJACK_DETECT_SUPP = 0x8113,
CTS_DEVICE_FW_REG_AUTO_COMPENSATE_EN = 0x8114,
CTS_DEVICE_FW_REG_ESD_PROTECTION = 0x8156,
CTS_DEVICE_FW_REG_FLAG_BITS = 0x8158,
CTS_DEVICE_FW_REG_COMPENSATE_CAP = 0xA000,
CTS_DEVICE_FW_REG_DEBUG_INTF = 0xF000,
};
/** Hardware IDs, read from hardware id register */
enum cts_dev_hwid {
CTS_DEV_HWID_ICNL9951 = 0x990510u,
CTS_DEV_HWID_ICNL9951R = 0x991510u,
CTS_DEV_HWID_ANY = 0,
CTS_DEV_HWID_INVALID = 0xFFFFFFFFu,
};
/* Firmware IDs, read from firmware register @ref CTS_DEV_FW_REG_CHIP_TYPE
* under normal mode
*/
enum cts_dev_fwid {
CTS_DEV_FWID_ICNL9951 = 0x9951u,
CTS_DEV_FWID_ICNL9951R = 0x99a3u,
CTS_DEV_FWID_ANY = 0u,
CTS_DEV_FWID_INVALID = 0xFFFFu
};
/** Commands written to firmware register @ref CTS_DEVICE_FW_REG_CMD under normal mode */
enum cts_firmware_cmd {
CTS_CMD_RESET = 1,
CTS_CMD_SUSPEND = 2,
CTS_CMD_ENTER_WRITE_PARA_TO_FLASH_MODE = 3,
CTS_CMD_WRITE_PARA_TO_FLASH = 4,
CTS_CMD_WRTITE_INT_HIGH = 5,
CTS_CMD_WRTITE_INT_LOW = 6,
CTS_CMD_RELASE_INT_TEST = 7,
CTS_CMD_RECOVERY_TX_VOL = 0x10,
CTS_CMD_DEC_TX_VOL_1 = 0x11,
CTS_CMD_DEC_TX_VOL_2 = 0x12,
CTS_CMD_DEC_TX_VOL_3 = 0x13,
CTS_CMD_DEC_TX_VOL_4 = 0x14,
CTS_CMD_DEC_TX_VOL_5 = 0x15,
CTS_CMD_DEC_TX_VOL_6 = 0x16,
CTS_CMD_ENABLE_READ_RAWDATA = 0x20,
CTS_CMD_DISABLE_READ_RAWDATA = 0x21,
CTS_CMD_SUSPEND_WITH_GESTURE = 0x40,
CTS_CMD_QUIT_GESTURE_MONITOR = 0x41,
CTS_CMD_CHARGER_ATTACHED = 0x55,
CTS_CMD_EARJACK_ATTACHED = 0x57,
CTS_CMD_EARJACK_DETACHED = 0x58,
CTS_CMD_CHARGER_DETACHED = 0x66,
CTS_CMD_ENABLE_FW_LOG_REDIRECT = 0x86,
CTS_CMD_DISABLE_FW_LOG_REDIRECT = 0x87,
CTS_CMD_ENABLE_READ_CNEG = 0x88,
CTS_CMD_DISABLE_READ_CNEG = 0x89,
CTS_CMD_FW_LOG_SHOW_FINISH = 0xE0,
#ifdef CONFIG_CTS_TP_PROXIMITY
CTS_CMD_PROXIMITY_STATUS = 0x80,
/* For vivo code, make a distinction between palm func and proximity func */
CTS_CMD_PROXIMITY_NEAR_VIVO = 0x30,
CTS_CMD_PROXIMITY_FAR_VIVO = 0x31,
#endif
};
#pragma pack(1)
/** Touch message read back from chip */
struct cts_device_touch_msg {
u8 event:4;
u8 id:4;
u8 xh:4;
u8 yh:4;
u8 xl;
u8 yl;
u8 pressure;
#define CTS_DEVICE_TOUCH_EVENT_NONE (0)
#define CTS_DEVICE_TOUCH_EVENT_DOWN (1)
#define CTS_DEVICE_TOUCH_EVENT_MOVE (2)
#define CTS_DEVICE_TOUCH_EVENT_STAY (3)
#define CTS_DEVICE_TOUCH_EVENT_UP (4)
};
/** Stylus message read back from chip */
struct cts_device_stylus_msg {
u8 event:4;
u8 id:4;
u8 tip_xh:4;
u8 tip_yh:4;
u8 tip_xl;
u8 tip_yl;
u8 ring_xh:4;
u8 ring_yh:4;
u8 ring_xl;
u8 ring_yl;
u8 battary;
u8 tilt;
u8 pressure_l;
u8 pressure_h:5;//use low 5 bits
u8 btn0:1;
u8 btn1:1;
u8 btn2:1;
u8 tiltx;
u8 tilty;
};
struct cts_firmware_status {
uint16_t charger:1;
uint16_t proximity:1;
uint16_t earjack:1;
uint16_t knuckle:1;
uint16_t glove:1;
uint16_t pocket:1;
uint16_t game:1;
uint16_t reserved:1;
uint16_t high_temperature:1;
uint16_t low_temperature:1;
uint16_t bend_mode:1;
uint16_t palm_status:1;
uint16_t noise_mode:1;
uint16_t base_trace:1;
uint16_t water_mode:1;
uint16_t ground:1;
};
/** Touch debug messages read back from chip [40 bytes] */
struct cts_touch_debug_msg {
u8 protocol_version;
u8 fw_version;
u32 reset_flag;
u16 frame_index;
u16 firmware_status;
u8 proximity;
u8 work_mode;
u8 power_mode;
u8 curr_freq;
u8 esd_0a_status;
u8 fw_esd_status;
u8 landscape_mode;
u16 curr_freq_noise;
u16 max_diff;
u8 max_diff_row;
u8 max_diff_col;
u16 max_neg_diff;
u8 max_neg_diff_row;
u8 max_neg_diff_col;
u8 data_method;
u8 data_type;
u8 reserved[11];
};
/** Touch information read back from chip */
struct cts_device_touch_info {
u8 vkey_state;
u8 num_msg:4;
#define PROTO_NORMAL 0x00
#define PROTO_COMPRESSED 0x01
u8 compressed_proto:2;
#define FINGER_ONLY 0x01
#define STYLUS_ONLY 0x02
#define FINGER_STYLUS 0x03
u8 finger_or_stylus:2;
u8 reserved0;
struct cts_device_touch_msg msgs[CFG_CTS_MAX_TOUCH_NUM];
u8 proximity;
u8 palm_major;
u8 palm_minor;
u8 palm_flags;
#ifdef CFG_CTS_FINGER_STYLUS_SUPPORTED
u8 stylus_num:4;
u8 stylus_vernum:4;
struct cts_device_stylus_msg smsgs[CFG_CTS_MAX_STYLUS_NUM];
u8 reserved1;
u8 reserved2;
#endif
};
struct cts_device_stylus_info {
u8 vkey_state;
u8 num_msg:4;
u8 compressed_proto:2;
u8 finger_or_stylus:2;
u8 reserved0;
u8 event_num:4;
u8 stylus_vernum:4;
struct cts_device_stylus_msg msgs[CFG_CTS_MAX_STYLUS_NUM];
u8 reserved1;
};
/** Gesture trace point read back from chip */
struct cts_device_gesture_point {
__le16 x;
__le16 y;
};
/** Gesture information read back from chip */
/* total size 112 bytes */
struct cts_device_gesture_info {
u8 gesture_id;
#define CTS_GESTURE_UP (0x11)
#define CTS_GESTURE_C (0x12)
#define CTS_GESTURE_O (0x13)
#define CTS_GESTURE_M (0x14)
#define CTS_GESTURE_W (0x15)
#define CTS_GESTURE_E (0x16)
#define CTS_GESTURE_S (0x17)
#define CTS_GESTURE_B (0x18)
#define CTS_GESTURE_T (0x19)
#define CTS_GESTURE_H (0x1A)
#define CTS_GESTURE_F (0x1B)
#define CTS_GESTURE_X (0x1C)
#define CTS_GESTURE_Z (0x1D)
#define CTS_GESTURE_V (0x1E)
#define CTS_GESTURE_D_TAP (0x50)
#define CTS_GESTURE_TAP (0x7F)
u8 num_points;
#define CTS_CHIP_MAX_GESTURE_TRACE_POINT (27u)
struct cts_device_gesture_point points[CTS_CHIP_MAX_GESTURE_TRACE_POINT];
u8 reserved[2];
};
struct cts_tcs_cmd {
uint16_t cmd_id : 8;
uint16_t class_id : 5;
uint16_t is_write : 1;
uint16_t is_read : 1;
uint16_t base_flag : 1;
};
#pragma pack()
struct cts_device;
enum cts_crc_type {
CTS_CRC16 = 1,
CTS_CRC32 = 2,
};
/** Chip hardware data, will never change */
struct cts_device_hwdata {
const char *name;
u32 hwid;
u16 fwid;
u8 num_row;
u8 num_col;
u32 sram_size;
/* Address width under program mode */
u8 program_addr_width;
const struct cts_sfctrl *sfctrl;
int (*enable_access_ddi_reg)(struct cts_device *cts_dev, bool enable);
};
enum int_data_type {
INT_DATA_TYPE_NONE = 0,
INT_DATA_TYPE_RAWDATA = BIT(0),
INT_DATA_TYPE_MANUAL_DIFF = BIT(1),
INT_DATA_TYPE_REAL_DIFF = BIT(2),
INT_DATA_TYPE_NOISE_DIFF = BIT(3),
INT_DATA_TYPE_BASEDATA = BIT(4),
INT_DATA_TYPE_CNEGDATA = BIT(5),
INT_DATA_TYPE_MASK = 0xF03F,
};
enum int_data_method {
INT_DATA_METHOD_NONE = 0,
INT_DATA_METHOD_HOST = 1,
INT_DATA_METHOD_POLLING = 2,
INT_DATA_METHOD_DEBUG = 3,
INT_DATA_METHOD_CNT = 4,
};
/** Chip firmware data */
struct cts_device_fwdata {
u16 version;
u16 res_x;
u16 res_y;
u8 rows;
u8 cols;
bool flip_x;
bool flip_y;
bool swap_axes;
u8 ddi_version;
u8 int_mode;
u8 esd_method;
u16 lib_version;
u16 int_keep_time;
u16 rawdata_target;
bool has_int_data;
u8 int_data_method;
u16 int_data_types;
size_t int_data_size;
u8 ic_application;
u8 pen_freq_num;
u8 cascade_num;
u8 pc_cols;
u8 pc_rows;
u8 pr_cols;
u8 pr_rows;
u8 pc_cols_used;
u8 pc_rows_used;
u8 pr_cols_used;
u8 pr_rows_used;
};
/** Chip runtime data */
struct cts_device_rtdata {
u8 slave_addr;
int addr_width;
bool program_mode;
bool has_flash;
bool suspended;
bool updating;
bool testing;
bool gesture_wakeup_enabled;
bool gesture_d_tap_enabled;
bool charger_exist;
bool fw_log_redirect_enabled;
bool glove_mode_enabled;
u8 esd_count;
u16 firmware_status;
struct cts_device_touch_info touch_info;
struct cts_device_gesture_info gesture_info;
#ifdef CONFIG_CTS_TP_PROXIMITY
bool proximity_status;
int proximity_num;
#endif
u16 tcscmd[ALIGN(PAGE_SIZE + 10, 4)];
int tcscmd_len;
u16 curr_cmd;
int curr_len;
};
struct cts_firmware {
const char *name; /* MUST set to non-NULL if driver builtin firmware */
u32 hwid;
u16 fwid;
u8 *data;
size_t size;
const struct firmware *fw;
};
struct cts_device {
struct cts_platform_data *pdata;
const struct cts_device_hwdata *hwdata;
struct cts_device_fwdata fwdata;
struct cts_device_rtdata rtdata;
struct cts_firmware *firmware;
const struct cts_flash *flash;
bool enabled;
u8 int_data[ALIGN(CFG_CTS_INT_DATA_MAX_SIZE + 10, 4)];
};
struct cts_platform_data;
struct chipone_ts_data {
#ifdef CONFIG_CTS_I2C_HOST
struct i2c_client *i2c_client;
#else
struct spi_device *spi_client;
#endif
struct device *device;
struct cts_device cts_dev;
struct cts_platform_data *pdata;
struct workqueue_struct *workqueue;
struct delayed_work fw_upgrade_work;
struct work_struct ts_resume_work;
#ifdef CONFIG_CTS_CHARGER_DETECT
void *charger_detect_data;
#endif
#ifdef CONFIG_CTS_EARJACK_DETECT
void *earjack_detect_data;
#endif
#ifdef CONFIG_CTS_ESD_PROTECTION
struct workqueue_struct *esd_workqueue;
struct delayed_work esd_work;
bool esd_enabled;
int esd_check_fail_cnt;
#endif
#ifdef CFG_CTS_HEARTBEAT_MECHANISM
struct workqueue_struct *heart_workqueue;
struct delayed_work heart_work;
#endif
#ifdef CONFIG_CTS_LEGACY_TOOL
struct proc_dir_entry *procfs_entry;
#endif
void *oem_data;
bool force_reflash;
// struct kobject *suspend_kobj;
#ifdef CONFIG_PM_DSI_EXTCON_NOTIFIER
struct extcon_dev *edev;
struct notifier_block extcon_nb;
#endif
};
/*static inline u32 get_unaligned_le24(const void *p)
{
const u8 *puc = (const u8 *)p;
return (puc[0] | (puc[1] << 8) | (puc[2] << 16));
}
static inline u32 get_unaligned_be24(const void *p)
{
const u8 *puc = (const u8 *)p;
return (puc[2] | (puc[1] << 8) | (puc[0] << 16));
}
static inline void put_unaligned_be24(u32 v, void *p)
{
u8 *puc = (u8 *) p;
puc[0] = (v >> 16) & 0xFF;
puc[1] = (v >> 8) & 0xFF;
puc[2] = (v >> 0) & 0xFF;
}*/
#define wrap(max, x) ((max) - 1 - (x))
extern void cts_lock_device(struct cts_device *cts_dev);
extern void cts_unlock_device(struct cts_device *cts_dev);
extern int cts_dev_readb(struct cts_device *cts_dev,
u32 addr, u8 *b, int retry, int delay);
extern int cts_dev_writeb(struct cts_device *cts_dev,
u32 addr, u8 b, int retry, int delay);
extern int cts_sram_writeb_retry(struct cts_device *cts_dev,
u32 addr, u8 b, int retry, int delay);
extern int cts_sram_writew_retry(struct cts_device *cts_dev,
u32 addr, u16 w, int retry, int delay);
extern int cts_sram_writel_retry(struct cts_device *cts_dev,
u32 addr, u32 l, int retry, int delay);
extern int cts_sram_writesb_retry(struct cts_device *cts_dev,
u32 addr, const void *src, size_t len, int retry, int delay);
extern int cts_sram_writesb_check_crc_retry(struct cts_device *cts_dev,
u32 addr, const void *src, size_t len, u32 crc, int retry);
extern int cts_sram_readb_retry(struct cts_device *cts_dev,
u32 addr, u8 *b, int retry, int delay);
extern int cts_sram_readw_retry(struct cts_device *cts_dev,
u32 addr, u16 *w, int retry, int delay);
extern int cts_sram_readl_retry(struct cts_device *cts_dev,
u32 addr, u32 *l, int retry, int delay);
extern int cts_sram_readsb_retry(struct cts_device *cts_dev,
u32 addr, void *dst, size_t len, int retry, int delay);
extern int cts_fw_reg_writeb_retry(struct cts_device *cts_dev,
u32 reg_addr, u8 b, int retry, int delay);
extern int cts_fw_reg_writew_retry(struct cts_device *cts_dev,
u32 reg_addr, u16 w, int retry, int delay);
extern int cts_fw_reg_writel_retry(struct cts_device *cts_dev,
u32 reg_addr, u32 l, int retry, int delay);
extern int cts_fw_reg_writesb_retry(struct cts_device *cts_dev,
u32 reg_addr, const void *src, size_t len, int retry, int delay);
extern int cts_fw_reg_readb_retry(struct cts_device *cts_dev,
u32 reg_addr, u8 *b, int retry, int delay);
extern int cts_fw_reg_readw_retry(struct cts_device *cts_dev,
u32 reg_addr, u16 *w, int retry, int delay);
extern int cts_fw_reg_readl_retry(struct cts_device *cts_dev,
u32 reg_addr, u32 *l, int retry, int delay);
extern int cts_fw_reg_readsb_retry(struct cts_device *cts_dev,
u32 reg_addr, void *dst, size_t len,
int retry, int delay);
extern int cts_fw_reg_readsb_retry_delay_idle(struct cts_device *cts_dev,
u32 reg_addr, void *dst, size_t len, int retry, int delay, int idle);
extern int cts_hw_reg_writeb_retry(struct cts_device *cts_dev,
u32 reg_addr, u8 b, int retry, int delay);
extern int cts_hw_reg_writew_retry(struct cts_device *cts_dev,
u32 reg_addr, u16 w, int retry, int delay);
extern int cts_hw_reg_writel_retry(struct cts_device *cts_dev,
u32 reg_addr, u32 l, int retry, int delay);
extern int cts_hw_reg_writesb_retry(struct cts_device *cts_dev,
u32 reg_addr, const void *src, size_t len, int retry, int delay);
extern int cts_hw_reg_readb_retry(struct cts_device *cts_dev,
u32 reg_addr, u8 *b, int retry, int delay);
extern int cts_hw_reg_readw_retry(struct cts_device *cts_dev,
u32 reg_addr, u16 *w, int retry, int delay);
extern int cts_hw_reg_readl_retry(struct cts_device *cts_dev,
u32 reg_addr, u32 *l, int retry, int delay);
extern int cts_hw_reg_readsb_retry(struct cts_device *cts_dev,
u32 reg_addr, void *dst, size_t len, int retry, int delay);
static inline int cts_hw_reg_readb(struct cts_device *cts_dev,
u32 reg_addr, u8 *b)
{
return cts_hw_reg_readb_retry(cts_dev, reg_addr, b, 1, 0);
}
static inline int cts_hw_reg_writeb(struct cts_device *cts_dev,
u32 reg_addr, u8 b)
{
return cts_hw_reg_writeb_retry(cts_dev, reg_addr, b, 1, 0);
}
static inline int cts_hw_reg_writew(struct cts_device *cts_dev,
u32 reg_addr, u16 w)
{
return cts_hw_reg_writew_retry(cts_dev, reg_addr, w, 1, 0);
}
static inline int cts_fw_reg_writeb(struct cts_device *cts_dev,
u32 reg_addr, u8 b)
{
return cts_fw_reg_writeb_retry(cts_dev, reg_addr, b, 1, 0);
}
static inline int cts_fw_reg_writew(struct cts_device *cts_dev,
u32 reg_addr, u16 w)
{
return cts_fw_reg_writew_retry(cts_dev, reg_addr, w, 1, 0);
}
static inline int cts_fw_reg_writel(struct cts_device *cts_dev,
u32 reg_addr, u32 l)
{
return cts_fw_reg_writel_retry(cts_dev, reg_addr, l, 1, 0);
}
static inline int cts_fw_reg_writesb(struct cts_device *cts_dev,
u32 reg_addr, const void *src, size_t len)
{
return cts_fw_reg_writesb_retry(cts_dev, reg_addr, src, len, 1, 0);
}
static inline int cts_fw_reg_readb(struct cts_device *cts_dev,
u32 reg_addr, u8 *b)
{
return cts_fw_reg_readb_retry(cts_dev, reg_addr, b, 1, 0);
}
static inline int cts_fw_reg_readw(struct cts_device *cts_dev,
u32 reg_addr, u16 *w)
{
return cts_fw_reg_readw_retry(cts_dev, reg_addr, w, 1, 0);
}
static inline int cts_fw_reg_readl(struct cts_device *cts_dev,
u32 reg_addr, u32 *l)
{
return cts_fw_reg_readl_retry(cts_dev, reg_addr, l, 1, 0);
}
static inline int cts_fw_reg_readsb(struct cts_device *cts_dev,
u32 reg_addr, void *dst, size_t len)
{
return cts_fw_reg_readsb_retry(cts_dev, reg_addr, dst, len, 1, 0);
}
static inline int cts_fw_reg_readsb_delay_idle(struct cts_device *cts_dev,
u32 reg_addr, void *dst, size_t len, int idle)
{
return cts_fw_reg_readsb_retry_delay_idle(cts_dev, reg_addr, dst, len,
1, 0, idle);
}
static inline int cts_hw_reg_writeb_relaxed(struct cts_device *cts_dev,
u32 reg_addr, u8 b)
{
return cts_hw_reg_writeb_retry(cts_dev, reg_addr, b, 1, 0);
}
static inline int cts_hw_reg_writew_relaxed(struct cts_device *cts_dev,
u32 reg_addr, u16 w)
{
return cts_hw_reg_writew_retry(cts_dev, reg_addr, w, 1, 0);
}
static inline int cts_hw_reg_writel_relaxed(struct cts_device *cts_dev,
u32 reg_addr, u32 l)
{
return cts_hw_reg_writel_retry(cts_dev, reg_addr, l, 1, 0);
}
static inline int cts_hw_reg_writesb(struct cts_device *cts_dev,
u32 reg_addr, const void *src, size_t len)
{
return cts_hw_reg_writesb_retry(cts_dev, reg_addr, src, len, 1, 0);
}
static inline int cts_hw_reg_readb_relaxed(struct cts_device *cts_dev,
u32 reg_addr, u8 *b)
{
return cts_hw_reg_readb_retry(cts_dev, reg_addr, b, 1, 0);
}
static inline int cts_hw_reg_readw_relaxed(struct cts_device *cts_dev,
u32 reg_addr, u16 *w)
{
return cts_hw_reg_readw_retry(cts_dev, reg_addr, w, 1, 0);
}
static inline int cts_hw_reg_readl_relaxed(struct cts_device *cts_dev,
u32 reg_addr, u32 *l)
{
return cts_hw_reg_readl_retry(cts_dev, reg_addr, l, 1, 0);
}
static inline int cts_hw_reg_readsb(struct cts_device *cts_dev,
u32 reg_addr, void *dst, size_t len)
{
return cts_hw_reg_readsb_retry(cts_dev, reg_addr, dst, len, 1, 0);
}
static inline int cts_sram_writeb(struct cts_device *cts_dev,
u32 addr, u8 b)
{
return cts_sram_writeb_retry(cts_dev, addr, b, 1, 0);
}
static inline int cts_sram_writew(struct cts_device *cts_dev,
u32 addr, u16 w)
{
return cts_sram_writew_retry(cts_dev, addr, w, 1, 0);
}
static inline int cts_sram_writel(struct cts_device *cts_dev,
u32 addr, u32 l)
{
return cts_sram_writel_retry(cts_dev, addr, l, 1, 0);
}
static inline int cts_sram_writesb(struct cts_device *cts_dev, u32 addr,
const void *src, size_t len)
{
return cts_sram_writesb_retry(cts_dev, addr, src, len, 10, 0);
}
static inline int cts_sram_readb(struct cts_device *cts_dev,
u32 addr, u8 *b)
{
return cts_sram_readb_retry(cts_dev, addr, b, 1, 0);
}
static inline int cts_sram_readw(struct cts_device *cts_dev,
u32 addr, u16 *w)
{
return cts_sram_readw_retry(cts_dev, addr, w, 1, 0);
}
static inline int cts_sram_readl(struct cts_device *cts_dev,
u32 addr, u32 *l)
{
return cts_sram_readl_retry(cts_dev, addr, l, 1, 0);
}
static inline int cts_sram_readsb(struct cts_device *cts_dev,
u32 addr, void *dst, size_t len)
{
return cts_sram_readsb_retry(cts_dev, addr, dst, len, 1, 0);
}
#ifdef CONFIG_CTS_I2C_HOST
static inline void cts_set_program_addr(struct cts_device *cts_dev)
{
cts_dev->rtdata.slave_addr = CTS_DEV_PROGRAM_MODE_I2CADDR;
cts_dev->rtdata.program_mode = true;
cts_dev->rtdata.addr_width = CTS_DEV_PROGRAM_MODE_ADDR_WIDTH;
}
static inline void cts_set_normal_addr(struct cts_device *cts_dev)
{
cts_dev->rtdata.slave_addr = CTS_DEV_NORMAL_MODE_I2CADDR;
cts_dev->rtdata.program_mode = false;
cts_dev->rtdata.addr_width = CTS_DEV_NORMAL_MODE_ADDR_WIDTH;
}
int cts_i2c_writeb(struct cts_device *cts_dev,
u32 addr, u8 b, int retry, int delay);
int cts_i2c_writeb(struct cts_device *cts_dev,
u32 addr, u8 b, int retry, int delay);
int cts_i2c_writesb(struct cts_device *cts_dev, u32 addr,
const u8 *src, size_t len, int retry, int delay);
int cts_i2c_readb(struct cts_device *cts_dev,
u32 addr, u8 *b, int retry, int delay);
int cts_i2c_readl(struct cts_device *cts_dev,
u32 addr, u32 *l, int retry, int delay);
#else
static inline void cts_set_program_addr(struct cts_device *cts_dev)
{
cts_dev->rtdata.slave_addr = CTS_DEV_PROGRAM_MODE_SPIADDR;
cts_dev->rtdata.program_mode = true;
cts_dev->rtdata.addr_width = CTS_DEV_PROGRAM_MODE_ADDR_WIDTH;
}
static inline void cts_set_normal_addr(struct cts_device *cts_dev)
{
cts_dev->rtdata.slave_addr = CTS_DEV_NORMAL_MODE_SPIADDR;
cts_dev->rtdata.program_mode = false;
cts_dev->rtdata.addr_width = CTS_DEV_NORMAL_MODE_ADDR_WIDTH;
}
#endif
extern int cts_irq_handler(struct cts_device *cts_dev);
extern void cts_firmware_upgrade_work(struct work_struct *work);
extern bool cts_is_device_suspended(struct cts_device *cts_dev);
extern int cts_suspend_device(struct cts_device *cts_dev);
extern int cts_resume_device(struct cts_device *cts_dev);
extern bool cts_is_device_program_mode(struct cts_device *cts_dev);
extern int cts_enter_program_mode(struct cts_device *cts_dev);
extern int cts_enter_normal_mode(struct cts_device *cts_dev);
extern int cts_probe_device(struct cts_device *cts_dev);
extern int cts_send_command(struct cts_device *cts_dev, u8 cmd);
extern int cts_read_sram_normal_mode(struct cts_device *cts_dev,
u32 addr, void *dst, size_t len, int retry, int delay);
#ifdef CFG_CTS_GESTURE
extern void cts_enable_gesture_wakeup(struct cts_device *cts_dev);
extern void cts_disable_gesture_wakeup(struct cts_device *cts_dev);
extern bool cts_is_gesture_wakeup_enabled(struct cts_device *cts_dev);
extern int cts_get_gesture_info(struct cts_device *cts_dev, void *gesture_info);
#endif /* CFG_CTS_GESTURE */
extern bool cts_is_d_tap_supported(struct cts_device *cts_dev);
extern int cts_set_d_tap_enabled(struct cts_device *cts_dev, bool enabled);
extern int cts_set_int_data_types(struct cts_device *cts_dev, u16 types);
extern int cts_set_int_data_method(struct cts_device *cts_dev, u8 method);
#ifdef CONFIG_CTS_ESD_PROTECTION
extern void cts_init_esd_protection(struct chipone_ts_data *cts_data);
extern void cts_enable_esd_protection(struct chipone_ts_data *cts_data);
extern void cts_disable_esd_protection(struct chipone_ts_data *cts_data);
extern void cts_deinit_esd_protection(struct chipone_ts_data *cts_data);
#else /* CONFIG_CTS_ESD_PROTECTION */
static inline void cts_init_esd_protection(struct chipone_ts_data *cts_data)
{
}
static inline void cts_enable_esd_protection(struct chipone_ts_data *cts_data)
{
}
static inline void cts_disable_esd_protection(struct chipone_ts_data *cts_data)
{
}
static inline void cts_deinit_esd_protection(struct chipone_ts_data *cts_data)
{
}
#endif /* CONFIG_CTS_ESD_PROTECTION */
#ifdef CFG_CTS_HEARTBEAT_MECHANISM
void cts_show_touch_debug_msg(void *debug);
void cts_heartbeat_mechanism_work(struct work_struct *work);
void cts_enable_heartbeat_mechanism(struct chipone_ts_data *cts_data);
void cts_disable_heartbeat_mechanism(struct chipone_ts_data *cts_data);
#endif
#ifdef CONFIG_CTS_GLOVE
extern int cts_enter_glove_mode(struct cts_device *cts_dev);
extern int cts_exit_glove_mode(struct cts_device *cts_dev);
int cts_is_glove_enabled(struct cts_device *cts_dev);
int cts_set_glove_enabled(struct cts_device *cts_dev, bool enabled);
#else
static inline int cts_enter_glove_mode(struct cts_device *cts_dev)
{
return 0;
}
static inline int cts_exit_glove_mode(struct cts_device *cts_dev)
{
return 0;
}
static inline int cts_is_glove_enabled(struct cts_device *cts_dev)
{
return 0;
}
static inline int cts_set_glove_enabled(struct cts_device *cts_dev, bool enabled)
{
return 0;
}
#endif
#ifdef CONFIG_CTS_CHARGER_DETECT
extern bool cts_is_charger_exist(struct cts_device *cts_dev);
extern int cts_set_dev_charger_attached(struct cts_device *cts_dev,
bool attached);
#else /* CONFIG_CTS_CHARGER_DETECT */
static inline bool cts_is_charger_exist(struct cts_device *cts_dev)
{
return false;
}
static inline int cts_set_dev_charger_attached(struct cts_device *cts_dev,
bool attached)
{
return 0;
}
#endif /* CONFIG_CTS_CHARGER_DETECT */
#ifdef CONFIG_CTS_EARJACK_DETECT
extern bool cts_is_earjack_exist(struct cts_device *cts_dev);
extern int cts_set_dev_earjack_attached(struct cts_device *cts_dev, bool attached);
#else /* CONFIG_CTS_EARJACK_DETECT */
static inline bool cts_is_earjack_exist(struct cts_device *cts_dev)
{
return false;
}
static inline int cts_set_dev_earjack_attached(struct cts_device *cts_dev, bool attached)
{
return 0;
}
#endif /* CONFIG_CTS_EARJACK_DETECT */
#ifdef CONFIG_CTS_LEGACY_TOOL
extern int cts_tool_init(struct chipone_ts_data *cts_data);
extern void cts_tool_deinit(struct chipone_ts_data *data);
#else /* CONFIG_CTS_LEGACY_TOOL */
static inline int cts_tool_init(struct chipone_ts_data *cts_data)
{
return 0;
}
static inline void cts_tool_deinit(struct chipone_ts_data *data)
{
}
#endif /* CONFIG_CTS_LEGACY_TOOL */
extern bool cts_is_device_enabled(struct cts_device *cts_dev);
extern int cts_start_device(struct cts_device *cts_dev);
extern int cts_stop_device(struct cts_device *cts_dev);
#ifdef CFG_CTS_UPDATE_CRCCHECK
extern int cts_sram_writesb_boot_crc_retry(struct cts_device *cts_dev,
size_t len, u32 crc, int retry);
#endif
extern const char *cts_dev_boot_mode2str(u8 boot_mode);
extern bool cts_is_fwid_valid(u16 fwid);
extern int cts_reset_device(struct cts_device *cts_dev);
extern int cts_wait_current_mode(struct cts_device *cts_dev, u8 tar_mode);
extern int kstrtobool(const char *s, bool *res);
extern int cts_suspend(struct chipone_ts_data *cts_data);
extern int cts_resume(struct chipone_ts_data *cts_data);
extern struct chipone_ts_data *g_cts_data;
#endif /* CTS_CORE_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,649 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#define LOG_TAG "Earjack"
#include "cts_config.h"
#include "cts_platform.h"
#include "cts_core.h"
#include "cts_sysfs.h"
#include "cts_strerror.h"
#ifdef CONFIG_CTS_EARJACK_DETECT
struct cts_earjack_detect_data {
bool enable;
bool running;
bool state;
const char *earjack_state_filepath;
struct delayed_work poll_work;
u32 poll_interval;
#ifdef CONFIG_CTS_SYSFS
bool sysfs_attr_group_created;
#endif /* CONFIG_CTS_SYSFS */
struct chipone_ts_data *cts_data;
};
/* Over-ride setting for DTS */
//#define CFG_CTS_DEF_EARJACK_DET_ENABLE
#define CFG_CTS_DEF_EARJACK_POLL_INTERVAL 2000u
#if defined(CONFIG_MTK_PLATFORM)
#define CFG_CTS_DEF_EARJACK_STATE_FILEPATH \
"/sys/bus/platform/drivers/Accdet_Driver/state"
#elif defined(CONFIG_ARCH_SPREADRUM)
#define CFG_CTS_DEF_EARJACK_STATE_FILEPATH \
"/sys/kernel/headset/state"
#else
/* Current QCOM NOT support earjack detect, please disable it or define the file path */
#define CFG_CTS_DEF_EARJACK_STATE_FILEPATH ""
#endif
static const char *earjack_state_str(bool state)
{
return state ? "ATTACHED" : "DETACHED";
}
static int parse_earjack_detect_dt(struct cts_earjack_detect_data *ed_data,
struct device_node *np)
{
const char *filepath;
int ret;
cts_info("Parse dt");
#ifdef CFG_CTS_DEF_EARJACK_DET_ENABLE
ed_data->enable = true;
#else /* CFG_CTS_DEF_EARJACK_DET_ENABLE */
ed_data->enable =
of_property_read_bool(np, "chipone,touch-earjack-detect-enable");
#endif /* CFG_CTS_DEF_EARJACK_DET_ENABLE */
ret = of_property_read_string(np,
"chipone,touch-earjack-state-filepath", &filepath);
if (ret) {
cts_warn("Parse state filepath failed %d(%s)", ret, cts_strerror(ret));
filepath = CFG_CTS_DEF_EARJACK_STATE_FILEPATH;
}
ed_data->earjack_state_filepath = kstrdup(filepath, GFP_KERNEL);
if (ed_data->earjack_state_filepath == NULL) {
cts_err("Dup earjack state filepath failed");
return -ENOMEM;
}
ed_data->poll_interval = CFG_CTS_DEF_EARJACK_POLL_INTERVAL;
ret = of_property_read_u32(np,
"chipone,touch-earjack-poll-interval", &ed_data->poll_interval);
if (ret) {
cts_warn("Parse poll interval failed %d(%s)", ret, cts_strerror(ret));
}
return 0;
}
static int start_earjack_detect(struct cts_earjack_detect_data *ed_data)
{
if (!ed_data->enable) {
cts_warn("Start detect while NOT enabled");
return -EINVAL;
}
if (ed_data->running) {
cts_warn("Start detect while already RUNNING");
return 0;
}
if (ed_data->earjack_state_filepath == NULL ||
ed_data->earjack_state_filepath[0] == '\n') {
cts_warn("Start detect with filepath = NULL/NUL");
return -EINVAL;
}
cts_info("Start detect check file: '%s'", ed_data->earjack_state_filepath);
if (!queue_delayed_work(ed_data->cts_data->workqueue,
&ed_data->poll_work,
msecs_to_jiffies(ed_data->poll_interval))) {
cts_warn("Queue detect work while already on the queue");
}
ed_data->running = true;
return 0;
}
static int stop_earjack_detect(struct cts_earjack_detect_data *ed_data)
{
if (!ed_data->running) {
cts_warn("Stop detect while NOT running");
return 0;
}
cts_info("Stop detect");
if (!cancel_delayed_work_sync(&ed_data->poll_work)) {
cts_warn("Cancel poll work while NOT pending");
}
ed_data->running = false;
return 0;
}
static int get_earjack_state(struct cts_earjack_detect_data *ed_data)
{
int ret;
char buff[10];
u32 state;
#ifndef CFG_CTS_FOR_GKI
struct file *file = NULL;
loff_t pos = 0;
int read_size;
#endif
cts_dbg("Get state from file '%s'", ed_data->earjack_state_filepath);
#ifdef CFG_CTS_FOR_GKI
cts_info("%s(): filp_open is forbiddon with GKI Version!", __func__);
#else
file = filp_open(ed_data->earjack_state_filepath, O_RDONLY, 0);
if (IS_ERR(file)) {
ret = (int)PTR_ERR(file);
cts_err("Open file '%s' failed %d(%s)",
ed_data->earjack_state_filepath, ret, cts_strerror(ret));
return PTR_ERR(file);
}
memset(buff, 0, sizeof(buff));
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0)
read_size = kernel_read(file, buff, sizeof(buff), &pos);
#else
read_size = kernel_read(file, pos, buff, sizeof(buff));
#endif
if (read_size < 0) {
cts_err("Read state file '%s' failed %d(%s)",
ed_data->earjack_state_filepath,
read_size, cts_strerror(read_size));
filp_close(file, NULL);
return read_size;
}
cts_dbg("Read state file content: '%s'", buff);
ret = filp_close(file, NULL);
if (ret) {
cts_warn("Close file '%s' failed %d(%s)",
ed_data->earjack_state_filepath, ret, cts_strerror(ret));
}
#endif
ret = kstrtou32(buff, 0, &state);
if (ret) {
cts_err("Invalid string from state file: '%s'", buff);
return ret;
}
/* Assume "0" means detached */
ed_data->state = !!state;
cts_dbg("State: %s", earjack_state_str(ed_data->state));
return 0;
}
/* Sysfs */
#ifdef CONFIG_CTS_SYSFS
#define EARJACK_DET_SYSFS_GROUP_NAME "earjack-det"
static int enable_earjack_detect(struct cts_earjack_detect_data *ed_data)
{
cts_info("Enable detect");
ed_data->enable = true;
return 0;
}
static int disable_earjack_detect(struct cts_earjack_detect_data *ed_data)
{
int ret;
cts_info("Disable detect");
ret = stop_earjack_detect(ed_data);
if (ret) {
cts_err("Stop detect failed %d(%s)", ret, cts_strerror(ret));
}
ed_data->enable = false;
return 0;
}
static ssize_t earjack_detect_enable_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct chipone_ts_data *cts_data = dev_get_drvdata(dev);
struct cts_earjack_detect_data *ed_data = cts_data->earjack_detect_data;
cts_info("Read sysfs '"EARJACK_DET_SYSFS_GROUP_NAME"/%s'", attr->attr.name);
return scnprintf(buf, PAGE_SIZE,
"Earjack detect: %s\n",
ed_data->enable ? "ENABLED" : "DISABLED");
}
/* Echo 0/n/N/of/Of/Of/OF/1/y/Y/on/oN/On/ON > enable */
static ssize_t earjack_detect_enable_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct chipone_ts_data *cts_data = dev_get_drvdata(dev);
struct cts_earjack_detect_data *ed_data = cts_data->earjack_detect_data;
bool enable;
int ret;
cts_info("Write sysfs '"EARJACK_DET_SYSFS_GROUP_NAME"/%s' size %zu",
attr->attr.name, count);
cts_parse_arg(buf, count);
if (cts_argc != 1) {
cts_err("Invalid num of args");
return -EINVAL;
}
ret = kstrtobool(cts_argv[0], &enable);
if (ret) {
cts_err("Invalid param of enable");
return ret;
}
if (enable) {
ret = enable_earjack_detect(ed_data);
} else {
ret = disable_earjack_detect(ed_data);
}
if (ret) {
cts_err("%s earjack detect failed %d(%s)",
enable ? "Enable" : "Disable", ret, cts_strerror(ret));
return ret;
}
return count;
}
static DEVICE_ATTR(enable, S_IWUSR | S_IRUGO,
earjack_detect_enable_show, earjack_detect_enable_store);
static ssize_t earjack_detect_running_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct chipone_ts_data *cts_data = dev_get_drvdata(dev);
struct cts_earjack_detect_data *ed_data = cts_data->earjack_detect_data;
cts_info("Read sysfs '"EARJACK_DET_SYSFS_GROUP_NAME"/%s'",
attr->attr.name);
return scnprintf(buf, PAGE_SIZE,
"Earjack detect: %sRunning\n",
ed_data->running ? "" : "Not-");
}
/* Echo 0/n/N/of/Of/Of/OF/1/y/Y/on/oN/On/ON > runing */
static ssize_t earjack_detect_running_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct chipone_ts_data *cts_data = dev_get_drvdata(dev);
struct cts_earjack_detect_data *ed_data = cts_data->earjack_detect_data;
bool running;
int ret;
cts_info("Write sysfs '"EARJACK_DET_SYSFS_GROUP_NAME"/%s' size %zu",
attr->attr.name, count);
cts_parse_arg(buf, count);
if (cts_argc != 1) {
cts_err("Invalid num of args");
return -EINVAL;
}
ret = kstrtobool(cts_argv[0], &running);
if (ret) {
cts_err("Invalid param of running");
return ret;
}
if (running) {
ret = start_earjack_detect(ed_data);
} else {
ret = stop_earjack_detect(ed_data);
}
if (ret) {
cts_err("%s earjack detect failed %d(%s)",
running ? "Start" : "Stop", ret, cts_strerror(ret));
return ret;
}
return count;
}
static DEVICE_ATTR(running, S_IWUSR | S_IRUGO,
earjack_detect_running_show, earjack_detect_running_store);
static ssize_t earjack_state_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct chipone_ts_data *cts_data = dev_get_drvdata(dev);
struct cts_earjack_detect_data *ed_data = cts_data->earjack_detect_data;
int ret;
cts_info("Read sysfs '"EARJACK_DET_SYSFS_GROUP_NAME"/%s'",
attr->attr.name);
ret = get_earjack_state(ed_data);
if (ret) {
return scnprintf(buf, PAGE_SIZE,
"Get earjack state failed %d(%s)\n",
ret, cts_strerror(ret));
}
return scnprintf(buf, PAGE_SIZE,
"Earjack state: %s\n", earjack_state_str(ed_data->state));
}
static DEVICE_ATTR(state, S_IRUGO, earjack_state_show, NULL);
static ssize_t earjack_detect_param_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct chipone_ts_data *cts_data = dev_get_drvdata(dev);
struct cts_earjack_detect_data *ed_data = cts_data->earjack_detect_data;
cts_info("Read sysfs '"EARJACK_DET_SYSFS_GROUP_NAME"/%s'",
attr->attr.name);
return scnprintf(buf, PAGE_SIZE,
"Filepath: '%s'\n"
"Poll int: %dms\n",
ed_data->earjack_state_filepath, ed_data->poll_interval);
}
/* echo filepath [interval] > param */
static ssize_t earjack_detect_param_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct chipone_ts_data *cts_data = dev_get_drvdata(dev);
struct cts_earjack_detect_data *ed_data = cts_data->earjack_detect_data;
u32 interval;
int ret;
cts_info("Write sysfs '"EARJACK_DET_SYSFS_GROUP_NAME"/%s' size %zu",
attr->attr.name, count);
cts_parse_arg(buf, count);
if (cts_argc < 1 || cts_argc > 2) {
cts_err("Invalid num of args");
return -EINVAL;
}
interval = ed_data->poll_interval;
if (cts_argc > 1) {
ret = kstrtou32(cts_argv[1], 0, &interval);
if (ret) {
cts_err("Arg interval is invalid");
return -EINVAL;
}
}
if (ed_data->earjack_state_filepath) {
kfree(ed_data->earjack_state_filepath);
}
ed_data->earjack_state_filepath = kstrdup(cts_argv[0], GFP_KERNEL);
if (ed_data->earjack_state_filepath == NULL) {
cts_err("Dup earjack state filepath failed");
return -ENOMEM;
}
ed_data->poll_interval = interval;
return count;
}
static DEVICE_ATTR(param, S_IWUSR | S_IRUGO,
earjack_detect_param_show, earjack_detect_param_store);
static struct attribute *earjack_detect_attrs[] = {
&dev_attr_enable.attr,
&dev_attr_running.attr,
&dev_attr_state.attr,
&dev_attr_param.attr,
NULL
};
static const struct attribute_group earjack_detect_attr_group = {
.name = EARJACK_DET_SYSFS_GROUP_NAME,
.attrs = earjack_detect_attrs,
};
#endif /* CONFIG_CTS_SYSFS */
static void poll_earjack_state_work(struct work_struct *work)
{
struct cts_earjack_detect_data *ed_data;
bool prev_state = false;
int ret;
cts_dbg("Poll earjack state work");
ed_data = container_of(to_delayed_work(work),
struct cts_earjack_detect_data, poll_work);
prev_state = ed_data->state;
ret = get_earjack_state(ed_data);
if (ret) {
cts_err("Get state failed %d(%s)", ret, cts_strerror(ret));
} else {
if (ed_data->state != prev_state) {
cts_info("State changed: %s -> %s",
earjack_state_str(prev_state),
earjack_state_str(ed_data->state));
cts_lock_device(&ed_data->cts_data->cts_dev);
ret = cts_set_dev_earjack_attached(
&ed_data->cts_data->cts_dev, ed_data->state);
cts_unlock_device(&ed_data->cts_data->cts_dev);
if (ret) {
cts_err("Set dev earjack attached to %s failed %d(%s)",
earjack_state_str(ed_data->state),
ret, cts_strerror(ret));
/* Set to previous state, try set again in next loop */
ed_data->state = prev_state;
}
}
}
if (!queue_delayed_work(ed_data->cts_data->workqueue,
&ed_data->poll_work,
msecs_to_jiffies(ed_data->poll_interval))) {
cts_warn("Queue detect work while already on the queue");
}
}
int cts_earjack_detect_init(struct chipone_ts_data *cts_data)
{
struct cts_earjack_detect_data *ed_data;
int ret = 0;
if (cts_data == NULL) {
cts_err("Init detect with cts_data = NULL");
return -EFAULT;
}
ed_data = kzalloc(sizeof(*ed_data), GFP_KERNEL);
if (ed_data == NULL) {
cts_err("Alloc earjack detect data failed");
return -ENOMEM;
}
cts_info("Init detect");
#ifdef CONFIG_CTS_OF
ret = parse_earjack_detect_dt(ed_data, cts_data->device->of_node);
#else /* CONFIG_CTS_OF */
#ifdef CFG_CTS_DEF_EARJACK_DET_ENABLE
ed_data->enable = true;
#else /* CFG_CTS_DEF_EARJACK_DET_ENABLE */
ed_data->enable = false;
#endif /* CFG_CTS_DEF_EARJACK_DET_ENABLE */
ed_data->poll_interval = CFG_CTS_DEF_EARJACK_POLL_INTERVAL;
ed_data->earjack_state_filepath = kstrdup(
CFG_CTS_DEF_EARJACK_STATE_FILEPATH, GFP_KERNEL);
if (ed_data->earjack_state_filepath == NULL) {
cts_err("Dup earjack state filepath failed");
ret = -ENOMEM;
}
#endif /* CONFIG_CTS_OF */
if (ret) {
cts_err("Get detect param failed %d(%s)",
ret, cts_strerror(ret));
goto free_ed_data;
}
cts_info("Detect: %sABLED", ed_data->enable ? "EN" : "DIS");
cts_info(" Filepath: '%s'", ed_data->earjack_state_filepath);
cts_info(" Poll Int: %dms", ed_data->poll_interval);
INIT_DELAYED_WORK(&ed_data->poll_work, poll_earjack_state_work);
#ifdef CONFIG_CTS_SYSFS
cts_info("Create sysfs attr group '%s'", EARJACK_DET_SYSFS_GROUP_NAME);
ret = sysfs_create_group(&cts_data->device->kobj,
&earjack_detect_attr_group);
if (ret) {
cts_warn("Create sysfs attr group '%s' failed %d(%s)",
EARJACK_DET_SYSFS_GROUP_NAME, ret, cts_strerror(ret));
} else {
ed_data->sysfs_attr_group_created = true;
}
#endif /* CONFIG_CTS_SYSFS */
cts_data->earjack_detect_data = ed_data;
ed_data->cts_data = cts_data;
return 0;
free_ed_data:
kfree(ed_data);
return ret;
}
int cts_earjack_detect_deinit(struct chipone_ts_data *cts_data)
{
struct cts_earjack_detect_data *ed_data;
int ret;
if (cts_data == NULL) {
cts_err("Deinit detect with cts_data = NULL");
return -EFAULT;
}
ed_data = cts_data->earjack_detect_data;
if (ed_data == NULL) {
cts_warn("Deinit detect with earjack_detect_data = NULL");
return 0;
}
cts_info("Deinit detect");
if (ed_data->running) {
ret = stop_earjack_detect(ed_data);
if (ret) {
cts_err("Stop detect failed %d(%s)",
ret, cts_strerror(ret));
}
}
#ifdef CONFIG_CTS_SYSFS
if (ed_data->sysfs_attr_group_created) {
cts_info("Remove sysfs attr group '%s'", EARJACK_DET_SYSFS_GROUP_NAME);
sysfs_remove_group(&cts_data->device->kobj, &earjack_detect_attr_group);
ed_data->sysfs_attr_group_created = false;
}
#endif /* CONFIG_CTS_SYSFS */
if(ed_data->earjack_state_filepath) {
kfree(ed_data->earjack_state_filepath);
ed_data->earjack_state_filepath = NULL;
}
kfree(ed_data);
cts_data->earjack_detect_data = NULL;
return 0;
}
int cts_is_earjack_attached(struct chipone_ts_data *cts_data, bool *attached)
{
struct cts_earjack_detect_data *ed_data;
int ret;
if (cts_data == NULL) {
cts_err("Get state with cts_data = NULL");
return -EFAULT;
}
ed_data = cts_data->earjack_detect_data;
if (ed_data == NULL) {
cts_err("Get state with earjack_detect_data = NULL");
return -ENODEV;
}
ret = get_earjack_state(ed_data);
if (ret) {
cts_err("Get state failed %d(%s)", ret, cts_strerror(ret));
return ret;
}
cts_info("Get curr state: %s", earjack_state_str(ed_data->state));
*attached = ed_data->state;
return 0;
}
int cts_start_earjack_detect(struct chipone_ts_data *cts_data)
{
struct cts_earjack_detect_data *ed_data;
if (cts_data == NULL) {
cts_err("Start detect with cts_data = NULL");
return -EFAULT;
}
ed_data = cts_data->earjack_detect_data;
if (ed_data == NULL) {
cts_err("Start detect with earjack_detect_data = NULL");
return -ENODEV;
}
return start_earjack_detect(ed_data);
}
int cts_stop_earjack_detect(struct chipone_ts_data *cts_data)
{
struct cts_earjack_detect_data *ed_data;
if (cts_data == NULL) {
cts_err("Stop detect with cts_data = NULL");
return -EFAULT;
}
ed_data = cts_data->earjack_detect_data;
if (ed_data == NULL) {
cts_err("Stop detect with earjack_detect_data = NULL");
return -ENODEV;
}
return stop_earjack_detect(ed_data);
}
#endif /* CONFIG_CTS_EARJACK_DETECT */

View File

@@ -0,0 +1,42 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#ifndef CTS_EARJACK_DETECT_H
#define CTS_EARJACK_DETECT_H
#include "cts_config.h"
//struct chipone_ts_data;
#ifdef CONFIG_CTS_EARJACK_DETECT
extern int cts_earjack_detect_init(struct chipone_ts_data *cts_data);
extern int cts_earjack_detect_deinit(struct chipone_ts_data *cts_data);
extern int cts_start_earjack_detect(struct chipone_ts_data *cts_data);
extern int cts_stop_earjack_detect(struct chipone_ts_data *cts_data);
extern int cts_is_earjack_attached(struct chipone_ts_data *cts_data,
bool *attached);
#else /* CONFIG_CTS_EARJACK_DETECT */
static inline int cts_earjack_detect_init(struct chipone_ts_data *cts_data)
{
return -ENOTSUPP;
}
static inline int cts_earjack_detect_deinit(struct chipone_ts_data *cts_data)
{
return -ENOTSUPP;
}
static inline int cts_start_earjack_detect(struct chipone_ts_data *cts_data)
{
return -ENODEV;
}
static inline int cts_stop_earjack_detect(struct chipone_ts_data *cts_data)
{
return -ENODEV;
}
static inline int cts_is_earjack_attached(struct chipone_ts_data *cts_data,
bool *attached)
{
return -ENODEV;
}
#endif /* CONFIG_CTS_EARJACK_DETECT */
#endif /* CTS_EARJACK_DETECT_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,33 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#ifndef CTS_FIRMWARE_H
#define CTS_FIRMWARE_H
#include "cts_config.h"
#include <linux/firmware.h>
#include <linux/vmalloc.h>
#define FIRMWARE_VERSION_OFFSET 0x100
#define FIRMWARE_VERSION(firmware) \
get_unaligned_le16((firmware)->data + FIRMWARE_VERSION_OFFSET)
struct cts_device;
extern int cts_request_newer_firmware_from_fs(struct cts_device *cts_dev,
const char *filepath, u16 curr_version);
extern bool cts_is_firmware_updating(struct cts_device *cts_dev);
extern int cts_request_firmware(struct cts_device *cts_dev,
u32 hwid, u16 fwid, u16 device_fw_ver);
extern int cts_update_firmware(struct cts_device *cts_dev);
#ifdef CFG_CTS_FIRMWARE_IN_FS
extern int cts_update_firmware_from_file(struct cts_device *cts_dev,
const char *filepath);
#endif /* CFG_CTS_FIRMWARE_IN_FS */
extern u16 cts_crc16(const u8 *data, size_t len);
extern u32 cts_crc32(const u8 *data, size_t len);
#endif /* CTS_FIRMWARE_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,12 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#ifndef CTS_OEM_H
#define CTS_OEM_H
struct chipone_ts_data;
extern int cts_oem_init(struct chipone_ts_data *cts_data);
extern int cts_oem_deinit(struct chipone_ts_data *cts_data);
#endif /* CTS_VENDOR_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,309 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#ifndef CTS_PLATFORM_H
#define CTS_PLATFORM_H
#include <linux/types.h>
#include <asm/byteorder.h>
#include <linux/bitops.h>
#include <linux/ctype.h>
//#include <linux/unaligned/access_ok.h>
#include <asm-generic/unaligned.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/gpio.h>
#include <linux/input.h>
#include <linux/input/mt.h>
#include <linux/spinlock.h>
#include <linux/rtmutex.h>
#include <linux/byteorder/generic.h>
#include <linux/proc_fs.h>
#include <linux/delay.h>
#include <linux/version.h>
#include <linux/jiffies.h>
#include <linux/hrtimer.h>
#include <linux/string.h>
#include <linux/suspend.h>
/* #include <linux/wakelock.h> */
#include <linux/firmware.h>
#include <linux/vmalloc.h>
#ifdef CONFIG_OF
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#endif /* CONFIG_OF */
#include <linux/fb.h>
#include <linux/notifier.h>
#include <linux/spi/spi.h>
#include <linux/spi/spidev.h>
#include "cts_config.h"
#include "cts_core.h"
#ifdef CFG_CTS_PLATFORM_MTK_TPD_SUPPORTED
#ifdef TPD_SUPPORT_I2C_DMA
#include <linux/dma-mapping.h>
#endif /* TPD_SUPPORT_I2C_DMA */
#ifdef CONFIG_MTK_BOOT
#include "mtk_boot_common.h"
#endif /* CONFIG_MTK_BOOT */
#include "tpd.h"
#include "tpd_debug.h"
#include "upmu_common.h"
#endif
extern bool cts_show_debug_log;
#ifndef LOG_TAG
#define LOG_TAG ""
#endif /* LOG_TAG */
enum cts_driver_log_level {
CTS_DRIVER_LOG_ERROR,
CTS_DRIVER_LOG_WARN,
CTS_DRIVER_LOG_INFO,
CTS_DRIVER_LOG_DEBUG,
};
extern int cts_start_driver_log_redirect(const char *filepath, bool append_to_file,
char *log_buffer, int log_buf_size, int log_level);
extern void cts_stop_driver_log_redirect(void);
extern int cts_get_driver_log_redirect_size(void);
extern void cts_log(int level, const char *fmt, ...);
#define cts_err(fmt, ...) \
cts_log(CTS_DRIVER_LOG_ERROR, "<E>CTS-" LOG_TAG " " fmt"\n", ##__VA_ARGS__)
#define cts_warn(fmt, ...) \
cts_log(CTS_DRIVER_LOG_WARN, "<W>CTS-" LOG_TAG " " fmt"\n", ##__VA_ARGS__)
#define cts_info(fmt, ...) \
cts_log(CTS_DRIVER_LOG_INFO, "<I>CTS-" LOG_TAG " " fmt"\n", ##__VA_ARGS__)
#define cts_dbg(fmt, ...) \
cts_log(CTS_DRIVER_LOG_DEBUG, "<D>CTS-" LOG_TAG " " fmt"\n", ##__VA_ARGS__)
struct cts_device;
struct cts_device_touch_msg;
struct cts_device_gesture_info;
struct cts_platform_data {
int irq;
#ifndef CFG_CTS_PLATFORM_MTK_TPD_SUPPORTED
int int_gpio;
#ifdef CFG_CTS_HAS_RESET_PIN
int rst_gpio;
#endif
#ifdef CFG_CTS_MANUAL_CS
int cs_gpio;
#endif
#endif
u32 res_x;
u32 res_y;
#ifdef CONFIG_CTS_VIRTUALKEY
u8 vkey_num;
u8 vkey_state;
u8 vkey_keycodes[CFG_CTS_MAX_VKEY_NUM];
#endif
#ifdef CFG_CTS_FW_UPDATE_SYS
const char *panel_supplier;
#endif
u32 build_id;
u32 config_id;
struct cts_device *cts_dev;
struct input_dev *ts_input_dev;
struct input_dev *pen_input_dev;
#ifndef CONFIG_GENERIC_HARDIRQS
struct work_struct ts_irq_work;
#endif
struct mutex dev_lock;
struct spinlock irq_lock;
bool irq_is_disable;
#ifdef CFG_CTS_GESTURE
u8 gesture_num;
u8 gesture_keymap[CFG_CTS_NUM_GESTURE][2];
bool irq_wake_enabled;
#endif
#ifdef CFG_CTS_PLATFORM_MTK_TPD_SUPPORTED
#ifdef TPD_SUPPORT_I2C_DMA
u8 *i2c_dma_buff_va;
dma_addr_t i2c_dma_buff_pa;
#endif /* TPD_SUPPORT_I2C_DMA */
#else
#ifdef CONFIG_CTS_PM_FB_NOTIFIER
struct notifier_block fb_notifier;
#endif
#endif
#ifdef CFG_CTS_FORCE_UP
struct delayed_work touch_timeout;
#endif
#ifdef CONFIG_CTS_I2C_HOST
struct i2c_client *i2c_client;
u8 i2c_fifo_buf[CFG_CTS_MAX_I2C_XFER_SIZE];
u8 i2c_rbuf[ALIGN(CFG_CTS_MAX_I2C_READ_SIZE, 4)];
#else
struct spi_device *spi_client;
u8 spi_cache_buf[ALIGN(CFG_CTS_MAX_SPI_XFER_SIZE + 10, 4)];
u8 spi_rx_buf[ALIGN(CFG_CTS_MAX_SPI_XFER_SIZE + 10, 4)];
u8 spi_tx_buf[ALIGN(CFG_CTS_MAX_SPI_XFER_SIZE + 10, 4)];
u32 spi_speed;
#ifdef CFG_CTS_PLATFORM_MTK_TPD_SUPPORTED
#ifdef CFG_CTS_MANUAL_CS
struct pinctrl *pinctrl1;
struct pinctrl_state *spi_cs_low, *spi_cs_high;
#endif
#endif/* CONFIG_CTS_I2C_HOST */
#ifdef TPD_SUPPORT_I2C_DMA
bool i2c_dma_available;
#endif /* TPD_SUPPORT_I2C_DMA */
#endif
};
#ifdef CONFIG_CTS_I2C_HOST
extern size_t cts_plat_get_max_i2c_xfer_size(struct cts_platform_data *pdata);
extern u8 *cts_plat_get_i2c_xfer_buf(struct cts_platform_data *pdata,
size_t xfer_size);
extern int cts_plat_i2c_write(struct cts_platform_data *pdata, u8 i2c_addr,
const void *src, size_t len, int retry, int delay);
extern int cts_plat_i2c_read(struct cts_platform_data *pdata, u8 i2c_addr,
const u8 *wbuf, size_t wlen, void *rbuf,
size_t rlen, int retry, int delay);
#else /* CONFIG_CTS_I2C_HOST */
extern size_t cts_plat_get_max_spi_xfer_size(struct cts_platform_data *pdata);
extern u8 *cts_plat_get_spi_xfer_buf(struct cts_platform_data *pdata,
size_t xfer_size);
extern int cts_plat_spi_write(struct cts_platform_data *pdata, u8 i2c_addr,
const void *src, size_t len, int retry, int delay);
extern int cts_plat_spi_read(struct cts_platform_data *pdata, u8 i2c_addr,
const u8 *wbuf, size_t wlen, void *rbuf,
size_t rlen, int retry, int delay);
extern int cts_plat_spi_read_delay_idle(struct cts_platform_data *pdata,
u8 dev_addr, const u8 *wbuf, size_t wlen, void *rbuf, size_t rlen,
int retry, int delay, int idle);
extern int cts_spi_send_recv(struct cts_platform_data *pdata, size_t len,
u8 *tx_buffer, u8 *rx_buffer);
#endif /* CONFIG_CTS_I2C_HOST */
#ifdef CONFIG_CTS_I2C_HOST
extern int cts_init_platform_data(struct cts_platform_data *pdata,
struct i2c_client *i2c_client);
#else
extern int cts_init_platform_data(struct cts_platform_data *pdata,
struct spi_device *spi);
#endif
extern int cts_plat_is_normal_mode(struct cts_platform_data *pdata);
#ifndef CFG_CTS_PLATFORM_MTK_TPD_SUPPORTED
extern int cts_deinit_platform_data(struct cts_platform_data *pdata);
#endif
extern int cts_plat_request_resource(struct cts_platform_data *pdata);
extern void cts_plat_free_resource(struct cts_platform_data *pdata);
extern int cts_plat_request_irq(struct cts_platform_data *pdata);
extern void cts_plat_free_irq(struct cts_platform_data *pdata);
extern int cts_plat_enable_irq(struct cts_platform_data *pdata);
extern int cts_plat_disable_irq(struct cts_platform_data *pdata);
#ifdef CFG_CTS_HAS_RESET_PIN
extern int cts_plat_reset_device(struct cts_platform_data *pdata);
#else /* CFG_CTS_HAS_RESET_PIN */
static inline int cts_plat_reset_device(struct cts_platform_data *pdata)
{
return 0;
}
#endif /* CFG_CTS_HAS_RESET_PIN */
extern int cts_plat_init_touch_device(struct cts_platform_data *pdata);
extern void cts_plat_deinit_touch_device(struct cts_platform_data *pdata);
#ifdef CFG_CTS_PALM_DETECT
void cts_report_palm_event(struct cts_platform_data *pdata);
#endif
extern int cts_plat_process_touch_msg(struct cts_platform_data *pdata,
struct cts_device_touch_msg *msgs, int num);
extern int cts_plat_process_stylus_msg(struct cts_platform_data *pdata,
struct cts_device_stylus_msg *msgs, int num);
#ifdef CFG_CTS_FINGER_STYLUS_SUPPORTED
extern int cts_plat_process_touch_stylus(struct cts_platform_data *pdata,
struct cts_device_touch_info *touch_info);
#endif
extern int cts_plat_release_all_touch(struct cts_platform_data *pdata);
#ifdef CONFIG_CTS_VIRTUALKEY
extern int cts_plat_init_vkey_device(struct cts_platform_data *pdata);
extern void cts_plat_deinit_vkey_device(struct cts_platform_data *pdata);
extern int cts_plat_process_vkey(struct cts_platform_data *pdata,
u8 vkey_state);
extern int cts_plat_release_all_vkey(struct cts_platform_data *pdata);
#else /* CONFIG_CTS_VIRTUALKEY */
static inline int cts_plat_init_vkey_device(struct cts_platform_data *pdata)
{
return 0;
}
static inline void cts_plat_deinit_vkey_device(struct cts_platform_data *pdata)
{
}
static inline int cts_plat_process_vkey(struct cts_platform_data *pdata,
u8 vkey_state)
{
return 0;
}
static inline int cts_plat_release_all_vkey(struct cts_platform_data *pdata)
{
return 0;
}
#endif /* CONFIG_CTS_VIRTUALKEY */
#ifdef CFG_CTS_GESTURE
extern int cts_plat_enable_irq_wake(struct cts_platform_data *pdata);
extern int cts_plat_disable_irq_wake(struct cts_platform_data *pdata);
extern int cts_plat_init_gesture(struct cts_platform_data *pdata);
extern void cts_plat_deinit_gesture(struct cts_platform_data *pdata);
extern int cts_plat_process_gesture_info(struct cts_platform_data *pdata,
struct cts_device_gesture_info *gesture_info);
#else /* CFG_CTS_GESTURE */
static inline int cts_plat_init_gesture(struct cts_platform_data *pdata)
{
return 0;
}
static inline void cts_plat_deinit_gesture(struct cts_platform_data *pdata)
{
}
#endif /* CFG_CTS_GESTURE */
extern int cts_plat_set_reset(struct cts_platform_data *pdata, int val);
extern int cts_plat_get_int_pin(struct cts_platform_data *pdata);
#ifdef CFG_CTS_MANUAL_CS
extern int cts_plat_set_cs(struct cts_platform_data *pdata, int val);
#endif
#endif /* CTS_PLATFORM_H */

View File

@@ -0,0 +1,38 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#ifndef CTS_SFCTRL_H
#define CTS_SFCTRL_H
#include "cts_core.h"
#include "cts_spi_flash.h"
struct cts_device;
struct cts_sfctrl_ops {
int (*rdid)(struct cts_device *cts_dev, u32 *id);
int (*se)(struct cts_device *cts_dev, u32 sector_addr);
int (*be)(struct cts_device *cts_dev, u32 sector_addr);
int (*read)(struct cts_device *cts_dev,
u32 flash_addr, void *dst, size_t len);
int (*read_to_sram)(struct cts_device *cts_dev,
u32 flash_addr, u32 sram_addr, size_t len);
int (*program)(struct cts_device *cts_dev,
u32 flash_addr, const void *src, size_t len);
int (*program_from_sram)(struct cts_device *cts_dev,
u32 flash_addr, u32 sram_addr, size_t len);
int (*calc_sram_crc)(struct cts_device *cts_dev,
u32 sram_addr, size_t len, u32 *crc);
int (*calc_flash_crc)(struct cts_device *cts_dev,
u32 flash_addr, size_t len, u32 *crc);
};
struct cts_sfctrl {
u32 reg_base;
u32 xchg_sram_base;
size_t xchg_sram_size;
const struct cts_sfctrl_ops *ops;
};
extern const struct cts_sfctrl_ops cts_sfctrlv2_ops;
#endif /* CTS_SFCTRL_H */

View File

@@ -0,0 +1,342 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#define LOG_TAG "SFCtrl"
#include "cts_config.h"
#include "cts_platform.h"
#include "cts_core.h"
#include "cts_sfctrl.h"
#define rSFCTRLv2_CMD_SEL (0x0000)
#define rSFCTRLv2_FLASH_ADDR (0x0004)
#define rSFCTRLv2_SRAM_ADDR (0x0008)
#define rSFCTRLv2_DATA_LENGTH (0x000C)
#define rSFCTRLv2_START_DEXC (0x0010)
#define rSFCTRLv2_RELEASE_FLASH (0x0014)
#define rSFCTRLv2_HW_STATE (0x0018)
#define rSFCTRLv2_CRC_RESULT (0x001C)
#define rSFCTRLv2_SRAM_CRC_START (0x0020)
#define rSFCTRLv2_FLASH_CRC_START (0x0022)
#define rSFCTRLv2_SF_BUSY (0x0024)
/** Constants for register @ref rSFCTRLv2_CMD_SEL */
enum sfctrlv2_cmd {
SFCTRLv2_CMD_FAST_READ = 0x01u,
SFCTRLv2_CMD_SE = 0x02u,
SFCTRLv2_CMD_BE = 0x03u,
SFCTRLv2_CMD_PP = 0x04u,
SFCTRLv2_CMD_RDSR = 0x05u,
SFCTRLv2_CMD_RDID = 0x06u
};
/** SPI flash controller v2 operation flags. */
enum sfctrlv2_opflags {
SFCTRLv2_OPFLAG_READ = BIT(0),
SFCTRLv2_OPFLAG_SET_FLASH_ADDR = BIT(1),
SFCTRLv2_OPFLAG_SRAM_DATA_XCHG = BIT(2),
SFCTRLv2_OPFLAG_SET_DATA_LENGTH = BIT(3),
SFCTRLv2_OPFLAG_WAIT_WIP_CLR = BIT(4),
};
#define SFCTRLv2_CMD_RDID_FLAGS \
(SFCTRLv2_OPFLAG_READ | \
SFCTRLv2_OPFLAG_SRAM_DATA_XCHG)
#define SFCTRLv2_CMD_RDSR_FLAGS \
(SFCTRLv2_OPFLAG_READ | \
SFCTRLv2_OPFLAG_SRAM_DATA_XCHG)
#define SFCTRLv2_CMD_SE_FLAGS \
(SFCTRLv2_OPFLAG_SET_FLASH_ADDR | \
SFCTRLv2_OPFLAG_WAIT_WIP_CLR)
#define SFCTRLv2_CMD_BE_FLAGS \
(SFCTRLv2_OPFLAG_SET_FLASH_ADDR | \
SFCTRLv2_OPFLAG_WAIT_WIP_CLR)
#define SFCTRLv2_CMD_PP_FLAGS \
(SFCTRLv2_OPFLAG_SET_FLASH_ADDR | \
SFCTRLv2_OPFLAG_SRAM_DATA_XCHG | \
SFCTRLv2_OPFLAG_SET_DATA_LENGTH | \
SFCTRLv2_OPFLAG_WAIT_WIP_CLR)
#define SFCTRLv2_CMD_FAST_READ_FLAGS \
(SFCTRLv2_OPFLAG_READ | \
SFCTRLv2_OPFLAG_SET_FLASH_ADDR | \
SFCTRLv2_OPFLAG_SRAM_DATA_XCHG | \
SFCTRLv2_OPFLAG_SET_DATA_LENGTH)
#define sfctrl_reg_addr(cts_dev, offset) \
((cts_dev)->hwdata->sfctrl->reg_base + offset)
#define DEFINE_SFCTRL_REG_ACCESS_FUNC(access_type, data_type) \
static inline int sfctrl_reg_ ## access_type(struct cts_device *cts_dev, \
u32 reg, data_type data) { \
return cts_hw_reg_ ## access_type(cts_dev, sfctrl_reg_addr(cts_dev, reg), data); \
}
DEFINE_SFCTRL_REG_ACCESS_FUNC(writeb_relaxed, u8)
DEFINE_SFCTRL_REG_ACCESS_FUNC(writew_relaxed, u16)
DEFINE_SFCTRL_REG_ACCESS_FUNC(writel_relaxed, u32)
DEFINE_SFCTRL_REG_ACCESS_FUNC(readb_relaxed, u8 *)
DEFINE_SFCTRL_REG_ACCESS_FUNC(readw_relaxed, u16 *)
DEFINE_SFCTRL_REG_ACCESS_FUNC(readl_relaxed, u32 *)
#define sfctrl_write_reg_check_ret(access_type, reg, val) \
do { \
int ret; \
cts_dbg("Write " #reg " to 0x%x", val); \
ret = sfctrl_reg_ ## access_type(cts_dev, reg, val); \
if (ret) { \
cts_err("Write " #reg " failed %d", ret); \
return ret; \
} \
} while (0)
#define sfctrl_read_reg_check_ret(access_type, reg, val) \
do { \
int ret; \
cts_dbg("Read " #reg ""); \
ret = sfctrl_reg_ ## access_type(cts_dev, reg, val); \
if (ret) { \
cts_err("Read " #reg " failed %d", ret); \
return ret; \
} \
} while (0)
static int wait_sfctrl_xfer_comp(struct cts_device *cts_dev)
{
int retries = 0;
u8 status;
do {
sfctrl_read_reg_check_ret(readb_relaxed, rSFCTRLv2_SF_BUSY, &status);
if (status == 0)
return 0;
mdelay(1);
} while (status && retries++ < 1000);
return -ETIMEDOUT;
}
static int sfctrlv2_rdsr(struct cts_device *cts_dev, u8 *status)
{
#define RDSR_XCHG_SRAM_ADDR (cts_dev->hwdata->sfctrl->xchg_sram_base + cts_dev->hwdata->sfctrl->xchg_sram_size - 1)
int ret;
sfctrl_write_reg_check_ret(writeb_relaxed, rSFCTRLv2_CMD_SEL,
SFCTRLv2_CMD_RDSR);
sfctrl_write_reg_check_ret(writel_relaxed, rSFCTRLv2_SRAM_ADDR,
RDSR_XCHG_SRAM_ADDR);
sfctrl_write_reg_check_ret(writeb_relaxed, rSFCTRLv2_START_DEXC, 1);
ret = wait_sfctrl_xfer_comp(cts_dev);
if (ret != 0) {
cts_err("Wait sfctrl ready failed %d", ret);
return ret;
}
ret = cts_sram_readb(cts_dev, RDSR_XCHG_SRAM_ADDR, status);
if (ret) {
cts_err("Read exchange sram failed %d", ret);
return ret;
}
#undef RDSR_XCHG_SRAM_ADDR
return 0;
}
static int wait_flash_wip_clear(struct cts_device *cts_dev)
{
#define FLASH_SR_WIP BIT(0) /*!< Write in progress */
int ret, retries = 0;
u8 status;
do {
ret = sfctrlv2_rdsr(cts_dev, &status);
if (ret) {
cts_err("Read flash status register failed %d", ret);
return ret;
}
if (status & FLASH_SR_WIP)
mdelay(1);
else
return 0;
} while (status & FLASH_SR_WIP && retries++ < 1000);
return -ETIMEDOUT;
#undef FLASH_SR_WIP
}
static int sfctrlv2_transfer(struct cts_device *cts_dev,
u8 cmd, void *data, u32 flash_addr, u32 sram_addr,
size_t size, u32 flags)
{
int ret;
sfctrl_write_reg_check_ret(writeb_relaxed, rSFCTRLv2_CMD_SEL, cmd);
if (flags & SFCTRLv2_OPFLAG_SRAM_DATA_XCHG) {
sfctrl_write_reg_check_ret(writel_relaxed, rSFCTRLv2_SRAM_ADDR,
sram_addr);
/** - Write data to exchange SRAM if operation is write and
* data != NULL(data not in SRAM)
*/
if ((!(flags & SFCTRLv2_OPFLAG_READ)) && data) {
ret = cts_sram_writesb(cts_dev, sram_addr, data, size);
if (ret) {
cts_err("Write data to exchange sram 0x%06x size %zu failed %d",
sram_addr, size, ret);
return ret;
}
}
}
if (flags & SFCTRLv2_OPFLAG_SET_FLASH_ADDR) {
sfctrl_write_reg_check_ret(writel_relaxed, rSFCTRLv2_FLASH_ADDR,
flash_addr);
}
if (flags & SFCTRLv2_OPFLAG_SET_DATA_LENGTH) {
sfctrl_write_reg_check_ret(writel_relaxed,
rSFCTRLv2_DATA_LENGTH, (u32) size);
}
sfctrl_write_reg_check_ret(writeb_relaxed, rSFCTRLv2_START_DEXC, 1);
ret = wait_sfctrl_xfer_comp(cts_dev);
if (ret != 0) {
cts_err("Wait sfctrl ready failed %d", ret);
return ret;
}
ret = wait_flash_wip_clear(cts_dev);
if (flags & SFCTRLv2_OPFLAG_WAIT_WIP_CLR && ret != 0) {
cts_err("Wait WIP clear failed %d", ret);
return ret;
}
if ((flags & SFCTRLv2_OPFLAG_READ) && data) {
ret = cts_sram_readsb(cts_dev, sram_addr, data, size);
if (ret) {
cts_err("Read data from exchange sram 0x%06x size %zu failed %d",
sram_addr, size, ret);
return ret;
}
}
return 0;
}
static int sfctrlv2_rdid(struct cts_device *cts_dev, u32 *id)
{
int ret;
u8 buf[4];
ret = sfctrlv2_transfer(cts_dev, SFCTRLv2_CMD_RDID, buf,
0, cts_dev->hwdata->sfctrl->xchg_sram_base, 3,
SFCTRLv2_CMD_RDID_FLAGS);
*id = ret ? 0 : get_unaligned_be24(buf);
return ret;
}
static int sfctrlv2_se(struct cts_device *cts_dev, u32 sector_addr)
{
return sfctrlv2_transfer(cts_dev, SFCTRLv2_CMD_SE, NULL,
sector_addr, 0, 0, SFCTRLv2_CMD_SE_FLAGS);
}
static int sfctrlv2_be(struct cts_device *cts_dev, u32 block_addr)
{
return sfctrlv2_transfer(cts_dev, SFCTRLv2_CMD_BE, NULL,
block_addr, 0, 0, SFCTRLv2_CMD_BE_FLAGS);
}
static int sfctrlv2_pp(struct cts_device *cts_dev,
u32 flash_addr, const void *src, size_t size)
{
return sfctrlv2_transfer(cts_dev, SFCTRLv2_CMD_PP, (void *)src,
flash_addr, cts_dev->hwdata->sfctrl->xchg_sram_base, size,
SFCTRLv2_CMD_PP_FLAGS);
}
static int sfctrlv2_program_flash_from_sram(struct cts_device *cts_dev,
u32 flash_addr, u32 sram_addr, size_t len)
{
return sfctrlv2_transfer(cts_dev, SFCTRLv2_CMD_PP, NULL,
flash_addr, sram_addr, len, SFCTRLv2_CMD_PP_FLAGS);
}
static int sfctrlv2_read(struct cts_device *cts_dev,
u32 flash_addr, void *dst, size_t size)
{
return sfctrlv2_transfer(cts_dev, SFCTRLv2_CMD_FAST_READ, dst,
flash_addr, cts_dev->hwdata->sfctrl->xchg_sram_base, size,
SFCTRLv2_CMD_FAST_READ_FLAGS);
}
static int sfctrlv2_read_flash_to_sram(struct cts_device *cts_dev,
u32 flash_addr, u32 sram_addr, size_t size)
{
return sfctrlv2_transfer(cts_dev, SFCTRLv2_CMD_FAST_READ, NULL,
flash_addr, sram_addr, size, SFCTRLv2_CMD_FAST_READ_FLAGS);
}
static int sfctrlv2_calc_sram_crc(struct cts_device *cts_dev,
u32 sram_addr, size_t size, u32 *crc)
{
int ret;
sfctrl_write_reg_check_ret(writel_relaxed, rSFCTRLv2_SRAM_ADDR, sram_addr);
mdelay(1);
sfctrl_write_reg_check_ret(writel_relaxed, rSFCTRLv2_DATA_LENGTH, (u32) size);
mdelay(1);
sfctrl_write_reg_check_ret(writeb_relaxed, rSFCTRLv2_SRAM_CRC_START, 1);
mdelay(10);
ret = wait_sfctrl_xfer_comp(cts_dev);
if (ret != 0) {
cts_err("Wait sfctrl ready failed %d", ret);
return ret;
}
sfctrl_read_reg_check_ret(readl_relaxed, rSFCTRLv2_CRC_RESULT, crc);
return 0;
}
static int sfctrlv2_calc_flash_crc(struct cts_device *cts_dev,
u32 flash_addr, size_t size, u32 *crc)
{
int ret;
cts_info("Calc crc from flash 0x%06x size %zu", flash_addr, size);
sfctrl_write_reg_check_ret(writel_relaxed, rSFCTRLv2_FLASH_ADDR, flash_addr);
sfctrl_write_reg_check_ret(writel_relaxed, rSFCTRLv2_DATA_LENGTH, (u32) size);
sfctrl_write_reg_check_ret(writeb_relaxed, rSFCTRLv2_FLASH_CRC_START, 1);
ret = wait_sfctrl_xfer_comp(cts_dev);
if (ret != 0) {
cts_err("Wait sfctrl ready failed %d", ret);
return ret;
}
sfctrl_read_reg_check_ret(readl_relaxed, rSFCTRLv2_CRC_RESULT, crc);
return 0;
}
const struct cts_sfctrl_ops cts_sfctrlv2_ops = {
.rdid = sfctrlv2_rdid,
.se = sfctrlv2_se,
.be = sfctrlv2_be,
.read = sfctrlv2_read,
.read_to_sram = sfctrlv2_read_flash_to_sram,
.program = sfctrlv2_pp,
.program_from_sram = sfctrlv2_program_flash_from_sram,
.calc_sram_crc = sfctrlv2_calc_sram_crc,
.calc_flash_crc = sfctrlv2_calc_flash_crc,
};

View File

@@ -0,0 +1,536 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#define LOG_TAG "Flash"
#include "cts_config.h"
#include "cts_platform.h"
#include "cts_core.h"
#include "cts_sfctrl.h"
#include "cts_spi_flash.h"
#include "cts_strerror.h"
/* NOTE: double check command sets and memory organization when you add
* more flash chips. This current list focusses on newer chips, which
* have been converging on command sets which including JEDEC ID.
*/
static const struct cts_flash cts_flashes[] = {
/* Winbond */
{ "Winbond,W25Q10EW",
0xEF6011, 256, 0x1000, 0x8000, 0x20000},
{ "Winbond,W25Q20EW",
0xEF6012, 256, 0x1000, 0x8000, 0x40000},
{ "Winbond,W25Q40EW",
0xEF6013, 256, 0x1000, 0x8000, 0x80000},
{ "Winbond,W25Q20BW",
0xEF5012, 256, 0x1000, 0x8000, 0x40000},
{ "Winbond,W25Q40BW",
0xEF5013, 256, 0x1000, 0x8000, 0x80000},
/* Giga device */
{ "Giga,GD25LQ10B",
0xC86011, 256, 0x1000, 0x8000, 0x20000},
{ "Giga,GD25LD20CEIGR",
0xC86012, 256, 0x1000, 0x8000, 0x40000},
{ "Giga,GD25LD40CEIGR",
0xC86013, 256, 0x1000, 0x8000, 0x80000},
/* Macronix */
{ "Macronix,MX25U1001E",
0xC22531, 32, 0x1000, 0x10000, 0x20000},
{ "Macronix,MX25R2035F",
0xC22812, 256, 0x1000, 0x8000, 0x40000},
{ "Macronix,MX25R4035F",
0xC22813, 256, 0x1000, 0x8000, 0x80000},
/* Puya-Semi */
{ "Puya-Semi,P25Q20LUVHIR",
0x856012, 256, 0x1000, 0x8000, 0x40000},
{ "Puya-Semi,P25Q40LUXHIR",
0x856013, 256, 0x1000, 0x8000, 0x80000},
{ "Puya-Semi,P25Q11L",
0x854011, 256, 0x1000, 0x8000, 0x20000},
{ "Puya-Semi,P25Q21L",
0x854012, 256, 0x1000, 0x8000, 0x40000},
{ "Puya-Semi,P25T22L",
0x854412, 256, 0x1000, 0x8000, 0x40000},
/* Boya */
{ "Boya,BY25D10",
0x684011, 256, 0x1000, 0x8000, 0x20000},
/* EON */
{ "EoN,EN25S20A",
0x1C3812, 256, 0x1000, 0x8000, 0x40000},
/* XTXTECH */
{ "XTX,XT25Q01",
0x0B6011, 256, 0x1000, 0, 0x20000},
{ "XTX,XT25Q02",
0x0B6012, 256, 0x1000, 0, 0x40000},
/* Xinxin-Semi */
{ "Xinxin-Semi,XM25QU20B",
0x205012, 256, 0x1000, 0x8000, 0x40000},
{ "Xinxin-Semi,XM25QU40B",
0x205013, 256, 0x1000, 0x8000, 0x80000},
{ "KangYong,XK25Q20T",
0xEB6012, 256, 0x1000, 0x8000, 0x40000},
/*ZBIT*/
{ "ZBIT,ZB25LD40B",
0x5E1013, 256, 0x1000, 0x8000, 0x80000},
};
static const struct cts_flash *find_flash_by_jedec_id(u32 jedec_id)
{
int i;
for (i = 0; i < ARRAY_SIZE(cts_flashes); i++) {
if (cts_flashes[i].jedec_id == jedec_id) {
return &cts_flashes[i];
}
}
return NULL;
}
static int probe_flash(struct cts_device *cts_dev)
{
int ret;
cts_info("Probe flash");
if (cts_dev->hwdata->sfctrl->ops->rdid != NULL) {
u32 id;
cts_info("Read JEDEC ID");
ret = cts_dev->hwdata->sfctrl->ops->rdid(cts_dev, &id);
if (ret) {
cts_err("Read JEDEC ID failed %d(%s)",
ret, cts_strerror(ret));
return ret;
}
cts_dev->flash = find_flash_by_jedec_id(id);
if (cts_dev->flash == NULL) {
cts_err("Unknown JEDEC ID: %06x", id);
return -ENODEV;
}
cts_info("Flash type: '%s'", cts_dev->flash->name);
return 0;
} else {
cts_err("Probe flash with sfctrl->ops->rdid == NULL");
return -ENOTSUPP;
}
}
/** Make sure sector addr is sector aligned && < flash total size */
static int erase_sector_retry(struct cts_device *cts_dev,
u32 sector_addr, int retry)
{
int ret, retries;
cts_info(" Erase sector 0x%06x", sector_addr);
retries = 0;
do {
retries++;
ret = cts_dev->hwdata->sfctrl->ops->se(cts_dev, sector_addr);
if (ret) {
cts_err("Erase sector 0x%06x failed %d(%s) retries %d",
sector_addr, ret, cts_strerror(ret), retries);
continue;
}
} while (retries < retry);
return ret;
}
/** Make sure sector addr is sector aligned && < flash total size */
static inline int erase_sector(struct cts_device *cts_dev,
u32 sector_addr)
{
return erase_sector_retry(cts_dev, sector_addr, CTS_FLASH_ERASE_DEFAULT_RETRY);
}
/** Make sure block addr is block aligned && < flash total size */
static int erase_block_retry(struct cts_device *cts_dev,
u32 block_addr, int retry)
{
int ret, retries;
cts_info(" Erase block 0x%06x", block_addr);
retries = 0;
do {
retries++;
ret = cts_dev->hwdata->sfctrl->ops->be(cts_dev, block_addr);
if (ret) {
cts_err("Erase block 0x%06x failed %d(%s) retries %d",
block_addr, ret, cts_strerror(ret), retries);
continue;
}
} while (retries < retry);
return ret;
}
/** Make sure block addr is block aligned && < flash total size */
static inline int erase_block(struct cts_device *cts_dev,
u32 block_addr)
{
return erase_block_retry(cts_dev, block_addr,
CTS_FLASH_ERASE_DEFAULT_RETRY);
}
int cts_prepare_flash_operation(struct cts_device *cts_dev)
{
int ret;
u8 diva = 0;
bool program_mode = cts_is_device_program_mode(cts_dev);
u32 hwid;
bool enabled = cts_is_device_enabled(cts_dev);
cts_info("Prepare for flash operation");
if (!program_mode) {
ret = cts_enter_program_mode(cts_dev);
if (ret) {
cts_err("Enter program mode failed %d(%s)",
ret, cts_strerror(ret));
goto err_start_device;
}
}
ret = cts_hw_reg_readb_retry(cts_dev, CTS_DEV_HW_REG_CLK_DIV_CFG, &diva, 5, 0);
if (ret) {
cts_warn("Read DIVA failed %d(%s)", ret, cts_strerror(ret));
} else {
cts_dbg("Device DIVA = %d", diva);
}
if (ret == 0 && diva == 0x0C) {
cts_info("DIVA is ready already");
} else {
int retries;
/* Set HCLK to 10MHz */
hwid = cts_dev->hwdata->hwid;
if (hwid == CTS_DEV_HWID_ICNL9951) {
ret = cts_hw_reg_writeb_retry(cts_dev, CTS_DEV_HW_REG_CLK_DIV_CFG, 0x0C, 5, 0);
if (ret) {
cts_err("Write DIVA failed %d(%s)",
ret, cts_strerror(ret));
goto err_enter_normal_mode;
}
}
/* Reset SFCTL */
ret = cts_hw_reg_writeb_retry(cts_dev, CTS_DEV_HW_REG_RESET_CONFIG, 0xFB, 5, 0);
if (ret) {
cts_err("Reset sfctl failed %d(%s)",
ret, cts_strerror(ret));
goto err_enter_normal_mode;
}
retries = 0;
do {
u8 state;
ret = cts_hw_reg_readb_relaxed(cts_dev, CTS_DEV_HW_REG_HW_STATUS, &state);
if (ret == 0 && (state & 0x40) != 0)
goto init_flash;
mdelay(2);
} while (++retries < 1000);
if (ret) {
cts_warn("Wait SFCTRL ready failed %d(%s)", ret, cts_strerror(ret));
}
// Go through and try
}
init_flash:
if (cts_dev->flash == NULL) {
cts_info("Flash is not initialized, try to probe...");
if ((ret = probe_flash(cts_dev)) != 0) {
cts_dev->rtdata.has_flash = false;
cts_warn("Probe flash failed %d(%s)",
ret, cts_strerror(ret));
return 0;
}
}
cts_dev->rtdata.has_flash = true;
return 0;
err_enter_normal_mode:
if (!program_mode) {
int r = cts_enter_normal_mode(cts_dev);
if (r) {
cts_err("Enter normal mode failed %d(%s)",
r, cts_strerror(r));
}
}
err_start_device:
if (enabled) {
int r = cts_start_device(cts_dev);
if (r) {
cts_err("Start device failed %d(%s)",
r, cts_strerror(r));
}
}
return ret;
}
int cts_post_flash_operation(struct cts_device *cts_dev)
{
u32 hwid;
cts_info("Post flash operation");
hwid = cts_dev->hwdata->hwid;
if (hwid == CTS_DEV_HWID_ICNL9951) {
return cts_hw_reg_writeb_retry(cts_dev, CTS_DEV_HW_REG_CLK_DIV_CFG, 4, 5, 0);
}
return 0;
}
int cts_read_flash_retry(struct cts_device *cts_dev,
u32 flash_addr, void *dst, size_t size, int retry)
{
const struct cts_sfctrl *sfctrl;
const struct cts_flash *flash;
int ret;
cts_info("Read from 0x%06x size %zu", flash_addr, size);
sfctrl = cts_dev->hwdata->sfctrl;
flash = cts_dev->flash;
if (flash == NULL ||
sfctrl == NULL ||
sfctrl->ops == NULL ||
sfctrl->ops->read == NULL) {
cts_err("Read not supported");
return -ENOTSUPP;
}
if (flash_addr > flash->total_size) {
cts_err("Read from 0x%06x > flash size 0x%06zx",
flash_addr, flash->total_size);
return -EINVAL;
}
size = min(size, flash->total_size - flash_addr);
cts_info("Read actually from 0x%06x size %zu", flash_addr, size);
while (size) {
size_t l;
l = min(sfctrl->xchg_sram_size, size);
ret = sfctrl->ops->read(cts_dev, flash_addr, dst, l);
if(ret < 0) {
cts_err("Read from 0x%06x size %zu failed %d(%s)",
flash_addr, size, ret, cts_strerror(ret));
return ret;
}
dst += l;
size -= l;
flash_addr += l;
}
return 0;
}
int cts_program_flash(struct cts_device *cts_dev,
u32 flash_addr, const void *src, size_t size)
{
const struct cts_sfctrl *sfctrl;
const struct cts_flash *flash;
int ret;
cts_info("Program to 0x%06x size %zu", flash_addr, size);
sfctrl = cts_dev->hwdata->sfctrl;
flash = cts_dev->flash;
if (flash == NULL ||
sfctrl == NULL ||
sfctrl->ops == NULL ||
sfctrl->ops->program == NULL) {
cts_err("Program not supported");
return -ENOTSUPP;
}
if (flash_addr >= flash->total_size) {
cts_err("Program from 0x%06x >= flash size 0x%06zx",
flash_addr, flash->total_size);
return -EINVAL;
}
size = min(size, flash->total_size - flash_addr);
cts_info("Program actually to 0x%06x size %zu", flash_addr, size);
while (size) {
size_t l, offset;
l = min(flash->page_size, size);
offset = flash_addr & (flash->page_size - 1);
if (offset) {
l = min(flash->page_size - offset, l);
}
ret = sfctrl->ops->program(cts_dev, flash_addr, src, l);
if(ret) {
cts_err("Program to 0x%06x size %zu failed %d(%s)",
flash_addr, l, ret, cts_strerror(ret));
return ret;
}
src += l;
size -= l;
flash_addr += l;
}
return 0;
}
int cts_program_flash_from_sram(struct cts_device *cts_dev,
u32 flash_addr, u32 sram_addr, size_t size)
{
const struct cts_sfctrl *sfctrl;
const struct cts_flash *flash;
int ret;
cts_info("Program to 0x%06x from sram 0x%06x size %zu",
flash_addr, sram_addr, size);
sfctrl = cts_dev->hwdata->sfctrl;
flash = cts_dev->flash;
if (flash == NULL ||
sfctrl == NULL ||
sfctrl->ops == NULL ||
sfctrl->ops->program_from_sram == NULL) {
cts_err("Program from sram not supported");
return -ENOTSUPP;
}
if (flash_addr >= flash->total_size) {
cts_err("Program from 0x%06x >= flash size 0x%06zx",
flash_addr, flash->total_size);
return -EINVAL;
}
size = min(size, flash->total_size - flash_addr);
cts_info("Program actually to 0x%06x from sram 0x%06x size %zu",
flash_addr, sram_addr, size);
while (size) {
size_t l, offset;
l = min(flash->page_size, size);
offset = flash_addr & (flash->page_size - 1);
if (offset) {
l = min(flash->page_size - offset, l);
}
ret = sfctrl->ops->program_from_sram(cts_dev,
flash_addr, sram_addr, l);
if(ret) {
cts_err("Program to 0x%06x from sram 0x%06x size %zu "
"failed %d(%s)",
flash_addr, sram_addr, l, ret, cts_strerror(ret));
return ret;
}
size -= l;
flash_addr += l;
sram_addr += l;
}
return 0;
}
int cts_erase_flash(struct cts_device *cts_dev, u32 addr, size_t size)
{
const struct cts_sfctrl *sfctrl;
const struct cts_flash *flash;
int ret;
cts_info("Erase from 0x%06x size %zu", addr, size);
sfctrl = cts_dev->hwdata->sfctrl;
flash = cts_dev->flash;
if (flash == NULL ||
sfctrl == NULL || sfctrl->ops == NULL ||
sfctrl->ops->se == NULL || sfctrl->ops->be == NULL ||
flash == NULL) {
cts_err("Oops");
return -EINVAL;
}
/* Addr and size MUST sector aligned */
addr = rounddown(addr, flash->sector_size);
size = roundup(size, flash->sector_size);
if (addr > flash->total_size) {
cts_err("Erase from 0x%06x > flash size 0x%06zx",
addr, flash->total_size);
return -EINVAL;
}
size = min(size, flash->total_size - addr);
cts_info("Erase actually from 0x%06x size %zu", addr, size);
if (flash->block_size) {
while (addr != ALIGN(addr, flash->block_size) &&
size >= flash->sector_size) {
ret = erase_sector(cts_dev, addr);
if (ret) {
cts_err("Erase sector 0x%06x size 0x%04zx failed %d(%s)",
addr, flash->sector_size, ret, cts_strerror(ret));
return ret;
}
addr += flash->sector_size;
size -= flash->sector_size;
}
while (size >= flash->block_size) {
ret = erase_block(cts_dev, addr);
if (ret) {
cts_err("Erase block 0x%06x size 0x%04zx failed %d(%s)",
addr, flash->block_size, ret, cts_strerror(ret));
return ret;
}
addr += flash->block_size;
size -= flash->block_size;
}
}
while (size >= flash->sector_size) {
ret = erase_sector(cts_dev, addr);
if (ret) {
cts_err("Erase sector 0x%06x size 0x%04zx failed %d(%s)",
addr, flash->sector_size, ret, cts_strerror(ret));
return ret;
}
addr += flash->sector_size;
size -= flash->sector_size;
}
return 0;
}

View File

@@ -0,0 +1,45 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#ifndef CTS_SPI_FLASH_H
#define CTS_SPI_FLASH_H
struct cts_flash {
const char *name;
u32 jedec_id; /* Device ID by command 0x9F */
size_t page_size; /* Page size by command 0x02 */
size_t sector_size; /* Sector size by command 0x20 */
/* Block size by command 0x52,
* if 0 means block erase NOT supported
*/
size_t block_size;
size_t total_size;
};
#define CTS_FLASH_READ_DEFAULT_RETRY (3)
#define CTS_FLASH_ERASE_DEFAULT_RETRY (3)
struct cts_device;
extern int cts_prepare_flash_operation(struct cts_device *cts_dev);
extern int cts_post_flash_operation(struct cts_device *cts_dev);
extern int cts_read_flash_retry(struct cts_device *cts_dev,
u32 flash_addr, void *dst, size_t size, int retry);
static inline int cts_read_flash(struct cts_device *cts_dev,
u32 flash_addr, void *dst, size_t size)
{
return cts_read_flash_retry(cts_dev, flash_addr, dst, size,
CTS_FLASH_READ_DEFAULT_RETRY);
}
extern int cts_erase_flash(struct cts_device *cts_dev, u32 addr,
size_t size);
extern int cts_program_flash(struct cts_device *cts_dev,
u32 flash_addr, const void *src, size_t size);
extern int cts_program_flash_from_sram(struct cts_device *cts_dev,
u32 flash_addr, u32 sram_addr, size_t size);
#endif /* CTS_SPI_FLASH_H */

View File

@@ -0,0 +1,175 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include <linux/kernel.h>
#include <linux/errno.h>
#include "cts_strerror.h"
#define ERROR_TEXT_ENTRY(errno, err_desc_str) \
[(errno)] = #errno ", " err_desc_str
static char *_error_text[] = {
[0] = "Success",
ERROR_TEXT_ENTRY(EPERM, "Operation not permitted"),
ERROR_TEXT_ENTRY(ENOENT, "No such file or directory"),
ERROR_TEXT_ENTRY(ESRCH, "No such process"),
ERROR_TEXT_ENTRY(EINTR, "Interrupted system call"),
ERROR_TEXT_ENTRY(EIO, "Input/output error"),
ERROR_TEXT_ENTRY(ENXIO, "No such device or address"),
ERROR_TEXT_ENTRY(E2BIG, "Argument list too long"),
ERROR_TEXT_ENTRY(ENOEXEC, "Exec format error"),
ERROR_TEXT_ENTRY(EBADF, "Bad file descriptor"),
ERROR_TEXT_ENTRY(ECHILD, "No child processes"),
ERROR_TEXT_ENTRY(EAGAIN, "Resource temporarily unavailable"),
ERROR_TEXT_ENTRY(ENOMEM, "Cannot allocate memory"),
ERROR_TEXT_ENTRY(EACCES, "Permission denied"),
ERROR_TEXT_ENTRY(EFAULT, "Bad address"),
ERROR_TEXT_ENTRY(ENOTBLK, "Block device required"),
ERROR_TEXT_ENTRY(EBUSY, "Device or resource busy"),
ERROR_TEXT_ENTRY(EEXIST, "File exists"),
ERROR_TEXT_ENTRY(EXDEV, "Invalid cross-device link"),
ERROR_TEXT_ENTRY(ENODEV, "No such device"),
ERROR_TEXT_ENTRY(ENOTDIR, "Not a directory"),
ERROR_TEXT_ENTRY(EISDIR, "Is a directory"),
ERROR_TEXT_ENTRY(EINVAL, "Invalid argument"),
ERROR_TEXT_ENTRY(EMFILE, "Too many open files"),
ERROR_TEXT_ENTRY(ENFILE, "Too many open files in system"),
ERROR_TEXT_ENTRY(ENOTTY, "Inappropriate ioctl for device"),
ERROR_TEXT_ENTRY(ETXTBSY, "Text file busy"),
ERROR_TEXT_ENTRY(EFBIG, "File too large"),
ERROR_TEXT_ENTRY(ENOSPC, "No space left on device"),
ERROR_TEXT_ENTRY(ESPIPE, "Illegal seek"),
ERROR_TEXT_ENTRY(EROFS, "Read-only file system"),
ERROR_TEXT_ENTRY(EMLINK, "Too many links"),
ERROR_TEXT_ENTRY(EPIPE, "Broken pipe"),
ERROR_TEXT_ENTRY(EDOM, "Numerical argument out of domain"),
ERROR_TEXT_ENTRY(ERANGE, "Numerical result out of range"),
ERROR_TEXT_ENTRY(EDEADLK, "Resource deadlock avoided"),
ERROR_TEXT_ENTRY(ENAMETOOLONG, "File name too long"),
ERROR_TEXT_ENTRY(ENOLCK, "No locks available"),
ERROR_TEXT_ENTRY(ENOSYS, "Function not implemented"),
ERROR_TEXT_ENTRY(ENOTEMPTY, "Directory not empty"),
ERROR_TEXT_ENTRY(ELOOP, "Too many levels of symbolic links"),
ERROR_TEXT_ENTRY(EWOULDBLOCK, "Operation would block"),
ERROR_TEXT_ENTRY(ENOMSG, "No message of desired type"),
ERROR_TEXT_ENTRY(EIDRM, "Identifier removed"),
ERROR_TEXT_ENTRY(ECHRNG, "Channel number out of range"),
ERROR_TEXT_ENTRY(EL2NSYNC, "Level 2 not synchronized"),
ERROR_TEXT_ENTRY(EL3HLT, "Level 3 halted"),
ERROR_TEXT_ENTRY(EL3RST, "Level 3 reset"),
ERROR_TEXT_ENTRY(ELNRNG, "Link number out of range"),
ERROR_TEXT_ENTRY(EUNATCH, "Protocol driver not attached"),
ERROR_TEXT_ENTRY(ENOCSI, "No CSI structure available"),
ERROR_TEXT_ENTRY(EL2HLT, "Level 2 halted"),
ERROR_TEXT_ENTRY(EBADE, "Invalid exchange"),
ERROR_TEXT_ENTRY(EBADR, "Invalid request descriptor"),
ERROR_TEXT_ENTRY(EXFULL, "Exchange full"),
ERROR_TEXT_ENTRY(ENOANO, "No anode"),
ERROR_TEXT_ENTRY(EBADRQC, "Invalid request code"),
ERROR_TEXT_ENTRY(EBADSLT, "Invalid slot"),
ERROR_TEXT_ENTRY(EDEADLOCK, "File locking deadlock error"),
ERROR_TEXT_ENTRY(EBFONT, "Bad font file format"),
ERROR_TEXT_ENTRY(ENOSTR, "Device not a stream"),
ERROR_TEXT_ENTRY(ENODATA, "No data available"),
ERROR_TEXT_ENTRY(ETIME, "Timer expired"),
ERROR_TEXT_ENTRY(ENOSR, "Out of streams resources"),
ERROR_TEXT_ENTRY(ENONET, "Machine is not on the network"),
ERROR_TEXT_ENTRY(ENOPKG, "Package not installed"),
ERROR_TEXT_ENTRY(EREMOTE, "Object is remote"),
ERROR_TEXT_ENTRY(ENOLINK, "Link has been severed"),
ERROR_TEXT_ENTRY(EADV, "Advertise error"),
ERROR_TEXT_ENTRY(ESRMNT, "Srmount error"),
ERROR_TEXT_ENTRY(ECOMM, "Communication error on send"),
ERROR_TEXT_ENTRY(EPROTO, "Protocol error"),
ERROR_TEXT_ENTRY(EMULTIHOP, "Multihop attempted"),
ERROR_TEXT_ENTRY(EDOTDOT, "RFS specific error"),
ERROR_TEXT_ENTRY(EBADMSG, "Bad message"),
ERROR_TEXT_ENTRY(EOVERFLOW, "Value too large for defined data type"),
ERROR_TEXT_ENTRY(ENOTUNIQ, "Name not unique on network"),
ERROR_TEXT_ENTRY(EBADFD, "File descriptor in bad state"),
ERROR_TEXT_ENTRY(EREMCHG, "Remote address changed"),
ERROR_TEXT_ENTRY(ELIBACC, "Can not access a needed shared library"),
ERROR_TEXT_ENTRY(ELIBBAD, "Accessing a corrupted shared library"),
ERROR_TEXT_ENTRY(ELIBSCN, ".lib section in a.out corrupted"),
ERROR_TEXT_ENTRY(ELIBMAX, "Attempting to link in too many shared libraries"),
ERROR_TEXT_ENTRY(ELIBEXEC, "Cannot exec a shared library directly"),
ERROR_TEXT_ENTRY(EILSEQ, "Invalid or incomplete multibyte or wide character"),
ERROR_TEXT_ENTRY(ERESTART, "Interrupted system call should be restarted"),
ERROR_TEXT_ENTRY(ESTRPIPE, "Streams pipe error"),
ERROR_TEXT_ENTRY(EUSERS, "Too many users"),
ERROR_TEXT_ENTRY(ENOTSOCK, "Socket operation on non-socket"),
ERROR_TEXT_ENTRY(EDESTADDRREQ, "Destination address required"),
ERROR_TEXT_ENTRY(EMSGSIZE, "Message too long"),
ERROR_TEXT_ENTRY(EPROTOTYPE, "Protocol wrong type for socket"),
ERROR_TEXT_ENTRY(ENOPROTOOPT, "Protocol not available"),
ERROR_TEXT_ENTRY(EPROTONOSUPPORT, "Protocol not supported"),
ERROR_TEXT_ENTRY(ESOCKTNOSUPPORT, "Socket type not supported"),
ERROR_TEXT_ENTRY(EOPNOTSUPP, "Operation not supported"),
ERROR_TEXT_ENTRY(EPFNOSUPPORT, "Protocol family not supported"),
ERROR_TEXT_ENTRY(EAFNOSUPPORT, "Address family not supported by protocol"),
ERROR_TEXT_ENTRY(EADDRINUSE, "Address already in use"),
ERROR_TEXT_ENTRY(EADDRNOTAVAIL, "Cannot assign requested address"),
ERROR_TEXT_ENTRY(ENETDOWN, "Network is down"),
ERROR_TEXT_ENTRY(ENETUNREACH, "Network is unreachable"),
ERROR_TEXT_ENTRY(ENETRESET, "Network dropped connection on reset"),
ERROR_TEXT_ENTRY(ECONNABORTED, "Software caused connection abort"),
ERROR_TEXT_ENTRY(ECONNRESET, "Connection reset by peer"),
ERROR_TEXT_ENTRY(ENOBUFS, "No buffer space available"),
ERROR_TEXT_ENTRY(EISCONN, "Transport endpoint is already connected"),
ERROR_TEXT_ENTRY(ENOTCONN, "Transport endpoint is not connected"),
ERROR_TEXT_ENTRY(ESHUTDOWN, "Cannot send after transport endpoint shutdown"),
ERROR_TEXT_ENTRY(ETOOMANYREFS, "Too many references: cannot splice"),
ERROR_TEXT_ENTRY(ETIMEDOUT, "Connection timed out"),
ERROR_TEXT_ENTRY(ECONNREFUSED, "Connection refused"),
ERROR_TEXT_ENTRY(EHOSTDOWN, "Host is down"),
ERROR_TEXT_ENTRY(EHOSTUNREACH, "No route to host"),
ERROR_TEXT_ENTRY(EALREADY, "Operation already in progress"),
ERROR_TEXT_ENTRY(EINPROGRESS, "Operation now in progress"),
ERROR_TEXT_ENTRY(ESTALE, "Stale file handle"),
ERROR_TEXT_ENTRY(EUCLEAN, "Structure needs cleaning"),
ERROR_TEXT_ENTRY(ENOTNAM, "Not a XENIX named type file"),
ERROR_TEXT_ENTRY(ENAVAIL, "No XENIX semaphores available"),
ERROR_TEXT_ENTRY(EISNAM, "Is a named type file"),
ERROR_TEXT_ENTRY(EREMOTEIO, "Remote I/O error"),
ERROR_TEXT_ENTRY(EDQUOT, "Disk quota exceeded"),
ERROR_TEXT_ENTRY(ENOMEDIUM, "No medium found"),
ERROR_TEXT_ENTRY(EMEDIUMTYPE, "Wrong medium type"),
ERROR_TEXT_ENTRY(ECANCELED, "Operation canceled"),
ERROR_TEXT_ENTRY(ENOKEY, "Required key not available"),
ERROR_TEXT_ENTRY(EKEYEXPIRED, "Key has expired"),
ERROR_TEXT_ENTRY(EKEYREVOKED, "Key has been revoked"),
ERROR_TEXT_ENTRY(EKEYREJECTED, "Key was rejected by service"),
ERROR_TEXT_ENTRY(EOWNERDEAD, "Owner died"),
ERROR_TEXT_ENTRY(ENOTRECOVERABLE, "State not recoverable"),
ERROR_TEXT_ENTRY(ERFKILL, "Operation not possible due to RF-kill"),
ERROR_TEXT_ENTRY(EHWPOISON, "Memory page has hardware error"),
ERROR_TEXT_ENTRY(ERESTARTSYS, "Restart system"),
ERROR_TEXT_ENTRY(ERESTARTNOINTR, "Restart monitor"),
ERROR_TEXT_ENTRY(ERESTARTNOHAND, "Restart if no handler"),
ERROR_TEXT_ENTRY(ENOIOCTLCMD, "No ioctl command"),
ERROR_TEXT_ENTRY(ERESTART_RESTARTBLOCK, "Restart by calling sys_restart_syscall"),
ERROR_TEXT_ENTRY(EPROBE_DEFER, "Driver requests probe retry"),
ERROR_TEXT_ENTRY(EOPENSTALE, "Open found a stale dentry"),
ERROR_TEXT_ENTRY(EBADHANDLE, "Illegal NFS file handle"),
ERROR_TEXT_ENTRY(ENOTSYNC, "Update synchronization mismatch"),
ERROR_TEXT_ENTRY(EBADCOOKIE, "Cookie is stale"),
ERROR_TEXT_ENTRY(ENOTSUPP, "Operation is not supported"),
ERROR_TEXT_ENTRY(ETOOSMALL, "Buffer or request is too small"),
ERROR_TEXT_ENTRY(ESERVERFAULT, "An untranslatable error occurred"),
ERROR_TEXT_ENTRY(EBADTYPE, "Type not supported by server"),
ERROR_TEXT_ENTRY(EJUKEBOX, "Request initiated, but will not complete before timeout"),
ERROR_TEXT_ENTRY(EIOCBQUEUED, "IOCB queued, will get completion event"),
};
#define ERROR_TEXT_ARRAY_SIZE (sizeof(_error_text) / sizeof(_error_text[0]))
char *cts_strerror(int errno)
{
if (errno > 0) {
return "<valid offset/length>";
} else if (-errno < (int) ERROR_TEXT_ARRAY_SIZE) {
char *s = _error_text[-errno];
if (s) {
return s;
}
}
return "<Unknown error>";
}

View File

@@ -0,0 +1,11 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#ifndef CTS_STRERROR_H
#define CTS_STRERROR_H
#define CTS_ERR_FMT_STR "%d(%s)"
#define CTS_ERR_ARG(errno) cts_strerror(errno)
char *cts_strerror(int errno);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,27 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#ifndef CTS_SYSFS_H
#define CTS_SYSFS_H
#include "cts_config.h"
struct device;
#ifdef CONFIG_CTS_SYSFS
extern int cts_argc;
extern char *cts_argv[];
extern int cts_sysfs_add_device(struct device *dev);
extern void cts_sysfs_remove_device(struct device *dev);
extern int cts_parse_arg(const char *buf, size_t count);
#else /* CONFIG_CTS_SYSFS */
static inline int cts_sysfs_add_device(struct device *dev)
{
return -ENOTSUPP;
}
static inline void cts_sysfs_remove_device(struct device *dev)
{
}
#endif /* CONFIG_CTS_SYSFS */
#endif /* CTS_SYSFS_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,127 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#ifndef _CTS_TCS_H_
#define _CTS_TCS_H_
int cts_tcs_read(struct cts_device *cts_dev,
u16 cmd, u8 *buf, size_t len);
int cts_tcs_write(struct cts_device *cts_dev,
u16 cmd, u8 *buf, size_t len);
int cts_tcs_get_hwid_info(struct cts_device *cts_dev, u8 *info);
int cts_tcs_get_fw_ver(struct cts_device *cts_dev, u16 *fwver);
int cts_tcs_get_lib_ver(struct cts_device *cts_dev, u16 *libver);
int cts_tcs_get_ddi_ver(struct cts_device *cts_dev, u8 *ddiver);
int cts_tcs_get_res_x(struct cts_device *cts_dev, u16 *res_x);
int cts_tcs_get_res_y(struct cts_device *cts_dev, u16 *res_y);
int cts_tcs_get_rows(struct cts_device *cts_dev, u8 *rows);
int cts_tcs_get_cols(struct cts_device *cts_dev, u8 *cols);
int cts_tcs_get_rx_tx_info(struct cts_device *cts_dev, u8 *info);
int cts_tcs_get_panel_rx_tx_info(struct cts_device *cts_dev, u8 *info);
int cts_tcs_get_flip_x(struct cts_device *cts_dev, bool *flip_x);
int cts_tcs_get_flip_y(struct cts_device *cts_dev, bool *flip_y);
int cts_tcs_get_swap_axes(struct cts_device *cts_dev, bool *swap_axes);
int cts_tcs_clr_gstr_ready_flag(struct cts_device *cts_dev);
int cts_tcs_get_int_mode(struct cts_device *cts_dev, u8 *int_mode);
int cts_tcs_get_int_keep_time(struct cts_device *cts_dev,
u16 *int_keep_time);
int cts_tcs_get_rawdata_target(struct cts_device *cts_dev,
u16 *rawdata_target);
int cts_tcs_get_esd_method(struct cts_device *cts_dev, u8 *esd_method);
int cts_tcs_get_touchinfo(struct cts_device *cts_dev,
struct cts_device_touch_info *touch_info);
int cts_tcs_get_gestureinfo(struct cts_device *cts_dev,
struct cts_device_gesture_info *gesture_info);
int cts_tcs_get_touch_status(struct cts_device *cts_dev);
int cts_tcs_get_esd_protection(struct cts_device *cts_dev,
u8 *esd_protection);
int cts_tcs_read_hw_reg(struct cts_device *cts_dev, u32 addr,
u8 *buf, size_t size);
int cts_tcs_write_hw_reg(struct cts_device *cts_dev, u32 addr,
u8 *buf, size_t size);
int cts_tcs_read_ddi_reg(struct cts_device *cts_dev, u32 addr,
u8 *regbuf, size_t size);
int cts_tcs_write_ddi_reg(struct cts_device *cts_dev, u32 addr,
u8 *regbuf, size_t size);
int cts_tcs_read_reg(struct cts_device *cts_dev, u32 addr,
u8 *buf, size_t size);
int cts_tcs_write_reg(struct cts_device *cts_dev, u32 addr,
u8 *buf, size_t size);
int cts_tcs_get_fw_id(struct cts_device *cts_dev, u16 *fwid);
int cts_tcs_get_workmode(struct cts_device *cts_dev, u8 *workmode);
int cts_tcs_set_workmode(struct cts_device *cts_dev, u8 workmode);
int cts_tcs_set_openshort_mode(struct cts_device *cts_dev, u8 mode);
int cts_tcs_get_curr_mode(struct cts_device *cts_dev, u8 *currmode);
int cts_tcs_get_krang_current_workmode(struct cts_device *cts_dev, u8 *workmode);
int cts_tcs_set_krang_workmode(struct cts_device *cts_dev, u8 workmode);
int cts_tcs_set_tx_vol(struct cts_device *cts_dev, u8 txvol);
int cts_tcs_set_short_test_type(struct cts_device *cts_dev, u8 short_type);
int cts_tcs_set_openshort_enable(struct cts_device *cts_dev, u8 enable);
int cts_tcs_is_openshort_enabled(struct cts_device *cts_dev, u8 *enabled);
int cts_tcs_set_esd_enable(struct cts_device *cts_dev, u8 enable);
int cts_tcs_set_cneg_enable(struct cts_device *cts_dev, u8 enable);
int cts_tcs_set_mnt_enable(struct cts_device *cts_dev, u8 enable);
int cts_tcs_is_display_on(struct cts_device *cts_dev, u8 *display_on);
int cts_tcs_set_display_on(struct cts_device *cts_dev, u8 display_on);
int cts_tcs_is_cneg_enabled(struct cts_device *cts_dev, u8 *enabled);
int cts_tcs_is_mnt_enabled(struct cts_device *cts_dev, u8 *enabled);
int cts_tcs_set_pwr_mode(struct cts_device *cts_dev, u8 pwr_mode);
int cts_tcs_get_has_int_data(struct cts_device *cts_dev, bool *has);
int cts_tcs_get_int_data_types(struct cts_device *cts_dev, u16 *type);
int cts_tcs_set_int_data_types(struct cts_device *cts_dev, u16 type);
int cts_tcs_get_int_data_method(struct cts_device *cts_dev, u8 *method);
int cts_tcs_set_int_data_method(struct cts_device *cts_dev, u8 method);
int cts_tcs_calc_int_data_size(struct cts_device *cts_dev);
int cts_tcs_polling_data(struct cts_device *cts_dev,u8 *buf, size_t size);
int cts_polling_test_data(struct cts_device *cts_dev,
u8 *buf, size_t size, enum int_data_type type);
int cts_tcs_tool_get_rawdata(struct cts_device *cts_dev, u8 *buf, u16 data_source);
int cts_tcs_tool_get_manual_diff(struct cts_device *cts_dev, u8 *buf, u16 data_source);
int cts_tcs_tool_get_real_diff(struct cts_device *cts_dev, u8 *buf, u16 data_source);
int cts_tcs_tool_get_basedata(struct cts_device *cts_dev, u8 *buf, u16 data_source);
int cts_tcs_top_get_rawdata(struct cts_device *cts_dev, u8 *buf, size_t size,
u16 data_source);
int cts_tcs_top_get_manual_diff(struct cts_device *cts_dev, u8 *buf,
size_t size, u16 data_source);
int cts_tcs_top_get_real_diff(struct cts_device *cts_dev, u8 *buf, size_t size,
u16 data_source);
int cts_tcs_top_get_noise_diff(struct cts_device *cts_dev, u8 *buf,size_t size,
u16 data_source);
int cts_tcs_top_get_basedata(struct cts_device *cts_dev, u8 *buf, size_t size,
u16 data_source);
int cts_tcs_top_get_cnegdata(struct cts_device *cts_dev, u8 *buf, size_t size,
u16 data_source);
int cts_tcs_reset_device(struct cts_device *cts_dev);
int cts_tcs_set_int_test(struct cts_device *cts_dev, u8 enable);
int cts_tcs_set_int_pin(struct cts_device *cts_dev, u8 high);
int cts_tcs_get_module_id(struct cts_device *cts_dev, u32 *modId);
int cts_tcs_tool_xtrans(struct cts_device *cts_dev, u8 *tx, size_t txlen,
u8 *rx, size_t rxlen);
int cts_tcs_set_charger_plug(struct cts_device *cts_dev, u8 set);
int cts_tcs_get_charger_plug(struct cts_device *cts_dev, u8 *isset);
int cts_tcs_set_earjack_plug(struct cts_device *cts_dev, u8 set);
int cts_tcs_get_earjack_plug(struct cts_device *cts_dev, u8 *isset);
int cts_tcs_set_panel_direction(struct cts_device *cts_dev, u8 direction);
int cts_tcs_get_panel_direction(struct cts_device *cts_dev, u8 *direction);
int cts_tcs_set_game_mode(struct cts_device *cts_dev, u8 enable);
int cts_tcs_get_game_mode(struct cts_device *cts_dev, u8 *enabled);
int cts_tcs_set_proximity_mode(struct cts_device *cts_dev, u8 enable);
void cts_tcs_reinit_fw_status(struct cts_device *cts_dev);
int cts_tcs_set_product_en(struct cts_device *cts_dev, u8 enable);
int cts_tcs_wait_krang_stop(struct cts_device *cts_dev);
extern int cts_tcs_set_glove_mode(struct cts_device *cts_dev, u8 enable);
#endif /* _CTS_TCS_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,113 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#ifndef CTS_TEST_H
#define CTS_TEST_H
struct cts_device;
#define CTS_TEST_FLAG_RESET_BEFORE_TEST (1u << 0)
#define CTS_TEST_FLAG_RESET_AFTER_TEST (1u << 1)
#define CTS_TEST_FLAG_DISPLAY_ON (1u << 2)
#define CTS_TEST_FLAG_DISABLE_GAS (1u << 3)
#define CTS_TEST_FLAG_DISABLE_LINESHIFT (1u << 4)
#define CTS_TEST_FLAG_VALIDATE_DATA (1u << 8)
#define CTS_TEST_FLAG_VALIDATE_PER_NODE (1u << 9)
#define CTS_TEST_FLAG_VALIDATE_MIN (1u << 10)
#define CTS_TEST_FLAG_VALIDATE_MAX (1u << 11)
#define CTS_TEST_FLAG_VALIDATE_SKIP_INVALID_NODE (1u << 12)
#define CTS_TEST_FLAG_STOP_TEST_IF_VALIDATE_FAILED (1u << 13)
#define CTS_TEST_FLAG_DUMP_TEST_DATA_TO_CONSOLE (1u << 16)
#define CTS_TEST_FLAG_DUMP_TEST_DATA_TO_USERSPACE (1u << 17)
#define CTS_TEST_FLAG_DUMP_TEST_DATA_TO_FILE (1u << 18)
#define CTS_TEST_FLAG_DUMP_TEST_DATA_TO_FILE_APPEND (1u << 19)
#define CTS_TEST_FLAG_DUMP_TEST_DATA_TO_FILE_CSV (1u << 20)
#define CTS_TEST_FLAG_DRIVER_LOG_TO_USERSPACE (1u << 24)
#define CTS_TEST_FLAG_DRIVER_LOG_TO_FILE (1u << 25)
#define CTS_TEST_FLAG_DRIVER_LOG_TO_FILE_APPEND (1u << 26)
#define MAKE_INVALID_NODE(r, c) (((c) << 16) | (r))
#define INVALID_NODE_ROW(node) ((u16)(node))
#define INVALID_NODE_COL(node) ((u16)((node) >> 16))
enum cts_test_item {
CTS_TEST_RESET_PIN = 1,
CTS_TEST_INT_PIN,
CTS_TEST_RAWDATA,
CTS_TEST_NOISE,
CTS_TEST_OPEN,
CTS_TEST_SHORT,
CTS_TEST_COMPENSATE_CAP,
CTS_TEST_STYLUS_RAWDATA,
CTS_TEST_STYLUS_NOISE,
};
struct cts_test_param {
int test_item;
__u32 flags;
__u32 num_invalid_node;
__u32 *invalid_nodes;
int *min;
int *max;
int *test_result;
s64 *elapsed_time_ms;
void *test_data_buf;
int test_data_buf_size;
int *test_data_wr_size;
const char *test_data_filepath;
int driver_log_level;
char *driver_log_buf;
int driver_log_buf_size;
int *driver_log_wr_size;
const char *driver_log_filepath;
void *priv_param;
int priv_param_size;
};
struct cts_rawdata_test_priv_param {
__u32 frames;
//__u8 work_mode;
};
struct cts_noise_test_priv_param {
__u32 frames;
//__u8 work_mode;
};
extern const char *cts_test_item_str(int test_item);
extern int cts_write_file(struct file *filp, const void *data, size_t size);
extern int cts_mkdir_for_file(const char *filepath, umode_t mode);
extern int cts_start_dump_test_data_to_file(const char *filepath,
bool append_to_file);
extern void cts_stop_dump_test_data_to_file(void);
extern int cts_test_reset_pin(struct cts_device *cts_dev,
struct cts_test_param *param);
extern int cts_test_int_pin(struct cts_device *cts_dev,
struct cts_test_param *param);
extern int cts_test_rawdata(struct cts_device *cts_dev,
struct cts_test_param *param);
extern int cts_test_noise(struct cts_device *cts_dev,
struct cts_test_param *param);
extern int cts_test_open(struct cts_device *cts_dev,
struct cts_test_param *param);
extern int cts_test_short(struct cts_device *cts_dev,
struct cts_test_param *param);
extern int cts_test_compensate_cap(struct cts_device *cts_dev,
struct cts_test_param *param);
extern int cts_test_stylus_rawdata(struct cts_device *cts_dev,
struct cts_test_param *param);
extern int cts_test_stylus_noise(struct cts_device *cts_dev,
struct cts_test_param *param);
extern int cts_test_stylus_mnt_rawdata(struct cts_device *cts_dev,
struct cts_test_param *param);
#endif /* CTS_TEST_H */

File diff suppressed because it is too large Load Diff

View File

@@ -157,6 +157,8 @@ struct cyttsp5_mt_platform_data {
char const *inp_dev_name;
int vkeys_x;
int vkeys_y;
int max_x;
int max_y;
int swap_x;
int swap_y;
int xy_exchange;

View File

@@ -295,6 +295,18 @@ static void *create_and_get_mt_pdata(struct device_node *dev_node)
if (!rc)
pdata->vkeys_y = value;
rc = of_property_read_u32(dev_node, "cy,max_x", &value);
if (!rc)
pdata->max_x = value;
else
pdata->max_x = -1;
rc = of_property_read_u32(dev_node, "cy,max_y", &value);
if (!rc)
pdata->max_y = value;
else
pdata->max_y = -1;
rc = of_property_read_u32(dev_node, "cy,revert_x", &value);
if (!rc)
pdata->swap_x = value;

View File

@@ -36,8 +36,8 @@
#define MT_PARAM_FUZZ(md, sig_ost) PARAM_FUZZ(md->pdata->frmwrk, sig_ost)
#define MT_PARAM_FLAT(md, sig_ost) PARAM_FLAT(md->pdata->frmwrk, sig_ost)
static int screen_max_x = 1872;
static int screen_max_y = 1404;
static int screen_max_x = 0;
static int screen_max_y = 0;
static int revert_x_flag = 0;
static int revert_y_flag = 0;
static int exchange_x_y_flag = 0;
@@ -636,17 +636,24 @@ static int cyttsp5_setup_input_device(struct device *dev)
max = max_y;
else if (i == CY_ABS_P_OST)
max = max_p;
/*change x-y max value*/
if(signal == ABS_MT_POSITION_X) {
if (screen_max_x > 0)
input_set_abs_params(md->input, signal, min, screen_max_x,
MT_PARAM_FUZZ(md, i), MT_PARAM_FLAT(md, i));
screen_max_x = max;
dev_info(dev, "screen_max_x = %d\n", screen_max_x);
}
if(signal == ABS_MT_POSITION_Y) {
} else if (signal == ABS_MT_POSITION_Y) {
if (screen_max_y > 0)
input_set_abs_params(md->input, signal, min, screen_max_y,
MT_PARAM_FUZZ(md, i), MT_PARAM_FLAT(md, i));
screen_max_y = max;
dev_info(dev, "screen_max_y = %d\n", screen_max_y);
} else {
input_set_abs_params(md->input, signal, min, max,
MT_PARAM_FUZZ(md, i), MT_PARAM_FLAT(md, i));
}
input_set_abs_params(md->input, signal, min, max,
MT_PARAM_FUZZ(md, i), MT_PARAM_FLAT(md, i));
parade_debug(dev, DEBUG_LEVEL_1,
"%s: register signal=%02X min=%d max=%d\n",
__func__, signal, min, max);
@@ -747,6 +754,11 @@ int cyttsp5_mt_probe(struct device *dev)
md->input->close = cyttsp5_mt_close;
input_set_drvdata(md->input, md);
if (mt_pdata->max_x > 0)
screen_max_x = mt_pdata->max_x;
if (mt_pdata->max_y > 0)
screen_max_y = mt_pdata->max_y;
/* get sysinfo */
md->si = _cyttsp5_request_sysinfo(dev);

View File

@@ -2068,6 +2068,17 @@ config VIDEO_AW8601
capability. This is designed for linear control of
voice coil motors, controlled via I2C serial interface.
config VIDEO_CES6301
tristate "CES6301 lens voice coil support"
depends on I2C && VIDEO_DEV
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
help
This is a driver for the CES6301 camera lens voice coil.
CES6301 is a 10 bit DAC with 120mA output current sink
capability. This is designed for linear control of
voice coil motors, controlled via I2C serial interface.
config VIDEO_CN3927V
tristate "CN3927V lens voice coil support"
depends on I2C && VIDEO_DEV

View File

@@ -32,6 +32,7 @@ obj-$(CONFIG_VIDEO_BT866) += bt866.o
obj-$(CONFIG_VIDEO_CAM_SLEEP_WAKEUP) += cam-sleep-wakeup.o
obj-$(CONFIG_VIDEO_CCS) += ccs/
obj-$(CONFIG_VIDEO_CCS_PLL) += ccs-pll.o
obj-$(CONFIG_VIDEO_CES6301) += ces6301.o
obj-$(CONFIG_VIDEO_CN3927V) += cn3927v.o
obj-$(CONFIG_VIDEO_CS3308) += cs3308.o
obj-$(CONFIG_VIDEO_CS5345) += cs5345.o

1133
drivers/media/i2c/ces6301.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -5,6 +5,9 @@
* Copyright (C) 2023 Rockchip Electronics Co., Ltd.
*
* V0.0X01.0X01 init first version.
* V0.0X01.0X01 update sensor driver.
* 1. adjust power sequence to suit spec.
* 2. fix bayer pattern to suit setting.
*/
#include <linux/clk.h>
@@ -84,7 +87,7 @@
#define OF_CAMERA_PINCTRL_STATE_SLEEP "rockchip,camera_sleep"
#define GC05A2_NAME "gc05a2"
#define GC05A2_MEDIA_BUS_FMT MEDIA_BUS_FMT_SRGGB10_1X10
#define GC05A2_MEDIA_BUS_FMT MEDIA_BUS_FMT_SGRBG10_1X10
static const char * const gc05a2_supply_names[] = {
"avdd", /* Analog power */
@@ -1185,14 +1188,16 @@ static int __gc05a2_power_on(struct gc05a2 *gc05a2)
dev_err(dev, "Failed to enable xvclk\n");
return ret;
}
if (!IS_ERR(gc05a2->reset_gpio))
gpiod_set_value_cansleep(gc05a2->reset_gpio, 0);
ret = regulator_bulk_enable(GC05A2_NUM_SUPPLIES, gc05a2->supplies);
if (ret < 0) {
dev_err(dev, "Failed to enable regulators\n");
goto disable_clk;
}
usleep_range(2000, 2100);
if (!IS_ERR(gc05a2->reset_gpio))
gpiod_set_value_cansleep(gc05a2->reset_gpio, 0);
usleep_range(1000, 1100);
if (!IS_ERR(gc05a2->reset_gpio))

File diff suppressed because it is too large Load Diff

View File

@@ -9,6 +9,7 @@
#include <linux/compat.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/extcon-provider.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
@@ -121,6 +122,7 @@ struct rk628_csi {
struct rk628_hdcp hdcp;
bool i2s_enable_default;
HAUDINFO audio_info;
struct extcon_dev *extcon;
struct rk628_combtxphy *txphy;
struct rk628_dsi dsi;
const struct rk628_plat_data *plat_data;
@@ -228,6 +230,11 @@ static u8 rk628f_edid_init_data[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD3,
};
static const unsigned int rk628_csi_extcon_cable[] = {
EXTCON_JACK_VIDEO_IN,
EXTCON_NONE,
};
static const struct mipi_timing rk628d_csi_mipi = {
0x4a, 0xf, 0x5d, 0x3a, 0x3a, 0x5a, 0x1f
};
@@ -497,6 +504,7 @@ static void rk628_csi_delayed_work_enable_hotplug(struct work_struct *work)
v4l2_ctrl_s_ctrl(csi->detect_tx_5v_ctrl, plugin);
v4l2_dbg(1, debug, sd, "%s: 5v_det:%d\n", __func__, plugin);
if (plugin) {
extcon_set_state_sync(csi->extcon, EXTCON_JACK_VIDEO_IN, true);
rk628_csi_enable_interrupts(sd, false);
rk628_hdmirx_audio_setup(csi->audio_info);
rk628_hdmirx_set_hdcp(csi->rk628, &csi->hdcp, csi->enable_hdcp);
@@ -507,6 +515,7 @@ static void rk628_csi_delayed_work_enable_hotplug(struct work_struct *work)
rk628_hdmirx_cec_state_reconfiguration(csi->rk628, csi->cec);
rk628_csi_enable_interrupts(sd, true);
} else {
extcon_set_state_sync(csi->extcon, EXTCON_JACK_VIDEO_IN, false);
rk628_hdmirx_plugout(sd);
}
mutex_unlock(&csi->confctl_mutex);
@@ -3094,6 +3103,19 @@ static int rk628_csi_probe(struct i2c_client *client,
if (IS_ERR(csi->classdev))
goto err_hdl;
csi->extcon = devm_extcon_dev_allocate(dev, rk628_csi_extcon_cable);
if (IS_ERR(csi->extcon)) {
err = PTR_ERR(csi->extcon);
v4l2_err(sd, "allocate extcon failed\n");
goto err_hdl;
}
err = devm_extcon_dev_register(dev, csi->extcon);
if (err) {
v4l2_err(sd, "failed to register extcon: %d\n", err);
goto err_hdl;
}
INIT_DELAYED_WORK(&csi->delayed_work_enable_hotplug,
rk628_csi_delayed_work_enable_hotplug);
INIT_DELAYED_WORK(&csi->delayed_work_res_change,
@@ -3104,6 +3126,7 @@ static int rk628_csi_probe(struct i2c_client *client,
rk628,
csi->i2s_enable_default);
if (!csi->audio_info) {
err = -ENOMEM;
v4l2_err(sd, "request audio info fail\n");
goto err_work_queues;
}

View File

@@ -5,6 +5,9 @@
* Copyright (C) 2023 Rockchip Electronics Co., Ltd.
*
* V0.0X01.0X00 first version.
* V0.0X01.0X01 update sensor driver.
* 1. adjust power sequence to suit spec.
* 2. add read/write reg error debug log.
*
*/
@@ -28,7 +31,7 @@
#include <media/v4l2-subdev.h>
#include <linux/pinctrl/consumer.h>
#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x00)
#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x01)
#define S5K3L8XX_MAJOR_I2C_ADDR 0x10
#define S5K3L8XX_MINOR_I2C_ADDR 0x2D
@@ -671,8 +674,11 @@ static int s5k3l8xx_write_reg(struct i2c_client *client, u16 reg,
while (val_i < 4)
buf[buf_i++] = val_p[val_i++];
if (i2c_master_send(client, buf, len + 2) != len + 2)
if (i2c_master_send(client, buf, len + 2) != len + 2) {
dev_err(&client->dev,
"write reg(0x%x val:0x%x) failed !\n", reg, val);
return -EIO;
}
return 0;
}
@@ -718,8 +724,11 @@ static int s5k3l8xx_read_reg(struct i2c_client *client, u16 reg,
msgs[1].buf = &data_be_p[4 - len];
ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
if (ret != ARRAY_SIZE(msgs))
if (ret != ARRAY_SIZE(msgs)) {
dev_err(&client->dev,
"read reg:0x%x failed !\n", reg);
return -EIO;
}
*val = be32_to_cpu(data_be);
@@ -1126,8 +1135,6 @@ static int __s5k3l8xx_power_on(struct s5k3l8xx *s5k3l8xx)
dev_err(dev, "Failed to enable xvclk\n");
return ret;
}
if (!IS_ERR(s5k3l8xx->reset_gpio))
gpiod_set_value_cansleep(s5k3l8xx->reset_gpio, 0);
ret = regulator_bulk_enable(S5K3L8XX_NUM_SUPPLIES, s5k3l8xx->supplies);
if (ret < 0) {
@@ -1135,6 +1142,14 @@ static int __s5k3l8xx_power_on(struct s5k3l8xx *s5k3l8xx)
goto disable_clk;
}
/* need reset after all vdd power on */
usleep_range(2000, 2100);
if (!IS_ERR(s5k3l8xx->reset_gpio))
gpiod_set_value_cansleep(s5k3l8xx->reset_gpio, 0);
usleep_range(1000, 1100);
if (!IS_ERR(s5k3l8xx->reset_gpio))
gpiod_set_value_cansleep(s5k3l8xx->reset_gpio, 1);
@@ -1142,8 +1157,8 @@ static int __s5k3l8xx_power_on(struct s5k3l8xx *s5k3l8xx)
if (!IS_ERR(s5k3l8xx->pwdn_gpio))
gpiod_set_value_cansleep(s5k3l8xx->pwdn_gpio, 1);
/* 8192 cycles prior to first SCCB transaction */
delay_us = s5k3l8xx_cal_delay(8192);
/* 23000 cycles prior to first SCCB transaction */
delay_us = s5k3l8xx_cal_delay(23000);
usleep_range(delay_us, delay_us * 2);
return 0;

View File

@@ -187,7 +187,8 @@ static void serdes_bridge_enable(struct drm_bridge *bridge)
if (!ret) {
extcon_set_state_sync(serdes->extcon, EXTCON_JACK_VIDEO_OUT, true);
SERDES_DBG_MFD("%s: extcon is true\n", __func__);
SERDES_DBG_MFD("%s: %s-%s extcon is true\n", __func__, dev_name(serdes->dev),
serdes->chip_data->name);
}
SERDES_DBG_MFD("%s: %s-%s ret=%d\n", __func__, dev_name(serdes->dev),
@@ -204,6 +205,9 @@ serdes_bridge_detect(struct drm_bridge *bridge)
if (serdes->chip_data->bridge_ops->detect)
status = serdes->chip_data->bridge_ops->detect(serdes);
SERDES_DBG_MFD("%s:%s %s, %s\n", __func__, dev_name(serdes->dev),
serdes->chip_data->name,
(status == connector_status_connected) ? "connected" : "disconnect");
return status;
}
@@ -223,7 +227,7 @@ static int serdes_bridge_get_modes(struct drm_bridge *bridge,
if (serdes_bridge->panel)
ret = drm_panel_get_modes(serdes_bridge->panel, connector);
SERDES_DBG_MFD("%s:name=%s, node=%s\n", __func__,
SERDES_DBG_MFD("%s:%s %s, node=%s\n", __func__, dev_name(serdes->dev),
serdes->chip_data->name, serdes_bridge->dev->of_node->name);
return ret;

View File

@@ -108,18 +108,9 @@ static void serdes_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
for (i = 0; i < chip->ngpio; i++) {
int gpio = i + chip->base;
const char *label, *level;
const char *level;
/* We report the GPIO even if it's not requested since
* we're also reporting things like alternate
* functions which apply even when the GPIO is not in
* use as a GPIO.
*/
label = gpiochip_is_requested(chip, i);
if (!label)
label = "Unrequested";
seq_printf(s, " %s-gpio-%02d ", label, gpio);
seq_printf(s, "gpio-%02d ", gpio);
if (serdes->chip_data->gpio_ops->get_level)
ret = serdes->chip_data->gpio_ops->get_level(serdes, i);

View File

@@ -213,7 +213,7 @@ static int serdes_panel_split_probe(struct platform_device *pdev)
if (ret)
return dev_err_probe(dev, ret, "failed to parse serdes DT\n");
serdes_panel_split->backlight = devm_of_find_backlight(dev);
serdes_panel_split->backlight = of_find_backlight_by_node(dev->of_node);
if (IS_ERR(serdes_panel_split->backlight))
return dev_err_probe(dev, PTR_ERR(serdes_panel_split->backlight),
"failed to get serdes backlight\n");
@@ -236,6 +236,10 @@ static int serdes_panel_split_probe(struct platform_device *pdev)
static int serdes_panel_split_remove(struct platform_device *pdev)
{
struct serdes_panel_split *serdes_panel_split = platform_get_drvdata(pdev);
struct backlight_device *backlight = serdes_panel_split->backlight;
if (backlight)
put_device(&backlight->dev);
drm_panel_remove(&serdes_panel_split->panel);

View File

@@ -219,7 +219,7 @@ static int serdes_panel_probe(struct platform_device *pdev)
if (ret)
return dev_err_probe(dev, ret, "failed to parse serdes DT\n");
serdes_panel->backlight = devm_of_find_backlight(dev);
serdes_panel->backlight = of_find_backlight_by_node(dev->of_node);
if (IS_ERR(serdes_panel->backlight))
return dev_err_probe(dev, PTR_ERR(serdes_panel->backlight),
"failed to get serdes backlight\n");
@@ -242,6 +242,10 @@ static int serdes_panel_probe(struct platform_device *pdev)
static int serdes_panel_remove(struct platform_device *pdev)
{
struct serdes_panel *serdes_panel = platform_get_drvdata(pdev);
struct backlight_device *backlight = serdes_panel->backlight;
if (backlight)
put_device(&backlight->dev);
drm_panel_remove(&serdes_panel->panel);

View File

@@ -29,10 +29,10 @@
#define DRIVER_NAME "rknpu"
#define DRIVER_DESC "RKNPU driver"
#define DRIVER_DATE "20240129"
#define DRIVER_DATE "20240226"
#define DRIVER_MAJOR 0
#define DRIVER_MINOR 9
#define DRIVER_PATCHLEVEL 4
#define DRIVER_PATCHLEVEL 5
#define LOG_TAG "RKNPU"
@@ -58,11 +58,6 @@ struct rknpu_irqs_data {
irqreturn_t (*irq_hdl)(int irq, void *ctx);
};
struct rknpu_reset_data {
const char *srst_a_name;
const char *srst_h_name;
};
struct rknpu_amount_data {
uint16_t offset_clr_all;
uint16_t offset_dt_wr;
@@ -80,9 +75,7 @@ struct rknpu_config {
__u32 pc_task_status_offset;
__u32 pc_dma_ctrl;
const struct rknpu_irqs_data *irqs;
const struct rknpu_reset_data *resets;
int num_irqs;
int num_resets;
__u64 nbuf_phyaddr;
__u64 nbuf_size;
__u64 max_submit_number;
@@ -132,8 +125,8 @@ struct rknpu_device {
void __iomem *bw_priority_base;
struct rknpu_fence_context *fence_ctx;
bool iommu_en;
struct reset_control *srst_a[RKNPU_MAX_CORES];
struct reset_control *srst_h[RKNPU_MAX_CORES];
struct reset_control **srsts;
int num_srsts;
struct clk_bulk_data *clks;
int num_clks;
struct regulator *vdd;

View File

@@ -162,7 +162,6 @@ static int rk3588_npu_set_read_margin(struct device *dev,
struct rockchip_opp_info *opp_info,
u32 rm)
{
struct rknpu_device *rknpu_dev = dev_get_drvdata(dev);
u32 offset = 0, val = 0;
int i, ret = 0;
@@ -174,7 +173,7 @@ static int rk3588_npu_set_read_margin(struct device *dev,
LOG_DEV_DEBUG(dev, "set rm to %d\n", rm);
for (i = 0; i < rknpu_dev->config->num_irqs; i++) {
for (i = 0; i < 3; i++) {
ret = regmap_read(opp_info->grf, offset, &val);
if (ret < 0) {
LOG_DEV_ERROR(dev, "failed to get rm from 0x%x\n",

View File

@@ -81,15 +81,6 @@ static const struct rknpu_irqs_data rk3588_npu_irqs[] = {
{ "npu2_irq", rknpu_core2_irq_handler }
};
static const struct rknpu_reset_data rknpu_resets[] = { { "srst_a",
"srst_h" } };
static const struct rknpu_reset_data rk3588_npu_resets[] = {
{ "srst_a0", "srst_h0" },
{ "srst_a1", "srst_h1" },
{ "srst_a2", "srst_h2" }
};
static const struct rknpu_amount_data rknpu_old_top_amount = {
.offset_clr_all = 0x8010,
.offset_dt_wr = 0x8034,
@@ -121,9 +112,7 @@ static const struct rknpu_config rk356x_rknpu_config = {
.pc_task_status_offset = 0x3c,
.pc_dma_ctrl = 0,
.irqs = rknpu_irqs,
.resets = rknpu_resets,
.num_irqs = ARRAY_SIZE(rknpu_irqs),
.num_resets = ARRAY_SIZE(rknpu_resets),
.nbuf_phyaddr = 0,
.nbuf_size = 0,
.max_submit_number = (1 << 12) - 1,
@@ -142,9 +131,7 @@ static const struct rknpu_config rk3588_rknpu_config = {
.pc_task_status_offset = 0x3c,
.pc_dma_ctrl = 0,
.irqs = rk3588_npu_irqs,
.resets = rk3588_npu_resets,
.num_irqs = ARRAY_SIZE(rk3588_npu_irqs),
.num_resets = ARRAY_SIZE(rk3588_npu_resets),
.nbuf_phyaddr = 0,
.nbuf_size = 0,
.max_submit_number = (1 << 12) - 1,
@@ -163,9 +150,7 @@ static const struct rknpu_config rk3583_rknpu_config = {
.pc_task_status_offset = 0x3c,
.pc_dma_ctrl = 0,
.irqs = rk3588_npu_irqs,
.resets = rk3588_npu_resets,
.num_irqs = 2,
.num_resets = 2,
.nbuf_phyaddr = 0,
.nbuf_size = 0,
.max_submit_number = (1 << 12) - 1,
@@ -184,9 +169,7 @@ static const struct rknpu_config rv1106_rknpu_config = {
.pc_task_status_offset = 0x3c,
.pc_dma_ctrl = 0,
.irqs = rknpu_irqs,
.resets = rknpu_resets,
.num_irqs = ARRAY_SIZE(rknpu_irqs),
.num_resets = ARRAY_SIZE(rknpu_resets),
.nbuf_phyaddr = 0,
.nbuf_size = 0,
.max_submit_number = (1 << 16) - 1,
@@ -205,9 +188,7 @@ static const struct rknpu_config rk3562_rknpu_config = {
.pc_task_status_offset = 0x48,
.pc_dma_ctrl = 1,
.irqs = rknpu_irqs,
.resets = rknpu_resets,
.num_irqs = ARRAY_SIZE(rknpu_irqs),
.num_resets = ARRAY_SIZE(rknpu_resets),
.nbuf_phyaddr = 0xfe400000,
.nbuf_size = 256 * 1024,
.max_submit_number = (1 << 16) - 1,

View File

@@ -128,6 +128,7 @@ static inline struct rknpu_job *rknpu_job_alloc(struct rknpu_device *rknpu_dev,
struct rknpu_submit *args)
{
struct rknpu_job *job = NULL;
int i = 0;
#ifdef CONFIG_ROCKCHIP_RKNPU_DRM_GEM
struct rknpu_gem_object *task_obj = NULL;
#endif
@@ -143,6 +144,8 @@ static inline struct rknpu_job *rknpu_job_alloc(struct rknpu_device *rknpu_dev,
((args->core_mask & RKNPU_CORE2_MASK) >> 2);
atomic_set(&job->run_count, job->use_core_num);
atomic_set(&job->interrupt_count, job->use_core_num);
for (i = 0; i < rknpu_dev->config->num_irqs; i++)
atomic_set(&job->submit_count[i], 0);
#ifdef CONFIG_ROCKCHIP_RKNPU_DRM_GEM
task_obj = (struct rknpu_gem_object *)(uintptr_t)args->task_obj_addr;
if (task_obj)

View File

@@ -28,27 +28,34 @@ static inline struct reset_control *rknpu_reset_control_get(struct device *dev,
int rknpu_reset_get(struct rknpu_device *rknpu_dev)
{
#ifndef FPGA_PLATFORM
struct reset_control *srst_a = NULL;
struct reset_control *srst_h = NULL;
int i = 0;
int num_srsts = 0;
for (i = 0; i < rknpu_dev->config->num_resets; i++) {
srst_a = rknpu_reset_control_get(
rknpu_dev->dev,
rknpu_dev->config->resets[i].srst_a_name);
if (IS_ERR(srst_a))
return PTR_ERR(srst_a);
rknpu_dev->srst_a[i] = srst_a;
srst_h = rknpu_reset_control_get(
rknpu_dev->dev,
rknpu_dev->config->resets[i].srst_h_name);
if (IS_ERR(srst_h))
return PTR_ERR(srst_h);
rknpu_dev->srst_h[i] = srst_h;
num_srsts = of_count_phandle_with_args(rknpu_dev->dev->of_node,
"resets", "#reset-cells");
if (num_srsts <= 0) {
LOG_DEV_ERROR(rknpu_dev->dev,
"failed to get rknpu resets from dtb\n");
return num_srsts;
}
rknpu_dev->srsts = devm_kcalloc(rknpu_dev->dev, num_srsts,
sizeof(*rknpu_dev->srsts), GFP_KERNEL);
if (!rknpu_dev->srsts)
return -ENOMEM;
for (i = 0; i < num_srsts; ++i) {
rknpu_dev->srsts[i] = devm_reset_control_get_exclusive_by_index(
rknpu_dev->dev, i);
if (IS_ERR(rknpu_dev->srsts[i])) {
rknpu_dev->num_srsts = i;
return PTR_ERR(rknpu_dev->srsts[i]);
}
}
rknpu_dev->num_srsts = num_srsts;
return num_srsts;
#endif
return 0;
@@ -93,7 +100,7 @@ int rknpu_soft_reset(struct rknpu_device *rknpu_dev)
#ifndef FPGA_PLATFORM
struct iommu_domain *domain = NULL;
struct rknpu_subcore_data *subcore_data = NULL;
int ret = -EINVAL, i = 0;
int ret = 0, i = 0;
if (rknpu_dev->bypass_soft_reset) {
LOG_WARN("bypass soft reset\n");
@@ -112,17 +119,17 @@ int rknpu_soft_reset(struct rknpu_device *rknpu_dev)
wake_up(&subcore_data->job_done_wq);
}
LOG_INFO("soft reset\n");
LOG_INFO("soft reset, num: %d\n", rknpu_dev->num_srsts);
for (i = 0; i < rknpu_dev->config->num_resets; i++) {
ret = rknpu_reset_assert(rknpu_dev->srst_a[i]);
ret |= rknpu_reset_assert(rknpu_dev->srst_h[i]);
for (i = 0; i < rknpu_dev->num_srsts; ++i)
ret |= rknpu_reset_assert(rknpu_dev->srsts[i]);
udelay(10);
udelay(10);
ret |= rknpu_reset_deassert(rknpu_dev->srst_a[i]);
ret |= rknpu_reset_deassert(rknpu_dev->srst_h[i]);
}
for (i = 0; i < rknpu_dev->num_srsts; ++i)
ret |= rknpu_reset_deassert(rknpu_dev->srsts[i]);
udelay(10);
if (ret) {
LOG_DEV_ERROR(rknpu_dev->dev,

View File

@@ -250,10 +250,25 @@ config ROCKCHIP_MINI_KERNEL
config ROCKCHIP_THUNDER_BOOT
bool "Rockchip Thunder Boot support"
depends on NO_GKI
select ROCKCHIP_THUNDER_BOOT_DEFER_FREE_MEMBLOCK if SMP
help
Say y here to enable Rockchip thunder boot support.
This option make the kernel boot faster.
config ROCKCHIP_THUNDER_BOOT_DEFER_FREE_MEMBLOCK
bool "Defer free large memblock to Buddy allocator"
depends on SMP
depends on NO_GKI
help
The physical memory of a system is divided into several types, like
memory reserved for device, for kernel pagetable, etc. The remaining
area is for Buddy allocator. Normally, The memory for Buddy is consist
of different size blocks, so, under meeting the memory request of kernel
booting, we can defer free the large block size to Buddy which can be
done later in work queue in parallel to other kernel threads, and the
size of the large block can be defined in kernel command line
by "defer_free_block_size" boot parameter.
config ROCKCHIP_THUNDER_BOOT_MMC
bool "Rockchip Thunder Boot from MMC"
depends on ROCKCHIP_THUNDER_BOOT

View File

@@ -59,7 +59,6 @@ struct pvtm_config {
int temp_prop[2];
const char *tz_name;
struct thermal_zone_device *tz;
struct regmap *grf;
};
struct lkg_conversion_table {
@@ -338,9 +337,6 @@ static int rockchip_parse_pvtm_config(struct device_node *np,
if (of_property_read_u32(np, "rockchip,pvtm-offset",
&pvtm->offset))
return -EINVAL;
pvtm->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
if (IS_ERR(pvtm->grf))
return -EINVAL;
return 0;
}
if (of_property_read_u32_array(np, "rockchip,pvtm-ch", pvtm->ch, 2))
@@ -725,11 +721,11 @@ static unsigned long rockchip_pvtpll_get_rate(struct rockchip_opp_info *info)
int i;
#define MIN_STABLE_DELTA 3
regmap_read(info->grf, info->pvtpll_avg_offset, &rate0);
regmap_read(info->pvtpll_base, info->pvtpll_avg_offset, &rate0);
/* max delay 2ms */
for (i = 0; i < 20; i++) {
udelay(100);
regmap_read(info->grf, info->pvtpll_avg_offset, &rate1);
regmap_read(info->pvtpll_base, info->pvtpll_avg_offset, &rate1);
delta = abs(rate1 - rate0);
rate0 = rate1;
if (delta <= MIN_STABLE_DELTA)
@@ -854,7 +850,7 @@ static void rockchip_pvtpll_calibrate_opp(struct rockchip_opp_info *info)
unsigned long rate, pvtpll_rate, old_rate, cur_rate, delta0, delta1;
int i = 0, max_count, step, cur_step, ret;
if (!info || !info->grf)
if (!info || !info->pvtpll_base)
return;
dev_dbg(info->dev, "calibrating opp ...\n");
@@ -1051,6 +1047,7 @@ out:
}
static int rockchip_get_pvtm_pvtpll(struct device *dev, struct device_node *np,
struct rockchip_opp_info *info,
const char *reg_name)
{
struct regulator *reg;
@@ -1067,6 +1064,9 @@ static int rockchip_get_pvtm_pvtpll(struct device *dev, struct device_node *np,
return pvtm_value;
}
if (!info || !info->pvtpll_base)
return -ENOMEM;
pvtm = kzalloc(sizeof(*pvtm), GFP_KERNEL);
if (!pvtm)
return -ENOMEM;
@@ -1102,7 +1102,7 @@ static int rockchip_get_pvtm_pvtpll(struct device *dev, struct device_node *np,
}
usleep_range(pvtm->sample_time, pvtm->sample_time + 100);
ret = regmap_read(pvtm->grf, pvtm->offset, &pvtm_value);
ret = regmap_read(info->pvtpll_base, pvtm->offset, &pvtm_value);
if (ret < 0) {
dev_err(dev, "failed to get pvtm from 0x%x\n", pvtm->offset);
goto resetore_volt;
@@ -1179,8 +1179,9 @@ static int rockchip_get_pvtm(struct device *dev, struct device_node *np,
}
static void rockchip_of_get_pvtm_sel(struct device *dev, struct device_node *np,
const char *reg_name, int bin, int process,
int *volt_sel, int *scale_sel)
struct rockchip_opp_info *info,
const char *reg_name, int *volt_sel,
int *scale_sel)
{
struct property *prop = NULL;
char name[NAME_MAX];
@@ -1188,7 +1189,7 @@ static void rockchip_of_get_pvtm_sel(struct device *dev, struct device_node *np,
u32 hw = 0;
if (of_property_read_bool(np, "rockchip,pvtm-pvtpll"))
pvtm = rockchip_get_pvtm_pvtpll(dev, np, reg_name);
pvtm = rockchip_get_pvtm_pvtpll(dev, np, info, reg_name);
else
pvtm = rockchip_get_pvtm(dev, np, reg_name);
if (pvtm <= 0)
@@ -1196,19 +1197,19 @@ static void rockchip_of_get_pvtm_sel(struct device *dev, struct device_node *np,
if (!volt_sel)
goto next;
if (process >= 0) {
if (info->process >= 0) {
snprintf(name, sizeof(name),
"rockchip,p%d-pvtm-voltage-sel", process);
"rockchip,p%d-pvtm-voltage-sel", info->process);
prop = of_find_property(np, name, NULL);
} else if (bin > 0) {
} else if (info->bin > 0) {
of_property_read_u32(np, "rockchip,pvtm-hw", &hw);
if (hw && (hw & BIT(bin))) {
if (hw && (hw & BIT(info->bin))) {
sprintf(name, "rockchip,pvtm-voltage-sel-hw");
prop = of_find_property(np, name, NULL);
}
if (!prop) {
snprintf(name, sizeof(name),
"rockchip,pvtm-voltage-sel-B%d", bin);
"rockchip,pvtm-voltage-sel-B%d", info->bin);
prop = of_find_property(np, name, NULL);
}
}
@@ -1222,9 +1223,9 @@ next:
if (!scale_sel)
return;
prop = NULL;
if (process >= 0) {
if (info->process >= 0) {
snprintf(name, sizeof(name),
"rockchip,p%d-pvtm-scaling-sel", process);
"rockchip,p%d-pvtm-scaling-sel", info->process);
prop = of_find_property(np, name, NULL);
}
if (!prop)
@@ -1485,8 +1486,8 @@ static void rockchip_get_scale_volt_sel(struct device *dev, char *lkg_name,
rockchip_of_get_lkg_sel(dev, np, lkg_name, info->process,
&lkg_volt_sel, &lkg_scale);
rockchip_of_get_pvtm_sel(dev, np, reg_name, info->bin, info->process,
&pvtm_volt_sel, &pvtm_scale);
rockchip_of_get_pvtm_sel(dev, np, info, reg_name, &pvtm_volt_sel,
&pvtm_scale);
rockchip_of_get_bin_sel(dev, np, info->bin, &bin_scale);
rockchip_of_get_bin_volt_sel(dev, np, info->bin, &bin_volt_sel);
info->scale = max3(lkg_scale, pvtm_scale, bin_scale);
@@ -1498,6 +1499,25 @@ static void rockchip_get_scale_volt_sel(struct device *dev, char *lkg_name,
of_node_put(np);
}
static int rockchip_opp_set_regulator_helper(struct device *dev,
struct rockchip_opp_info *info)
{
struct opp_table *opp_table;
if (!info || !info->data || !info->data->config_regulators)
return 0;
opp_table = dev_pm_opp_get_opp_table(dev);
if (IS_ERR(opp_table))
return PTR_ERR(opp_table);
opp_table->config_regulators = info->data->config_regulators;
dev_pm_opp_put_opp_table(opp_table);
return 0;
}
static int rockchip_opp_set_config(struct device *dev, struct rockchip_opp_info *info,
const char *clk_name, const char *reg_name)
{
@@ -1560,6 +1580,16 @@ static int rockchip_opp_set_config(struct device *dev, struct rockchip_opp_info
return info->opp_token;
}
/*
* The dev_pm_opp_set_config() only support setting regulator helper
* for multiple regulators, but on some platforms, still need to set
* regulator helper for single regulator.
*/
if (rockchip_opp_set_regulator_helper(dev, info)) {
dev_err(dev, "failed to set opp regulator helper\n");
return -EINVAL;
}
return 0;
}
@@ -1671,8 +1701,16 @@ int rockchip_init_opp_info(struct device *dev, struct rockchip_opp_info *info,
if (IS_ERR(info->grf))
info->grf = NULL;
info->dsu_grf = syscon_regmap_lookup_by_phandle(np, "rockchip,dsu-grf");
if (IS_ERR(info->dsu_grf))
if (IS_ERR(info->dsu_grf)) {
info->dsu_grf = NULL;
info->cci_grf = syscon_regmap_lookup_by_phandle(np, "rockchip,cci-grf");
if (IS_ERR(info->cci_grf))
info->cci_grf = NULL;
}
info->pvtpll_base = syscon_regmap_lookup_by_phandle(np, "rockchip,pvtpll");
if (IS_ERR(info->pvtpll_base))
info->pvtpll_base = info->grf;
ret = rockchip_get_opp_clk(dev, np, info);
if (ret)
@@ -2278,7 +2316,7 @@ int rockchip_opp_config_clks(struct device *dev, struct opp_table *opp_table,
unsigned long *target = data;
int ret;
if (!info->is_runtime_active)
if (info->is_scmi_clk && !info->is_runtime_active)
return 0;
ret = clk_bulk_prepare_enable(info->nclocks, info->clocks);

View File

@@ -442,11 +442,11 @@ static ssize_t spidev_rkmst_misc_write(struct file *filp, const char __user *buf
if (!tempbuf)
return -ENOMEM;
prandom_bytes(tempbuf, len);
get_random_bytes(tempbuf, len);
spidev_rkmst_xfer(spidev, tempbuf, NULL, addr, len);
start_time = ktime_get();
for (i = 0; i < loops; i++) {
prandom_bytes(spidev->txbuf, len);
get_random_bytes(spidev->txbuf, len);
spidev_rkmst_xfer(spidev, spidev->txbuf, spidev->rxbuf, addr, len);
if (memcmp(spidev->rxbuf, tempbuf, len)) {
dev_err(&spi->dev, "dulplex autotest failed, loops=%d\n", i);
@@ -487,7 +487,7 @@ static ssize_t spidev_rkmst_misc_write(struct file *filp, const char __user *buf
start_time = ktime_get();
for (i = 0; i < loops; i++) {
prandom_bytes(spidev->txbuf, len);
get_random_bytes(spidev->txbuf, len);
spidev_rkmst_xfer(spidev, spidev->txbuf, NULL, addr, len);
spidev_rkmst_xfer(spidev, NULL, spidev->rxbuf, addr, len);
if (memcmp(spidev->rxbuf, spidev->txbuf, len)) {
@@ -601,13 +601,11 @@ static int spidev_rkmst_probe(struct spi_device *spi)
return 0;
}
static int spidev_rkmst_remove(struct spi_device *spi)
static void spidev_rkmst_remove(struct spi_device *spi)
{
struct spidev_rkmst_data *spidev = dev_get_drvdata(&spi->dev);
misc_deregister(&spidev->misc_dev);
return 0;
}
#ifdef CONFIG_OF

View File

@@ -108,6 +108,7 @@ static int spidev_slv_write_and_read(struct spidev_rkslv_data *spidev, const voi
.tx_buf = tx_buf,
.rx_buf = rx_buf,
.len = len,
.bits_per_word = bit_per_word,
};
struct spi_message m;
int ret;
@@ -375,7 +376,7 @@ static int spidev_rkslv_probe(struct spi_device *spi)
return 0;
}
static int spidev_rkslv_remove(struct spi_device *spi)
static void spidev_rkslv_remove(struct spi_device *spi)
{
struct spidev_rkslv_data *spidev = dev_get_drvdata(&spi->dev);
@@ -383,8 +384,6 @@ static int spidev_rkslv_remove(struct spi_device *spi)
spi_slave_abort(spi);
kthread_stop(spidev->tsk);
misc_deregister(&spidev->misc_dev);
return 0;
}
#ifdef CONFIG_OF

View File

@@ -24,7 +24,7 @@ extern unsigned long max_pfn;
*/
extern unsigned long long max_possible_pfn;
#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT
#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT_DEFER_FREE_MEMBLOCK
extern int defer_free_memblock(void *unused);
#endif

View File

@@ -76,6 +76,7 @@ struct pvtpll_opp_table {
* @volt_rm_tbl: Pointer to voltage to memory read margin conversion table.
* @grf: General Register Files regmap.
* @dsu_grf: DSU General Register Files regmap.
* @cci_grf: CCI General Register Files regmap.
* @clocks: Pvtpll clocks.
* @nclocks: Number of pvtpll clock.
* @intermediate_threshold_freq: The frequency threshold of intermediate rate.
@@ -103,13 +104,17 @@ struct rockchip_opp_info {
struct mutex dvfs_mutex;
const struct rockchip_opp_data *data;
struct pvtpll_opp_table *opp_table;
struct regmap *pvtpll_base;
unsigned int pvtpll_avg_offset;
unsigned int pvtpll_min_rate;
unsigned int pvtpll_volt_step;
struct volt_rm_table *volt_rm_tbl;
struct regmap *grf;
struct regmap *dsu_grf;
union {
struct regmap *dsu_grf;
struct regmap *cci_grf;
};
struct clk_bulk_data *clocks;
int nclocks;
unsigned long intermediate_threshold_freq;

View File

@@ -1817,7 +1817,7 @@ static noinline void __init kernel_init_freeable(void)
smp_init();
sched_init_smp();
#if defined(CONFIG_ROCKCHIP_THUNDER_BOOT) && defined(CONFIG_SMP)
#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT_DEFER_FREE_MEMBLOCK
kthread_run(defer_free_memblock, NULL, "defer_mem");
#endif

View File

@@ -101,9 +101,14 @@ struct pglist_data __refdata contig_page_data;
EXPORT_SYMBOL(contig_page_data);
#endif
#if defined(CONFIG_ROCKCHIP_THUNDER_BOOT) && defined(CONFIG_SMP)
static unsigned long defer_start __initdata;
static unsigned long defer_end __initdata;
#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT_DEFER_FREE_MEMBLOCK
static int db_count __initdata;
#define DB_COUNT_MAX 4
static struct deferred_block {
unsigned long defer_start;
unsigned long defer_end;
} db[DB_COUNT_MAX] __initdata;
#define DEFAULT_DEFER_FREE_BLOCK_SIZE SZ_256M
static unsigned long defer_free_block_size __initdata =
@@ -2065,24 +2070,26 @@ static void __init __free_pages_memory(unsigned long start, unsigned long end)
}
}
#if defined(CONFIG_ROCKCHIP_THUNDER_BOOT) && defined(CONFIG_SMP)
#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT_DEFER_FREE_MEMBLOCK
int __init defer_free_memblock(void *unused)
{
if (defer_start == 0)
return 0;
int i;
pr_debug("start = %ld, end = %ld\n", defer_start, defer_end);
for (i = 0; i < db_count; i++) {
pr_debug("%s: start = %ld, end = %ld\n",
__func__, db[i].defer_start, db[i].defer_end);
__free_pages_memory(defer_start, defer_end);
__free_pages_memory(db[i].defer_start, db[i].defer_end);
totalram_pages_add(defer_end - defer_start);
totalram_pages_add(db[i].defer_end - db[i].defer_start);
pr_info("%s: size %luM free %luM [%luM - %luM] total %luM\n", __func__,
defer_free_block_size >> 20,
(defer_end - defer_start) >> (20 - PAGE_SHIFT),
defer_end >> (20 - PAGE_SHIFT),
defer_start >> (20 - PAGE_SHIFT),
totalram_pages() >> (20 - PAGE_SHIFT));
pr_info("%s: size %luM free %luM [%luM - %luM] total %luM\n",
__func__, defer_free_block_size >> 20,
(db[i].defer_end - db[i].defer_start) >> (20 - PAGE_SHIFT),
db[i].defer_start >> (20 - PAGE_SHIFT),
db[i].defer_end >> (20 - PAGE_SHIFT),
totalram_pages() >> (20 - PAGE_SHIFT));
}
return 0;
}
#endif
@@ -2097,11 +2104,12 @@ static unsigned long __init __free_memory_core(phys_addr_t start,
if (start_pfn >= end_pfn)
return 0;
#if defined(CONFIG_ROCKCHIP_THUNDER_BOOT) && defined(CONFIG_SMP)
if ((end - start) > defer_free_block_size) {
defer_start = start_pfn;
defer_end = end_pfn;
#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT_DEFER_FREE_MEMBLOCK
pr_debug("%s, start = %pa, end = %pa\n", __func__, &start, &end);
if ((end - start) > defer_free_block_size && (db_count < ARRAY_SIZE(db))) {
db[db_count].defer_start = start_pfn;
db[db_count].defer_end = end_pfn;
db_count++;
return 0;
}
#endif

View File

@@ -322,6 +322,7 @@ static const struct snd_soc_dai_ops rockchip_mdais_dai_ops = {
static const struct snd_soc_component_driver rockchip_mdais_component = {
.name = DAIS_DRV_NAME,
.legacy_dai_naming = 1,
};
static const struct of_device_id rockchip_mdais_match[] = {

View File

@@ -691,10 +691,13 @@ static int rk_multicodecs_probe(struct platform_device *pdev)
mc_data->adc = devm_iio_channel_get(&pdev->dev, "adc-detect");
if (IS_ERR(mc_data->adc)) {
if (PTR_ERR(mc_data->adc) != -EPROBE_DEFER) {
mc_data->adc = NULL;
dev_warn(&pdev->dev, "Failed to get ADC channel");
if (PTR_ERR(mc_data->adc) == -EPROBE_DEFER) {
dev_warn(&pdev->dev, "deferred by saradc not ready\n");
return -EPROBE_DEFER;
}
mc_data->adc = NULL;
dev_warn(&pdev->dev, "Has no ADC channel\n");
} else {
if (mc_data->adc->channel->type != IIO_VOLTAGE)
return -EINVAL;

View File

@@ -163,6 +163,7 @@ static struct snd_soc_dai_driver rk_spdifrx_dai = {
static const struct snd_soc_component_driver rk_spdifrx_component = {
.name = "rockchip-spdifrx",
.legacy_dai_naming = 1,
};
static bool rk_spdifrx_wr_reg(struct device *dev, unsigned int reg)