2019-11-23 07:40:14 +09:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-only
|
|
|
|
/*
|
2021-02-02 11:30:03 +09:00
|
|
|
* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
|
2024-03-01 20:41:18 +09:00
|
|
|
* Copyright (c) 2021-2024, Qualcomm Innovation Center, Inc. All rights reserved.
|
2019-11-23 07:40:14 +09:00
|
|
|
*/
|
|
|
|
|
|
|
|
#define pr_fmt(fmt) "%s: " fmt, __func__
|
|
|
|
|
|
|
|
#include <linux/bitops.h>
|
|
|
|
#include <linux/device.h>
|
|
|
|
#include <linux/err.h>
|
|
|
|
#include <linux/init.h>
|
|
|
|
#include <linux/kernel.h>
|
|
|
|
#include <linux/module.h>
|
|
|
|
#include <linux/mutex.h>
|
|
|
|
#include <linux/nvmem-consumer.h>
|
|
|
|
#include <linux/of.h>
|
|
|
|
#include <linux/of_address.h>
|
|
|
|
#include <linux/platform_device.h>
|
|
|
|
#include <linux/pwm.h>
|
|
|
|
#include <linux/qpnp/qpnp-pbs.h>
|
2021-09-23 08:14:19 +09:00
|
|
|
#include <linux/qpnp/qti-pwm.h>
|
2019-11-23 07:40:14 +09:00
|
|
|
#include <linux/regmap.h>
|
|
|
|
#include <linux/seq_file.h>
|
|
|
|
#include <linux/slab.h>
|
|
|
|
#include <linux/types.h>
|
|
|
|
|
|
|
|
#define REG_SIZE_PER_LPG 0x100
|
|
|
|
#define LPG_BASE "lpg-base"
|
|
|
|
#define LUT_BASE "lut-base"
|
|
|
|
|
|
|
|
/* LPG module registers */
|
|
|
|
#define REG_LPG_PERPH_SUBTYPE 0x05
|
|
|
|
#define REG_LPG_PATTERN_CONFIG 0x40
|
|
|
|
#define REG_LPG_PWM_SIZE_CLK 0x41
|
|
|
|
#define REG_LPG_PWM_FREQ_PREDIV_CLK 0x42
|
|
|
|
#define REG_LPG_PWM_TYPE_CONFIG 0x43
|
|
|
|
#define REG_LPG_PWM_VALUE_LSB 0x44
|
|
|
|
#define REG_LPG_PWM_VALUE_MSB 0x45
|
|
|
|
#define REG_LPG_ENABLE_CONTROL 0x46
|
|
|
|
#define REG_LPG_PWM_SYNC 0x47
|
|
|
|
#define REG_LPG_RAMP_STEP_DURATION_LSB 0x50
|
|
|
|
#define REG_LPG_RAMP_STEP_DURATION_MSB 0x51
|
|
|
|
#define REG_LPG_PAUSE_HI_MULTIPLIER 0x52
|
|
|
|
#define REG_LPG_PAUSE_LO_MULTIPLIER 0x54
|
|
|
|
#define REG_LPG_HI_INDEX 0x56
|
|
|
|
#define REG_LPG_LO_INDEX 0x57
|
|
|
|
|
2021-04-27 17:44:10 +09:00
|
|
|
/* PWM module registers */
|
|
|
|
#define REG_PWM_STATUS1 0x08
|
|
|
|
#define FM_MODE_PRESENT BIT(0)
|
|
|
|
|
|
|
|
#define REG_PWM_FM_MODE 0x50
|
|
|
|
#define FM_MODE_ENABLE BIT(7)
|
|
|
|
|
2019-11-23 07:40:14 +09:00
|
|
|
/* REG_LPG_PATTERN_CONFIG */
|
|
|
|
#define LPG_PATTERN_EN_PAUSE_LO BIT(0)
|
|
|
|
#define LPG_PATTERN_EN_PAUSE_HI BIT(1)
|
|
|
|
#define LPG_PATTERN_RAMP_TOGGLE BIT(2)
|
|
|
|
#define LPG_PATTERN_REPEAT BIT(3)
|
|
|
|
#define LPG_PATTERN_RAMP_LO_TO_HI BIT(4)
|
|
|
|
|
|
|
|
/* REG_LPG_PERPH_SUBTYPE */
|
|
|
|
#define SUBTYPE_PWM 0x0b
|
2022-06-09 05:51:35 +09:00
|
|
|
#define SUBTYPE_HI_RES_PWM 0x0c
|
2019-11-23 07:40:14 +09:00
|
|
|
#define SUBTYPE_LPG_LITE 0x11
|
|
|
|
|
|
|
|
/* REG_LPG_PWM_SIZE_CLK */
|
|
|
|
#define LPG_PWM_SIZE_LPG_MASK BIT(4)
|
|
|
|
#define LPG_PWM_SIZE_PWM_MASK BIT(2)
|
2022-06-09 05:51:35 +09:00
|
|
|
#define LPG_PWM_SIZE_PWM_HI_RES_MASK GENMASK(6, 4)
|
2019-11-23 07:40:14 +09:00
|
|
|
#define LPG_PWM_SIZE_LPG_SHIFT 4
|
|
|
|
#define LPG_PWM_SIZE_PWM_SHIFT 2
|
2022-06-09 05:51:35 +09:00
|
|
|
#define LPG_PWM_SIZE_PWM_HI_RES_SHIFT 4
|
2019-11-23 07:40:14 +09:00
|
|
|
#define LPG_PWM_CLK_FREQ_SEL_MASK GENMASK(1, 0)
|
2022-06-09 05:51:35 +09:00
|
|
|
#define LPG_PWM_HI_RES_CLK_FREQ_SEL_MASK GENMASK(2, 0)
|
2019-11-23 07:40:14 +09:00
|
|
|
|
|
|
|
/* REG_LPG_PWM_FREQ_PREDIV_CLK */
|
|
|
|
#define LPG_PWM_FREQ_PREDIV_MASK GENMASK(6, 5)
|
|
|
|
#define LPG_PWM_FREQ_PREDIV_SHIFT 5
|
|
|
|
#define LPG_PWM_FREQ_EXPONENT_MASK GENMASK(2, 0)
|
|
|
|
|
|
|
|
/* REG_LPG_PWM_TYPE_CONFIG */
|
|
|
|
#define LPG_PWM_EN_GLITCH_REMOVAL_MASK BIT(5)
|
|
|
|
|
|
|
|
/* REG_LPG_PWM_VALUE_LSB */
|
|
|
|
#define LPG_PWM_VALUE_LSB_MASK GENMASK(7, 0)
|
|
|
|
|
|
|
|
/* REG_LPG_PWM_VALUE_MSB */
|
|
|
|
#define LPG_PWM_VALUE_MSB_MASK BIT(0)
|
2022-06-09 05:51:35 +09:00
|
|
|
#define LPG_PWM_HI_RES_VALUE_MSB_MASK GENMASK(7, 0)
|
2019-11-23 07:40:14 +09:00
|
|
|
|
|
|
|
/* REG_LPG_ENABLE_CONTROL */
|
|
|
|
#define LPG_EN_LPG_OUT_BIT BIT(7)
|
|
|
|
#define LPG_EN_LPG_OUT_SHIFT 7
|
|
|
|
#define LPG_PWM_SRC_SELECT_MASK BIT(2)
|
|
|
|
#define LPG_PWM_SRC_SELECT_SHIFT 2
|
|
|
|
#define LPG_EN_RAMP_GEN_MASK BIT(1)
|
|
|
|
#define LPG_EN_RAMP_GEN_SHIFT 1
|
|
|
|
|
|
|
|
/* REG_LPG_PWM_SYNC */
|
|
|
|
#define LPG_PWM_VALUE_SYNC BIT(0)
|
|
|
|
|
|
|
|
#define NUM_PWM_SIZE 2
|
2022-06-09 05:51:35 +09:00
|
|
|
#define NUM_PWM_HI_RES_SIZE 8
|
2019-11-23 07:40:14 +09:00
|
|
|
#define NUM_PWM_CLK 3
|
2022-06-09 05:51:35 +09:00
|
|
|
#define NUM_PWM_HI_RES_CLK 4
|
2019-11-23 07:40:14 +09:00
|
|
|
#define NUM_CLK_PREDIV 4
|
|
|
|
#define NUM_PWM_EXP 8
|
|
|
|
|
|
|
|
#define LPG_HI_LO_IDX_MASK GENMASK(5, 0)
|
|
|
|
|
|
|
|
/* LUT module registers */
|
|
|
|
#define REG_LPG_LUT_1_LSB 0x42
|
|
|
|
#define REG_LPG_LUT_RAMP_CONTROL 0xc8
|
|
|
|
|
|
|
|
#define LPG_LUT_VALUE_MSB_MASK BIT(0)
|
|
|
|
#define LPG_LUT_COUNT_MAX 47
|
|
|
|
|
|
|
|
/* LPG config settings in SDAM */
|
|
|
|
#define SDAM_REG_PBS_SEQ_EN 0x42
|
|
|
|
#define PBS_SW_TRG_BIT BIT(0)
|
|
|
|
|
|
|
|
#define SDAM_REG_RAMP_STEP_DURATION 0x47
|
|
|
|
|
|
|
|
#define SDAM_LUT_EN_OFFSET 0x0
|
|
|
|
#define SDAM_PATTERN_CONFIG_OFFSET 0x1
|
|
|
|
#define SDAM_END_INDEX_OFFSET 0x3
|
|
|
|
#define SDAM_START_INDEX_OFFSET 0x4
|
|
|
|
#define SDAM_PBS_SCRATCH_LUT_COUNTER_OFFSET 0x6
|
2021-04-14 06:50:32 +09:00
|
|
|
#define SDAM_PAUSE_START_MULTIPLIER_OFFSET 0x8
|
|
|
|
#define SDAM_PAUSE_END_MULTIPLIER_OFFSET 0x9
|
2019-11-23 07:40:14 +09:00
|
|
|
|
|
|
|
/* SDAM_REG_LUT_EN */
|
|
|
|
#define SDAM_LUT_EN_BIT BIT(0)
|
|
|
|
|
|
|
|
/* SDAM_REG_PATTERN_CONFIG */
|
|
|
|
#define SDAM_PATTERN_LOOP_ENABLE BIT(3)
|
2021-04-14 06:50:32 +09:00
|
|
|
#define SDAM_PATTERN_EN_PAUSE_START BIT(1)
|
|
|
|
#define SDAM_PATTERN_EN_PAUSE_END BIT(0)
|
|
|
|
#define SDAM_PAUSE_COUNT_MAX (U8_MAX - 1)
|
2019-11-23 07:40:14 +09:00
|
|
|
|
|
|
|
#define SDAM_LUT_COUNT_MAX 64
|
|
|
|
|
|
|
|
enum lpg_src {
|
|
|
|
LUT_PATTERN = 0,
|
|
|
|
PWM_VALUE,
|
|
|
|
};
|
|
|
|
|
2020-05-27 11:22:03 +09:00
|
|
|
enum ppg_num_nvmems {
|
|
|
|
PPG_NO_NVMEMS,
|
|
|
|
PPG_NVMEMS_1, /* A single nvmem for both LUT and LPG channel config */
|
|
|
|
PPG_NVMEMS_2, /* Two separate nvmems for LUT and LPG channel config */
|
|
|
|
};
|
|
|
|
|
2019-11-23 07:40:14 +09:00
|
|
|
static const int pwm_size[NUM_PWM_SIZE] = {6, 9};
|
2022-06-09 05:51:35 +09:00
|
|
|
static const int pwm_hi_res_size[NUM_PWM_HI_RES_SIZE] = {8, 9, 10, 11, 12, 13, 14, 15};
|
2019-11-23 07:40:14 +09:00
|
|
|
static const int clk_freq_hz[NUM_PWM_CLK] = {1024, 32768, 19200000};
|
2022-06-09 05:51:35 +09:00
|
|
|
static const int clk_freq_hz_hi_res[NUM_PWM_HI_RES_CLK] = {1024, 32768, 19200000, 76800000};
|
2021-04-27 17:44:10 +09:00
|
|
|
/* clk_period_ns = NSEC_PER_SEC / clk_freq_hz */
|
|
|
|
static const int clk_period_ns[NUM_PWM_CLK] = {976562, 30517, 52};
|
2022-06-09 05:51:35 +09:00
|
|
|
static const int clk_period_ns_hi_res[NUM_PWM_HI_RES_CLK] = {976562, 30517, 52, 13};
|
2019-11-23 07:40:14 +09:00
|
|
|
static const int clk_prediv[NUM_CLK_PREDIV] = {1, 3, 5, 6};
|
|
|
|
static const int pwm_exponent[NUM_PWM_EXP] = {0, 1, 2, 3, 4, 5, 6, 7};
|
|
|
|
|
|
|
|
struct lpg_ramp_config {
|
|
|
|
u16 step_ms;
|
|
|
|
u8 pause_hi_count;
|
|
|
|
u8 pause_lo_count;
|
|
|
|
u8 hi_idx;
|
|
|
|
u8 lo_idx;
|
|
|
|
bool ramp_dir_low_to_hi;
|
|
|
|
bool pattern_repeat;
|
|
|
|
bool toggle;
|
|
|
|
u32 *pattern;
|
|
|
|
u32 pattern_length;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct lpg_pwm_config {
|
|
|
|
u32 pwm_size;
|
|
|
|
u32 pwm_clk;
|
|
|
|
u32 prediv;
|
|
|
|
u32 clk_exp;
|
|
|
|
u16 pwm_value;
|
|
|
|
u64 best_period_ns;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct qpnp_lpg_lut {
|
|
|
|
struct qpnp_lpg_chip *chip;
|
|
|
|
struct mutex lock;
|
2020-05-27 11:22:03 +09:00
|
|
|
enum ppg_num_nvmems nvmem_count;
|
2019-11-23 07:40:14 +09:00
|
|
|
u32 reg_base;
|
|
|
|
u32 *pattern; /* patterns in percentage */
|
2020-05-27 09:56:41 +09:00
|
|
|
u32 ramp_step_tick_us;
|
2019-11-23 07:40:14 +09:00
|
|
|
};
|
|
|
|
|
|
|
|
struct qpnp_lpg_channel {
|
|
|
|
struct qpnp_lpg_chip *chip;
|
|
|
|
struct lpg_pwm_config pwm_config;
|
|
|
|
struct lpg_ramp_config ramp_config;
|
2021-09-23 08:14:19 +09:00
|
|
|
enum pwm_output_type output_type;
|
2019-11-23 07:40:14 +09:00
|
|
|
u32 lpg_idx;
|
|
|
|
u32 reg_base;
|
|
|
|
u32 max_pattern_length;
|
|
|
|
u32 lpg_sdam_base;
|
|
|
|
u8 src_sel;
|
|
|
|
u8 subtype;
|
|
|
|
bool lut_written;
|
2021-04-27 17:44:10 +09:00
|
|
|
bool enable_pfm;
|
2019-11-23 07:40:14 +09:00
|
|
|
u64 current_period_ns;
|
|
|
|
u64 current_duty_ns;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct qpnp_lpg_chip {
|
|
|
|
struct pwm_chip pwm_chip;
|
|
|
|
struct regmap *regmap;
|
|
|
|
struct device *dev;
|
|
|
|
struct qpnp_lpg_channel *lpgs;
|
|
|
|
struct qpnp_lpg_lut *lut;
|
|
|
|
struct mutex bus_lock;
|
|
|
|
u32 *lpg_group;
|
2020-05-27 11:21:23 +09:00
|
|
|
struct nvmem_device *lpg_chan_nvmem;
|
|
|
|
struct nvmem_device *lut_nvmem;
|
2019-11-23 07:40:14 +09:00
|
|
|
struct device_node *pbs_dev_node;
|
|
|
|
u32 num_lpgs;
|
|
|
|
unsigned long pbs_en_bitmap;
|
|
|
|
bool use_sdam;
|
|
|
|
};
|
|
|
|
|
|
|
|
static int qpnp_lpg_read(struct qpnp_lpg_channel *lpg, u16 addr, u8 *val)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
unsigned int tmp;
|
|
|
|
|
|
|
|
mutex_lock(&lpg->chip->bus_lock);
|
|
|
|
rc = regmap_read(lpg->chip->regmap, lpg->reg_base + addr, &tmp);
|
|
|
|
if (rc < 0)
|
|
|
|
dev_err(lpg->chip->dev, "Read addr 0x%x failed, rc=%d\n",
|
|
|
|
lpg->reg_base + addr, rc);
|
|
|
|
else
|
|
|
|
*val = (u8)tmp;
|
|
|
|
mutex_unlock(&lpg->chip->bus_lock);
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int qpnp_lpg_write(struct qpnp_lpg_channel *lpg, u16 addr, u8 val)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
mutex_lock(&lpg->chip->bus_lock);
|
|
|
|
rc = regmap_write(lpg->chip->regmap, lpg->reg_base + addr, val);
|
|
|
|
if (rc < 0)
|
|
|
|
dev_err(lpg->chip->dev, "Write addr 0x%x with value 0x%x failed, rc=%d\n",
|
|
|
|
lpg->reg_base + addr, val, rc);
|
|
|
|
mutex_unlock(&lpg->chip->bus_lock);
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int qpnp_lpg_masked_write(struct qpnp_lpg_channel *lpg,
|
|
|
|
u16 addr, u8 mask, u8 val)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
mutex_lock(&lpg->chip->bus_lock);
|
|
|
|
rc = regmap_update_bits(lpg->chip->regmap, lpg->reg_base + addr,
|
|
|
|
mask, val);
|
|
|
|
if (rc < 0)
|
|
|
|
dev_err(lpg->chip->dev, "Update addr 0x%x to val 0x%x with mask 0x%x failed, rc=%d\n",
|
|
|
|
lpg->reg_base + addr, val, mask, rc);
|
|
|
|
mutex_unlock(&lpg->chip->bus_lock);
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int qpnp_lut_write(struct qpnp_lpg_lut *lut, u16 addr, u8 val)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
mutex_lock(&lut->chip->bus_lock);
|
|
|
|
rc = regmap_write(lut->chip->regmap, lut->reg_base + addr, val);
|
|
|
|
if (rc < 0)
|
|
|
|
dev_err(lut->chip->dev, "Write addr 0x%x with value %d failed, rc=%d\n",
|
|
|
|
lut->reg_base + addr, val, rc);
|
|
|
|
mutex_unlock(&lut->chip->bus_lock);
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int qpnp_lut_masked_write(struct qpnp_lpg_lut *lut,
|
|
|
|
u16 addr, u8 mask, u8 val)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
mutex_lock(&lut->chip->bus_lock);
|
|
|
|
rc = regmap_update_bits(lut->chip->regmap, lut->reg_base + addr,
|
|
|
|
mask, val);
|
|
|
|
if (rc < 0)
|
|
|
|
dev_err(lut->chip->dev, "Update addr 0x%x to val 0x%x with mask 0x%x failed, rc=%d\n",
|
|
|
|
lut->reg_base + addr, val, mask, rc);
|
|
|
|
mutex_unlock(&lut->chip->bus_lock);
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2020-05-27 11:21:23 +09:00
|
|
|
static int qpnp_lpg_chan_nvmem_write(struct qpnp_lpg_chip *chip, u16 addr,
|
|
|
|
u8 val)
|
2019-11-23 07:40:14 +09:00
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
mutex_lock(&chip->bus_lock);
|
2020-05-27 11:21:23 +09:00
|
|
|
rc = nvmem_device_write(chip->lpg_chan_nvmem, addr, 1, &val);
|
2019-11-23 07:40:14 +09:00
|
|
|
if (rc < 0)
|
|
|
|
dev_err(chip->dev, "write SDAM add 0x%x failed, rc=%d\n",
|
|
|
|
addr, rc);
|
|
|
|
|
|
|
|
mutex_unlock(&chip->bus_lock);
|
|
|
|
|
|
|
|
return rc > 0 ? 0 : rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int qpnp_lpg_sdam_write(struct qpnp_lpg_channel *lpg, u16 addr, u8 val)
|
|
|
|
{
|
|
|
|
struct qpnp_lpg_chip *chip = lpg->chip;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
mutex_lock(&chip->bus_lock);
|
2020-05-27 11:21:23 +09:00
|
|
|
rc = nvmem_device_write(chip->lpg_chan_nvmem,
|
2019-11-23 07:40:14 +09:00
|
|
|
lpg->lpg_sdam_base + addr, 1, &val);
|
|
|
|
if (rc < 0)
|
|
|
|
dev_err(chip->dev, "write SDAM add 0x%x failed, rc=%d\n",
|
|
|
|
lpg->lpg_sdam_base + addr, rc);
|
|
|
|
|
|
|
|
mutex_unlock(&chip->bus_lock);
|
|
|
|
|
|
|
|
return rc > 0 ? 0 : rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int qpnp_lpg_sdam_masked_write(struct qpnp_lpg_channel *lpg,
|
|
|
|
u16 addr, u8 mask, u8 val)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
u8 tmp;
|
|
|
|
struct qpnp_lpg_chip *chip = lpg->chip;
|
|
|
|
|
|
|
|
mutex_lock(&chip->bus_lock);
|
|
|
|
|
2020-05-27 11:21:23 +09:00
|
|
|
rc = nvmem_device_read(chip->lpg_chan_nvmem,
|
2019-11-23 07:40:14 +09:00
|
|
|
lpg->lpg_sdam_base + addr, 1, &tmp);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(chip->dev, "Read SDAM addr %d failed, rc=%d\n",
|
|
|
|
lpg->lpg_sdam_base + addr, rc);
|
|
|
|
goto unlock;
|
|
|
|
}
|
|
|
|
|
|
|
|
tmp = tmp & ~mask;
|
|
|
|
tmp |= val & mask;
|
2020-05-27 11:21:23 +09:00
|
|
|
rc = nvmem_device_write(chip->lpg_chan_nvmem,
|
2019-11-23 07:40:14 +09:00
|
|
|
lpg->lpg_sdam_base + addr, 1, &tmp);
|
|
|
|
if (rc < 0)
|
|
|
|
dev_err(chip->dev, "write SDAM addr %d failed, rc=%d\n",
|
|
|
|
lpg->lpg_sdam_base + addr, rc);
|
|
|
|
|
|
|
|
unlock:
|
|
|
|
mutex_unlock(&chip->bus_lock);
|
|
|
|
|
|
|
|
return rc > 0 ? 0 : rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int qpnp_lut_sdam_write(struct qpnp_lpg_lut *lut,
|
|
|
|
u16 addr, u8 *val, size_t length)
|
|
|
|
{
|
|
|
|
struct qpnp_lpg_chip *chip = lut->chip;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
if (addr >= SDAM_LUT_COUNT_MAX)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
mutex_lock(&chip->bus_lock);
|
2020-05-27 11:21:23 +09:00
|
|
|
rc = nvmem_device_write(chip->lut_nvmem,
|
2019-11-23 07:40:14 +09:00
|
|
|
lut->reg_base + addr, length, val);
|
|
|
|
if (rc < 0)
|
|
|
|
dev_err(chip->dev, "write SDAM addr %d failed, rc=%d\n",
|
|
|
|
lut->reg_base + addr, rc);
|
|
|
|
|
|
|
|
mutex_unlock(&chip->bus_lock);
|
|
|
|
|
|
|
|
return rc > 0 ? 0 : rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct qpnp_lpg_channel *pwm_dev_to_qpnp_lpg(struct pwm_chip *pwm_chip,
|
|
|
|
struct pwm_device *pwm)
|
|
|
|
{
|
|
|
|
|
|
|
|
struct qpnp_lpg_chip *chip = container_of(pwm_chip,
|
|
|
|
struct qpnp_lpg_chip, pwm_chip);
|
|
|
|
u32 hw_idx = pwm->hwpwm;
|
|
|
|
|
|
|
|
if (hw_idx >= chip->num_lpgs) {
|
|
|
|
dev_err(chip->dev, "hw index %d out of range [0-%d]\n",
|
|
|
|
hw_idx, chip->num_lpgs - 1);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return &chip->lpgs[hw_idx];
|
|
|
|
}
|
|
|
|
|
|
|
|
static int __find_index_in_array(int member, const int array[], int length)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < length; i++) {
|
|
|
|
if (member == array[i])
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int qpnp_lpg_set_glitch_removal(struct qpnp_lpg_channel *lpg, bool en)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
u8 mask, val;
|
|
|
|
|
|
|
|
val = en ? LPG_PWM_EN_GLITCH_REMOVAL_MASK : 0;
|
|
|
|
mask = LPG_PWM_EN_GLITCH_REMOVAL_MASK;
|
|
|
|
rc = qpnp_lpg_masked_write(lpg, REG_LPG_PWM_TYPE_CONFIG, mask, val);
|
|
|
|
if (rc < 0)
|
|
|
|
dev_err(lpg->chip->dev, "Write LPG_PWM_TYPE_CONFIG failed, rc=%d\n",
|
|
|
|
rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int qpnp_lpg_set_pwm_config(struct qpnp_lpg_channel *lpg)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
u8 val, mask, shift;
|
|
|
|
int pwm_size_idx, pwm_clk_idx, prediv_idx, clk_exp_idx;
|
|
|
|
|
2022-06-09 05:51:35 +09:00
|
|
|
if (lpg->subtype == SUBTYPE_HI_RES_PWM) {
|
|
|
|
pwm_size_idx = __find_index_in_array(lpg->pwm_config.pwm_size,
|
|
|
|
pwm_hi_res_size, ARRAY_SIZE(pwm_hi_res_size));
|
|
|
|
pwm_clk_idx = __find_index_in_array(lpg->pwm_config.pwm_clk,
|
|
|
|
clk_freq_hz_hi_res, ARRAY_SIZE(clk_freq_hz_hi_res));
|
|
|
|
} else {
|
|
|
|
pwm_size_idx = __find_index_in_array(lpg->pwm_config.pwm_size,
|
|
|
|
pwm_size, ARRAY_SIZE(pwm_size));
|
|
|
|
pwm_clk_idx = __find_index_in_array(lpg->pwm_config.pwm_clk,
|
|
|
|
clk_freq_hz, ARRAY_SIZE(clk_freq_hz));
|
|
|
|
}
|
|
|
|
|
2019-11-23 07:40:14 +09:00
|
|
|
prediv_idx = __find_index_in_array(lpg->pwm_config.prediv,
|
|
|
|
clk_prediv, ARRAY_SIZE(clk_prediv));
|
|
|
|
clk_exp_idx = __find_index_in_array(lpg->pwm_config.clk_exp,
|
|
|
|
pwm_exponent, ARRAY_SIZE(pwm_exponent));
|
|
|
|
|
|
|
|
if (pwm_size_idx < 0 || pwm_clk_idx < 0
|
|
|
|
|| prediv_idx < 0 || clk_exp_idx < 0)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
/* pwm_clk_idx is 1 bit lower than the register value */
|
|
|
|
pwm_clk_idx += 1;
|
|
|
|
if (lpg->subtype == SUBTYPE_PWM) {
|
|
|
|
shift = LPG_PWM_SIZE_PWM_SHIFT;
|
2022-06-09 05:51:35 +09:00
|
|
|
mask = LPG_PWM_SIZE_PWM_MASK | LPG_PWM_CLK_FREQ_SEL_MASK;
|
|
|
|
} else if (lpg->subtype == SUBTYPE_HI_RES_PWM) {
|
|
|
|
shift = LPG_PWM_SIZE_PWM_HI_RES_SHIFT;
|
|
|
|
mask = LPG_PWM_SIZE_PWM_HI_RES_MASK | LPG_PWM_HI_RES_CLK_FREQ_SEL_MASK;
|
2019-11-23 07:40:14 +09:00
|
|
|
} else {
|
|
|
|
shift = LPG_PWM_SIZE_LPG_SHIFT;
|
2022-06-09 05:51:35 +09:00
|
|
|
mask = LPG_PWM_SIZE_LPG_MASK | LPG_PWM_CLK_FREQ_SEL_MASK;
|
2019-11-23 07:40:14 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
val = pwm_size_idx << shift | pwm_clk_idx;
|
|
|
|
rc = qpnp_lpg_masked_write(lpg, REG_LPG_PWM_SIZE_CLK, mask, val);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(lpg->chip->dev, "Write LPG_PWM_SIZE_CLK failed, rc=%d\n",
|
|
|
|
rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
val = prediv_idx << LPG_PWM_FREQ_PREDIV_SHIFT | clk_exp_idx;
|
|
|
|
mask = LPG_PWM_FREQ_PREDIV_MASK | LPG_PWM_FREQ_EXPONENT_MASK;
|
|
|
|
rc = qpnp_lpg_masked_write(lpg, REG_LPG_PWM_FREQ_PREDIV_CLK, mask, val);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(lpg->chip->dev, "Write LPG_PWM_FREQ_PREDIV_CLK failed, rc=%d\n",
|
|
|
|
rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lpg->src_sel == LUT_PATTERN)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
val = lpg->pwm_config.pwm_value >> 8;
|
2022-06-09 05:51:35 +09:00
|
|
|
if (lpg->subtype == SUBTYPE_HI_RES_PWM)
|
|
|
|
mask = LPG_PWM_HI_RES_VALUE_MSB_MASK;
|
|
|
|
else
|
|
|
|
mask = LPG_PWM_VALUE_MSB_MASK;
|
2019-11-23 07:40:14 +09:00
|
|
|
rc = qpnp_lpg_masked_write(lpg, REG_LPG_PWM_VALUE_MSB, mask, val);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(lpg->chip->dev, "Write LPG_PWM_VALUE_MSB failed, rc=%d\n",
|
|
|
|
rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
val = lpg->pwm_config.pwm_value & LPG_PWM_VALUE_LSB_MASK;
|
|
|
|
rc = qpnp_lpg_write(lpg, REG_LPG_PWM_VALUE_LSB, val);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(lpg->chip->dev, "Write LPG_PWM_VALUE_LSB failed, rc=%d\n",
|
|
|
|
rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
val = LPG_PWM_VALUE_SYNC;
|
|
|
|
rc = qpnp_lpg_write(lpg, REG_LPG_PWM_SYNC, val);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(lpg->chip->dev, "Write LPG_PWM_SYNC failed, rc=%d\n",
|
|
|
|
rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2021-04-27 17:44:10 +09:00
|
|
|
static int qpnp_lpg_set_pfm_config(struct qpnp_lpg_channel *lpg)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
u8 val, mask;
|
|
|
|
int pwm_clk_idx, clk_exp_idx;
|
|
|
|
|
2022-06-09 05:51:35 +09:00
|
|
|
if (lpg->subtype == SUBTYPE_HI_RES_PWM)
|
|
|
|
pwm_clk_idx = __find_index_in_array(lpg->pwm_config.pwm_clk,
|
|
|
|
clk_freq_hz_hi_res, ARRAY_SIZE(clk_freq_hz_hi_res));
|
|
|
|
else
|
|
|
|
pwm_clk_idx = __find_index_in_array(lpg->pwm_config.pwm_clk,
|
|
|
|
clk_freq_hz, ARRAY_SIZE(clk_freq_hz));
|
|
|
|
|
2021-04-27 17:44:10 +09:00
|
|
|
clk_exp_idx = __find_index_in_array(lpg->pwm_config.clk_exp,
|
|
|
|
pwm_exponent, ARRAY_SIZE(pwm_exponent));
|
|
|
|
|
|
|
|
if (pwm_clk_idx < 0 || clk_exp_idx < 0)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
/* pwm_clk_idx is 1 bit lower than the register value */
|
|
|
|
pwm_clk_idx += 1;
|
|
|
|
|
|
|
|
val = pwm_clk_idx;
|
2022-06-09 05:51:35 +09:00
|
|
|
if (lpg->subtype == SUBTYPE_HI_RES_PWM)
|
|
|
|
mask = LPG_PWM_HI_RES_CLK_FREQ_SEL_MASK;
|
|
|
|
else
|
|
|
|
mask = LPG_PWM_CLK_FREQ_SEL_MASK;
|
|
|
|
|
2021-04-27 17:44:10 +09:00
|
|
|
rc = qpnp_lpg_masked_write(lpg, REG_LPG_PWM_SIZE_CLK, mask, val);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(lpg->chip->dev, "Write LPG_PWM_SIZE_CLK failed, rc=%d\n",
|
|
|
|
rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
val = clk_exp_idx;
|
|
|
|
mask = LPG_PWM_FREQ_EXPONENT_MASK;
|
|
|
|
rc = qpnp_lpg_masked_write(lpg, REG_LPG_PWM_FREQ_PREDIV_CLK, mask, val);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(lpg->chip->dev, "Write LPG_PWM_FREQ_PREDIV_CLK failed, rc=%d\n",
|
|
|
|
rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
val = lpg->pwm_config.pwm_value;
|
|
|
|
rc = qpnp_lpg_masked_write(lpg, REG_LPG_PWM_VALUE_LSB,
|
|
|
|
LPG_PWM_VALUE_LSB_MASK, val);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(lpg->chip->dev, "Write LPG_PWM_VALUE_LSB failed, rc=%d\n",
|
|
|
|
rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
val = LPG_PWM_VALUE_SYNC;
|
|
|
|
rc = qpnp_lpg_write(lpg, REG_LPG_PWM_SYNC, val);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(lpg->chip->dev, "Write LPG_PWM_SYNC failed, rc=%d\n",
|
|
|
|
rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2019-11-23 07:40:14 +09:00
|
|
|
static int qpnp_lpg_set_sdam_lut_pattern(struct qpnp_lpg_channel *lpg,
|
|
|
|
unsigned int *pattern, unsigned int length)
|
|
|
|
{
|
|
|
|
struct qpnp_lpg_lut *lut = lpg->chip->lut;
|
|
|
|
int i, rc = 0;
|
|
|
|
u8 val[SDAM_LUT_COUNT_MAX + 1], addr;
|
|
|
|
|
|
|
|
if (length > lpg->max_pattern_length) {
|
|
|
|
dev_err(lpg->chip->dev, "new pattern length (%d) larger than predefined (%d)\n",
|
|
|
|
length, lpg->max_pattern_length);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Program LUT pattern */
|
|
|
|
mutex_lock(&lut->lock);
|
|
|
|
addr = lpg->ramp_config.lo_idx;
|
|
|
|
for (i = 0; i < length; i++)
|
|
|
|
val[i] = pattern[i] * 255 / 100;
|
|
|
|
|
|
|
|
rc = qpnp_lut_sdam_write(lut, addr, val, length);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(lpg->chip->dev, "Write pattern in SDAM failed, rc=%d\n",
|
|
|
|
rc);
|
|
|
|
goto unlock;
|
|
|
|
}
|
|
|
|
|
|
|
|
lpg->ramp_config.pattern_length = length;
|
|
|
|
unlock:
|
|
|
|
mutex_unlock(&lut->lock);
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2020-05-27 11:22:03 +09:00
|
|
|
#define SDAM_START_BASE 0x40
|
|
|
|
static u8 qpnp_lpg_get_sdam_lut_idx(struct qpnp_lpg_channel *lpg, u8 idx)
|
|
|
|
{
|
|
|
|
struct qpnp_lpg_chip *chip = lpg->chip;
|
|
|
|
u8 val = idx;
|
|
|
|
|
|
|
|
if (chip->lut->nvmem_count == PPG_NVMEMS_2)
|
|
|
|
val += (chip->lut->reg_base - SDAM_START_BASE);
|
|
|
|
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
2019-11-23 07:40:14 +09:00
|
|
|
static int qpnp_lpg_set_sdam_ramp_config(struct qpnp_lpg_channel *lpg)
|
|
|
|
{
|
|
|
|
struct lpg_ramp_config *ramp = &lpg->ramp_config;
|
|
|
|
u8 addr, mask, val;
|
|
|
|
int rc = 0;
|
|
|
|
|
|
|
|
/* clear PBS scatchpad register */
|
|
|
|
val = 0;
|
|
|
|
rc = qpnp_lpg_sdam_write(lpg,
|
|
|
|
SDAM_PBS_SCRATCH_LUT_COUNTER_OFFSET, val);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(lpg->chip->dev, "Write SDAM_PBS_SCRATCH_LUT_COUNTER_OFFSET failed, rc=%d\n",
|
|
|
|
rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2020-05-27 09:56:41 +09:00
|
|
|
/* Set ramp step duration, in ticks */
|
|
|
|
val = (ramp->step_ms * 1000 / lpg->chip->lut->ramp_step_tick_us) & 0xff;
|
2019-11-23 07:40:14 +09:00
|
|
|
if (val > 0)
|
|
|
|
val--;
|
|
|
|
addr = SDAM_REG_RAMP_STEP_DURATION;
|
2020-05-27 11:21:23 +09:00
|
|
|
rc = qpnp_lpg_chan_nvmem_write(lpg->chip, addr, val);
|
2019-11-23 07:40:14 +09:00
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(lpg->chip->dev, "Write SDAM_REG_RAMP_STEP_DURATION failed, rc=%d\n",
|
|
|
|
rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set hi_idx and lo_idx */
|
2020-05-27 11:22:03 +09:00
|
|
|
val = qpnp_lpg_get_sdam_lut_idx(lpg, ramp->hi_idx);
|
|
|
|
rc = qpnp_lpg_sdam_write(lpg, SDAM_END_INDEX_OFFSET, val);
|
2019-11-23 07:40:14 +09:00
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(lpg->chip->dev, "Write SDAM_REG_END_INDEX failed, rc=%d\n",
|
|
|
|
rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2020-05-27 11:22:03 +09:00
|
|
|
val = qpnp_lpg_get_sdam_lut_idx(lpg, ramp->lo_idx);
|
|
|
|
rc = qpnp_lpg_sdam_write(lpg, SDAM_START_INDEX_OFFSET, val);
|
2019-11-23 07:40:14 +09:00
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(lpg->chip->dev, "Write SDAM_REG_START_INDEX failed, rc=%d\n",
|
|
|
|
rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set LPG_PATTERN_CONFIG */
|
|
|
|
addr = SDAM_PATTERN_CONFIG_OFFSET;
|
|
|
|
mask = SDAM_PATTERN_LOOP_ENABLE;
|
|
|
|
val = 0;
|
|
|
|
if (ramp->pattern_repeat)
|
|
|
|
val |= SDAM_PATTERN_LOOP_ENABLE;
|
2021-04-14 06:50:32 +09:00
|
|
|
if (ramp->pause_hi_count) {
|
|
|
|
val |= SDAM_PATTERN_EN_PAUSE_START;
|
|
|
|
mask |= SDAM_PATTERN_EN_PAUSE_START;
|
|
|
|
}
|
|
|
|
if (ramp->pause_lo_count) {
|
|
|
|
val |= SDAM_PATTERN_EN_PAUSE_END;
|
|
|
|
mask |= SDAM_PATTERN_EN_PAUSE_END;
|
|
|
|
}
|
2019-11-23 07:40:14 +09:00
|
|
|
|
|
|
|
rc = qpnp_lpg_sdam_masked_write(lpg, addr, mask, val);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(lpg->chip->dev, "Write SDAM_REG_PATTERN_CONFIG failed, rc=%d\n",
|
|
|
|
rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2021-04-14 06:50:32 +09:00
|
|
|
/* Set PAUSE HI and LO */
|
|
|
|
rc = qpnp_lpg_sdam_write(lpg, SDAM_PAUSE_START_MULTIPLIER_OFFSET,
|
|
|
|
ramp->pause_hi_count);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(lpg->chip->dev, "Write SDAM_REG_PAUSE_START_MULTIPLIER failed, rc=%d\n",
|
|
|
|
rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = qpnp_lpg_sdam_write(lpg, SDAM_PAUSE_END_MULTIPLIER_OFFSET,
|
|
|
|
ramp->pause_lo_count);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(lpg->chip->dev, "Write SDAM_REG_PAUSE_END_MULTIPLIER failed, rc=%d\n",
|
|
|
|
rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2019-11-23 07:40:14 +09:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int qpnp_lpg_set_lut_pattern(struct qpnp_lpg_channel *lpg,
|
|
|
|
unsigned int *pattern, unsigned int length)
|
|
|
|
{
|
|
|
|
struct qpnp_lpg_lut *lut = lpg->chip->lut;
|
|
|
|
u16 full_duty_value, pwm_values[SDAM_LUT_COUNT_MAX + 1] = {0};
|
|
|
|
int i, rc = 0;
|
|
|
|
u8 lsb, msb, addr;
|
|
|
|
|
|
|
|
if (lpg->chip->use_sdam)
|
|
|
|
return qpnp_lpg_set_sdam_lut_pattern(lpg, pattern, length);
|
|
|
|
|
|
|
|
if (length > lpg->max_pattern_length) {
|
|
|
|
dev_err(lpg->chip->dev, "new pattern length (%d) larger than predefined (%d)\n",
|
|
|
|
length, lpg->max_pattern_length);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Program LUT pattern */
|
|
|
|
mutex_lock(&lut->lock);
|
|
|
|
addr = REG_LPG_LUT_1_LSB + lpg->ramp_config.lo_idx * 2;
|
|
|
|
for (i = 0; i < length; i++) {
|
|
|
|
full_duty_value = 1 << lpg->pwm_config.pwm_size;
|
|
|
|
pwm_values[i] = pattern[i] * full_duty_value / 100;
|
|
|
|
|
|
|
|
if (unlikely(pwm_values[i] > full_duty_value)) {
|
|
|
|
dev_err(lpg->chip->dev, "PWM value %d exceed the max %d\n",
|
|
|
|
pwm_values[i], full_duty_value);
|
|
|
|
rc = -EINVAL;
|
|
|
|
goto unlock;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pwm_values[i] == full_duty_value)
|
|
|
|
pwm_values[i] = full_duty_value - 1;
|
|
|
|
|
|
|
|
lsb = pwm_values[i] & 0xff;
|
|
|
|
msb = pwm_values[i] >> 8;
|
|
|
|
rc = qpnp_lut_write(lut, addr++, lsb);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(lpg->chip->dev, "Write NO.%d LUT pattern LSB (%d) failed, rc=%d\n",
|
|
|
|
i, lsb, rc);
|
|
|
|
goto unlock;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = qpnp_lut_masked_write(lut, addr++,
|
|
|
|
LPG_LUT_VALUE_MSB_MASK, msb);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(lpg->chip->dev, "Write NO.%d LUT pattern MSB (%d) failed, rc=%d\n",
|
|
|
|
i, msb, rc);
|
|
|
|
goto unlock;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
lpg->ramp_config.pattern_length = length;
|
|
|
|
unlock:
|
|
|
|
mutex_unlock(&lut->lock);
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int qpnp_lpg_set_ramp_config(struct qpnp_lpg_channel *lpg)
|
|
|
|
{
|
|
|
|
struct lpg_ramp_config *ramp = &lpg->ramp_config;
|
|
|
|
u8 lsb, msb, addr, mask, val;
|
|
|
|
int rc = 0;
|
|
|
|
|
|
|
|
if (lpg->chip->use_sdam)
|
|
|
|
return qpnp_lpg_set_sdam_ramp_config(lpg);
|
|
|
|
|
|
|
|
/* Set ramp step duration */
|
|
|
|
lsb = ramp->step_ms & 0xff;
|
|
|
|
msb = ramp->step_ms >> 8;
|
|
|
|
addr = REG_LPG_RAMP_STEP_DURATION_LSB;
|
|
|
|
rc = qpnp_lpg_write(lpg, addr, lsb);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(lpg->chip->dev, "Write RAMP_STEP_DURATION_LSB failed, rc=%d\n",
|
|
|
|
rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
rc = qpnp_lpg_write(lpg, addr + 1, msb);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(lpg->chip->dev, "Write RAMP_STEP_DURATION_MSB failed, rc=%d\n",
|
|
|
|
rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set hi_idx and lo_idx */
|
|
|
|
rc = qpnp_lpg_masked_write(lpg, REG_LPG_HI_INDEX,
|
|
|
|
LPG_HI_LO_IDX_MASK, ramp->hi_idx);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(lpg->chip->dev, "Write LPG_HI_IDX failed, rc=%d\n",
|
|
|
|
rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = qpnp_lpg_masked_write(lpg, REG_LPG_LO_INDEX,
|
|
|
|
LPG_HI_LO_IDX_MASK, ramp->lo_idx);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(lpg->chip->dev, "Write LPG_LO_IDX failed, rc=%d\n",
|
|
|
|
rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set pause_hi/lo_count */
|
|
|
|
rc = qpnp_lpg_write(lpg, REG_LPG_PAUSE_HI_MULTIPLIER,
|
|
|
|
ramp->pause_hi_count);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(lpg->chip->dev, "Write LPG_PAUSE_HI_MULTIPLIER failed, rc=%d\n",
|
|
|
|
rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = qpnp_lpg_write(lpg, REG_LPG_PAUSE_LO_MULTIPLIER,
|
|
|
|
ramp->pause_lo_count);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(lpg->chip->dev, "Write LPG_PAUSE_LO_MULTIPLIER failed, rc=%d\n",
|
|
|
|
rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set LPG_PATTERN_CONFIG */
|
|
|
|
addr = REG_LPG_PATTERN_CONFIG;
|
|
|
|
mask = LPG_PATTERN_EN_PAUSE_LO | LPG_PATTERN_EN_PAUSE_HI
|
|
|
|
| LPG_PATTERN_RAMP_TOGGLE | LPG_PATTERN_REPEAT
|
|
|
|
| LPG_PATTERN_RAMP_LO_TO_HI;
|
|
|
|
val = 0;
|
|
|
|
if (ramp->pause_lo_count != 0)
|
|
|
|
val |= LPG_PATTERN_EN_PAUSE_LO;
|
|
|
|
if (ramp->pause_hi_count != 0)
|
|
|
|
val |= LPG_PATTERN_EN_PAUSE_HI;
|
|
|
|
if (ramp->ramp_dir_low_to_hi)
|
|
|
|
val |= LPG_PATTERN_RAMP_LO_TO_HI;
|
|
|
|
if (ramp->pattern_repeat)
|
|
|
|
val |= LPG_PATTERN_REPEAT;
|
|
|
|
if (ramp->toggle)
|
|
|
|
val |= LPG_PATTERN_RAMP_TOGGLE;
|
|
|
|
|
|
|
|
rc = qpnp_lpg_masked_write(lpg, addr, mask, val);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(lpg->chip->dev, "Write LPG_PATTERN_CONFIG failed, rc=%d\n",
|
|
|
|
rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2021-04-27 17:44:10 +09:00
|
|
|
static int __qpnp_lpg_calc_pwm_period(u64 period_ns,
|
2019-11-23 07:40:14 +09:00
|
|
|
struct lpg_pwm_config *pwm_config)
|
|
|
|
{
|
|
|
|
struct qpnp_lpg_channel *lpg = container_of(pwm_config,
|
|
|
|
struct qpnp_lpg_channel, pwm_config);
|
2022-06-09 05:51:35 +09:00
|
|
|
struct lpg_pwm_config configs[NUM_PWM_HI_RES_SIZE];
|
2019-11-23 07:40:14 +09:00
|
|
|
int i, j, m, n;
|
|
|
|
u64 tmp1, tmp2;
|
|
|
|
u64 clk_period_ns = 0, pwm_clk_period_ns;
|
|
|
|
u64 clk_delta_ns = U64_MAX, min_clk_delta_ns = U64_MAX;
|
|
|
|
u64 pwm_period_delta = U64_MAX, min_pwm_period_delta = U64_MAX;
|
2022-06-09 05:51:35 +09:00
|
|
|
int pwm_size_step, clk_len, pwm_size_len;
|
|
|
|
const int *pwm_size_arr, *clk_freq_hz_arr;
|
2019-11-23 07:40:14 +09:00
|
|
|
|
|
|
|
/*
|
|
|
|
* (2^pwm_size) * (2^pwm_exp) * prediv * NSEC_PER_SEC
|
|
|
|
* pwm_period = ---------------------------------------------------
|
|
|
|
* clk_freq_hz
|
|
|
|
*
|
|
|
|
* Searching the closest settings for the requested PWM period.
|
|
|
|
*/
|
2022-06-09 05:51:35 +09:00
|
|
|
if (lpg->subtype == SUBTYPE_HI_RES_PWM) {
|
|
|
|
pwm_size_arr = pwm_hi_res_size;
|
|
|
|
pwm_size_len = NUM_PWM_HI_RES_SIZE;
|
|
|
|
clk_freq_hz_arr = clk_freq_hz_hi_res;
|
|
|
|
clk_len = NUM_PWM_HI_RES_CLK;
|
|
|
|
} else {
|
|
|
|
pwm_size_arr = pwm_size;
|
|
|
|
pwm_size_len = NUM_PWM_SIZE;
|
|
|
|
clk_freq_hz_arr = clk_freq_hz;
|
|
|
|
clk_len = NUM_PWM_CLK;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lpg->chip->use_sdam) {
|
2019-11-23 07:40:14 +09:00
|
|
|
/* SDAM pattern control can only use 9 bit resolution */
|
|
|
|
n = 1;
|
2022-06-09 05:51:35 +09:00
|
|
|
pwm_size_len = 2;
|
|
|
|
}
|
2019-11-23 07:40:14 +09:00
|
|
|
else
|
|
|
|
n = 0;
|
2022-06-09 05:51:35 +09:00
|
|
|
for (; n < pwm_size_len; n++) {
|
|
|
|
pwm_clk_period_ns = period_ns >> pwm_size_arr[n];
|
|
|
|
for (i = clk_len - 1; i >= 0; i--) {
|
|
|
|
for (j = 0; j < clk_len; j++) {
|
2019-11-23 07:40:14 +09:00
|
|
|
for (m = 0; m < ARRAY_SIZE(pwm_exponent); m++) {
|
|
|
|
tmp1 = 1 << pwm_exponent[m];
|
|
|
|
tmp1 *= clk_prediv[j];
|
|
|
|
tmp2 = NSEC_PER_SEC;
|
2022-06-09 05:51:35 +09:00
|
|
|
do_div(tmp2, clk_freq_hz_arr[i]);
|
2019-11-23 07:40:14 +09:00
|
|
|
|
|
|
|
clk_period_ns = tmp1 * tmp2;
|
|
|
|
|
|
|
|
clk_delta_ns = abs(pwm_clk_period_ns
|
|
|
|
- clk_period_ns);
|
|
|
|
/*
|
|
|
|
* Find the closest setting for
|
|
|
|
* PWM frequency predivide value
|
|
|
|
*/
|
|
|
|
if (clk_delta_ns < min_clk_delta_ns) {
|
|
|
|
min_clk_delta_ns
|
|
|
|
= clk_delta_ns;
|
|
|
|
configs[n].pwm_clk
|
2022-06-09 05:51:35 +09:00
|
|
|
= clk_freq_hz_arr[i];
|
2019-11-23 07:40:14 +09:00
|
|
|
configs[n].prediv
|
|
|
|
= clk_prediv[j];
|
|
|
|
configs[n].clk_exp
|
|
|
|
= pwm_exponent[m];
|
|
|
|
configs[n].pwm_size
|
2022-06-09 05:51:35 +09:00
|
|
|
= pwm_size_arr[n];
|
2019-11-23 07:40:14 +09:00
|
|
|
configs[n].best_period_ns
|
|
|
|
= clk_period_ns;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-09 05:51:35 +09:00
|
|
|
configs[n].best_period_ns *= 1 << pwm_size_arr[n];
|
2019-11-23 07:40:14 +09:00
|
|
|
/* Find the closest setting for PWM period */
|
2022-06-09 05:51:35 +09:00
|
|
|
pwm_period_delta = min_clk_delta_ns << pwm_size_arr[n];
|
2019-11-23 07:40:14 +09:00
|
|
|
if (pwm_period_delta < min_pwm_period_delta) {
|
|
|
|
min_pwm_period_delta = pwm_period_delta;
|
|
|
|
memcpy(pwm_config, &configs[n],
|
|
|
|
sizeof(struct lpg_pwm_config));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Larger PWM size can achieve better resolution for PWM duty */
|
2022-06-09 05:51:35 +09:00
|
|
|
for (n = pwm_size_len - 1; n > 0; n--) {
|
|
|
|
if (pwm_config->pwm_size >= pwm_size_arr[n])
|
2019-11-23 07:40:14 +09:00
|
|
|
break;
|
2022-06-09 05:51:35 +09:00
|
|
|
pwm_size_step = pwm_size_arr[n] - pwm_config->pwm_size;
|
2019-11-23 07:40:14 +09:00
|
|
|
if (pwm_config->clk_exp >= pwm_size_step) {
|
2022-06-09 05:51:35 +09:00
|
|
|
pwm_config->pwm_size = pwm_size_arr[n];
|
2019-11-23 07:40:14 +09:00
|
|
|
pwm_config->clk_exp -= pwm_size_step;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pr_debug("PWM setting for period_ns %llu: pwm_clk = %dHZ, prediv = %d, exponent = %d, pwm_size = %d\n",
|
|
|
|
period_ns, pwm_config->pwm_clk, pwm_config->prediv,
|
|
|
|
pwm_config->clk_exp, pwm_config->pwm_size);
|
|
|
|
pr_debug("Actual period: %lluns\n", pwm_config->best_period_ns);
|
2021-04-27 17:44:10 +09:00
|
|
|
|
|
|
|
return 0;
|
2019-11-23 07:40:14 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
static void __qpnp_lpg_calc_pwm_duty(u64 period_ns, u64 duty_ns,
|
|
|
|
struct lpg_pwm_config *pwm_config)
|
|
|
|
{
|
|
|
|
u16 pwm_value, max_pwm_value;
|
|
|
|
u64 tmp;
|
|
|
|
|
|
|
|
tmp = (u64)duty_ns << pwm_config->pwm_size;
|
|
|
|
pwm_value = (u16)div64_u64(tmp, period_ns);
|
|
|
|
|
|
|
|
max_pwm_value = (1 << pwm_config->pwm_size) - 1;
|
|
|
|
if (pwm_value > max_pwm_value)
|
|
|
|
pwm_value = max_pwm_value;
|
|
|
|
pwm_config->pwm_value = pwm_value;
|
|
|
|
}
|
|
|
|
|
2021-04-27 17:44:10 +09:00
|
|
|
static int __qpnp_lpg_calc_pfm_period(u64 period_ns,
|
|
|
|
struct lpg_pwm_config *pwm_config)
|
|
|
|
{
|
2022-06-09 05:51:35 +09:00
|
|
|
struct qpnp_lpg_channel *lpg = container_of(pwm_config,
|
|
|
|
struct qpnp_lpg_channel, pwm_config);
|
|
|
|
int clk, exp, lsb, clk_len;
|
2021-04-27 17:44:10 +09:00
|
|
|
int best_clk = 0, best_exp = 0, best_lsb = -EINVAL;
|
|
|
|
u64 lsb_tmp, period_tmp, curr_p_err, last_p_err = 0;
|
|
|
|
u64 min_p_err = U64_MAX;
|
2022-06-09 05:51:35 +09:00
|
|
|
const int *clk_freq_hz_arr, *clk_period_ns_arr;
|
2021-04-27 17:44:10 +09:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 2 * (pwm_value_lsb + 1) * (2^pwm_exp) * NSEC_PER_SEC
|
|
|
|
* pwm_period = ---------------------------------------------------
|
|
|
|
* clk_freq_hz
|
|
|
|
*
|
|
|
|
* For each (clk, exp) solve above equation for pwm_value_lsb, and then
|
|
|
|
* use this pwm_lsb to calculate pwm_period and compare with desired
|
|
|
|
* period. Store the triplet values that yield the closest value to
|
|
|
|
* desired period.
|
|
|
|
*/
|
2022-06-09 05:51:35 +09:00
|
|
|
|
|
|
|
if (lpg->subtype == SUBTYPE_HI_RES_PWM) {
|
|
|
|
clk_freq_hz_arr = clk_freq_hz_hi_res;
|
|
|
|
clk_period_ns_arr = clk_period_ns_hi_res;
|
|
|
|
clk_len = NUM_PWM_HI_RES_CLK;
|
|
|
|
} else {
|
|
|
|
clk_freq_hz_arr = clk_freq_hz;
|
|
|
|
clk_period_ns_arr = clk_period_ns;
|
|
|
|
clk_len = NUM_PWM_CLK;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (clk = 0; clk < clk_len; clk++) {
|
2021-04-27 17:44:10 +09:00
|
|
|
last_p_err = U64_MAX;
|
|
|
|
for (exp = 0; exp < NUM_PWM_EXP; exp++) {
|
2022-06-09 05:51:35 +09:00
|
|
|
lsb_tmp = div_u64(period_ns, clk_period_ns_arr[clk]);
|
2021-04-27 17:44:10 +09:00
|
|
|
lsb_tmp >>= (exp + 1);
|
|
|
|
lsb = lsb_tmp - 1;
|
|
|
|
if (lsb >= 0 && lsb <= U8_MAX) {
|
|
|
|
period_tmp = (lsb + 1);
|
|
|
|
period_tmp <<= (exp + 1);
|
2022-06-09 05:51:35 +09:00
|
|
|
period_tmp *= clk_period_ns_arr[clk];
|
2021-04-27 17:44:10 +09:00
|
|
|
curr_p_err = abs(period_ns - period_tmp);
|
|
|
|
|
|
|
|
if (curr_p_err < min_p_err) {
|
|
|
|
min_p_err = curr_p_err;
|
|
|
|
|
|
|
|
/* Closest settings found! Save them. */
|
|
|
|
best_clk = clk;
|
|
|
|
best_exp = exp;
|
|
|
|
best_lsb = lsb;
|
|
|
|
/*
|
|
|
|
* No need to set pwm_size or prediv in
|
|
|
|
* `struct pwm_config` as they are
|
|
|
|
* no-ops in PFM mode.
|
|
|
|
*/
|
|
|
|
pwm_config->best_period_ns = period_tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (curr_p_err > last_p_err)
|
|
|
|
/* No need to iterate further */
|
|
|
|
break;
|
|
|
|
last_p_err = curr_p_err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (best_lsb < 0) {
|
|
|
|
pr_err("Cannot generate %llu ns\n", period_ns);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2022-06-09 05:51:35 +09:00
|
|
|
pwm_config->pwm_clk = clk_freq_hz_arr[best_clk];
|
2021-04-27 17:44:10 +09:00
|
|
|
pwm_config->clk_exp = pwm_exponent[best_exp];
|
|
|
|
pwm_config->pwm_value = best_lsb;
|
|
|
|
|
|
|
|
pr_debug("PFM setting for period_ns %llu: pwm_clk = %d Hz, exponent = %d, pwm_val_lsb = %d\n",
|
|
|
|
period_ns, pwm_config->pwm_clk,
|
|
|
|
pwm_config->clk_exp, pwm_config->pwm_value);
|
|
|
|
pr_debug("Actual PFM period: %llu ns\n", pwm_config->best_period_ns);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-11-23 07:40:14 +09:00
|
|
|
static int qpnp_lpg_config(struct qpnp_lpg_channel *lpg,
|
|
|
|
u64 duty_ns, u64 period_ns)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
if (duty_ns > period_ns) {
|
|
|
|
dev_err(lpg->chip->dev, "Duty %lluns is larger than period %lluns\n",
|
|
|
|
duty_ns, period_ns);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (period_ns != lpg->current_period_ns) {
|
2021-04-27 17:44:10 +09:00
|
|
|
if (lpg->enable_pfm) {
|
|
|
|
rc = __qpnp_lpg_calc_pfm_period(period_ns,
|
|
|
|
&lpg->pwm_config);
|
|
|
|
if (rc)
|
|
|
|
return rc;
|
|
|
|
} else {
|
|
|
|
rc = __qpnp_lpg_calc_pwm_period(period_ns,
|
|
|
|
&lpg->pwm_config);
|
|
|
|
if (rc)
|
|
|
|
return rc;
|
2019-11-23 07:40:14 +09:00
|
|
|
|
2021-04-27 17:44:10 +09:00
|
|
|
/* program LUT if PWM period is changed */
|
|
|
|
if (lpg->src_sel == LUT_PATTERN) {
|
|
|
|
rc = qpnp_lpg_set_lut_pattern(lpg,
|
2019-11-23 07:40:14 +09:00
|
|
|
lpg->ramp_config.pattern,
|
|
|
|
lpg->ramp_config.pattern_length);
|
2021-04-27 17:44:10 +09:00
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(lpg->chip->dev, "set LUT pattern failed for LPG%d, rc=%d\n",
|
|
|
|
lpg->lpg_idx, rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
lpg->lut_written = true;
|
2019-11-23 07:40:14 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-27 17:44:10 +09:00
|
|
|
/* Don't calculate duty cycle for PFM as it is fixed at 50% */
|
|
|
|
if ((period_ns != lpg->current_period_ns ||
|
|
|
|
duty_ns != lpg->current_duty_ns) && !lpg->enable_pfm)
|
2019-11-23 07:40:14 +09:00
|
|
|
__qpnp_lpg_calc_pwm_duty(period_ns, duty_ns, &lpg->pwm_config);
|
|
|
|
|
2021-04-27 17:44:10 +09:00
|
|
|
if (lpg->enable_pfm)
|
|
|
|
rc = qpnp_lpg_set_pfm_config(lpg);
|
|
|
|
else
|
|
|
|
rc = qpnp_lpg_set_pwm_config(lpg);
|
|
|
|
|
2019-11-23 07:40:14 +09:00
|
|
|
if (rc < 0) {
|
2021-04-27 17:44:10 +09:00
|
|
|
dev_err(lpg->chip->dev, "Config %s failed for channel %d, rc=%d\n",
|
|
|
|
lpg->enable_pfm ? "PFM" : "PWM", lpg->lpg_idx, rc);
|
2019-11-23 07:40:14 +09:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
lpg->current_period_ns = period_ns;
|
|
|
|
lpg->current_duty_ns = duty_ns;
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int qpnp_lpg_pwm_config(struct pwm_chip *pwm_chip,
|
|
|
|
struct pwm_device *pwm, u64 duty_ns, u64 period_ns)
|
|
|
|
{
|
|
|
|
struct qpnp_lpg_channel *lpg;
|
|
|
|
|
|
|
|
lpg = pwm_dev_to_qpnp_lpg(pwm_chip, pwm);
|
|
|
|
if (lpg == NULL) {
|
|
|
|
dev_err(pwm_chip->dev, "lpg not found\n");
|
|
|
|
return -ENODEV;
|
|
|
|
}
|
|
|
|
|
|
|
|
return qpnp_lpg_config(lpg, duty_ns, period_ns);
|
|
|
|
}
|
|
|
|
|
2020-05-27 11:22:03 +09:00
|
|
|
#define SDAM_PBS_TRIG_SET 0xe5
|
|
|
|
#define SDAM_PBS_TRIG_CLR 0xe6
|
|
|
|
static int qpnp_lpg_clear_pbs_trigger(struct qpnp_lpg_chip *chip)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
rc = qpnp_lpg_chan_nvmem_write(chip,
|
|
|
|
SDAM_REG_PBS_SEQ_EN, 0);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(chip->dev, "Write SDAM_REG_PBS_SEQ_EN failed, rc=%d\n",
|
|
|
|
rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (chip->lut->nvmem_count == PPG_NVMEMS_2) {
|
|
|
|
rc = qpnp_lpg_chan_nvmem_write(chip, SDAM_PBS_TRIG_CLR,
|
|
|
|
PBS_SW_TRG_BIT);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(chip->dev, "Failed to fire PBS seq, rc=%d\n",
|
|
|
|
rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int qpnp_lpg_set_pbs_trigger(struct qpnp_lpg_chip *chip)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
rc = qpnp_lpg_chan_nvmem_write(chip,
|
|
|
|
SDAM_REG_PBS_SEQ_EN, PBS_SW_TRG_BIT);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(chip->dev, "Write SDAM_REG_PBS_SEQ_EN failed, rc=%d\n",
|
|
|
|
rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (chip->lut->nvmem_count == PPG_NVMEMS_1) {
|
|
|
|
if (!chip->pbs_dev_node) {
|
|
|
|
dev_err(chip->dev, "PBS device unavailable\n");
|
|
|
|
return -ENODEV;
|
|
|
|
}
|
|
|
|
rc = qpnp_pbs_trigger_event(chip->pbs_dev_node,
|
|
|
|
PBS_SW_TRG_BIT);
|
|
|
|
} else {
|
|
|
|
rc = qpnp_lpg_chan_nvmem_write(chip, SDAM_PBS_TRIG_SET,
|
|
|
|
PBS_SW_TRG_BIT);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rc < 0)
|
|
|
|
dev_err(chip->dev, "Failed to trigger PBS, rc=%d\n", rc);
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2019-11-23 07:40:14 +09:00
|
|
|
static int qpnp_lpg_pbs_trigger_enable(struct qpnp_lpg_channel *lpg, bool en)
|
|
|
|
{
|
|
|
|
struct qpnp_lpg_chip *chip = lpg->chip;
|
|
|
|
int rc = 0;
|
|
|
|
|
|
|
|
if (en) {
|
|
|
|
if (chip->pbs_en_bitmap == 0) {
|
2020-05-27 11:22:03 +09:00
|
|
|
rc = qpnp_lpg_set_pbs_trigger(chip);
|
|
|
|
if (rc < 0)
|
2019-11-23 07:40:14 +09:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
set_bit(lpg->lpg_idx, &chip->pbs_en_bitmap);
|
|
|
|
} else {
|
|
|
|
clear_bit(lpg->lpg_idx, &chip->pbs_en_bitmap);
|
|
|
|
if (chip->pbs_en_bitmap == 0) {
|
2020-05-27 11:22:03 +09:00
|
|
|
rc = qpnp_lpg_clear_pbs_trigger(chip);
|
|
|
|
if (rc < 0)
|
2019-11-23 07:40:14 +09:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int qpnp_lpg_pwm_src_enable(struct qpnp_lpg_channel *lpg, bool en)
|
|
|
|
{
|
|
|
|
struct qpnp_lpg_chip *chip = lpg->chip;
|
|
|
|
struct qpnp_lpg_lut *lut = chip->lut;
|
|
|
|
struct pwm_device *pwm;
|
|
|
|
u8 mask, val;
|
|
|
|
int i, lpg_idx, rc;
|
|
|
|
|
|
|
|
mask = LPG_PWM_SRC_SELECT_MASK | LPG_EN_LPG_OUT_BIT |
|
|
|
|
LPG_EN_RAMP_GEN_MASK;
|
|
|
|
val = lpg->src_sel << LPG_PWM_SRC_SELECT_SHIFT;
|
|
|
|
|
|
|
|
if (lpg->src_sel == LUT_PATTERN && !chip->use_sdam)
|
|
|
|
val |= 1 << LPG_EN_RAMP_GEN_SHIFT;
|
|
|
|
|
|
|
|
if (en)
|
|
|
|
val |= 1 << LPG_EN_LPG_OUT_SHIFT;
|
|
|
|
|
|
|
|
rc = qpnp_lpg_masked_write(lpg, REG_LPG_ENABLE_CONTROL, mask, val);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(chip->dev, "Write LPG_ENABLE_CONTROL failed, rc=%d\n",
|
|
|
|
rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (chip->use_sdam) {
|
|
|
|
if (lpg->src_sel == LUT_PATTERN && en) {
|
|
|
|
val = SDAM_LUT_EN_BIT;
|
|
|
|
en = true;
|
|
|
|
} else {
|
|
|
|
val = 0;
|
|
|
|
en = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = qpnp_lpg_sdam_write(lpg, SDAM_LUT_EN_OFFSET, val);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(chip->dev, "Write SDAM_REG_LUT_EN failed, rc=%d\n",
|
|
|
|
rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
qpnp_lpg_pbs_trigger_enable(lpg, en);
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lpg->src_sel == LUT_PATTERN && en) {
|
|
|
|
val = 1 << lpg->lpg_idx;
|
|
|
|
for (i = 0; i < chip->num_lpgs; i++) {
|
|
|
|
if (chip->lpg_group == NULL)
|
|
|
|
break;
|
|
|
|
if (chip->lpg_group[i] == 0)
|
|
|
|
break;
|
|
|
|
lpg_idx = chip->lpg_group[i] - 1;
|
|
|
|
pwm = &chip->pwm_chip.pwms[lpg_idx];
|
2021-09-23 08:14:19 +09:00
|
|
|
if ((lpg->output_type == PWM_OUTPUT_MODULATED)
|
2019-11-23 07:40:14 +09:00
|
|
|
&& pwm_is_enabled(pwm)) {
|
|
|
|
rc = qpnp_lpg_masked_write(&chip->lpgs[lpg_idx],
|
|
|
|
REG_LPG_ENABLE_CONTROL,
|
|
|
|
LPG_EN_LPG_OUT_BIT, 0);
|
|
|
|
if (rc < 0)
|
|
|
|
break;
|
|
|
|
rc = qpnp_lpg_masked_write(&chip->lpgs[lpg_idx],
|
|
|
|
REG_LPG_ENABLE_CONTROL,
|
|
|
|
LPG_EN_LPG_OUT_BIT,
|
|
|
|
LPG_EN_LPG_OUT_BIT);
|
|
|
|
if (rc < 0)
|
|
|
|
break;
|
|
|
|
val |= 1 << lpg_idx;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mutex_lock(&lut->lock);
|
|
|
|
rc = qpnp_lut_write(lut, REG_LPG_LUT_RAMP_CONTROL, val);
|
|
|
|
if (rc < 0)
|
|
|
|
dev_err(chip->dev, "Write LPG_LUT_RAMP_CONTROL failed, rc=%d\n",
|
|
|
|
rc);
|
|
|
|
mutex_unlock(&lut->lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2021-09-23 08:14:19 +09:00
|
|
|
int qpnp_lpg_pwm_set_output_type(struct pwm_device *pwm,
|
|
|
|
enum pwm_output_type output_type)
|
2019-11-23 07:40:14 +09:00
|
|
|
{
|
|
|
|
struct qpnp_lpg_channel *lpg;
|
|
|
|
enum lpg_src src_sel;
|
|
|
|
int rc;
|
|
|
|
bool is_enabled;
|
|
|
|
|
2021-09-23 08:14:19 +09:00
|
|
|
if (!pwm) {
|
|
|
|
pr_err("pwm cannot be NULL\n");
|
|
|
|
return -ENODEV;
|
|
|
|
}
|
|
|
|
|
|
|
|
lpg = pwm_dev_to_qpnp_lpg(pwm->chip, pwm);
|
2019-11-23 07:40:14 +09:00
|
|
|
if (lpg == NULL) {
|
2021-09-23 08:14:19 +09:00
|
|
|
dev_err(pwm->chip->dev, "lpg not found\n");
|
2019-11-23 07:40:14 +09:00
|
|
|
return -ENODEV;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lpg->chip->lut == NULL) {
|
|
|
|
pr_debug("lpg%d only support PWM mode\n", lpg->lpg_idx);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-09-23 08:14:19 +09:00
|
|
|
if (output_type == lpg->output_type)
|
|
|
|
return 0;
|
|
|
|
|
2019-11-23 07:40:14 +09:00
|
|
|
src_sel = (output_type == PWM_OUTPUT_MODULATED) ?
|
|
|
|
LUT_PATTERN : PWM_VALUE;
|
|
|
|
if (src_sel == lpg->src_sel)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
is_enabled = pwm_is_enabled(pwm);
|
|
|
|
if (is_enabled) {
|
|
|
|
/*
|
|
|
|
* Disable the channel first then enable it later to make
|
|
|
|
* sure the output type is changed successfully. This is
|
|
|
|
* especially useful in SDAM use case to stop the PBS
|
|
|
|
* sequence when changing the PWM output type from
|
|
|
|
* MODULATED to FIXED.
|
|
|
|
*/
|
|
|
|
rc = qpnp_lpg_pwm_src_enable(lpg, false);
|
|
|
|
if (rc < 0) {
|
2021-09-23 08:14:19 +09:00
|
|
|
dev_err(pwm->chip->dev, "Enable PWM output failed for channel %d, rc=%d\n",
|
2019-11-23 07:40:14 +09:00
|
|
|
lpg->lpg_idx, rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (src_sel == LUT_PATTERN) {
|
|
|
|
/* program LUT if it's never been programmed */
|
|
|
|
if (!lpg->lut_written) {
|
|
|
|
rc = qpnp_lpg_set_lut_pattern(lpg,
|
|
|
|
lpg->ramp_config.pattern,
|
|
|
|
lpg->ramp_config.pattern_length);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(lpg->chip->dev, "set LUT pattern failed for LPG%d, rc=%d\n",
|
|
|
|
lpg->lpg_idx, rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
lpg->lut_written = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = qpnp_lpg_set_ramp_config(lpg);
|
|
|
|
if (rc < 0) {
|
2021-09-23 08:14:19 +09:00
|
|
|
dev_err(pwm->chip->dev, "Config LPG%d ramping failed, rc=%d\n",
|
2019-11-23 07:40:14 +09:00
|
|
|
lpg->lpg_idx, rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
lpg->src_sel = src_sel;
|
|
|
|
|
|
|
|
if (is_enabled) {
|
|
|
|
rc = qpnp_lpg_set_pwm_config(lpg);
|
|
|
|
if (rc < 0) {
|
2021-09-23 08:14:19 +09:00
|
|
|
dev_err(pwm->chip->dev, "Config PWM failed for channel %d, rc=%d\n",
|
2019-11-23 07:40:14 +09:00
|
|
|
lpg->lpg_idx, rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = qpnp_lpg_pwm_src_enable(lpg, true);
|
|
|
|
if (rc < 0) {
|
2021-09-23 08:14:19 +09:00
|
|
|
dev_err(pwm->chip->dev, "Enable PWM output failed for channel %d, rc=%d\n",
|
2019-11-23 07:40:14 +09:00
|
|
|
lpg->lpg_idx, rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-23 08:14:19 +09:00
|
|
|
lpg->output_type = output_type;
|
|
|
|
|
2019-11-23 07:40:14 +09:00
|
|
|
return 0;
|
|
|
|
}
|
2021-09-23 08:14:19 +09:00
|
|
|
EXPORT_SYMBOL(qpnp_lpg_pwm_set_output_type);
|
|
|
|
|
|
|
|
int qpnp_lpg_pwm_get_output_types_supported(struct pwm_device *pwm)
|
|
|
|
{
|
|
|
|
enum pwm_output_type type = PWM_OUTPUT_FIXED;
|
|
|
|
struct qpnp_lpg_channel *lpg;
|
|
|
|
|
|
|
|
if (!pwm) {
|
|
|
|
pr_err("pwm cannot be NULL\n");
|
|
|
|
return -ENODEV;
|
|
|
|
}
|
|
|
|
|
|
|
|
lpg = pwm_dev_to_qpnp_lpg(pwm->chip, pwm);
|
|
|
|
if (lpg == NULL) {
|
|
|
|
dev_err(pwm->chip->dev, "lpg not found\n");
|
|
|
|
return -ENODEV;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lpg->chip->lut != NULL)
|
|
|
|
type |= PWM_OUTPUT_MODULATED;
|
|
|
|
|
|
|
|
return type;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(qpnp_lpg_pwm_get_output_types_supported);
|
2019-11-23 07:40:14 +09:00
|
|
|
|
|
|
|
static int qpnp_lpg_pwm_enable(struct pwm_chip *pwm_chip,
|
|
|
|
struct pwm_device *pwm)
|
|
|
|
{
|
|
|
|
struct qpnp_lpg_channel *lpg;
|
|
|
|
int rc = 0;
|
|
|
|
|
|
|
|
lpg = pwm_dev_to_qpnp_lpg(pwm_chip, pwm);
|
|
|
|
if (lpg == NULL) {
|
|
|
|
dev_err(pwm_chip->dev, "lpg not found\n");
|
|
|
|
return -ENODEV;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Update PWM_VALUE_SYNC to make sure PWM_VALUE
|
|
|
|
* will be updated everytime before enabling.
|
|
|
|
*/
|
|
|
|
if (lpg->src_sel == PWM_VALUE) {
|
|
|
|
rc = qpnp_lpg_write(lpg, REG_LPG_PWM_SYNC, LPG_PWM_VALUE_SYNC);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(lpg->chip->dev, "Write LPG_PWM_SYNC failed, rc=%d\n",
|
|
|
|
rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = qpnp_lpg_set_glitch_removal(lpg, true);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(lpg->chip->dev, "Enable glitch-removal failed, rc=%d\n",
|
|
|
|
rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = qpnp_lpg_pwm_src_enable(lpg, true);
|
|
|
|
if (rc < 0)
|
|
|
|
dev_err(pwm_chip->dev, "Enable PWM output failed for channel %d, rc=%d\n",
|
|
|
|
lpg->lpg_idx, rc);
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void qpnp_lpg_pwm_disable(struct pwm_chip *pwm_chip,
|
|
|
|
struct pwm_device *pwm)
|
|
|
|
{
|
|
|
|
struct qpnp_lpg_channel *lpg;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
lpg = pwm_dev_to_qpnp_lpg(pwm_chip, pwm);
|
|
|
|
if (lpg == NULL) {
|
|
|
|
dev_err(pwm_chip->dev, "lpg not found\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = qpnp_lpg_pwm_src_enable(lpg, false);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(pwm_chip->dev, "Disable PWM output failed for channel %d, rc=%d\n",
|
|
|
|
lpg->lpg_idx, rc);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = qpnp_lpg_set_glitch_removal(lpg, false);
|
|
|
|
if (rc < 0)
|
|
|
|
dev_err(lpg->chip->dev, "Disable glitch-removal failed, rc=%d\n",
|
|
|
|
rc);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int qpnp_lpg_pwm_apply(struct pwm_chip *pwm_chip, struct pwm_device *pwm,
|
|
|
|
const struct pwm_state *state)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
if (state->period != pwm->state.period ||
|
|
|
|
state->duty_cycle != pwm->state.duty_cycle) {
|
|
|
|
rc = qpnp_lpg_pwm_config(pwm->chip, pwm,
|
|
|
|
state->duty_cycle, state->period);
|
|
|
|
if (rc < 0)
|
|
|
|
return rc;
|
|
|
|
|
|
|
|
pwm->state.duty_cycle = state->duty_cycle;
|
|
|
|
pwm->state.period = state->period;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (state->enabled != pwm->state.enabled) {
|
|
|
|
if (state->enabled) {
|
|
|
|
rc = qpnp_lpg_pwm_enable(pwm->chip, pwm);
|
|
|
|
if (rc < 0)
|
|
|
|
return rc;
|
|
|
|
} else {
|
|
|
|
qpnp_lpg_pwm_disable(pwm->chip, pwm);
|
|
|
|
}
|
|
|
|
|
|
|
|
pwm->state.enabled = state->enabled;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct pwm_ops qpnp_lpg_pwm_ops = {
|
|
|
|
.apply = qpnp_lpg_pwm_apply,
|
|
|
|
.owner = THIS_MODULE,
|
|
|
|
};
|
|
|
|
|
|
|
|
static int qpnp_get_lpg_channels(struct qpnp_lpg_chip *chip, u32 *base)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
const __be32 *addr;
|
|
|
|
|
|
|
|
addr = of_get_address(chip->dev->of_node, 0, NULL, NULL);
|
|
|
|
if (!addr) {
|
|
|
|
dev_err(chip->dev, "Get %s address failed\n", LPG_BASE);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
*base = be32_to_cpu(addr[0]);
|
|
|
|
rc = of_property_read_u32(chip->dev->of_node, "qcom,num-lpg-channels",
|
|
|
|
&chip->num_lpgs);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(chip->dev, "Failed to get qcom,num-lpg-channels, rc=%d\n",
|
|
|
|
rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (chip->num_lpgs == 0) {
|
|
|
|
dev_err(chip->dev, "No LPG channels specified\n");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-04-14 06:50:32 +09:00
|
|
|
static int qpnp_lpg_parse_ramp_props_dt(struct device_node *node,
|
|
|
|
struct qpnp_lpg_chip *chip,
|
|
|
|
u32 lpg_chan_id, u32 max_count)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
u32 tmp;
|
|
|
|
struct qpnp_lpg_channel *lpg;
|
|
|
|
struct lpg_ramp_config *ramp;
|
|
|
|
|
|
|
|
/* lpg channel id is indexed from 1 in hardware */
|
|
|
|
lpg = &chip->lpgs[lpg_chan_id - 1];
|
|
|
|
ramp = &lpg->ramp_config;
|
|
|
|
|
|
|
|
rc = of_property_read_u32(node, "qcom,ramp-step-ms", &tmp);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(chip->dev, "get qcom,ramp-step-ms failed for lpg%d, rc=%d\n",
|
|
|
|
lpg_chan_id, rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
ramp->step_ms = (u16)tmp;
|
|
|
|
|
|
|
|
rc = of_property_read_u32(node, "qcom,ramp-low-index", &tmp);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(chip->dev, "get qcom,ramp-low-index failed for lpg%d, rc=%d\n",
|
|
|
|
lpg_chan_id, rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
ramp->lo_idx = (u8)tmp;
|
|
|
|
if (ramp->lo_idx >= max_count) {
|
|
|
|
dev_err(chip->dev, "qcom,ramp-low-index should less than max %d\n",
|
|
|
|
max_count);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = of_property_read_u32(node, "qcom,ramp-high-index", &tmp);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(chip->dev, "get qcom,ramp-high-index failed for lpg%d, rc=%d\n",
|
|
|
|
lpg_chan_id, rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
ramp->hi_idx = (u8)tmp;
|
|
|
|
|
|
|
|
if (ramp->hi_idx > max_count) {
|
|
|
|
dev_err(chip->dev, "qcom,ramp-high-index shouldn't exceed max %d\n",
|
|
|
|
max_count);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (chip->use_sdam && ramp->hi_idx <= ramp->lo_idx) {
|
|
|
|
dev_err(chip->dev, "high-index(%d) should be larger than low-index(%d) when SDAM used\n",
|
|
|
|
ramp->hi_idx, ramp->lo_idx);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ramp->pattern_length = ramp->hi_idx - ramp->lo_idx + 1;
|
|
|
|
ramp->pattern = &chip->lut->pattern[ramp->lo_idx];
|
|
|
|
lpg->max_pattern_length = ramp->pattern_length;
|
|
|
|
|
|
|
|
ramp->pattern_repeat = of_property_read_bool(node,
|
|
|
|
"qcom,ramp-pattern-repeat");
|
|
|
|
|
2022-04-01 05:47:13 +09:00
|
|
|
ramp->pause_hi_count = 0;
|
2021-04-14 06:50:32 +09:00
|
|
|
rc = of_property_read_u32(node, "qcom,ramp-pause-hi-count", &tmp);
|
2022-04-01 05:47:13 +09:00
|
|
|
if (!rc) {
|
|
|
|
if (chip->use_sdam && tmp > SDAM_PAUSE_COUNT_MAX)
|
|
|
|
return -EINVAL;
|
|
|
|
ramp->pause_hi_count = (u8)tmp;
|
|
|
|
}
|
2021-04-14 06:50:32 +09:00
|
|
|
|
2022-04-01 05:47:13 +09:00
|
|
|
ramp->pause_lo_count = 0;
|
2021-04-14 06:50:32 +09:00
|
|
|
rc = of_property_read_u32(node, "qcom,ramp-pause-lo-count", &tmp);
|
2022-04-01 05:47:13 +09:00
|
|
|
if (!rc) {
|
|
|
|
if (chip->use_sdam && tmp > SDAM_PAUSE_COUNT_MAX)
|
|
|
|
return -EINVAL;
|
|
|
|
ramp->pause_lo_count = (u8)tmp;
|
|
|
|
}
|
2021-04-14 06:50:32 +09:00
|
|
|
|
|
|
|
if (chip->use_sdam)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
ramp->ramp_dir_low_to_hi = of_property_read_bool(node,
|
|
|
|
"qcom,ramp-from-low-to-high");
|
|
|
|
|
|
|
|
ramp->toggle = of_property_read_bool(node, "qcom,ramp-toggle");
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2020-01-29 08:09:03 +09:00
|
|
|
static int qpnp_lpg_parse_pattern_dt(struct qpnp_lpg_chip *chip,
|
|
|
|
u32 max_count)
|
2019-11-23 07:40:14 +09:00
|
|
|
{
|
|
|
|
struct device_node *child;
|
|
|
|
struct qpnp_lpg_channel *lpg;
|
|
|
|
struct lpg_ramp_config *ramp;
|
|
|
|
int rc = 0, i;
|
2020-01-29 08:09:03 +09:00
|
|
|
u32 length, lpg_chan_id, tmp;
|
2019-11-23 07:40:14 +09:00
|
|
|
|
|
|
|
chip->lut->chip = chip;
|
|
|
|
mutex_init(&chip->lut->lock);
|
|
|
|
|
|
|
|
rc = of_property_count_elems_of_size(chip->dev->of_node,
|
|
|
|
"qcom,lut-patterns", sizeof(u32));
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(chip->dev, "Read qcom,lut-patterns failed, rc=%d\n",
|
|
|
|
rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
length = rc;
|
|
|
|
if (length > max_count) {
|
|
|
|
dev_err(chip->dev, "qcom,lut-patterns length %d exceed max %d\n",
|
|
|
|
length, max_count);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
chip->lut->pattern = devm_kcalloc(chip->dev, max_count,
|
|
|
|
sizeof(*chip->lut->pattern), GFP_KERNEL);
|
|
|
|
if (!chip->lut->pattern)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
rc = of_property_read_u32_array(chip->dev->of_node, "qcom,lut-patterns",
|
|
|
|
chip->lut->pattern, length);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(chip->dev, "Get qcom,lut-patterns failed, rc=%d\n",
|
|
|
|
rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (of_get_available_child_count(chip->dev->of_node) == 0) {
|
|
|
|
dev_err(chip->dev, "No ramp configuration for any LPG\n");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
for_each_available_child_of_node(chip->dev->of_node, child) {
|
|
|
|
rc = of_property_read_u32(child, "qcom,lpg-chan-id",
|
|
|
|
&lpg_chan_id);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(chip->dev, "Get qcom,lpg-chan-id failed for node %s, rc=%d\n",
|
|
|
|
child->name, rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lpg_chan_id < 1 || lpg_chan_id > chip->num_lpgs) {
|
|
|
|
dev_err(chip->dev, "lpg-chann-id %d is out of range 1~%d\n",
|
|
|
|
lpg_chan_id, chip->num_lpgs);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2021-04-27 17:44:10 +09:00
|
|
|
if (chip->lpgs[lpg_chan_id - 1].enable_pfm) {
|
Merge keystone/android-mainline-keystone-qcom-release.6.0 (dcb3fbd) into msm-pineapple
* refs/heads/tmp-dcb3fbd:
ANDROID: GKI: Enable HCTR2
ANDROID: GKI: Change UCLAMP_BUCKETS_COUNT to 20
ANDROID: 16k target: don't write defconfig to source tree
ANDROID: GKI: Add ARM64_16K_PAGES variant
ANDROID: kleaf: add 16k variant of kernel_aarch64
Linux 6.0
i2c: davinci: fix PM disable depth imbalance in davinci_i2c_probe
dt-bindings: i2c: st,stm32-i2c: Document wakeup-source property
dt-bindings: i2c: st,stm32-i2c: Document interrupt-names property
MIPS: pci: lantiq: switch to using gpiod API
mips: allow firmware to pass RNG seed to kernel
damon/sysfs: fix possible memleak on damon_sysfs_add_target
mm: fix BUG splat with kvmalloc + GFP_ATOMIC
MAINTAINERS: drop entry to removed file in ARM/RISCPC ARCHITECTURE
drm/amdgpu/gfx11: switch to amdgpu_gfx_rlc_init_microcode
drm/amdgpu: add helper to init rlc firmware
drm/amdgpu: add helper to init rlc fw in header v2_4
drm/amdgpu: add helper to init rlc fw in header v2_3
drm/amdgpu: add helper to init rlc fw in header v2_2
drm/amdgpu: add helper to init rlc fw in header v2_1
drm/amdgpu: add helper to init rlc fw in header v2_0
drm/amdgpu: save rlcv/rlcp ucode version in amdgpu_gfx
ACPI: LPSS: Deduplicate skipping device in acpi_lpss_create_device()
ACPI: LPSS: Replace loop with first entry retrieval
BACKPORT: FROMLIST: dma-heap: Let dma heap use dma_map_attrs to map & unmap iova
Revert "pstore: migrate to crypto acomp interface"
MIPS: Simplify __bswapdi2() and __bswapsi2()
MIPS: Silence missing prototype warning
mips: update config files
KVM: selftests: Compare insn opcodes directly in fix_hypercall_test
KVM: selftests: Implement memcmp(), memcpy(), and memset() for guest use
KVM: x86: Hide IA32_PLATFORM_DCA_CAP[31:0] from the guest
KVM: selftests: Gracefully handle empty stack traces
KVM: selftests: replace assertion with warning in access_tracking_perf_test
checkpatch: warn on usage of VM_BUG_ON() and other BUG variants
coding-style.rst: document BUG() and WARN() rules ("do not crash the kernel")
Documentation: devres: add missing IO helper
Documentation: devres: update IRQ helper
Documentation/mm: modify page_referenced to folio_referenced
Documentation/CoC: Reflect current CoC interpretation and practices
docs/doc-guide: Add documentation on SPHINX_IMGMATH
docs: process/5.Posting.rst: clarify use of Reported-by: tag
docs, kprobes: Fix the wrong location of Kprobes
drm/amdgpu: Enable sram on vcn_4_0_2
drm/amdgpu: Enable VCN DPG for GC11_0_1
perf build: Fixup disabling of -Wdeprecated-declarations for the python scripting engine
docs: add a man-pages link to the front page
docs: put atomic*.txt and memory-barriers.txt into the core-api book
docs: move asm-annotations.rst into core-api
docs: remove some index.rst cruft
docs: reconfigure the HTML left column
docs: Rewrite the front page
docs: promote the title of process/index.rst
perf tests mmap-basic: Remove unused variable to address clang 15 warning
perf parse-events: Ignore clang 15 warning about variable set but unused in bison produced code
drm/amd/display: Prevent OTG shutdown during PSR SU
perf tests record: Fail the test if the 'errs' counter is not zero
perf test: Fix test case 87 ("perf record tests") for hybrid systems
ANDROID: timer: Add vendor hook for timer calc index
LoongArch: Clean up loongson3_smp_ops declaration
LoongArch: Fix and cleanup csr_era handling in do_ri()
LoongArch: Align the address of kernel_entry to 4KB
mptcp: fix unreleased socket in accept queue
mptcp: factor out __mptcp_close() without socket lock
net: ethernet: mtk_eth_soc: fix mask of RX_DMA_GET_SPORT{,_V2}
net: mscc: ocelot: fix tagged VLAN refusal while under a VLAN-unaware bridge
clk: imx93: drop of_match_ptr
clk: iproc: Do not rely on node name for correct PLL setup
io_uring/poll: disable level triggered poll
clk: sunxi-ng: h6: Fix default PLL GPU rate
drm/i915/gt: Perf_limit_reasons are only available for Gen11+
clk: imx: imx6sx: remove the SET_RATE_PARENT flag for QSPI clocks
m68k: Rework BI_VIRT_RNG_SEED as BI_RNG_SEED
m68k: Process bootinfo records before saving them
ACPI: x86: s2idle: Add another ID to s2idle_dmi_table
ACPI: x86: s2idle: Fix a NULL pointer dereference
[coredump] don't use __kernel_write() on kmap_local_page()
x86/cacheinfo: Add a cpu_llc_shared_mask() UP variant
Revert "net: set proper memcg for net_init hooks allocations"
MAINTAINERS: Drop records pointing to 01.org/linux-acpi
ACPI: Kconfig: Drop link to https://01.org/linux-acpi
ACPI: docs: Drop useless DSDT override documentation
ACPI: DPTF: Drop stale link from Kconfig help
perf arm-spe: augment the data source type with neoverse_spe list
perf tests vmlinux-kallsyms: Update is_ignored_symbol function to match the kernel ignored list
ata: libata-sata: Fix device queue depth control
ata: libata-scsi: Fix initialization of device queue depth
can: c_can: don't cache TX messages for C_CAN cores
vdpa/mlx5: Fix MQ to support non power of two num queues
vduse: prevent uninitialized memory accesses
virtio-blk: Fix WARN_ON_ONCE in virtio_queue_rq()
virtio_test: fixup for vq reset
virtio-crypto: fix memory-leak
vdpa/ifcvf: fix the calculation of queuepair
drm/amdgpu: Add amdgpu suspend-resume code path under SRIOV
drm/amdgpu: Remove fence_process in count_emitted
drm/amdgpu: Correct the position in patch_cond_exec
drm/amd/display: fill in clock values when DPM is not enabled
drm/amd/display: Avoid unnecessary pixel rate divider programming
drm/amd/display: Remove assert for odm transition case
drm/amd/display: Fix typo in get_pixel_rate_div
drm/amd/display: Fix audio on display after unplugging another
drm/amd/display: Add explicit FIFO disable for DP blank
drm/amd/display: Wrap OTG disable workaround with FIFO control
drm/amd/display: Do DIO FIFO enable after DP video stream enable
drm/amd/display: Update DCN32 to use new SR latencies
drm/amd/display: Avoid avoid unnecessary pixel rate divider programming
drm/amdkfd: fix dropped interrupt in kfd_int_process_v11
drm/amdgpu: pass queue size and is_aql_queue to MES
drm/amdkfd: fix MQD init for GFX11 in init_mqd
drm/amd/pm: use adverse selection for dpm features unsupported by driver
drm/amd/pm: enable gfxoff feature for SMU 13.0.0
drm/amdgpu: avoid gfx register accessing during gfxoff
x86/alternative: Fix race in try_get_desc()
MIPS: Lantiq: vmmc: fix compile break introduced by gpiod patch
Documentation: devres: add missing SPI helper
Documentation: devres: add missing PINCTRL helpers
docs: hugetlbpage.rst: fix a typo of hugepage size
docs/zh_CN: Add new translation of admin-guide/bootconfig.rst
docs/zh_CN: Update zh_CN/admin-guide/README.rst to 6.0-rc2
docs/zh_CN: core-api: Add packing Chinese translation
docs/zh_CN: core-api: Add generic-radix-tree Chinese translation
docs/zh_CN: core-api: Add circular-buffers Chinese translation
docs/zh_CN: core-api: Add idr Chinese translation
docs: x86: replace do_IRQ int the entry_64.rst with common_interrupt()
usb: chipidea: clarify Documentation/ABI text
Documentation: W1: minor typo corrections
Documentation: fb: udlfb: clean up text and formatting
docs/core-api: expand Fedora instructions for GCC plugins
Documentation: spufs: correct a duplicate word typo
docs/zh_CN: Update zh_CN/process/coding-style.rst to 6.0-rc2
Documentation/hw-vuln: Update spectre doc
Documentation: filesystems: correct possessive "its"
Documentation: stable: Document alternative for referring upstream commit hash
docs: update mediator information in CoC docs
docs/zh_CN: add dt kernel-api translation
docs/zh_CN: add dt overlay-notes translation
docs/zh_CN: add dt dynamic-resolution-notes translation
docs/zh_CN: add dt changesets translation
docs/zh_CN: add PCI acpi-info translation
Documentation: process/submitting-patches: misspelling "mesages"
Delete duplicate words from kernel docs
docs: admin-guide: for kernel bugs refer to other kernel documentation
docs: admin-guide: do not mention the 'run a.out user programs' feature
Documentation/ABI: correct possessive "its" typos
Remove duplicate words inside documentation
docs/conf.py: Respect env variable SPHINX_IMGMATH
docs/conf.py: Treat mathjax as fallback math renderer
docs/zh_CN: Update zh_CN/process/submit-checklist.rst to 6.0-rc2
docs: scheduler: Update new path for the sysctl knobs
docs/zh_TW: Remove oops-tracing
docs/zh_CN: Remove IRQ and oops-tracing
docs/zh_CN: Update the translation of io_ordering to 6.0-rc2
Documentation: ext4: correct the document about superblock
Documentation: filesystems: xfs: update pseudocode and typo fixes
docs/zh_CN: Fix two missing labels in zh_CN/process
docs/zh_CN: Update zh_CN/process/submitting-patches.rst to 5.19
docs/zh_CN: Update zh_CN/process/email-clients.rst to 5.19
ANDROID: dma/debug: fix warning of check_sync
ice: xsk: drop power of 2 ring size restriction for AF_XDP
ice: xsk: change batched Tx descriptor cleaning
net: usb: qmi_wwan: Add new usb-id for Dell branded EM7455
Input: snvs_pwrkey - fix SNVS_HPVIDR1 register address
KVM: selftests: Skip tests that require EPT when it is not available
mmc: hsq: Fix data stomping during mmc recovery
selftests: Fix the if conditions of in test_extra_filter()
uas: ignore UAS for Thinkplus chips
usb-storage: Add Hiksemi USB3-FW to IGNORE_UAS
uas: add no-uas quirk for Hiksemi usb_disk
usb: dwc3: st: Fix node's child name
usb: typec: ucsi: Remove incorrect warning
net: phy: Don't WARN for PHY_UP state in mdio_bus_phy_resume()
net: stmmac: power up/down serdes in stmmac_open/release
wifi: mac80211: mlme: Fix double unlock on assoc success handling
wifi: mac80211: mlme: Fix missing unlock on beacon RX
wifi: mac80211: fix memory corruption in minstrel_ht_update_rates()
wifi: mac80211: fix regression with non-QoS drivers
wifi: mac80211: ensure vif queues are operational after start
wifi: mac80211: don't start TX with fq->lock to fix deadlock
wifi: cfg80211: fix MCS divisor value
media: rkvdec: Disable H.264 error detection
media: mediatek: vcodec: Drop platform_get_resource(IORESOURCE_IRQ)
media: dvb_vb2: fix possible out of bound access
media: v4l2-ioctl.c: fix incorrect error path
media: v4l2-compat-ioctl32.c: zero buffer passed to v4l2_compat_get_array_args()
nvme-pci: disable Write Zeroes on Phison E3C/E4C
nvme: Fix IOC_PR_CLEAR and IOC_PR_RELEASE ioctls for nvme devices
libata: add ATA_HORKAGE_NOLPM for Pioneer BDR-207M and BDR-205
ARM: dts: integrator: Fix DMA ranges
net: hippi: Add missing pci_disable_device() in rr_init_one()
net/mlxbf_gige: Fix an IS_ERR() vs NULL bug in mlxbf_gige_mdio_probe
cxgb4: fix missing unlock on ETHOFLD desc collect fail path
net: sched: act_ct: fix possible refcount leak in tcf_ct_init()
x86/uaccess: avoid check_object_size() in copy_from_user_nmi()
mm/page_isolation: fix isolate_single_pageblock() isolation behavior
mm,hwpoison: check mm when killing accessing process
mm/hugetlb: correct demote page offset logic
mm: prevent page_frag_alloc() from corrupting the memory
mm: bring back update_mmu_cache() to finish_fault()
frontswap: don't call ->init if no ops are registered
mm/huge_memory: use pfn_to_online_page() in split_huge_pages_all()
mm: fix madivse_pageout mishandling on non-LRU page
powerpc/64s/radix: don't need to broadcast IPI for radix pmd collapse flush
mm: gup: fix the fast GUP race against THP collapse
usbnet: Fix memory leak in usbnet_disconnect()
io_uring: register single issuer task at creation
ext4: fixup possible uninitialized variable access in ext4_mb_choose_next_group_cr1()
Revert "net: mvpp2: debugfs: fix memory leak when using debugfs_lookup()"
drm/i915/gt: Restrict forced preemption to the active context
perf tests powerpc: Fix branch stack sampling test to include sanity check for branch filter
perf parse-events: Remove "not supported" hybrid cache events
perf print-events: Fix "perf list" can not display the PMU prefix for some hybrid cache events
perf tools: Get a perf cgroup more portably in BPF
cpufreq: qcom-cpufreq-hw: Add cpufreq qos for LMh
gpio: mvebu: Fix check for pwm support on non-A8K platforms
cpufreq: Add __init annotation to module init funcs
cpufreq: tegra194: change tegra239_cpufreq_soc to static
Linux 6.0-rc7
PM / devfreq: rockchip-dfi: Fix an error message
PM / devfreq: mtk-cci: Handle sram regulator probe deferral
ACPI: x86: s2idle: Add a quirk for ASUSTeK COMPUTER INC. ROG Flow X13
ACPI: x86: s2idle: Add a quirk for Lenovo Slim 7 Pro 14ARH7
ACPI: x86: s2idle: Add a quirk for ASUS ROG Zephyrus G14
ACPI: x86: s2idle: Add a quirk for ASUS TUF Gaming A17 FA707RE
ACPI: x86: s2idle: Add module parameter to prefer Microsoft GUID
ACPI: x86: s2idle: If a new AMD _HID is missing assume Rembrandt
ACPI: x86: s2idle: Move _HID handling for AMD systems into structures
Input: synaptics - disable Intertouch for Lenovo T14 and P14s AMD G1
Input: iqs62x-keys - drop unused device node references
Input: melfas_mip4 - fix return value check in mip4_probe()
devdax: Fix soft-reservation memory description
powercap: intel_rapl: Use standard Energy Unit for SPR Dram RAPL domain
PM: runtime: Return -EINPROGRESS from rpm_resume() in the RPM_NOWAIT case
platform/x86: int3472: Add board data for Surface Go2 IR camera
platform/x86: int3472: Support multiple gpio lookups in board data
platform/x86: int3472: Support multiple clock consumers
ACPI: bus: Add iterator for dependent devices
ACPI: scan: Add acpi_dev_get_next_consumer_dev()
ACPI: resource: Add ASUS model S5402ZA to quirks
ACPI: AMBA: Add ARM DMA-330 controller to the supported list
ACPI: APEI: Remove unneeded result variables
ACPI: fan: Reorder symbols to get rid of a few forward declarations
ACPI: CPPC: Disable FIE if registers in PCC regions
LoongArch: Use acpi_arch_dma_setup() and remove ARCH_HAS_PHYS_TO_DMA
ACPI: scan: Support multiple DMA windows with different offsets
ACPI: AC: Remove the leftover struct acpi_ac_bl
ACPI: x86: Add a quirk for Dell Inspiron 14 2-in-1 for StorageD3Enable
PNPBIOS: remove unused pnpid32_to_pnpid() declaration
MIPS: IRQ: remove orphan allocate_irqno() declaration
MIPS: remove orphan sb1250_time_init() declaration
MIPS: Lantiq: switch vmmc to use gpiod API
MIPS: lantiq: enable all hardware interrupts on second VPE
sfc: correct filter_table_remove method for EF10 PFs
Makefile.debug: re-enable debug info for .S files
Makefile.debug: set -g unconditional on CONFIG_DEBUG_INFO_SPLIT
io_uring: ensure that cached task references are always put on exit
ACPI: processor idle: Practically limit "Dummy wait" workaround to old Intel systems
ANDROID: GKI: Build-in REGMAP_SPMI
certs: make system keyring depend on built-in x509 parser
Kconfig: remove unused function 'menu_get_root_menu'
scripts/clang-tools: remove unused module
ANDROID: GKI: x86: Enable CONFIG_SPMI
cgroup: cgroup_get_from_id() must check the looked-up kn is a directory
ARM: dts: integrator: Tag PCI host with device_type
Revert "drm: bridge: analogix/dp: add panel prepare/unprepare in suspend/resume time"
net: mt7531: ensure all MACs are powered down before reset
net: mt7531: only do PLL once after the reset
MAINTAINERS: rectify file entry in TEAM DRIVER
vmlinux.lds.h: CFI: Reduce alignment of jump-table to function alignment
ARM: sunplus: fix serial console kconfig and build problems
net: macb: Fix ZynqMP SGMII non-wakeup source resume failure
tun: support not enabling carrier in TUNSETIFF
drm/bridge: lt8912b: fix corrupted image output
drm/bridge: lt8912b: set hdmi or dvi mode
drm/bridge: lt8912b: add vsync hsync
Revert "firmware: arm_scmi: Add clock management to the SCMI power domain"
MAINTAINERS: switch graphics to airlied other addresses
KVM: x86: Inject #UD on emulated XSETBV if XSAVES isn't enabled
KVM: x86: Always enable legacy FP/SSE in allowed user XFEATURES
KVM: x86: Reinstate kvm_vcpu_arch.guest_supported_xcr0
KVM: x86/mmu: add missing update to max_mmu_rmap_size
selftests: kvm: Fix a compile error in selftests/kvm/rseq_test.c
mm: slub: fix flush_cpu_slab()/__free_slab() invocations in task context.
ACPI: PCI: Rework acpi_get_pci_dev()
ACPI: PCC: Fix Tx acknowledge in the PCC address space handler
ACPI: PCC: replace wait_for_completion()
ACPI: PCC: Release resources on address space setup failure path
ACPI: HMAT: Drop unused dev_fmt() and redundant 'HMAT' prefix
reset: npcm: fix iprst2 and iprst4 setting
ext4: limit the number of retries after discarding preallocations blocks
ext4: fix bug in extents parsing when eh_entries == 0 and eh_depth > 0
serial: sifive: enable clocks for UART when probed
serial: 8250: omap: Use serial8250_em485_supported
serial: fsl_lpuart: Reset prior to registration
selftests: forwarding: add shebang for sch_red.sh
bnxt: prevent skb UAF after handing over to PTP worker
net: marvell: Fix refcounting bugs in prestera_port_sfp_bind()
net: sched: fix possible refcount leak in tc_new_tfilter()
net: sunhme: Fix packet reception for len < RX_COPY_THRESHOLD
udp: Use WARN_ON_ONCE() in udp_read_skb()
selftests: bonding: cause oops in bond_rr_gen_slave_id
bonding: fix NULL deref in bond_rr_gen_slave_id
net: phy: micrel: fix shared interrupt on LAN8814
perf/arm-cmn: Add more bits to child node address offset field
usb: typec: anx7411: Fix build error without CONFIG_POWER_SUPPLY
ANDROID: Enable BUILD_GKI_CERTIFICATION_TOOLS for x86_64 GKI
counter: 104-quad-8: Fix skipped IRQ lines during events configuration
arm64: topology: fix possible overflow in amu_fie_setup()
arm64: mm: don't acquire mutex when rewriting swapper
ALSA: hda: intel-dsp-config: add missing RaptorLake PCI IDs
thunderbolt: Explicitly reset plug events delay back to USB4 spec value
drivers/base: Fix unsigned comparison to -1 in CPUMAP_FILE_MAX_BYTES
net/smc: Stop the CLC flow if no link to map buffers on
media: flexcop-usb: fix endpoint type check
efi: libstub: check Shim mode using MokSBStateRT
efi: x86: Wipe setup_data on pure EFI boot
ARM: 9247/1: mm: set readonly for MT_MEMORY_RO with ARM_LPAE
ARM: 9244/1: dump: Fix wrong pg_level in walk_pmd()
ARM: 9243/1: riscpc: Unbreak the build
ext4: use buckets for cr 1 block scan instead of rbtree
ext4: use locality group preallocation for small closed files
ext4: make directory inode spreading reflect flexbg size
ext4: avoid unnecessary spreading of allocations among groups
ext4: make mballoc try target group first even with mb_optimize_scan
ice: Fix ice_xdp_xmit() when XDP TX queue number is not sufficient
drm/mediatek: dsi: Move mtk_dsi_stop() call back to mtk_dsi_poweroff()
drm/amd/display: Reduce number of arguments of dml314's CalculateFlipSchedule()
drm/amd/display: Reduce number of arguments of dml314's CalculateWatermarksAndDRAMSpeedChangeSupport()
drm/amdgpu: don't register a dirty callback for non-atomic
drm/amd/pm: drop the pptable related workarounds for SMU 13.0.0
drm/amd/pm: add support for 3794 pptable for SMU13.0.0
drm/amd/display: correct num_dsc based on HW cap
drm/amd/display: Disable OTG WA for the plane_state NULL case on DCN314
drm/amd/display: Add shift and mask for ICH_RESET_AT_END_OF_LINE
drm/amd/display: increase dcn315 pstate change latency
drm/amd/display: Fix DP MST timeslot issue when fallback happened
drm/amd/display: Display distortion after hotplug 5K tiled display
drm/amd/display: Update dummy P-state search to use DCN32 DML
drm/amd/display: skip audio setup when audio stream is enabled
drm/amd/display: update gamut remap if plane has changed
drm/amd/display: Assume an LTTPR is always present on fixed_vs links
drm/amd/display: fix dcn315 memory channel count and width read
drm/amd/display: Fix double cursor on non-video RGB MPO
drm/amd/display: Only consider pixle rate div policy for DCN32+
drm/amd/display: Port DCN30 420 logic to DCN32
drm/amdgpu: Update PTE flags with TF enabled
s390/vfio-ap: bypass unnecessary processing of AP resources
i2c: mux: harden i2c_mux_alloc() against integer overflows
ANDROID: selftests: incfs: Increase timeout in concurrent_reads_and_writes_test
i2c: mlxbf: Fix frequency calculation
perf tools: Honor namespace when synthesizing build-ids
tools headers cpufeatures: Sync with the kernel sources
perf kcore_copy: Do not check /proc/modules is unchanged
libperf evlist: Fix polling of system-wide events
perf record: Fix cpu mask bit setting for mixed mmaps
perf test: Skip wp modify test on old kernels
intel_idle: Add AlderLake-N support
powercap: intel_rapl: fix UBSAN shift-out-of-bounds issue
KVM: s390: pci: register pci hooks without interpretation
KVM: s390: pci: fix GAIT physical vs virtual pointers usage
KVM: s390: Pass initialized arg even if unused
KVM: s390: pci: fix plain integer as NULL pointer warnings
perf jit: Include program header in ELF files
perf test: Add a new test for perf stat cgroup BPF counter
perf stat: Use evsel->core.cpus to iterate cpus in BPF cgroup counters
perf stat: Fix cpu map index in bperf cgroup code
perf stat: Fix BPF program section name
mmc: core: Terminate infinite loop in SD-UHS voltage switch
net: atlantic: fix potential memory leak in aq_ndev_close()
iommu/vt-d: Check correct capability for sagaw determination
Revert "iommu/vt-d: Fix possible recursive locking in intel_iommu_init()"
can: gs_usb: gs_usb_set_phys_id(): return with error if identify is not supported
can: gs_usb: gs_can_open(): fix race dev->can.state condition
can: flexcan: flexcan_mailbox_read() fix return value for drop = true
gpiolib: cdev: Set lineevent_state::irq after IRQ register successfully
gpio: tqmx86: fix uninitialized variable girq
cpufreq: tegra194: Add support for Tegra239
cpufreq: qcom-cpufreq-hw: Fix uninitialized throttled_freq warning
arch: um: Mark the stack non-executable to fix a binutils warning
ANDROID: [GKI] Include ioremap_guard in cmdline arg
ANDROID: [GKI] Include bootconfig in CONFIG_CMDLINE
ANDROID: incfs: Add check for ATTR_KILL_SUID and ATTR_MODE in incfs_setattr
ANDROID: GKI: vendor code needs __balance_callbacks access
ANDROID: topology: Add a flag to indicate topology has been updated
ANDROID: arch_topology: Add vendor hook
ANDROID: Sched: Add vendor hooks in scheduler
ANDROID: arm64: Export system_32bit_el0_cpumask symbol
ANDROID: arch_topology: Export thermal pressure symbol
ANDROID: sched: add hook point in do_sched_yield()
ANDROID: sched: Add flags parameter to enq/deq after tracehooks
ANDROID: sched: vendor hook for sched_getaffinity
ANDROID: sched: core: hook for get_nohz_timer_target
ANDROID: kernel: sched: tracehook for is_cpu_allowed
ANDROID: sched: add hook to rto_next_cpu
ANDROID: sched: allow access to critical common code for CPU Pause
ANDROID: sched: support pick_migrate_task in common kernel
ANDROID: Sched: Add restricted vendor hooks for scheduler
net: sh_eth: Fix PHY state warning splat during system resume
net: ravb: Fix PHY state warning splat during system resume
netfilter: nf_ct_ftp: fix deadlock when nat rewrite is needed
netfilter: ebtables: fix memory leak when blob is malformed
netfilter: nf_tables: fix percpu memory leak at nf_tables_addchain()
netfilter: nf_tables: fix nft_counters_enabled underflow at nf_tables_addchain()
netfilter: conntrack: remove nf_conntrack_helper documentation
MAINTAINERS: Add myself as a reviewer for Qualcomm ETHQOS Ethernet driver
ice: Fix interface being down after reset with link-down-on-close flag on
ice: config netdev tc before setting queues number
net/sched: taprio: make qdisc_leaf() see the per-netdev-queue pfifo child qdiscs
net/sched: taprio: avoid disabling offload when it was never enabled
ipv6: Fix crash when IPv6 is administratively disabled
net: enetc: deny offload of tc-based TSN features on VF interfaces
net: enetc: move enetc_set_psfp() out of the common enetc_set_features()
wireguard: netlink: avoid variable-sized memcpy on sockaddr
wireguard: selftests: do not install headers on UML
wireguard: ratelimiter: disable timings test by default
sfc/siena: fix null pointer dereference in efx_hard_start_xmit
sfc/siena: fix TX channel offset when using legacy interrupts
efi: efibc: Guard against allocation failure
net: clear msg_get_inq in __get_compat_msghdr()
selftests: forwarding: Add test cases for unresolved multicast routes
ipmr: Always call ip{,6}_mr_forward() from RCU read-side critical section
net: ipa: properly limit modem routing table use
of: mdio: Add of_node_put() when breaking out of for_each_xx
drm/i915/gem: Really move i915_gem_context.link under ref protection
drm/i915/gem: Flush contexts on driver release
Revert "block: freeze the queue earlier in del_gendisk"
gpio: ftgpio010: Make irqchip immutable
gpio: mockup: Fix potential resource leakage when register a chip
gpio: mockup: fix NULL pointer dereference when removing debugfs
tcp: read multiple skbs in tcp_read_skb()
Revert "ALSA: usb-audio: Split endpoint setups for hw_params and prepare"
Revert "net: fec: Use a spinlock to guard `fep->ptp_clk_on`"
Revert "fec: Restart PPS after link state change"
net: dsa: microchip: lan937x: fix maximum frame length check
open: always initialize ownership fields
drm/hisilicon: Add depends on MMU
drm/mgag200: Force 32 bpp on the console
gve: Fix GFP flags when allocing pages
bnxt_en: fix flags to check for supported fw version
sfc: fix null pointer dereference in efx_hard_start_xmit
sfc: fix TX channel offset when using legacy interrupts
net: ethernet: mtk_eth_soc: enable XDP support just for MT7986 SoC
net: mana: Add rmb after checking owner bits
MAINTAINERS: gve: update developers
netdevsim: Fix hwstats debugfs file permissions
i40e: Fix set max_tx_rate when it is lower than 1 Mbps
i40e: Fix VF set max MTU size
iavf: Fix set max MTU size with port VLAN and jumbo frames
mlxbf_gige: clear MDIO gateway lock after read
iavf: Fix bad page state
um: Prevent KASAN splats in dump_stack()
um: fix default console kernel parameter
um: Cleanup compiler warning in arch/x86/um/tls_32.c
um: Cleanup syscall_handler_t cast in syscalls_32.h
ASoC: tas2770: Reinit regcache on reset
ASoC: nau8824: Fix semaphore is released unexpectedly
KVM: arm64: Use kmemleak_free_part_phys() to unregister hyp_mem_base
efi/dev-path-parser: Refactor _UID handling to use acpi_dev_uid_to_integer()
spi: pxa2xx: Refactor _UID handling to use acpi_dev_uid_to_integer()
perf: qcom_l2_pmu: Refactor _UID handling to use acpi_dev_uid_to_integer()
i2c: mlxbf: Refactor _UID handling to use acpi_dev_uid_to_integer()
i2c: amd-mp2-plat: Refactor _UID handling to use acpi_dev_uid_to_integer()
ACPI: x86: Refactor _UID handling to use acpi_dev_uid_to_integer()
ACPI: LPSS: Refactor _UID handling to use acpi_dev_uid_to_integer()
ACPI: utils: Add acpi_dev_uid_to_integer() helper to get _UID as integer
s390/dasd: fix Oops in dasd_alias_get_start_dev due to missing pavgroup
MIPS: BCM47XX: Cast memcmp() of function to (void *)
ASoC: Intel: sof_sdw: add support for Dell SKU 0AFF
mips: ralink: convert to DEFINE_SHOW_ATTRIBUTE
mips: kernel: convert to DEFINE_SHOW_ATTRIBUTE
mips: cavium: convert to DEFINE_SHOW_ATTRIBUTE
MIPS: AR7: remove orphan declarations from arch/mips/include/asm/mach-ar7/ar7.h
MIPS: remove orphan sni_cpu_time_init() declaration
MIPS: IRQ: remove orphan declarations from arch/mips/include/asm/irq.h
MIPS: Octeon: remove orphan octeon_hal_setup_reserved32() declaration
MIPS: Octeon: remove orphan cvmx_fpa_setup_pool() declaration
MIPS: Octeon: remove orphan octeon_swiotlb declaration
MIPS: Loongson2ef: remove orphan sbx00_acpi_init() declaration
mips: bmips: bcm63268: add TWD block binding
MIPS: SGI-IP27: Fix platform-device leak in bridge_platform_create()
MIPS: SGI-IP30: Fix platform-device leak in bridge_platform_create()
MIPS: Loongson32: Fix PHY-mode being left unspecified
MIPS: lantiq: export clk_get_io() for lantiq_wdt.ko
mm/slab_common: fix possible double free of kmem_cache
ALSA: core: Fix double-free at snd_card_new()
m68k: defconfig: Update defconfigs for v6.0-rc2
m68k: Allow kexec on M68KCLASSIC with MMU enabled only
m68k: Move from strlcpy with unused retval to strscpy
ALSA: hda/realtek: Add a quirk for HP OMEN 16 (8902) mute LED
fpga: m10bmc-sec: Fix possible memory leak of flash_buf
drm/panel: simple: Fix innolux_g121i1_l01 bus_format
Linux 6.0-rc6
io_uring/opdef: rename SENDZC_NOTIF to SEND_ZC
io_uring/net: fix zc fixed buf lifetime
i2c: mlxbf: prevent stack overflow in mlxbf_i2c_smbus_start_transaction()
i2c: mlxbf: incorrect base address passed during io write
RISC-V: Avoid coupling the T-Head CMOs and Zicbom
riscv: fix a nasty sigreturn bug...
riscv: make t-head erratas depend on MMU
riscv: fix RISCV_ISA_SVPBMT kconfig dependency warning
kasan: call kasan_malloc() from __kmalloc_*track_caller()
Documentation: i2c: fix references to other documents
MAINTAINERS: remove Nehal Shah from AMD MP2 I2C DRIVER
i2c: imx: If pm_runtime_get_sync() returned 1 device access is possible
arm64: dts: qcom: sm8350: fix UFS PHY serdes size
tcp: Use WARN_ON_ONCE() in tcp_read_skb()
ALSA: hda/hdmi: Fix the converter reuse for the silent stream
net: Add tests for bonding and team address list management
net: team: Unsync device addresses on ndo_stop
net: bonding: Unsync device addresses on ndo_stop
net: bonding: Share lacpdu_mcast_addr definition
net: marvell: prestera: add support for for Aldrin2
net/ieee802154: fix uninit value bug in dgram_sendmsg
irqchip/loongson-pch-lpc: Add dependence on LoongArch
xen/xenbus: fix xenbus_setup_ring()
scsi: mpt3sas: Fix return value check of dma_get_required_mask()
scsi: qla2xxx: Fix memory leak in __qlt_24xx_handle_abts()
scsi: qedf: Fix a UAF bug in __qedf_probe()
soc: bcm: brcmstb: biuctrl: Avoid double of_node_put()
io_uring/msg_ring: check file type before putting
ALSA: hda/realtek: Add quirk for ASUS GA503R laptop
ALSA: hda/realtek: Add pincfg for ASUS G533Z HP jack
ALSA: hda/realtek: Add pincfg for ASUS G513 HP jack
ALSA: hda/realtek: Re-arrange quirk table entries
ALSA: hda/realtek: Enable 4-speaker output Dell Precision 5530 laptop
Revert "driver core: Set fw_devlink.strict=1 by default"
blk-lib: fix blkdev_issue_secure_erase
parisc: Allow CONFIG_64BIT with ARCH=parisc
parisc: remove obsolete manual allocation aligning in iosapic
drm/amdgpu/mes: zero the sdma_hqd_mask of 2nd SDMA engine for SDMA 6.0.1
drm/amdgpu: make sure to init common IP before gmc
drm/amdgpu: move nbio sdma_doorbell_range() into sdma code for vega
drm/amdgpu: move nbio ih_doorbell_range() into ih code for vega
arm64: dts: qcom: sc8280xp-x13s: Update firmware location
selftests/landlock: Fix out-of-tree builds
pinctrl: ocelot: Fix interrupt controller
gpio: mt7621: Make the irqchip immutable
mmc: moxart: fix 4-bit bus width and remove 8-bit bus width
mmc: sdhci: Fix host->cmd is null
ALSA: hda/realtek: Enable 4-speaker output Dell Precision 5570 laptop
cifs: update internal module number
cifs: add missing spinlock around tcon refcount
drm/rockchip: Fix return type of cdn_dp_connector_mode_valid
clk: microchip: mpfs: make the rtc's ahb clock critical
clk: microchip: mpfs: fix clk_cfg array bounds violation
cifs: always initialize struct msghdr smb_msg completely
cifs: don't send down the destination address to sendmsg for a SOCK_STREAM
arm64: dts: imx8mp-venice-gw74xx: fix port/phy validation
block: blk_queue_enter() / __bio_queue_enter() must return -EAGAIN for nowait
drm/amd/display: Mark dml30's UseMinimumDCFCLK() as noinline for stack usage
drm/amd/display: Reduce number of arguments of dml31's CalculateFlipSchedule()
drm/amd/display: Reduce number of arguments of dml31's CalculateWatermarksAndDRAMSpeedChangeSupport()
drm/amd/display: Reduce number of arguments of dml32_CalculatePrefetchSchedule()
drm/amd/display: Reduce number of arguments of dml32_CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport()
drm/amd/display: Refactor SubVP calculation to remove FPU
drm/amd/display: Limit user regamma to a valid value
drm/amd/display: add workaround for subvp cursor corruption for DCN32/321
drm/amd/display: SW cursor fallback for SubVP
drm/amd/display: Round cursor width up for MALL allocation
drm/amd/display: Correct dram channel width for dcn314
drm/amd/display: Relax swizzle checks for video non-RGB formats on DCN314
drm/amd/display: Hook up DCN314 specific dml implementation
drm/amd/display: Enable dlg and vba compilation for dcn314
drm/amd/display: Fix compilation errors on DCN314
drm/amd/display: Fix divide by zero in DML
drm/amd/display: Fixing DIG FIFO Error
drm/amd/display: Update MBLK calculation for SubVP
drm/amd/display: Revert "Fallback to SW cursor if SubVP + cursor too big"
drm/amdgpu: Skip reset error status for psp v13_0_0
drm/amdgpu: add HDP remap functionality to nbio 7.7
drm/amdgpu: change the alignment size of TMR BO to 1M
drm/amdgpu: Enable full reset when RAS is supported on gc v11_0_0
drm/amdgpu: use dirty framebuffer helper
drm/amdgpu: Don't enable LTR if not supported
drm/amd/pm: disable BACO entry/exit completely on several sienna cichlid cards
Revert "fs/exec: allow to unshare a time namespace on vfork+exec"
Revert "selftests/timens: add a test for vfork+exit"
dt-bindings: pinctrl: qcom: drop non-working codeaurora.org emails
dt-bindings: power: qcom,rpmpd: drop non-working codeaurora.org emails
gpio: ixp4xx: Make irqchip immutable
MAINTAINERS: Update HiSilicon GPIO Driver maintainer
io_uring/rw: fix error'ed retry return values
dt-bindings: apple,aic: Fix required item "apple,fiq-index" in affinity description
USB: serial: option: add Quectel RM520N
USB: serial: option: add Quectel BG95 0x0203 composition
btrfs: zoned: wait for extent buffer IOs before finishing a zone
btrfs: fix hang during unmount when stopping a space reclaim worker
btrfs: fix hang during unmount when stopping block group reclaim worker
tools/include/uapi: Fix <asm/errno.h> for parisc and xtensa
Input: hp_sdc: fix spelling typo in comment
ASoC: imx-card: Fix refcount issue with of_node_put
RISC-V: Clean up the Zicbom block size probing
Documentation: mptcp: fix pm_type formatting
mptcp: fix fwd memory accounting on coalesce
net: phy: aquantia: wait for the suspend/resume operations to finish
ALSA: hda: Fix Nvidia dp infoframe
ARM: dts: lan966x: Fix the interrupt number for internal PHYs
parisc: ccio-dma: Add missing iounmap in error path in ccio_probe()
ALSA: hda/realtek: Add quirk for Huawei WRT-WX9
ALSA: hda/tegra: set depop delay for tegra
ALSA: hda: add Intel 5 Series / 3400 PCI DID
nfsd_splice_actor(): handle compound pages
arm64: dts: imx8mp-venice-gw74xx: fix ksz9477 cpu port
arm64: dts: imx8mp-venice-gw74xx: fix CAN STBY polarity
drm/mediatek: Fix wrong dither settings
cifs: revalidate mapping when doing direct writes
irqchip: Select downstream irqchip drivers for LoongArch CPU
irqchip/gic-v3-its: Remove cpumask_var_t allocation
irqchip/stm32-exti: Remove check on always false condition
dt-bindings: memory-controllers: fsl,imx8m-ddrc: drop Leonard Crestez
Revert "drm/i915/display: Re-add check for low voltage sku for max dp source rate"
drm/i915/gt: Fix perf limit reasons bit positions
drm/i915/guc: Cancel GuC engine busyness worker synchronously
drm/i915: Set correct domains values at _i915_vma_move_to_active
drm/i915/vdsc: Set VDSC PIC_HEIGHT before using for DP DSC
MIPS: dts: lantiq: rename dts files with soc name being the prefix
MIPS: Fix comments typo
MIPS: ath25: clean up non-kernel-doc comment warning
MIPS: move from strlcpy with unused retval to strscpy
MIPS: Fix comment typo
arm64: dts: tqma8mqml: Include phy-imx8-pcie.h header
wifi: mt76: fix 5 GHz connection regression on mt76x0/mt76x2
wifi: mt76: fix reading current per-tid starting sequence number for aggregation
wifi: iwlwifi: Mark IWLMEI as broken
arm64: defconfig: enable ARCH_NXP
arm64: dts: imx8mp-tqma8mpql-mba8mpxl: add missing pinctrl for RTC alarm
ASoC: rt5640: Fix the issue of the abnormal JD2 status
mm: fix dereferencing possible ERR_PTR
vmscan: check folio_test_private(), not folio_get_private()
mm: fix VM_BUG_ON in __delete_from_swap_cache()
tools: fix compilation after gfp_types.h split
mm/damon/dbgfs: fix memory leak when using debugfs_lookup()
mm/migrate_device.c: copy pte dirty bit to page
mm/migrate_device.c: add missing flush_cache_page()
mm/migrate_device.c: flush TLB while holding PTL
x86/mm: disable instrumentations of mm/pgprot.c
mm/memory-failure: fall back to vma_address() when ->notify_failure() fails
mm/memory-failure: fix detection of memory_failure() handlers
xfs: fix SB_BORN check in xfs_dax_notify_failure()
xfs: quiet notify_failure EOPNOTSUPP cases
mm/page_alloc: fix race condition between build_all_zonelists and page allocation
ntfs: fix BUG_ON in ntfs_lookup_inode_by_name()
Linux 6.0-rc5
iommu: Fix false ownership failure on AMD systems with PASID activated
iommu/vt-d: Fix possible recursive locking in intel_iommu_init()
cpufreq: intel_pstate: Add Tigerlake support in no-HWP mode
usb: typec: intel_pmc_mux: Use the helper acpi_dev_get_memory_resources()
ACPI: resource: Skip IRQ override on Asus Vivobook K3402ZA/K3502ZA
ACPI: LPSS: Use the helper acpi_dev_get_memory_resources()
ACPI: APD: Use the helper acpi_dev_get_memory_resources()
ACPI: resource: Add helper function acpi_dev_get_memory_resources()
ACPI: resource: Filter out the non memory resources in is_memory()
ACPI: tables: FPDT: Don't call acpi_os_map_memory() on invalid phys address
ALSA: hda: Fix hang at HD-audio codec unbinding due to refcount saturation
arm64: mm: fix resume for 52-bit enabled builds
mksysmap: Fix the mismatch of 'L0' symbols in System.map
Bluetooth: Fix HCIGETDEVINFO regression
hwmon: (asus-ec-sensors) autoload module via DMI data
mips: Select SPARSEMEM_EXTREME
io_uring/rw: fix short rw error handling
drm/rockchip: vop2: Fix eDP/HDMI sync polarities
drm/gma500: Fix (vblank) IRQs not working after suspend/resume
drm/gma500: Fix WARN_ON(lock->magic != lock) error
drm/gma500: Fix BUG: sleeping function called from invalid context errors
block: add missing request flags to debugfs code
net: core: fix flow symmetric hash
ipvlan: Fix out-of-bound bugs caused by unset skb->mac_header
drm/meson: Fix OSD1 RGB to YCbCr coefficient
drm/meson: Correct OSD1 global alpha value
thunderbolt: Add support for Intel Maple Ridge single port controller
NFSD: fix regression with setting ACLs.
mm/slub: fix to return errno if kmalloc() fails
tracefs: Only clobber mode/uid/gid on remount if asked
kprobes: Prohibit probes in gate area
perf: RISC-V: fix access beyond allocated array
soc: sunxi: sram: Fix debugfs info for A64 SRAM C
x86/sgx: Handle VA page allocation failure for EAUG on PF.
soc: sunxi: sram: Fix probe function ordering issues
x86/sgx: Do not fail on incomplete sanitization on premature stop of ksgxd
soc: sunxi: sram: Prevent the driver from being unbound
soc: sunxi: sram: Actually claim SRAM regions
iavf: Fix cached head and tail value for iavf_get_tx_pending
iavf: Fix change VF's mac address
ice: Fix crash by keep old cfg when update TCs more than queues
perf record: Fix synthesis failure warnings
hwmon: (mr75203) enable polling for all VM channels
hwmon: (mr75203) fix multi-channel voltage reading
perf tools: Don't install data files with x permissions
hwmon: (mr75203) fix voltage equation for negative source input
hwmon: (mr75203) update pvt->v_num and vm_num to the actual number of used sensors
hwmon: (mr75203) fix VM sensor allocation when "intel,vm-map" not defined
dt-bindings: hwmon: (mr75203) fix "intel,vm-map" property to be optional
perf script: Fix Cannot print 'iregs' field for hybrid systems
perf lock: Remove redundant word 'contention' in help message
ice: Don't double unplug aux on peer initiated reset
drm/panel-edp: Fix delays for Innolux N116BCA-EA1
perf dlfilter dlfilter-show-cycles: Fix types for print format
libperf evlist: Fix per-thread mmaps for multi-threaded targets
Revert "SUNRPC: Remove unreachable error condition"
NFSv4.2: Update mode bits after ALLOCATE and DEALLOCATE
io_uring/net: copy addr for zc on POLL_FIRST
ARM: dts: fix Moxa SDIO 'compatible', remove 'sdhci' misnomer
arm64/ptrace: Don't clear calling process' TIF_SME on OOM
fs: only do a memory barrier for the first set_buffer_uptodate()
drm/panfrost: devfreq: set opp to the recommended one to configure regulator
sch_sfb: Also store skb len before calling child enqueue
net: phy: lan87xx: change interrupt src of link_up to comm_ready
drm/ttm: cleanup the resource of ghost objects after locking them
drm/amdgpu: prevent toc firmware memory leak
drm/amdgpu: correct doorbell range/size value for CSDMA_DOORBELL_RANGE
drm/amdkfd: print address in hex format rather than decimal
drm/amd/display: fix memory leak when using debugfs_lookup()
drm/amd/pm: add missing SetMGpuFanBoostLimitRpm mapping for SMU 13.0.7
drm/amd/amdgpu: add rlc_firmware_header_v2_4 to amdgpu_firmware_header
powerpc/pseries: Fix plpks crash on non-pseries
tools: Add new "test" taint to kernel-chktaint
ANDROID: remove inclusions from hook definition headers
ANDROID: subsystem-specific vendor_hooks.c for sched
ANDROID: remove CONFIG_TRACEPOINTS from hook definition headers
io_uring: recycle kbuf recycle on tw requeue
io_uring/kbuf: fix not advancing READV kbuf ring
efi: capsule-loader: Fix use-after-free in efi_capsule_write
arch_topology: Make cluster topology span at least SMT CPUs
ANDROID: clang: update to 15.0.1
FROMLIST: fortify: Fix __compiletime_strlen() under UBSAN_BOUNDS_LOCAL
dt-bindings: interconnect: fsl,imx8m-noc: drop Leonard Crestez
net/smc: Fix possible access to freed memory in link clear
serial: tegra-tcu: Use uart_xmit_advance(), fixes icount.tx accounting
serial: tegra: Use uart_xmit_advance(), fixes icount.tx accounting
serial: Create uart_xmit_advance()
usb: dwc3: core: leave default DMA if the controller does not support 64-bit DMA
net: ethernet: mtk_eth_soc: check max allowed hash in mtk_ppe_check_skb
net: skb: export skb drop reaons to user by TRACE_DEFINE_ENUM
net: ethernet: mtk_eth_soc: fix typo in __mtk_foe_entry_clear
netfilter: nfnetlink_osf: fix possible bogus match in nf_osf_find()
netfilter: nf_conntrack_irc: Tighten matching on DCC message
iommu/virtio: Fix interaction with VFIO
iommu/vt-d: Fix lockdep splat due to klist iteration in atomic context
iommu/vt-d: Fix recursive lock issue in iommu_flush_dev_iotlb()
iommu/vt-d: Correctly calculate sagaw value of IOMMU
iommu/vt-d: Fix kdump kernels boot failure with scalable mode
MIPS: OCTEON: irq: Fix octeon_irq_force_ciu_mapping()
selftests: nft_concat_range: add socat support
netfilter: nf_conntrack_sip: fix ct_sip_walk_headers
MIPS: octeon: Get rid of preprocessor directives around RESERVE32
net: dsa: felix: access QSYS_TAG_CONFIG under tas_lock in vsc9959_sched_speed_set
net: dsa: felix: disable cut-through forwarding for frames oversized for tc-taprio
net: dsa: felix: tc-taprio intervals smaller than MTU should send at least one packet
s390/smp: enforce lowcore protection on CPU restart
s390/boot: fix absolute zero lowcore corruption on boot
gpio: mpc8xxx: Fix support for IRQ_TYPE_LEVEL_LOW flow_type in mpc85xx
ALSA: usb-audio: Clear fixed clock rate at closing EP
iommu/amd: use full 64-bit value in build_completion_wait()
dma-mapping: mark dma_supported static
swiotlb: fix a typo
swiotlb: avoid potential left shift overflow
dma-debug: improve search for partial syncs
Revert "swiotlb: panic if nslabs is too small"
RDMA/irdma: Report RNR NAK generation in device caps
RDMA/irdma: Use s/g array in post send only when its valid
RDMA/irdma: Return correct WC error for bind operation failure
RDMA/irdma: Return error on MR deregister CQP failure
RDMA/irdma: Report the correct max cqes from query device
wifi: iwlwifi: don't spam logs with NSS>2 messages
efi/x86: libstub: remove unused variable
nvme: requeue aen after firmware activation
nvmet: fix mar and mor off-by-one errors
ALSA: emu10k1: Fix out of bounds access in snd_emu10k1_pcm_channel_alloc()
scsi: mpt3sas: Fix use-after-free warning
rv/reactor: add __init/__exit annotations to module init/exit funcs
tracing: Fix to check event_mutex is held while accessing trigger list
tracing: hold caller_addr to hardirq_{enable,disable}_ip
tracepoint: Allow trace events in modules with TAINT_TEST
MAINTAINERS: add scripts/tracing/ to TRACING
MAINTAINERS: Add Runtime Verification (RV) entry
rv/monitors: Make monitor's automata definition static
afs: Return -EAGAIN, not -EREMOTEIO, when a file already locked
ANDROID: Convert db845c to a mixed build.
ANDROID: GKI: Add GKI_HIDDEN_MCP251XFD_CONFIGS
drm/i915: consider HAS_FLAT_CCS() in needs_ccs_pages
drm/i915: Implement WaEdpLinkRateDataReload
drm/i915/slpc: Let's fix the PCODE min freq table setup for SLPC
drm/i915/bios: Copy the whole MIPI sequence block
ANDROID: kleaf: Do not include GKI modules in default output of //common:kernel_aarch64.
cpuset: Add Waiman Long as a cpuset maintainer
btrfs: fix the max chunk size and stripe length calculation
perf c2c: Prevent potential memory leak in c2c_he_zalloc()
perf genelf: Switch deprecated openssl MD5_* functions to new EVP API
tools/perf: Fix out of bound access to cpu mask array
perf affinity: Fix out of bound access to "sched_cpus" mask
net: usb: qmi_wwan: add Quectel RM520N
drm/ttm: update bulk move object of ghost BO
perf/core: Fix reentry problem in perf_output_read_group()
net: dsa: qca8k: fix NULL pointer dereference for of_device_get_match_data
tcp: fix early ETIMEDOUT after spurious non-SACK RTO
ALSA: hda: Once again fix regression of page allocations with IOMMU
arm64/bti: Disable in kernel BTI when cross section thunks are broken
ARM: dts: am5748: keep usb4_tm disabled
ALSA: usb-audio: Fix an out-of-bounds bug in __snd_usb_parse_audio_interface()
ALSA: hda/tegra: Align BDL entry to 4KB boundary
nvme-tcp: fix regression that causes sporadic requests to time out
nvme-tcp: fix UAF when detecting digest errors
arm64: dts: imx8mm-verdin: extend pmic voltages
hwmon: (tps23861) fix byte order in resistance register
io_uring/notif: Remove the unused function io_notif_complete()
Drivers: hv: Never allocate anything besides framebuffer from framebuffer memory region
Drivers: hv: Always reserve framebuffer region for Gen1 VMs
PCI: Move PCI_VENDOR_ID_MICROSOFT/PCI_DEVICE_ID_HYPERV_VIDEO definitions to pci_ids.h
tools: hv: kvp: remove unnecessary (void*) conversions
Drivers: hv: remove duplicate word in a comment
erofs: fix pcluster use-after-free on UP platforms
erofs: avoid the potentially wrong m_plen for big pcluster
erofs: fix error return code in erofs_fscache_{meta_,}read_folio
asm-generic: Conditionally enable do_softirq_own_stack() via Kconfig.
btrfs: zoned: fix mounting with conventional zones
btrfs: zoned: set pseudo max append zone limit in zone emulation mode
btrfs: zoned: fix API misuse of zone finish waiting
stmmac: intel: Simplify intel_eth_pci_remove()
net: mvpp2: debugfs: fix memory leak when using debugfs_lookup()
ALSA: hda/sigmatel: Fix unused variable warning for beep power change
nvmet: fix a use-after-free
ALSA: pcm: oss: Fix race at SNDCTL_DSP_SYNC
MAINTAINERS: Update maintainers of HiSilicon RoCE
RDMA/mlx5: Fix UMR cleanup on error flow of driver init
RDMA/mlx5: Set local port to one when accessing counters
RDMA/mlx5: Rely on RoCE fw cap instead of devlink when setting profile
IB/core: Fix a nested dead lock as part of ODP flow
USB: core: Fix RST error in hub.c
sched/debug: fix dentry leak in update_sched_domain_debugfs
debugfs: add debugfs_lookup_and_remove()
driver core: fix driver_set_override() issue with empty strings
arm64: dts: rockchip: Remove 'enable-active-low' from rk3566-quartz64-a
arm64: dts: rockchip: Remove 'enable-active-low' from rk3399-puma
arm64: dts: rockchip: fix property for usb2 phy supply on rk3568-evb1-v10
arm64: dts: rockchip: fix property for usb2 phy supply on rock-3a
ipv6: sr: fix out-of-bounds read when setting HMAC data.
bonding: accept unsolicited NA message
bonding: add all node mcast address when slave up
bonding: use unspecified address if no available link local address
dmaengine: zynqmp_dma: Typecast with enum to fix the coverity warning
dmaengine: ti: k3-udma-private: Fix refcount leak bug in of_xudma_dev_get()
arm64: dts: imx8ulp: add #reset-cells for pcc
arm64: dts: tqma8mpxl-ba8mpxl: Fix button GPIOs
arm64: dts: imx8mn: remove GPU power domain reset
Linux 6.0-rc4
Makefile.extrawarn: re-enable -Wformat for clang; take 2
dmaengine: xilinx_dma: Report error in case of dma_set_mask_and_coherent API failure
dmaengine: xilinx_dma: cleanup for fetching xlnx,num-fstores property
dmaengine: xilinx_dma: Fix devm_platform_ioremap_resource error handling
arm64: dts: rockchip: Set RK3399-Gru PCLK_EDP to 24 MHz
arm64: dts: imx8mm: Reverse CPLD_Dn GPIO label mapping on MX8Menlo
ALSA: hda/sigmatel: Keep power up while beep is enabled
RDMA/siw: Pass a pointer to virt_to_page()
exfat: fix overflow for large capacity partition
gpio: ws16c48: Make irq_chip immutable
gpio: 104-idio-16: Make irq_chip immutable
gpio: 104-idi-48: Make irq_chip immutable
gpio: 104-dio-48e: Make irq_chip immutable
ACPI: property: Silence missing-declarations warning in apple.c
ACPI: platform: Use PLATFORM_DEVID_NONE in acpi_create_platform_device()
ACPI: platform: Sort forbidden_id_list[] in ascending order
ACPI: platform: Use sizeof(*pointer) instead of sizeof(type)
ACPI: platform: Remove redundant print on -ENOMEM
ACPI: platform: Get rid of redundant 'else'
ACPI: property: Use acpi_dev_parent()
ACPI: bus: Refactor ACPI matching functions for better readability
ACPI: bus: Drop kernel doc annotation from acpi_bus_notify()
ACPI: docs: enumeration: Fix a few typos and wording mistakes
ACPI: tools: pfrut: Do not initialize ret in main()
ACPI: EC: Drop unneeded result variable from ec_write()
ACPI: video: Add Toshiba Satellite/Portege Z830 quirk
ACPI: APEI: Add BERT error log footer
powercap: intel_rapl: Add support for RAPTORLAKE_S
cpufreq: amd-pstate: Fix initial highest_perf value
cpuidle: Remove redundant check in cpuidle_switch_governor()
PM: wakeup: Add extra debugging statement for multiple active IRQs
block: don't add partitions if GD_SUPPRESS_PART_SCAN is set
mm: pagewalk: Fix race between unmap and page walker
wifi: use struct_group to copy addresses
wifi: mac80211_hwsim: check length for virtio packets
wifi: mac80211: fix locking in auth/assoc timeout
wifi: mac80211: mlme: release deflink channel in error case
wifi: mac80211: fix link warning in RX agg timer expiry
LoongArch: mm: Remove the unneeded result variable
LoongArch: Fix arch_remove_memory() undefined build error
LoongArch: Fix section mismatch due to acpi_os_ioremap()
LoongArch: Improve dump_tlb() output messages
LoongArch: Adjust arch_do_signal_or_restart() to adapt generic entry
LoongArch: Avoid orphan input sections
net: dsa: microchip: fix kernel oops on ksz8 switches
xen-netback: only remove 'hotplug-status' when the vif is actually destroyed
Revert "arch_topology: Make cluster topology span at least SMT CPUs"
net: fec: Use a spinlock to guard `fep->ptp_clk_on`
net: fec: add pm_qos support on imx6q platform
Bluetooth: hci_sync: Fix hci_read_buffer_size_sync
iavf: Detach device during reset task
i40e: Fix kernel crash during module removal
i40e: Fix ADQ rate limiting for PF
perf stat: Fix L2 Topdown metrics disappear for raw events
Documentation: document ublk
ice: use bitmap_free instead of devm_kfree
ice: Fix DMA mappings leak
drm/edid: Handle EDID 1.4 range descriptor h/vfreq offsets
landlock: Fix file reparenting without explicit LANDLOCK_ACCESS_FS_REFER
spi: spi: Fix queue hang if previous transfer failed
spi: mux: Fix mux interaction with fast path optimisations
tcp: TX zerocopy should not sense pfmemalloc status
tipc: fix shift wrapping bug in map_get()
sch_sfb: Don't assume the skb is still around after enqueueing to child
soc: fsl: select FSL_GUTS driver for DPIO
xen/grants: prevent integer overflow in gnttab_dma_alloc_pages()
xen-blkfront: Cache feature_persistent value before advertisement
xen-blkfront: Advertise feature-persistent as user requested
xen-blkback: Advertise feature-persistent as user requested
powerpc/papr_scm: Ensure rc is always initialized in papr_scm_pmu_register()
Revert "powerpc/irq: Don't open code irq_soft_mask helpers"
Revert "usb: gadget: udc-xilinx: replace memcpy with memcpy_toio"
ALSA: aloop: Fix random zeros in capture data when using jiffies timer
Revert "net: phy: meson-gxl: improve link-up behavior"
KVM: x86: check validity of argument to KVM_SET_MP_STATE
perf/x86/core: Completely disable guest PEBS via guest's global_ctrl
KVM: x86: fix memoryleak in kvm_arch_vcpu_create()
KVM: x86: Mask off unsupported and unknown bits of IA32_ARCH_CAPABILITIES
kunit: fix Kconfig for build-in tests USB4 and Nitro Enclaves
kunit: fix assert_type for comparison macros
rcutorture: Use the barrier operation specified by cur_ops
arch_topology: Make cluster topology span at least SMT CPUs
platform/x86: p2sb: Fix UAF when caller uses resource name
platform/x86: asus-wmi: Increase FAN_CURVE_BUF_LEN to 32
firmware_loader: Fix memory leak in firmware upload
firmware_loader: Fix use-after-free during unregister
kbuild: disable header exports for UML in a straightforward way
selftests/net: return back io_uring zc send tests
io_uring/net: simplify zerocopy send user API
io_uring/notif: remove notif registration
Revert "io_uring: rename IORING_OP_FILES_UPDATE"
Revert "io_uring: add zc notification flush requests"
selftests/net: temporarily disable io_uring zc test
NFSv4: Turn off open-by-filehandle and NFS re-export for NFSv4.0
SUNRPC: Fix call completion races with call_decode()
arch_topology: Silence early cacheinfo errors when non-existent
binder: fix alloc->vma_vm_mm null-ptr dereference
misc: fastrpc: increase maximum session count
misc: fastrpc: fix memory corruption on open
misc: fastrpc: fix memory corruption on probe
usb: storage: Add ASUS <0x0b05:0x1932> to IGNORE_UAS
driver core: Don't probe devices after bus_type.match() probe deferral
ALSA: usb-audio: Split endpoint setups for hw_params and prepare
platform/mellanox: Remove redundant 'NULL' check
platform/mellanox: Remove unnecessary code
platform/mellanox: mlxreg-lc: Fix locking issue
platform/mellanox: mlxreg-lc: Fix coverity warning
platform/x86: acer-wmi: Acer Aspire One AOD270/Packard Bell Dot keymap fixes
arm64: mm: Reserve enough pages for the initial ID map
perf/arm_pmu_platform: fix tests for platform_get_irq() failure
arm64: head: Ignore bogus KASLR displacement on non-relocatable kernels
arm64/kexec: Fix missing extra range for crashkres_low.
rxrpc: Remove rxrpc_get_reply_time() which is no longer used
afs: Use the operation issue time instead of the reply time for callbacks
rxrpc: Fix calc of resend age
rxrpc: Fix local destruction being repeated
rxrpc: Fix an insufficiently large sglist in rxkad_verify_packet_2()
rxrpc: Fix ICMP/ICMP6 error handling
mm/slab_common: Deleting kobject in kmem_cache_destroy() without holding slab_mutex/cpu_hotplug_lock
perf/x86/core: Completely disable guest PEBS via guest's global_ctrl
perf/x86/intel: Fix unchecked MSR access error for Alder Lake N
soundwire: qcom: fix device status array range
ALSA: usb-audio: Register card again for iface over delayed_register option
ALSA: usb-audio: Inform the delayed registration more properly
net/smc: Remove redundant refcount increase
RDMA/srp: Set scmnd->result only when scmnd is not NULL
scsi: core: Fix a use-after-free
scsi: core: Revert "Make sure that targets outlive devices"
scsi: core: Revert "Make sure that hosts outlive targets"
scsi: core: Revert "Simplify LLD module reference counting"
scsi: core: Revert "Call blk_mq_free_tag_set() earlier"
scsi: lpfc: Add missing destroy_workqueue() in error path
scsi: lpfc: Return DID_TRANSPORT_DISRUPTED instead of DID_REQUEUE
cpufreq: tegra194: Remove the unneeded result variable
Revert "sch_cake: Return __NET_XMIT_STOLEN when consuming enqueued skb"
tcp: make global challenge ack rate limitation per net-ns and default disabled
tcp: annotate data-race around challenge_timestamp
net: dsa: hellcreek: Print warning only once
ip: fix triggering of 'icmp redirect'
clk: ingenic-tcu: Properly enable registers before accessing timers
netfilter: nf_conntrack_irc: Fix forged IP logic
mm/rmap: Fix anon_vma->degree ambiguity leading to double-reuse
sch_cake: Return __NET_XMIT_STOLEN when consuming enqueued skb
x86/cpu: Add CPU model numbers for Meteor Lake
drm/amd/amdgpu: skip ucode loading if ucode_size == 0
selftests: net: sort .gitignore file
Documentation: networking: correct possessive "its"
kcm: fix strp_init() order and cleanup
PM: suspend: move from strlcpy() with unused retval to strscpy()
mlxbf_gige: compute MDIO period based on i1clk
intel_idle: move from strlcpy() with unused retval to strscpy()
cpuidle: powernv: move from strlcpy() with unused retval to strscpy()
Revert "clk: core: Honor CLK_OPS_PARENT_ENABLE for clk gate ops"
cpufreq: amd-pstate: update pstate frequency transition delay time
cpufreq: amd_pstate: map desired perf into pstate scope for powersave governor
cpufreq: amd_pstate: fix wrong lowest perf fetch
cpufreq: amd-pstate: fix white-space
cpufreq: amd-pstate: simplify cpudata pointer assignment
cpuidle: coupled: Drop duplicate word from a comment
Revert "ANDROID: virt_wifi: Add data ops for scan data simulation"
perf script: Skip dummy event attr check
riscv: dts: microchip: use an mpfs specific l2 compatible
dt-bindings: riscv: sifive-l2: add a PolarFire SoC compatible
gpio: realtek-otto: switch to 32-bit I/O
cachefiles: make on-demand request distribution fairer
cachefiles: fix error return code in cachefiles_ondemand_copen()
vfio/type1: Unpin zero pages
fscache: fix misdocumented parameter
USB: serial: ch341: fix disabled rx timer on older devices
USB: serial: ch341: fix lost character on LCR updates
powerpc: Fix hard_irq_disable() with sanitizer
ethernet: rocker: fix sleep in atomic context bug in neigh_timer_handler
USB: serial: cp210x: add Decagon UCA device id
perf metric: Return early if no CPU PMU table exists
selftests/nolibc: Avoid generated files being committed
selftests/nolibc: add a "help" target
selftests/nolibc: "sysroot" target installs a local copy of the sysroot
selftests/nolibc: add a "run" target to start the kernel in QEMU
selftests/nolibc: add a "defconfig" target
selftests/nolibc: add a "kernel" target to build the kernel with the initramfs
selftests/nolibc: support glibc as well
selftests/nolibc: condition some tests on /proc existence
selftests/nolibc: recreate and populate /dev and /proc if missing
selftests/nolibc: on x86, support exiting with isa-debug-exit
selftests/nolibc: exit with poweroff on success when getpid() == 1
selftests/nolibc: add a few tests for some libc functions
selftests/nolibc: implement a few tests for various syscalls
selftests/nolibc: support a test definition format
selftests/nolibc: add basic infrastructure to ease creation of nolibc tests
tools/nolibc: make sys_mmap() automatically use the right __NR_mmap definition
tools/nolibc: fix build warning in sys_mmap() when my_syscall6 is not defined
tools/nolibc: make argc 32-bit in riscv startup code
tools/memory-model: Clarify LKMM's limitations in litmus-tests.txt
docs/memory-barriers.txt: Fixup long lines
docs/memory-barriers.txt: Fix confusing name of 'data dependency barrier'
rcu-tasks: Make RCU Tasks Trace check for userspace execution
rcu-tasks: Ensure RCU Tasks Trace loops have quiescent states
rcu-tasks: Convert RCU_LOCKDEP_WARN() to WARN_ONCE()
srcu: Make Tiny SRCU use full-sized grace-period counters
srcu: Make Tiny SRCU poll_state_synchronize_srcu() more precise
srcu: Add GP and maximum requested GP to Tiny SRCU rcutorture output
rcutorture: Make "srcud" option also test polled grace-period API
rcutorture: Limit read-side polling-API testing
rcu: Add functions to compare grace-period state values
rcutorture: Expand rcu_torture_write_types() first "if" statement
rcutorture: Use 1-suffixed variable in rcu_torture_write_types() check
rcu: Make synchronize_rcu() fastpath update only boot-CPU counters
rcutorture: Adjust rcu_poll_need_2gp() for rcu_gp_oldstate field removal
rcu: Remove ->rgos_polled field from rcu_gp_oldstate structure
rcu: Make synchronize_rcu_expedited() fast path update .expedited_sequence
rcu: Remove expedited grace-period fast-path forward-progress helper
rcu: Make synchronize_rcu() fast path update ->gp_seq counters
rcu-tasks: Remove grace-period fast-path rcu-tasks helper
rcu: Set rcu_data structures' initial ->gpwrap value to true
rcu: Disable run-time single-CPU grace-period optimization
rcu: Add full-sized polling for cond_sync_exp_full()
rcu: Add full-sized polling for cond_sync_full()
rcu: Remove blank line from poll_state_synchronize_rcu() docbook header
rcu: Add full-sized polling for start_poll_expedited()
rcu: Add full-sized polling for start_poll()
rcutorture: Verify long-running reader prevents full polling from completing
rcutorture: Remove redundant RTWS_DEF_FREE check
rcutorture: Verify RCU reader prevents full polling from completing
rcutorture: Allow per-RCU-flavor polled double-GP check
rcutorture: Abstract synchronous and polled API testing
rcu: Add full-sized polling for get_state()
rcu: Add full-sized polling for get_completed*() and poll_state*()
rcu/nocb: Add CPU number to CPU-{,de}offload failure messages
rcu/nocb: Choose the right rcuog/rcuop kthreads to output
rcu/kvfree: Update KFREE_DRAIN_JIFFIES interval
rcu/kfree: Fix kfree_rcu_shrink_count() return value
rcu: Back off upon fill_page_cache_func() allocation failure
rcu: Exclude outgoing CPU when it is the last to leave
rcu: Avoid triggering strict-GP irq-work when RCU is idle
sched/debug: Show the registers of 'current' in dump_cpu_task()
sched/debug: Try trigger_single_cpu_backtrace(cpu) in dump_cpu_task()
rcu: Update rcu_access_pointer() header for rcu_dereference_protected()
rcu: Document reason for rcu_all_qs() call to preempt_disable()
rcu: Make tiny RCU support leak callbacks for debug-object errors
rcu: Add QS check in rcu_exp_handler() for non-preemptible kernels
rcu: Update rcu_preempt_deferred_qs() comments for !PREEMPT kernels
rcu: Fix rcu_read_unlock_strict() strict QS reporting
doc/rcu: Update LWN article URLs and add 2019 article
doc: SLAB_TYPESAFE_BY_RCU uses cannot rely on spinlocks
doc: Update rcu_access_pointer() advice in rcu_dereference.rst
doc: Fix list: rcu_access_pointer() is not lockdep-checked
doc: Use rcu_barrier() to rate-limit RCU callbacks
doc: Call out queue_rcu_work() for blocking RCU callbacks
doc: Emphasize the need for explicit RCU read-side markers
gpio: pca953x: Add mutex_lock for regcache sync in PM
netfilter: nf_tables: clean up hook list when offload flags check fails
regulator: Fix qcom,spmi-regulator schema
netfilter: br_netfilter: Drop dst references before setting.
netfilter: remove nf_conntrack_helper sysctl and modparam toggles
Revert "usb: add quirks for Lenovo OneLink+ Dock"
media: uvcvideo: Fix InterfaceProtocol for Quanta camera
ARM: dts: at91: sama5d2_icp: don't keep vdd_other enabled all the time
ARM: dts: at91: sama5d27_wlsom1: don't keep ldo2 enabled all the time
ARM: dts: at91: sama7g5ek: specify proper regulator output ranges
ARM: dts: at91: sama5d2_icp: specify proper regulator output ranges
ARM: dts: at91: sama5d27_wlsom1: specify proper regulator output ranges
ARM: at91: pm: fix DDR recalibration when resuming from backup and self-refresh
ARM: at91: pm: fix self-refresh for sama7g5
net: lan966x: improve error handle in lan966x_fdma_rx_get_frame()
nfp: fix the access to management firmware hanging
net: phy: micrel: Make the GPIO to be non-exclusive
net: virtio_net: fix notification coalescing comments
nvmet-tcp: fix unhandled tcp states in nvmet_tcp_state_change()
nvmet-auth: add missing goto in nvmet_setup_auth()
nvme-pci: add NVME_QUIRK_BOGUS_NID for Lexar NM610
cifs: fix small mempool leak in SMB2_negotiate()
smb3: use filemap_write_and_wait_range instead of filemap_write_and_wait
drm/amdgpu: only init tap_delay ucode when it's included in ucode binary
drm/amd/display: Fix black flash when switching from ODM2to1 to ODMBypass
drm/amd/display: Fix check for stream and plane
drm/amd/display: Re-initialize viewport after pipe merge
drm/amd/display: Use correct plane for CAB cursor size allocation
drm/amdgpu: ensure no PCIe peer access for CPU XGMI iolinks
drm/amd/pm: bump SMU 13.0.0 driver_if header version
drm/amd/pm: use vbios carried pptable for all SMU13.0.7 SKUs
drm/amd/pm: use vbios carried pptable for those supported SKUs
drm/amd/display: fix wrong register access
drm/amd/display: use actual cursor size instead of max for CAB allocation
drm/amd/display: disable display fresh from MALL on an edge case for DCN321
drm/amd/display: Fix CAB cursor size allocation for DCN32/321
drm/amd/display: Missing HPO instance added
drm/amd/display: set dig fifo read start level to 7 before dig fifo reset
drm/amdgpu: Fix use-after-free in amdgpu_cs_ioctl
drm/amd/display: Fix OTG H timing reset for dcn314
drm/amd/display: Fix DCN32 DPSTREAMCLK_CNTL programming
drm/amdgpu: Update mes_v11_api_def.h
drm/amdgpu: disable FRU access on special SIENNA CICHLID card
s390/hugetlb: fix prepare_hugepage_range() check for 2 GB hugepages
s390: update defconfigs
s390: fix nospec table alignments
s390/mm: remove useless hugepage address alignment
wifi: iwlegacy: 4965: corrected fix for potential off-by-one overflow in il4965_rs_fill_link_cmd()
wifi: wilc1000: fix DMA on stack objects
staging: rtl8712: fix use after free bugs
reset: microchip-sparx5: issue a reset on startup
reset: imx7: Fix the iMX8MP PCIe PHY PERST support
usb: cdns3: fix issue with rearming ISO OUT endpoint
usb: cdns3: fix incorrect handling TRB_SMM flag for ISOC transfer
usb: gadget: mass_storage: Fix cdrom data transfers on MAC-OS
media: mceusb: Use new usb_control_msg_*() routines
USB: core: Prevent nested device-reset calls
USB: gadget: Fix obscure lockdep violation for udc_mutex
usb: dwc2: fix wrong order of phy_power_on and phy_init
usb: gadget: udc-xilinx: replace memcpy with memcpy_toio
usb: typec: Remove retimers properly
usb: dwc3: disable USB core PHY management
usb: add quirks for Lenovo OneLink+ Dock
net/sched: fix netdevice reference leaks in attach_default_qdiscs()
tty: n_gsm: avoid call of sleeping functions from atomic context
tty: n_gsm: replace kicktimer with delayed_work
tty: n_gsm: initialize more members at gsm_alloc_mux()
tty: n_gsm: add sanity check for gsm->receive in gsm_receive_buf()
tty: serial: atmel: Preserve previous USART mode if RS485 disabled
tty: serial: lpuart: disable flow control while waiting for the transmit engine to complete
tty: Fix lookahead_buf crash with serdev
serial: fsl_lpuart: RS485 RTS polariy is inverse
vt: Clear selection before changing the font
ACPI: Drop redundant acpi_dev_parent() header
ACPI: PM: Fix NULL argument handling in acpi_device_get/set_power()
ARM: 9229/1: amba: Fix use-after-free in amba_read_periphid()
dt-bindings: i2c: renesas,riic: Fix 'unevaluatedProperties' warnings
net: sched: tbf: don't call qdisc_put() while holding tree lock
cpufreq: bmips-cpufreq: Use module_init and add module_exit
RDMA/hns: Remove the num_qpc_timer variable
RDMA/hns: Fix wrong fixed value of qp->rq.wqe_shift
RDMA/hns: Fix supported page size
phy: marvell: phy-mvebu-a3700-comphy: Remove broken reset support
hwmon: (gpio-fan) Fix array out of bounds access
MAINTAINERS: Update Bjorn's email address
arm64: dts: qcom: sc7280: move USB wakeup-source property
arm64: dts: qcom: thinkpad-x13s: Fix firmware location
arm64: dts: qcom: sm8150: Fix fastrpc iommu values
tracing: Define the is_signed_type() macro once
docs: i2c: piix4: Fix typos, add markup, drop link
Input: iforce - add support for Boeder Force Feedback Wheel
soc: brcmstb: pm-arm: Fix refcount leak and __iomem leak bugs
bus: mhi: host: Fix up null pointer access in mhi_irq_handler
drm/i915: Skip wm/ddb readout for disabled pipes
drm/i915/glk: ECS Liva Q2 needs GLK HDMI port timing quirk
drm/i915: fix null pointer dereference
drm/i915/backlight: Disable pps power hook for aux based backlight
drm/i915/display: avoid warnings when registering dual panel backlight
drm/i915/dsi: fix dual-link DSI backlight and CABC ports for display 11+
drm/i915/dsi: filter invalid backlight and CABC ports
drm/i915/guc: clear stalled request after a reset
drm/i915/ttm: fix CCS handling
USB: serial: option: add support for Cinterion MV32-WA/WB RmNet mode
USB: serial: ftdi_sio: add Omron CS1W-CIF31 device id
USB: serial: option: add Quectel EM060K modem
MIPS: loongson32: ls1c: Fix hang during startup
net: Use u64_stats_fetch_begin_irq() for stats fetch.
net: dsa: xrs700x: Use irqsave variant for u64 stats update
USB: serial: option: add support for OPPO R11 diag port
KVM: s390: pci: Hook to access KVM lowlevel from VFIO
ARM: configs: at91: remove CONFIG_MICROCHIP_PIT64B
docs: i2c: i2c-topology: reorder sections more logically
docs: i2c: i2c-topology: fix incorrect heading
docs: i2c: i2c-topology: fix typo
ieee802154: cc2520: add rc code in cc2520_tx()
net: mac802154: Fix a condition in the receive path
ARM: ixp4xx: fix typos in comments
RDMA/cma: Fix arguments order in net device validation
arm64: dts: renesas: r8a779g0: Fix HSCIF0 interrupt number
scripts/extract-ikconfig: add zstd compression support
scripts: remove obsolete gcc-ld script
smb3: fix temporary data corruption in insert range
smb3: fix temporary data corruption in collapse range
smb3: Move the flush out of smb2_copychunk_range() into its callers
gpio: mockup: remove gpio debugfs when remove device
RDMA/irdma: Fix drain SQ hang with no completion
ALSA: usb-audio: Add quirk for LH Labs Geek Out HD Audio 1V5
ALSA: hda/realtek: Add speaker AMP init for Samsung laptops with ALC298
Input: iforce - wake up after clearing IFORCE_XMIT_RUNNING flag
r8152: add PID for the Lenovo OneLink+ Dock
nfp: flower: fix ingress police using matchall filter
openvswitch: fix memory leak at failed datapath creation
net: smsc911x: Stop and start PHY during suspend and resume
tg3: Disable tg3 device on system reboot to avoid triggering AER
net: sparx5: fix handling uneven length packets in manual extraction
docs/conf.py: add function attribute '__fix_address' to conf.py
Smack: Provide read control for io_uring_cmd
io_uring/net: fix overexcessive retries
/dev/null: add IORING_OP_URING_CMD support
selinux: implement the security_uring_cmd() LSM hook
lsm,io_uring: add LSM hooks for the new uring_cmd file op
ALSA: control: Re-order bounds checking in get_ctl_id_hash()
wifi: mt76: mt7921e: fix crash in chip reset fail
platform/x86: thinkpad_acpi: Explicitly set to balanced mode on startup
crypto: lib - remove unneeded selection of XOR_BLOCKS
platform/x86: asus-wmi: Fix the name of the mic-mute LED classdev
pinctrl: sunxi: Fix name for A100 R_PIO
Bluetooth: hci_sync: hold hdev->lock when cleanup hci_conn
Bluetooth: move from strlcpy with unused retval to strscpy
Bluetooth: hci_event: Fix checking conn for le_conn_complete_evt
Bluetooth: ISO: Fix not handling shutdown condition
Bluetooth: hci_sync: fix double mgmt_pending_free() in remove_adv_monitor()
Bluetooth: MGMT: Fix Get Device Flags
Bluetooth: L2CAP: Fix build errors in some archs
Bluetooth: hci_sync: Fix suspend performance regression
Bluetooth: hci_event: Fix vendor (unknown) opcode status handling
powerpc/rtas: Fix RTAS MSR[HV] handling for Cell
Revert "powerpc: Remove unused FW_FEATURE_NATIVE references"
powerpc: align syscall table for ppc32
bpf: Don't use tnum_range on array range checking for poke descriptors
selftests/bpf: Add regression test for pruning fix
bpf: Do mark_chain_precision for ARG_CONST_ALLOC_SIZE_OR_ZERO
of/device: Fix up of_dma_configure_id() stub
Docs/admin-guide/mm/damon/usage: fix the example code snip
docs: Update version number from 5.x to 6.x in README.rst
ACPI: bus: Remove the unneeded result variable
ACPI: OSI: Update Documentation on custom _OSI strings
ACPI: OSI: Remove Linux-HPI-Hybrid-Graphics _OSI string
ACPI: OSI: Remove Linux-Lenovo-NV-HDMI-Audio _OSI string
ACPI: OSI: Remove Linux-Dell-Video _OSI string
Revert "xhci: turn off port power in shutdown"
xhci: Add grace period after xHC start to prevent premature runtime suspend.
xhci: Fix null pointer dereference in remove if xHC has only one roothub
drm/mediatek: dsi: Add atomic {destroy,duplicate}_state, reset callbacks
ASoC: fsl_aud2htx: Add error handler for pm_runtime_enable
ASoC: fsl_aud2htx: register platform component before registering cpu dai
HID: nintendo: fix rumble worker null pointer deref
HID: intel-ish-hid: ipc: Add Meteor Lake PCI device ID
pinctrl: rockchip: Enhance support for IRQ_TYPE_EDGE_BOTH
ACPI: CPPC: Add ACPI disabled check to acpi_cpc_valid()
regulator: pfuze100: Fix the global-out-of-bounds access in pfuze100_regulator_probe()
dma-buf/dma-resv: check if the new fence is really later
HID: input: fix uclogic tablets
HID: Add Apple Touchbar on T2 Macs in hid_have_special_driver list
HID: add Lenovo Yoga C630 battery quirk
HID: AMD_SFH: Add a DMI quirk entry for Chromebooks
tee: fix compiler warning in tee_shm_register()
HID: thrustmaster: Add sparco wheel and fix array length
hid: intel-ish-hid: ishtp: Fix ishtp client sending disordered message
HID: ishtp-hid-clientHID: ishtp-hid-client: Fix comment typo
HID: asus: ROG NKey: Ignore portion of 0x5a report
HID: hidraw: fix memory leak in hidraw_release()
efi: libstub: Disable struct randomization
HID: steam: Prevent NULL pointer dereference in steam_{recv,send}_report
wifi: mac80211: potential NULL dereference in ieee80211_tx_control_port()
wifi: cfg80211: debugfs: fix return type in ht40allow_map_read()
wifi: mac80211: Don't finalize CSA in IBSS mode if state is disconnected
wifi: mac80211: fix possible leak in ieee80211_tx_control_port()
wifi: mac80211: always free sta in __sta_info_alloc in case of error
wifi: mac80211: Fix UAF in ieee80211_scan_rx()
powerpc/pci: Enable PCI domains in /proc when PCI bus numbers are not unique
ACPI: Drop parent field from struct acpi_device
ALSA: control: Fix an out-of-bounds bug in get_ctl_id_hash()
dt-bindings: opp: Add missing (unevaluated|additional)Properties on child nodes
ALSA: hda: intel-nhlt: Correct the handling of fmt_config flexible array
ALSA: seq: Fix data-race at module auto-loading
drm/i915/backlight: Disable pps power hook for aux based backlight
drm/i915/display: avoid warnings when registering dual panel backlight
drm/i915/dsi: fix dual-link DSI backlight and CABC ports for display 11+
drm/i915/dsi: filter invalid backlight and CABC ports
drm/i915/guc: clear stalled request after a reset
drm/i915/ttm: fix CCS handling
clk: bcm: rpi: Show clock id limit in error case
clk: bcm: rpi: Add missing newline
clk: bcm: rpi: Prevent out-of-bounds access
bpf: Fix a data-race around bpf_jit_limit.
cpufreq: schedutil: Move max CPU capacity to sugov_policy
Input: goodix - add compatible string for GT1158
ACPI: move from strlcpy() with unused retval to strscpy()
ACPI: PM: Fix acpi_dev_state_d0() kerneldoc
ASoC: SOF: ipc4-topology: fix alh_group_ida max value
ASoC: mchp-spdiftx: Fix clang -Wbitfield-constant-conversion
ACPI: scan: Eliminate __acpi_device_add()
ACPI: scan: Rearrange initialization of ACPI device objects
ACPI: scan: Rename acpi_bus_get_parent() and rearrange it
ACPI: Rename acpi_bus_get/put_acpi_device()
soundwire: qcom: remove duplicate reset control get
ALSA: seq: oss: Fix data-race for max_midi_devs access
ASoC: SOF: Kconfig: Make IPC_MESSAGE_INJECTOR depend on SND_SOC_SOF
ASoC: SOF: Kconfig: Make IPC_FLOOD_TEST depend on SND_SOC_SOF
arm64: dts: rockchip: fix upper usb port on BPI-R2-Pro
arm64: dts: rockchip: Fix typo in lisense text for PX30.Core
arm64: dts: rockchip: Pull up wlan wake# on Gru-Bob
arm64: dts: rockchip: Lower sd speed on quartz64-b
ASoC: fsl_mqs: Fix supported clock DAI format
ASoC: nau8540: Implement hw constraint for rates
ASoC: nau8825: Implement hw constraint for rates
ASoC: nau8824: Implement hw constraint for rates
ASoC: nau8824: Fix semaphore unbalance at error paths
ASoC: nau8821: Implement hw constraint for rates
firmware: arm_scmi: Harmonize SCMI tracing message format
firmware: arm_scmi: Add SCMI PM driver remove routine
firmware: arm_scmi: Fix the asynchronous reset requests
firmware: arm_scmi: Harden accesses to the reset domains
Revert "iommu/of: Delete usage of driver_deferred_probe_check_state()"
Revert "PM: domains: Delete usage of driver_deferred_probe_check_state()"
Revert "net: mdio: Delete usage of driver_deferred_probe_check_state()"
Revert "driver core: Delete driver_deferred_probe_check_state()"
net/ieee802154: fix repeated words in comments
ieee802154/adf7242: defer destroy_workqueue call
Revert "usb: typec: ucsi: add a common function ucsi_unregister_connectors()"
usb: dwc3: qcom: suppress unused-variable warning
MAINTAINERS: add include/dt-bindings/input to INPUT DRIVERS
clk: bcm: rpi: Fix error handling of raspberrypi_fw_get_rate
powerpc/papr_scm: Fix nvdimm event mappings
Input: rk805-pwrkey - fix module autoloading
clk: core: Fix runtime PM sequence in clk_core_unprepare()
clk: core: Honor CLK_OPS_PARENT_ENABLE for clk gate ops
firmware: arm_scmi: Harden accesses to the sensor domains
firmware: arm_scmi: Improve checks in the info_get operations
firmware: arm_scmi: Fix missing kernel-doc in optee
spi: cadence-quadspi: Disable irqs during indirect reads
regulator: core: Clean up on enable failure
ASoC: mediatek: mt8186: fix DMIC record noise
ALSA: memalloc: Revive x86-specific WC page allocations again
mmc: core: Fix inconsistent sd3_bus_mode at UHS-I SD voltage switch failure
mmc: core: Fix UHS-I SD 1.8V workaround branch
pinctrl: qcom: sc8180x: Fix wrong pin numbers
pinctrl: qcom: sc8180x: Fix gpio_wakeirq_map
drm/i915/gvt: Fix Comet Lake
drm/i915/reg: Fix spelling mistake "Unsupport" -> "Unsupported"
arm64: dts: freescale: verdin-imx8mp: fix atmel_mxt_ts reset polarity
arm64: dts: freescale: verdin-imx8mm: fix atmel_mxt_ts reset polarity
arm64: dts: imx8mp: Fix I2C5 GPIO assignment on i.MX8M Plus DHCOM
arm64: dts: imx8mm-venice-gw7901: fix port/phy validation
arm64: dts: verdin-imx8mm: add otg2 pd to usbphy
iio: light: cm32181: make cm32181_pm_ops static
iio: ad7292: Prevent regulator double disable
dt-bindings: iio: gyroscope: bosch,bmg160: correct number of pins
iio: adc: mcp3911: use correct formula for AD conversion
iio: adc: mcp3911: correct "microchip,device-addr" property
soc: imx: gpcv2: Assert reset before ungating clock
arm64: dts: ls1028a-qds-65bb: don't use in-band autoneg for 2500base-x
ARM: dts: imx6qdl-kontron-samx6i: fix spi-flash compatible
ARM: dts: imx6qdl-kontron-samx6i: remove duplicated node
ARM: dts: imx6qdl-vicut1.dtsi: Fix node name backlight_led
RDMA/rtrs-srv: Pass the correct number of entries for dma mapped SGL
RDMA/rtrs-clt: Use the right sg_cnt after ib_dma_map_sg
arm64: dts: imx8mq-tqma8mq: Remove superfluous interrupt-names
arm64: dts: imx8mp: Adjust ECSPI1 pinmux on i.MX8M Plus DHCOM
arm64: dts: imx8mp-venice-gw74xx: fix sai2 pin settings
batman-adv: Fix hang up with small MTU hard-interface
clk: ti: Fix missing of_node_get() ti_find_clock_provider()
riscv: kvm: move extern sbi_ext declarations to a header
riscv: kvm: vcpu_timer: fix unused variable warnings
docs/ja_JP/SubmittingPatches: Remove reference to submitting-drivers.rst
gpio: pxa: use devres for the clock struct
MAINTAINERS: rectify entry for XILINX GPIO DRIVER
KVM: selftests: Fix ambiguous mov in KVM_ASM_SAFE()
KVM: selftests: Fix KVM_EXCEPTION_MAGIC build with Clang
KVM: VMX: Heed the 'msr' argument in msr_write_intercepted()
kvm: x86: mmu: Always flush TLBs when enabling dirty logging
kvm: x86: mmu: Drop the need_remote_flush() function
dt-bindings: usb: mtu3: add compatible for mt8188
USB: cdc-acm: Add Icom PMR F3400 support (0c26:0020)
usb: gadget: f_uac2: fix superspeed transfer
Revert "binder_alloc: Add missing mmap_lock calls when using the VMA"
ARM: dts: versatile: Update spi clock-names property
ARM: dts: realview: Update spi clock-names property
ARM: dts: integratorap: Update spi node properties
usb: xhci-mtk: fix bandwidth release issue
usb: xhci-mtk: relax TT periodic bandwidth allocation
bpf, cgroup: Fix kernel BUG in purge_effective_progs
usb: typec: altmodes/displayport: correct pin assignment for UFP receptacles
ip_tunnel: Respect tunnel key's "flow_flags" in IP tunnels
usb: misc: onboard_usb_hub: Drop reset delay in onboard_hub_power_off()
usb: dwc3: gadget: Avoid duplicate requests to enable Run/Stop
usb: dwc3: pci: Add support for Intel Raptor Lake
usb: typec: intel_pmc_mux: Add new ACPI ID for Meteor Lake IOM device
dt-bindings: usb: qcom,dwc3: Add SM6375 compatible
usb: dwc3: qcom: clean up suspend callbacks
usb: dwc3: qcom: fix wakeup implementation
dt-bindings: usb: qcom,dwc3: add wakeup-source property
usb: dwc3: qcom: fix peripheral and OTG suspend
usb: dwc3: qcom: fix runtime PM wakeup
usb: dwc3: qcom: fix use-after-free on runtime-PM wakeup
usb: dwc3: qcom: fix gadget-only builds
Revert "usb: dwc3: qcom: Keep power domain on to retain controller status"
usb: dwc3: fix PHY disable sequence
docs: kerneldoc-preamble: Test xeCJK.sty before loading
MAINTAINERS: Update email of Neil Armstrong
maintainer-pgp-guide: minor wording tweaks
maintainer-pgp-guide: add a section on PGP-signed patches
maintainer-pgp-guide: update ECC support information
maintainer-pgp-guide: remove keyserver instructions
maintainer-pgp-guide: use key terminology consistent with upstream
Documentation: irqdomain: Fix typo of "at least once"
docs/zh_CN: Update the translation of gpio to 6.0-rc1
usb-storage: Add ignore-residue quirk for NXP PN7462AU
usb: typec: tcpm: Return ENOTSUPP for power supply prop writes
serial: document start_rx member at struct uart_ops
musb: fix USB_MUSB_TUSB6010 dependency
binder_alloc: Add missing mmap_lock calls when using the VMA
binder: fix UAF of ref->proc caused by race condition
regmap: spi: Reserve space for register address/padding
ASoC: SOF: ipc4-topology: fix wrong use of sizeof in sof_ipc4_widget_setup_comp_src()
thunderbolt: Check router generation before connecting xHCI
thunderbolt: Use the actual buffer in tb_async_error()
bpf: Restrict bpf_sys_bpf to CAP_PERFMON
bpf: Partially revert flexible-array member replacement
skmsg: Fix wrong last sg check in sk_msg_recvmsg()
hwmon: (pmbus) Fix vout margin caching
hwmon: (pmbus) Use dev_err_probe() to filter -EPROBE_DEFER error messages
ASoC: qcom: sm8250: add missing module owner
arm64: dts: imx8mm-verdin: use level interrupt for mcp251xfd
arm64: dts: imx8mm-verdin: update CAN clock to 40MHz
Revert "soc: imx: imx8m-blk-ctrl: set power device name"
of: fdt: fix off-by-one error in unflatten_dt_nodes()
workqueue: don't skip lockdep work dependency in cancel_work_sync()
staging: r8188eu: Add Rosewill USB-N150 Nano to device tables
staging: r8188eu: add firmware dependency
ASoC: fsl_sai: fix incorrect mclk number in error message
cpufreq: Add SM6115 to cpufreq-dt-platdev blocklist
OPP: Fix an un-initialized variable usage
iio: light: cm3605: Fix an error handling path in cm3605_probe()
iio: adc: mcp3911: make use of the sign bit
peci: cpu: Fix use-after-free in adev_release()
peci: aspeed: fix error check return value of platform_get_irq()
drm/msm/rd: Fix FIFO-full deadlock
drm/msm/gpu: Drop qos request if devm_devfreq_add_device() fails
ARM: dts: bcmbca: bcm6878: cosmetic change
ARM: dts: bcmbca: bcm6878: fix timer node cpu mask flag
ARM: dts: bcmbca: bcm6846: fix interrupt controller node
ARM: dts: bcmbca: bcm6846: clean up psci node
ARM: dts: bcmbca: bcm6846: fix timer node cpu mask flag
ARM: dts: bcmbca: bcm63178: cosmetic change
ARM: dts: bcmbca: bcm63178: fix interrupt controller node
ARM: dts: bcmbca: bcm63178: clean up psci node
ARM: dts: bcmbca: bcm63178: fix timer node cpu mask flag
tools: hv: Remove an extraneous "the"
drm/hyperv: Fix an error handling path in hyperv_vmbus_probe()
xsk: Fix corrupted packets for XDP_SHARED_UMEM
ASoC: cs42l42: Only report button state if there was a button interrupt
arm64: dts: juno: Add missing MHU secure-irq
arm64: dts: arm: juno: Remove legacy Coresight 'slave-mode' property
platform/surface: aggregator_registry: Add HID devices for sensors and UCSI client to SP8
platform/surface: aggregator_registry: Rename HID device nodes based on new findings
platform/surface: aggregator_registry: Rename HID device nodes based on their function
platform/surface: aggregator_registry: Add support for Surface Laptop Go 2
platform/x86: x86-android-tablets: Fix broken touchscreen on Chuwi Hi8 with Windows BIOS
platform/x86: pmc_atom: Fix SLP_TYPx bitfield mask
drm/i915/gvt: Fix kernel-doc
drm/i915/gvt: Fix kernel-doc
drm/i915/gvt: Fix kernel-doc
drm/i915/gvt: fix typo in comment
spi: bitbang: Fix lsb-first Rx
selftests/bpf: Add lru_bug to s390x deny list
Input: goodix - add support for GT1158
dt-bindings: input: touchscreen: add compatible string for Goodix GT1158
drm/msm/dsi: Fix number of regulators for SDM660
drm/msm/dsi: Fix number of regulators for msm8996_dsi_cfg
drm/msm/dp: delete DP_RECOVERED_CLOCK_OUT_EN to fix tps4
MAINTAINERS: add the Polarfire SoC's i2c driver
MAINTAINERS: add PolarFire SoC dt bindings
fsdax: Fix infinite loop in dax_iomap_rw()
drm/msm/dpu: populate wb or intf before reset_intf_cfg
drm/msm/dsi: fix the inconsistent indenting
drm/msm/dp: make eDP panel as the first connected connector
nvdimm/namespace: drop nested variable in create_namespace_pmem()
ndtest: Cleanup all of blk namespace specific code
pmem: fix a name collision
ARM: dts: am33xx: Fix MMCHS0 dma properties
Conflicts:
Documentation/devicetree/bindings
Documentation/devicetree/bindings/arm/amlogic/amlogic,meson-gx-ao-secure.yaml
Documentation/devicetree/bindings/display/amlogic,meson-dw-hdmi.yaml
Documentation/devicetree/bindings/display/amlogic,meson-vpu.yaml
Documentation/devicetree/bindings/display/bridge/analogix,anx7814.yaml
Documentation/devicetree/bindings/display/bridge/ite,it66121.yaml
Documentation/devicetree/bindings/display/panel/sgd,gktw70sdae4se.yaml
Documentation/devicetree/bindings/dma/moxa,moxart-dma.txt
Documentation/devicetree/bindings/hwmon/moortec,mr75203.yaml
Documentation/devicetree/bindings/i2c/amlogic,meson6-i2c.yaml
Documentation/devicetree/bindings/i2c/renesas,riic.yaml
Documentation/devicetree/bindings/i2c/st,stm32-i2c.yaml
Documentation/devicetree/bindings/iio/gyroscope/bosch,bmg160.yaml
Documentation/devicetree/bindings/input/touchscreen/goodix.yaml
Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml
Documentation/devicetree/bindings/interrupt-controller/apple,aic.yaml
Documentation/devicetree/bindings/mailbox/amlogic,meson-gxbb-mhu.yaml
Documentation/devicetree/bindings/media/amlogic,axg-ge2d.yaml
Documentation/devicetree/bindings/media/amlogic,gx-vdec.yaml
Documentation/devicetree/bindings/media/amlogic,meson-gx-ao-cec.yaml
Documentation/devicetree/bindings/memory-controllers/fsl/imx8m-ddrc.yaml
Documentation/devicetree/bindings/mfd/khadas,mcu.yaml
Documentation/devicetree/bindings/net/amlogic,meson-dwmac.yaml
Documentation/devicetree/bindings/opp/opp-v2-kryo-cpu.yaml
Documentation/devicetree/bindings/opp/opp-v2-qcom-level.yaml
Documentation/devicetree/bindings/phy/amlogic,axg-mipi-dphy.yaml
Documentation/devicetree/bindings/phy/amlogic,meson-g12a-usb2-phy.yaml
Documentation/devicetree/bindings/phy/amlogic,meson-g12a-usb3-pcie-phy.yaml
Documentation/devicetree/bindings/pinctrl/qcom,sc7280-lpass-lpi-pinctrl.yaml
Documentation/devicetree/bindings/pinctrl/qcom,sc7280-pinctrl.yaml
Documentation/devicetree/bindings/power/amlogic,meson-ee-pwrc.yaml
Documentation/devicetree/bindings/power/qcom,rpmpd.yaml
Documentation/devicetree/bindings/regulator/qcom,spmi-regulator.yaml
Documentation/devicetree/bindings/reset/amlogic,meson-reset.yaml
Documentation/devicetree/bindings/riscv/sifive-l2-cache.yaml
Documentation/devicetree/bindings/rng/amlogic,meson-rng.yaml
Documentation/devicetree/bindings/serial/amlogic,meson-uart.yaml
Documentation/devicetree/bindings/soc/amlogic/amlogic,canvas.yaml
Documentation/devicetree/bindings/spi/amlogic,meson-gx-spicc.yaml
Documentation/devicetree/bindings/spi/amlogic,meson6-spifc.yaml
Documentation/devicetree/bindings/usb/amlogic,meson-g12a-usb-ctrl.yaml
Documentation/devicetree/bindings/usb/mediatek,mtu3.yaml
Documentation/devicetree/bindings/usb/qcom,dwc3.yaml
Documentation/devicetree/bindings/watchdog/amlogic,meson-gxbb-wdt.yaml
drivers/bus/mhi/host/main.c
drivers/cpufreq/qcom-cpufreq-hw.c
kernel/sched/Makefile
Change-Id: I399f2841e8004cc7dd00ef6547f0fff1305beb02
Upstream-Build:ks_qcom-android-mainline-keystone-qcom-release@9153521 SKQ4.221007.002
Signed-off-by: jianzhou <quic_jianzhou@quicinc.com>
2022-10-24 15:33:09 +09:00
|
|
|
dev_err(chip->dev, "Cannot configure ramp for PFM-enabled channel %d\n",
|
|
|
|
lpg_chan_id);
|
2021-04-27 17:44:10 +09:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2019-11-23 07:40:14 +09:00
|
|
|
if (chip->use_sdam) {
|
|
|
|
rc = of_property_read_u32(child,
|
|
|
|
"qcom,lpg-sdam-base",
|
|
|
|
&tmp);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(chip->dev, "get qcom,lpg-sdam-base failed for lpg%d, rc=%d\n",
|
|
|
|
lpg_chan_id, rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
chip->lpgs[lpg_chan_id - 1].lpg_sdam_base = tmp;
|
|
|
|
}
|
|
|
|
|
2021-04-14 06:50:32 +09:00
|
|
|
rc = qpnp_lpg_parse_ramp_props_dt(child, chip, lpg_chan_id,
|
|
|
|
max_count);
|
|
|
|
if (rc) {
|
|
|
|
dev_err(chip->dev, "Parsing ramp props failed for lpg%d, rc=%d\n",
|
|
|
|
lpg_chan_id, rc);
|
2019-11-23 07:40:14 +09:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = of_property_count_elems_of_size(chip->dev->of_node,
|
|
|
|
"qcom,sync-channel-ids", sizeof(u32));
|
|
|
|
if (rc < 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
length = rc;
|
|
|
|
if (length > chip->num_lpgs) {
|
|
|
|
dev_err(chip->dev, "qcom,sync-channel-ids has too many channels: %d\n",
|
|
|
|
length);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
chip->lpg_group = devm_kcalloc(chip->dev, chip->num_lpgs,
|
|
|
|
sizeof(u32), GFP_KERNEL);
|
|
|
|
if (!chip->lpg_group)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
rc = of_property_read_u32_array(chip->dev->of_node,
|
|
|
|
"qcom,sync-channel-ids", chip->lpg_group, length);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(chip->dev, "Get qcom,sync-channel-ids failed, rc=%d\n",
|
|
|
|
rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < length; i++) {
|
|
|
|
if (chip->lpg_group[i] <= 0 ||
|
|
|
|
chip->lpg_group[i] > chip->num_lpgs) {
|
|
|
|
dev_err(chip->dev, "lpg_group[%d]: %d is not a valid channel\n",
|
|
|
|
i, chip->lpg_group[i]);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The LPG channel in the same group should have the same ramping
|
|
|
|
* configuration, so force to use the ramping configuration of the
|
|
|
|
* 1st LPG channel in the group for synchronization.
|
|
|
|
*/
|
|
|
|
lpg = &chip->lpgs[chip->lpg_group[0] - 1];
|
|
|
|
ramp = &lpg->ramp_config;
|
|
|
|
|
|
|
|
for (i = 1; i < length; i++) {
|
|
|
|
lpg = &chip->lpgs[chip->lpg_group[i] - 1];
|
|
|
|
memcpy(&lpg->ramp_config, ramp, sizeof(struct lpg_ramp_config));
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-01-29 08:09:03 +09:00
|
|
|
static bool lut_is_defined(struct qpnp_lpg_chip *chip, const __be32 **addr)
|
|
|
|
{
|
|
|
|
*addr = of_get_address(chip->dev->of_node, 1, NULL, NULL);
|
|
|
|
if (*addr == NULL)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-05-27 11:21:23 +09:00
|
|
|
static int qpnp_lpg_get_nvmem_dt(struct qpnp_lpg_chip *chip)
|
|
|
|
{
|
|
|
|
int rc = 0;
|
|
|
|
struct nvmem_device *ppg_nv, *lut_nv, *lpg_nv;
|
|
|
|
|
|
|
|
/* Ensure backward compatibility */
|
|
|
|
ppg_nv = devm_nvmem_device_get(chip->dev, "ppg_sdam");
|
|
|
|
if (IS_ERR(ppg_nv)) {
|
|
|
|
lut_nv = devm_nvmem_device_get(chip->dev, "lut_sdam");
|
|
|
|
if (IS_ERR(lut_nv)) {
|
|
|
|
rc = PTR_ERR(lut_nv);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
lpg_nv = devm_nvmem_device_get(chip->dev, "lpg_chan_sdam");
|
|
|
|
if (IS_ERR(lpg_nv)) {
|
|
|
|
rc = PTR_ERR(lpg_nv);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
chip->lut_nvmem = lut_nv;
|
|
|
|
chip->lpg_chan_nvmem = lpg_nv;
|
2020-05-27 11:22:03 +09:00
|
|
|
chip->lut->nvmem_count = PPG_NVMEMS_2;
|
2020-05-27 11:21:23 +09:00
|
|
|
} else {
|
|
|
|
chip->lut_nvmem = chip->lpg_chan_nvmem = ppg_nv;
|
2020-05-27 11:22:03 +09:00
|
|
|
chip->lut->nvmem_count = PPG_NVMEMS_1;
|
2020-05-27 11:21:23 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
err:
|
|
|
|
if (rc != -EPROBE_DEFER)
|
|
|
|
dev_err(chip->dev, "Failed to get nvmem device, rc=%d\n",
|
|
|
|
rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2021-04-27 17:44:10 +09:00
|
|
|
static int qpnp_lpg_parse_pfm_support(struct qpnp_lpg_chip *chip)
|
|
|
|
{
|
|
|
|
u32 chan_idx;
|
|
|
|
u32 num_pfm_channels;
|
|
|
|
u8 val;
|
|
|
|
int i, rc;
|
|
|
|
|
|
|
|
rc = of_property_count_elems_of_size(chip->dev->of_node,
|
|
|
|
"qcom,pfm-chan-ids",
|
|
|
|
sizeof(u32));
|
|
|
|
if (rc < 0)
|
|
|
|
return rc;
|
|
|
|
|
|
|
|
if (rc == 0 || rc > chip->num_lpgs)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
num_pfm_channels = rc;
|
|
|
|
|
|
|
|
for (i = 0; i < num_pfm_channels; i++) {
|
|
|
|
rc = of_property_read_u32_index(chip->dev->of_node,
|
|
|
|
"qcom,pfm-chan-ids", i, &chan_idx);
|
|
|
|
if (rc) {
|
|
|
|
dev_err(chip->dev, "Read pfm channel %d failed, rc=%d\n",
|
|
|
|
i, rc);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (chan_idx < 1 || chan_idx > chip->num_lpgs) {
|
|
|
|
dev_err(chip->dev, "pfm chan id %u is out of range 1~%d\n",
|
|
|
|
chan_idx, chip->num_lpgs);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
chan_idx--; /* zero-based indexing */
|
|
|
|
|
2022-06-09 05:51:35 +09:00
|
|
|
if (chip->lpgs[chan_idx].subtype == SUBTYPE_PWM ||
|
|
|
|
chip->lpgs[chan_idx].subtype == SUBTYPE_HI_RES_PWM) {
|
2021-04-27 17:44:10 +09:00
|
|
|
rc = qpnp_lpg_read(&chip->lpgs[chan_idx],
|
|
|
|
REG_PWM_STATUS1, &val);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(chip->dev, "Read status1 failed, rc=%d\n",
|
|
|
|
rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (val & FM_MODE_PRESENT)
|
|
|
|
chip->lpgs[chan_idx].enable_pfm = true;
|
|
|
|
else
|
|
|
|
return -EOPNOTSUPP;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2020-05-27 09:56:41 +09:00
|
|
|
#define DEFAULT_TICK_DURATION_US 7800
|
2020-01-29 08:09:03 +09:00
|
|
|
static int qpnp_lpg_parse_dt(struct qpnp_lpg_chip *chip)
|
|
|
|
{
|
|
|
|
int rc = 0, i;
|
|
|
|
u32 base;
|
|
|
|
const __be32 *addr;
|
|
|
|
|
|
|
|
rc = qpnp_get_lpg_channels(chip, &base);
|
|
|
|
if (rc < 0)
|
|
|
|
return rc;
|
|
|
|
|
|
|
|
chip->lpgs = devm_kcalloc(chip->dev, chip->num_lpgs,
|
|
|
|
sizeof(*chip->lpgs), GFP_KERNEL);
|
|
|
|
if (!chip->lpgs)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
for (i = 0; i < chip->num_lpgs; i++) {
|
|
|
|
chip->lpgs[i].chip = chip;
|
|
|
|
chip->lpgs[i].lpg_idx = i;
|
|
|
|
chip->lpgs[i].reg_base = base + i * REG_SIZE_PER_LPG;
|
|
|
|
chip->lpgs[i].src_sel = PWM_VALUE;
|
|
|
|
rc = qpnp_lpg_read(&chip->lpgs[i], REG_LPG_PERPH_SUBTYPE,
|
|
|
|
&chip->lpgs[i].subtype);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(chip->dev, "Read subtype failed, rc=%d\n", rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-27 17:44:10 +09:00
|
|
|
if (of_find_property(chip->dev->of_node,
|
|
|
|
"qcom,pfm-chan-ids", NULL)) {
|
|
|
|
rc = qpnp_lpg_parse_pfm_support(chip);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(chip->dev, "PFM channels specified incorrectly\n");
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-29 08:09:03 +09:00
|
|
|
if (of_find_property(chip->dev->of_node, "nvmem", NULL)) {
|
2020-04-15 09:56:38 +09:00
|
|
|
chip->lut = devm_kmalloc(chip->dev, sizeof(*chip->lut),
|
|
|
|
GFP_KERNEL);
|
|
|
|
if (!chip->lut)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
2020-05-27 11:21:23 +09:00
|
|
|
rc = qpnp_lpg_get_nvmem_dt(chip);
|
|
|
|
if (rc < 0)
|
2020-01-29 08:09:03 +09:00
|
|
|
return rc;
|
|
|
|
|
|
|
|
chip->use_sdam = true;
|
2020-05-27 11:22:03 +09:00
|
|
|
if (of_find_property(chip->dev->of_node, "qcom,pbs-client",
|
|
|
|
NULL)) {
|
|
|
|
chip->pbs_dev_node = of_parse_phandle(
|
|
|
|
chip->dev->of_node,
|
|
|
|
"qcom,pbs-client", 0);
|
|
|
|
if (!chip->pbs_dev_node) {
|
|
|
|
dev_err(chip->dev, "Missing qcom,pbs-client property\n");
|
|
|
|
return -ENODEV;
|
|
|
|
}
|
2020-01-29 08:09:03 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
rc = of_property_read_u32(chip->dev->of_node,
|
|
|
|
"qcom,lut-sdam-base", &chip->lut->reg_base);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(chip->dev, "Read qcom,lut-sdam-base failed, rc=%d\n",
|
|
|
|
rc);
|
|
|
|
of_node_put(chip->pbs_dev_node);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2020-05-27 09:56:41 +09:00
|
|
|
chip->lut->ramp_step_tick_us = DEFAULT_TICK_DURATION_US;
|
2021-11-10 08:42:39 +09:00
|
|
|
of_property_read_u32(chip->dev->of_node, "qcom,tick-duration-us",
|
2020-05-27 09:56:41 +09:00
|
|
|
&chip->lut->ramp_step_tick_us);
|
|
|
|
|
2020-01-29 08:09:03 +09:00
|
|
|
rc = qpnp_lpg_parse_pattern_dt(chip, SDAM_LUT_COUNT_MAX);
|
|
|
|
if (rc < 0) {
|
|
|
|
of_node_put(chip->pbs_dev_node);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
} else if (lut_is_defined(chip, &addr)) {
|
2020-04-15 09:56:38 +09:00
|
|
|
chip->lut = devm_kmalloc(chip->dev, sizeof(*chip->lut),
|
|
|
|
GFP_KERNEL);
|
|
|
|
if (!chip->lut)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
2020-01-29 08:09:03 +09:00
|
|
|
chip->lut->reg_base = be32_to_cpu(*addr);
|
|
|
|
|
2020-04-15 09:56:38 +09:00
|
|
|
rc = qpnp_lpg_parse_pattern_dt(chip, LPG_LUT_COUNT_MAX);
|
|
|
|
if (rc < 0)
|
|
|
|
return rc;
|
|
|
|
} else {
|
|
|
|
pr_debug("Neither SDAM nor LUT specified\n");
|
|
|
|
}
|
2020-01-29 08:09:03 +09:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-11-23 07:40:14 +09:00
|
|
|
static int qpnp_lpg_sdam_hw_init(struct qpnp_lpg_chip *chip)
|
|
|
|
{
|
|
|
|
struct qpnp_lpg_channel *lpg;
|
|
|
|
int i, rc = 0;
|
|
|
|
|
|
|
|
if (!chip->use_sdam)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
for (i = 0; i < chip->num_lpgs; i++) {
|
|
|
|
lpg = &chip->lpgs[i];
|
|
|
|
if (lpg->lpg_sdam_base != 0) {
|
|
|
|
rc = qpnp_lpg_sdam_write(lpg, SDAM_LUT_EN_OFFSET, 0);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(chip->dev, "Write SDAM_REG_LUT_EN failed, rc=%d\n",
|
|
|
|
rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
rc = qpnp_lpg_sdam_write(lpg,
|
|
|
|
SDAM_PBS_SCRATCH_LUT_COUNTER_OFFSET, 0);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(lpg->chip->dev, "Write SDAM_REG_PBS_SCRATCH_LUT_COUNTER failed, rc=%d\n",
|
|
|
|
rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int qpnp_lpg_probe(struct platform_device *pdev)
|
|
|
|
{
|
2021-04-27 17:44:10 +09:00
|
|
|
int rc, i;
|
2019-11-23 07:40:14 +09:00
|
|
|
struct qpnp_lpg_chip *chip;
|
2021-04-27 17:44:10 +09:00
|
|
|
struct qpnp_lpg_channel *lpg;
|
2019-11-23 07:40:14 +09:00
|
|
|
|
|
|
|
chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
|
|
|
|
if (!chip)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
chip->dev = &pdev->dev;
|
|
|
|
chip->regmap = dev_get_regmap(chip->dev->parent, NULL);
|
|
|
|
if (!chip->regmap) {
|
|
|
|
dev_err(chip->dev, "Getting regmap failed\n");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
mutex_init(&chip->bus_lock);
|
|
|
|
rc = qpnp_lpg_parse_dt(chip);
|
|
|
|
if (rc < 0) {
|
2021-02-02 11:30:03 +09:00
|
|
|
if (rc != -EPROBE_DEFER)
|
|
|
|
dev_err(chip->dev, "Devicetree properties parsing failed, rc=%d\n",
|
2019-11-23 07:40:14 +09:00
|
|
|
rc);
|
|
|
|
goto err_out;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = qpnp_lpg_sdam_hw_init(chip);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(chip->dev, "SDAM HW init failed, rc=%d\n",
|
|
|
|
rc);
|
|
|
|
goto err_out;
|
|
|
|
}
|
|
|
|
|
2021-04-27 17:44:10 +09:00
|
|
|
for (i = 0; i < chip->num_lpgs; i++) {
|
|
|
|
lpg = &chip->lpgs[i];
|
2021-09-23 08:14:19 +09:00
|
|
|
lpg->output_type = PWM_OUTPUT_FIXED;
|
2023-05-23 06:12:09 +09:00
|
|
|
|
2024-03-01 20:41:18 +09:00
|
|
|
if (chip->lut != NULL) {
|
|
|
|
rc = qpnp_lpg_pwm_src_enable(lpg, false);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(chip->dev, "Disable PWM output failed for channel %d, rc=%d\n",
|
2023-05-23 06:12:09 +09:00
|
|
|
lpg->lpg_idx, rc);
|
2024-03-01 20:41:18 +09:00
|
|
|
return rc;
|
|
|
|
}
|
2023-05-23 06:12:09 +09:00
|
|
|
}
|
|
|
|
|
2021-04-27 17:44:10 +09:00
|
|
|
if (lpg->enable_pfm) {
|
|
|
|
rc = qpnp_lpg_write(lpg, REG_PWM_FM_MODE,
|
|
|
|
FM_MODE_ENABLE);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(chip->dev, "Write fm_mode_enable failed, rc=%d\n",
|
|
|
|
rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-23 07:40:14 +09:00
|
|
|
dev_set_drvdata(chip->dev, chip);
|
|
|
|
chip->pwm_chip.dev = chip->dev;
|
|
|
|
chip->pwm_chip.base = -1;
|
|
|
|
chip->pwm_chip.npwm = chip->num_lpgs;
|
|
|
|
chip->pwm_chip.ops = &qpnp_lpg_pwm_ops;
|
|
|
|
|
|
|
|
rc = pwmchip_add(&chip->pwm_chip);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(chip->dev, "Add pwmchip failed, rc=%d\n", rc);
|
|
|
|
goto err_out;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
err_out:
|
|
|
|
mutex_destroy(&chip->bus_lock);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int qpnp_lpg_remove(struct platform_device *pdev)
|
|
|
|
{
|
|
|
|
struct qpnp_lpg_chip *chip = dev_get_drvdata(&pdev->dev);
|
|
|
|
|
2020-05-27 11:22:03 +09:00
|
|
|
of_node_put(chip->pbs_dev_node);
|
2021-09-23 12:32:24 +09:00
|
|
|
pwmchip_remove(&chip->pwm_chip);
|
2019-11-23 07:40:14 +09:00
|
|
|
mutex_destroy(&chip->bus_lock);
|
|
|
|
dev_set_drvdata(chip->dev, NULL);
|
|
|
|
|
2021-09-23 12:32:24 +09:00
|
|
|
return 0;
|
2019-11-23 07:40:14 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
static const struct of_device_id qpnp_lpg_of_match[] = {
|
|
|
|
{ .compatible = "qcom,pwm-lpg",},
|
|
|
|
{ },
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct platform_driver qpnp_lpg_driver = {
|
|
|
|
.driver = {
|
|
|
|
.name = "qcom,pwm-lpg",
|
|
|
|
.of_match_table = qpnp_lpg_of_match,
|
|
|
|
},
|
|
|
|
.probe = qpnp_lpg_probe,
|
|
|
|
.remove = qpnp_lpg_remove,
|
|
|
|
};
|
|
|
|
module_platform_driver(qpnp_lpg_driver);
|
|
|
|
|
|
|
|
MODULE_DESCRIPTION("QTI LPG driver");
|
|
|
|
MODULE_LICENSE("GPL v2");
|
|
|
|
MODULE_ALIAS("pwm:pwm-lpg");
|