diff --git a/drivers/pwm/pwm-rockchip-irq-callbacks.h b/drivers/pwm/pwm-rockchip-irq-callbacks.h index c157fef5d6ed..fe238d87e63c 100644 --- a/drivers/pwm/pwm-rockchip-irq-callbacks.h +++ b/drivers/pwm/pwm-rockchip-irq-callbacks.h @@ -7,6 +7,7 @@ #define _PWM_ROCKCHIP_IRQ_CALLBACKS_H_ #include +#include static void rockchip_pwm_oneshot_callback(struct pwm_device *pwm, struct pwm_state *state) { diff --git a/drivers/pwm/pwm-rockchip.c b/drivers/pwm/pwm-rockchip.c index 86f638f50ecd..4dd469f146ae 100644 --- a/drivers/pwm/pwm-rockchip.c +++ b/drivers/pwm/pwm-rockchip.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include "pwm-rockchip-irq-callbacks.h" @@ -52,7 +53,6 @@ #define PWM_ONESHOT_COUNT_SHIFT 24 #define PWM_ONESHOT_COUNT_MASK (0xff << PWM_ONESHOT_COUNT_SHIFT) -#define PWM_ONESHOT_COUNT_MAX 256 #define PWM_REG_INTSTS(n) ((3 - (n)) * 0x10 + 0x10) #define PWM_REG_INT_EN(n) ((3 - (n)) * 0x10 + 0x14) @@ -73,8 +73,12 @@ struct rockchip_pwm_chip { bool vop_pwm_en; /* indicate voppwm mirror register state */ bool center_aligned; bool oneshot_en; + bool freq_meter_support; + bool counter_support; + bool wave_support; int channel_id; int irq; + u8 capture_cnt; }; struct rockchip_pwm_regs { @@ -82,16 +86,45 @@ struct rockchip_pwm_regs { unsigned long period; unsigned long cntr; unsigned long ctrl; + unsigned long version; +}; + +struct rockchip_pwm_funcs { + int (*enable)(struct pwm_chip *chip, struct pwm_device *pwm, bool enable); + void (*config)(struct pwm_chip *chip, struct pwm_device *pwm, + const struct pwm_state *state); + void (*set_capture)(struct pwm_chip *chip, struct pwm_device *pwm, bool enable); + int (*get_capture_result)(struct pwm_chip *chip, struct pwm_device *pwm, + struct pwm_capture *catpure_res); + int (*set_counter)(struct pwm_chip *chip, struct pwm_device *pwm, bool enable); + int (*get_counter_result)(struct pwm_chip *chip, struct pwm_device *pwm, + unsigned long *counter_res, bool is_clear); + int (*set_freq_meter)(struct pwm_chip *chip, struct pwm_device *pwm, + bool enable, unsigned long delay_ms); + int (*get_freq_meter_result)(struct pwm_chip *chip, struct pwm_device *pwm, + unsigned long delay_ms, unsigned long *freq_hz); + int (*global_ctrl)(struct pwm_chip *chip, struct pwm_device *pwm, + enum rockchip_pwm_global_ctrl_cmd cmd); + int (*set_wave_table)(struct pwm_chip *chip, struct pwm_device *pwm, + struct rockchip_pwm_wave_table *table_config, + enum rockchip_pwm_wave_table_width_mode width_mode); + int (*set_wave)(struct pwm_chip *chip, struct pwm_device *pwm, + struct rockchip_pwm_wave_config *config); + irqreturn_t (*irq_handler)(int irq, void *data); }; struct rockchip_pwm_data { struct rockchip_pwm_regs regs; + struct rockchip_pwm_funcs funcs; unsigned int prescaler; bool supports_polarity; bool supports_lock; bool vop_pwm; u32 enable_conf; u32 enable_conf_mask; + u32 oneshot_cnt_max; + u32 oneshot_rpt_max; + u32 wave_table_max; }; static inline struct rockchip_pwm_chip *to_rockchip_pwm_chip(struct pwm_chip *c) @@ -107,7 +140,7 @@ static void rockchip_pwm_get_state(struct pwm_chip *chip, u32 enable_conf = pc->data->enable_conf; u64 tmp; u32 val; - u32 dclk_div; + u32 dclk_div = 1; int ret; if (!pc->oneshot_en) { @@ -140,7 +173,7 @@ static void rockchip_pwm_get_state(struct pwm_chip *chip, clk_disable(pc->pclk); } -static irqreturn_t rockchip_pwm_oneshot_irq(int irq, void *data) +static irqreturn_t rockchip_pwm_irq_v1(int irq, void *data) { struct rockchip_pwm_chip *pc = data; struct pwm_state state; @@ -168,8 +201,8 @@ static irqreturn_t rockchip_pwm_oneshot_irq(int irq, void *data) return IRQ_HANDLED; } -static void rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, - const struct pwm_state *state) +static void rockchip_pwm_config_v1(struct pwm_chip *chip, struct pwm_device *pwm, + const struct pwm_state *state) { struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); unsigned long period, duty, delay_ns; @@ -179,7 +212,7 @@ static void rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, u8 dclk_div = 1; #ifdef CONFIG_PWM_ROCKCHIP_ONESHOT - if (state->oneshot_count > 0 && state->oneshot_count <= PWM_ONESHOT_COUNT_MAX) + if (state->oneshot_count > 0 && state->oneshot_count <= pc->data->oneshot_cnt_max) dclk_div = 2; #endif @@ -210,7 +243,7 @@ static void rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, } #ifdef CONFIG_PWM_ROCKCHIP_ONESHOT - if (state->oneshot_count > 0 && state->oneshot_count <= PWM_ONESHOT_COUNT_MAX) { + if (state->oneshot_count > 0 && state->oneshot_count <= pc->data->oneshot_cnt_max) { u32 int_ctrl; /* @@ -233,9 +266,11 @@ static void rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, ctrl &= ~PWM_ONESHOT_COUNT_MASK; ctrl |= (state->oneshot_count - 1) << PWM_ONESHOT_COUNT_SHIFT; - int_ctrl = readl_relaxed(pc->base + PWM_REG_INT_EN(pc->channel_id)); - int_ctrl |= PWM_CH_INT(pc->channel_id); - writel_relaxed(int_ctrl, pc->base + PWM_REG_INT_EN(pc->channel_id)); + if (pc->irq >= 0) { + int_ctrl = readl_relaxed(pc->base + PWM_REG_INT_EN(pc->channel_id)); + int_ctrl |= PWM_CH_INT(pc->channel_id); + writel_relaxed(int_ctrl, pc->base + PWM_REG_INT_EN(pc->channel_id)); + } } else { u32 int_ctrl; @@ -244,7 +279,8 @@ static void rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, ctrl |= PWM_SEL_NO_SCALED_CLOCK; if (state->oneshot_count) - dev_err(chip->dev, "Oneshot_count must be between 1 and 256.\n"); + dev_err(chip->dev, "Oneshot_count must be between 1 and %d.\n", + pc->data->oneshot_cnt_max); pc->oneshot_en = false; ctrl &= ~PWM_MODE_MASK; @@ -292,9 +328,7 @@ static void rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, local_irq_restore(flags); } -static int rockchip_pwm_enable(struct pwm_chip *chip, - struct pwm_device *pwm, - bool enable) +static int rockchip_pwm_enable_v1(struct pwm_chip *chip, struct pwm_device *pwm, bool enable) { struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); u32 enable_conf = pc->data->enable_conf; @@ -333,6 +367,21 @@ static int rockchip_pwm_enable(struct pwm_chip *chip, return 0; } +static void rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, + const struct pwm_state *state) +{ + struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); + + pc->data->funcs.config(chip, pwm, state); +} + +static int rockchip_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm, bool enable) +{ + struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); + + return pc->data->funcs.enable(chip, pwm, enable); +} + static int rockchip_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, const struct pwm_state *state) { @@ -374,6 +423,235 @@ out: return ret; } +int rockchip_pwm_set_counter(struct pwm_device *pwm, bool enable) +{ + struct pwm_chip *chip; + struct rockchip_pwm_chip *pc; + struct pwm_state curstate; + int ret = 0; + + if (!pwm) + return -EINVAL; + + chip = pwm->chip; + pc = to_rockchip_pwm_chip(chip); + + if (!pc->counter_support || + !pc->data->funcs.set_counter || !pc->data->funcs.get_counter_result) { + dev_err(chip->dev, "Unsupported counter mode\n"); + return -EINVAL; + } + + pwm_get_state(pwm, &curstate); + if (curstate.enabled) { + dev_err(chip->dev, "Failed to enable counter mode because PWM%d is busy\n", + pc->channel_id); + return -EBUSY; + } + + ret = clk_enable(pc->pclk); + if (ret) + return ret; + + ret = pc->data->funcs.set_counter(chip, pwm, enable); + if (ret) { + dev_err(chip->dev, "Failed to abtain counter arbitration for PWM%d\n", + pc->channel_id); + goto err_disable_pclk; + } + +err_disable_pclk: + clk_disable(pc->pclk); + + return ret; +} +EXPORT_SYMBOL_GPL(rockchip_pwm_set_counter); + +int rockchip_pwm_get_counter_result(struct pwm_device *pwm, + unsigned long *counter_res, bool is_clear) +{ + struct pwm_chip *chip; + struct rockchip_pwm_chip *pc; + int ret = 0; + + if (!pwm || !counter_res) + return -EINVAL; + + chip = pwm->chip; + pc = to_rockchip_pwm_chip(chip); + + if (!pc->counter_support || + !pc->data->funcs.set_counter || !pc->data->funcs.get_counter_result) { + dev_err(chip->dev, "Unsupported counter mode\n"); + return -EINVAL; + } + + ret = clk_enable(pc->pclk); + if (ret) + return ret; + + ret = pc->data->funcs.get_counter_result(chip, pwm, counter_res, is_clear); + if (ret) { + dev_err(chip->dev, "Failed to get counter result for PWM%d\n", + pc->channel_id); + goto err_disable_pclk; + } + +err_disable_pclk: + clk_disable(pc->pclk); + + return ret; +} +EXPORT_SYMBOL_GPL(rockchip_pwm_get_counter_result); + +int rockchip_pwm_set_freq_meter(struct pwm_device *pwm, unsigned long delay_ms, + unsigned long *freq_hz) +{ + struct pwm_chip *chip; + struct rockchip_pwm_chip *pc; + struct pwm_state curstate; + int ret = 0; + + if (!pwm || !freq_hz) + return -EINVAL; + + chip = pwm->chip; + pc = to_rockchip_pwm_chip(chip); + + if (!pc->freq_meter_support || + !pc->data->funcs.set_freq_meter || !pc->data->funcs.get_freq_meter_result) { + dev_err(chip->dev, "Unsupported frequency meter mode\n"); + return -EINVAL; + } + + pwm_get_state(pwm, &curstate); + if (curstate.enabled) { + dev_err(chip->dev, "Failed to enable frequency meter mode because PWM%d is busy\n", + pc->channel_id); + return -EBUSY; + } + + ret = clk_enable(pc->pclk); + if (ret) + return ret; + + ret = pc->data->funcs.set_freq_meter(chip, pwm, true, delay_ms); + if (ret) { + dev_err(chip->dev, "Failed to abtain frequency meter arbitration for PWM%d\n", + pc->channel_id); + } else { + ret = pc->data->funcs.get_freq_meter_result(chip, pwm, delay_ms, freq_hz); + if (ret) { + dev_err(chip->dev, "Failed to get frequency meter result for PWM%d\n", + pc->channel_id); + } + } + pc->data->funcs.set_freq_meter(chip, pwm, false, 0); + + clk_disable(pc->pclk); + + return ret; +} +EXPORT_SYMBOL_GPL(rockchip_pwm_set_freq_meter); + +int rockchip_pwm_global_ctrl(struct pwm_device *pwm, enum rockchip_pwm_global_ctrl_cmd cmd) +{ + struct pwm_chip *chip; + struct rockchip_pwm_chip *pc; + struct pwm_state curstate; + int ret = 0; + + if (!pwm) + return -EINVAL; + + chip = pwm->chip; + pc = to_rockchip_pwm_chip(chip); + + if (!pc->data->funcs.global_ctrl) { + dev_err(chip->dev, "Unsupported global control\n"); + return -EINVAL; + } + + pwm_get_state(pwm, &curstate); + if (curstate.enabled) { + dev_err(chip->dev, "Failed to execute global ctrl cmd %d because PWM%d is busy\n", + cmd, pc->channel_id); + return -EBUSY; + } + + ret = clk_enable(pc->pclk); + if (ret) + return ret; + + ret = pc->data->funcs.global_ctrl(chip, pwm, cmd); + if (ret) { + dev_err(chip->dev, "Failed to execute global ctrl cmd %d for PWM%d\n", + cmd, pc->channel_id); + goto err_disable_pclk; + } + +err_disable_pclk: + clk_disable(pc->pclk); + + return ret; +} +EXPORT_SYMBOL_GPL(rockchip_pwm_global_ctrl); + +int rockchip_pwm_set_wave(struct pwm_device *pwm, struct rockchip_pwm_wave_config *config) +{ + struct pwm_chip *chip; + struct rockchip_pwm_chip *pc; + int ret = 0; + + if (!pwm || !config) + return -EINVAL; + + chip = pwm->chip; + pc = to_rockchip_pwm_chip(chip); + + if (!pc->wave_support || + !pc->data->funcs.set_wave_table || !pc->data->funcs.set_wave) { + dev_err(chip->dev, "Unsupported wave generator mode\n"); + return -EINVAL; + } + + ret = clk_enable(pc->pclk); + if (ret) + return ret; + + if (config->duty_table) { + ret = pc->data->funcs.set_wave_table(chip, pwm, config->duty_table, + config->width_mode); + if (ret) { + dev_err(chip->dev, "Failed to set wave duty table for PWM%d\n", + pc->channel_id); + goto err_disable_pclk; + } + } + + if (config->period_table) { + ret = pc->data->funcs.set_wave_table(chip, pwm, config->period_table, + config->width_mode); + if (ret) { + dev_err(chip->dev, "Failed to set wave period table for PWM%d\n", + pc->channel_id); + goto err_disable_pclk; + } + } + + ret = pc->data->funcs.set_wave(chip, pwm, config); + if (ret) { + dev_err(chip->dev, "Failed to set wave generator for PWM%d\n", pc->channel_id); + goto err_disable_pclk; + } + +err_disable_pclk: + clk_disable(pc->pclk); + + return ret; +} +EXPORT_SYMBOL_GPL(rockchip_pwm_set_wave); + #ifdef CONFIG_DEBUG_FS static int rockchip_pwm_debugfs_show(struct seq_file *s, void *data) { @@ -433,6 +711,7 @@ static const struct pwm_ops rockchip_pwm_ops = { static const struct rockchip_pwm_data pwm_data_v1 = { .regs = { + .version = 0x5c, .duty = 0x04, .period = 0x08, .cntr = 0x00, @@ -444,10 +723,16 @@ static const struct rockchip_pwm_data pwm_data_v1 = { .vop_pwm = false, .enable_conf = PWM_CTRL_OUTPUT_EN | PWM_CTRL_TIMER_EN, .enable_conf_mask = BIT(1) | BIT(3), + .oneshot_cnt_max = 0x100, + .funcs = { + .enable = rockchip_pwm_enable_v1, + .config = rockchip_pwm_config_v1, + }, }; static const struct rockchip_pwm_data pwm_data_v2 = { .regs = { + .version = 0x5c, .duty = 0x08, .period = 0x04, .cntr = 0x00, @@ -460,10 +745,16 @@ static const struct rockchip_pwm_data pwm_data_v2 = { .enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE | PWM_CONTINUOUS, .enable_conf_mask = GENMASK(2, 0) | BIT(5) | BIT(8), + .oneshot_cnt_max = 0x100, + .funcs = { + .enable = rockchip_pwm_enable_v1, + .config = rockchip_pwm_config_v1, + }, }; static const struct rockchip_pwm_data pwm_data_vop = { .regs = { + .version = 0x5c, .duty = 0x08, .period = 0x04, .cntr = 0x0c, @@ -476,10 +767,16 @@ static const struct rockchip_pwm_data pwm_data_vop = { .enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE | PWM_CONTINUOUS, .enable_conf_mask = GENMASK(2, 0) | BIT(5) | BIT(8), + .oneshot_cnt_max = 0x100, + .funcs = { + .enable = rockchip_pwm_enable_v1, + .config = rockchip_pwm_config_v1, + }, }; static const struct rockchip_pwm_data pwm_data_v3 = { .regs = { + .version = 0x5c, .duty = 0x08, .period = 0x04, .cntr = 0x00, @@ -492,6 +789,12 @@ static const struct rockchip_pwm_data pwm_data_v3 = { .enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE | PWM_CONTINUOUS, .enable_conf_mask = GENMASK(2, 0) | BIT(5) | BIT(8), + .oneshot_cnt_max = 0x100, + .funcs = { + .enable = rockchip_pwm_enable_v1, + .config = rockchip_pwm_config_v1, + .irq_handler = rockchip_pwm_irq_v1, + }, }; static const struct of_device_id rockchip_pwm_dt_ids[] = { @@ -580,23 +883,6 @@ static int rockchip_pwm_probe(struct platform_device *pdev) goto err_pclk; } - if (IS_ENABLED(CONFIG_PWM_ROCKCHIP_ONESHOT)) { - pc->irq = platform_get_irq(pdev, 0); - if (pc->irq < 0) { - dev_err(&pdev->dev, "Get oneshot mode irq failed\n"); - ret = pc->irq; - goto err_pclk; - } - - ret = devm_request_irq(&pdev->dev, pc->irq, rockchip_pwm_oneshot_irq, - IRQF_NO_SUSPEND | IRQF_SHARED, - "rk_pwm_oneshot_irq", pc); - if (ret) { - dev_err(&pdev->dev, "Claim oneshot IRQ failed\n"); - goto err_pclk; - } - } - pc->pinctrl = devm_pinctrl_get(&pdev->dev); if (IS_ERR(pc->pinctrl)) { dev_err(&pdev->dev, "Get pinctrl failed!\n"); @@ -620,6 +906,22 @@ static int rockchip_pwm_probe(struct platform_device *pdev) pc->chip.npwm = 1; pc->clk_rate = clk_get_rate(pc->clk); + if (IS_ENABLED(CONFIG_PWM_ROCKCHIP_ONESHOT) && pc->data->funcs.irq_handler) { + pc->irq = platform_get_irq_optional(pdev, 0); + if (pc->irq < 0) { + dev_warn(&pdev->dev, + "Can't get oneshot mode irq and oneshot interrupt is unsupported\n"); + } else { + ret = devm_request_irq(&pdev->dev, pc->irq, pc->data->funcs.irq_handler, + IRQF_NO_SUSPEND | IRQF_SHARED, + "rk_pwm_oneshot_irq", pc); + if (ret) { + dev_err(&pdev->dev, "Claim oneshot IRQ failed\n"); + goto err_pclk; + } + } + } + if (pc->data->supports_polarity) { pc->chip.of_xlate = of_pwm_xlate_with_flags; pc->chip.of_pwm_n_cells = 3; diff --git a/include/linux/pwm-rockchip.h b/include/linux/pwm-rockchip.h new file mode 100644 index 000000000000..32d1bbfa1fdb --- /dev/null +++ b/include/linux/pwm-rockchip.h @@ -0,0 +1,187 @@ +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */ +/* + * Copyright (c) 2023 Rockchip Electronics Co., Ltd. + */ + +#ifndef _PWM_ROCKCHIP_H_ +#define _PWM_ROCKCHIP_H_ + +#include + +/** + * enum rockchip_pwm_global_ctrl_cmd - commands for pwm global ctrl + * @PWM_GLOBAL_CTRL_JOIN: join the global control group + * @PWM_GLOBAL_CTRL_EXIT: exit the global control group + * @PWM_GLOBAL_CTRL_GRANT: obtian the permission of global control + * @PWM_GLOBAL_CTRL_RECLAIM: reclaim the permission of global control + * @PWM_GLOBAL_CTRL_UPDATE: update the configs for all channels in group + * @PWM_GLOBAL_CTRL_ENABLE: enable all channels in group + * @PWM_GLOBAL_CTRL_DISABLE: disable all channels in group + */ +enum rockchip_pwm_global_ctrl_cmd { + PWM_GLOBAL_CTRL_JOIN, + PWM_GLOBAL_CTRL_EXIT, + PWM_GLOBAL_CTRL_GRANT, + PWM_GLOBAL_CTRL_RECLAIM, + PWM_GLOBAL_CTRL_UPDATE, + PWM_GLOBAL_CTRL_ENABLE, + PWM_GLOBAL_CTRL_DISABLE, +}; + +/** + * struct rockchip_pwm_wave_table - wave table config object + * @offset: the offset of wave table to set + * @len: the length of wave table to set + * @table: the values of wave table to set (in nanoseconds) + * @ + */ +struct rockchip_pwm_wave_table { + u16 offset; + u16 len; + u64 *table; +}; + +/** + * enum rockchip_pwm_wave_table_width_mode - element width of pwm wave table + * @PWM_WAVE_TABLE_8BITS_WIDTH: each element in table is 8bits + * @PWM_WAVE_TABLE_16BITS_WIDTH: each element in table is 16bits + */ +enum rockchip_pwm_wave_table_width_mode { + PWM_WAVE_TABLE_8BITS_WIDTH, + PWM_WAVE_TABLE_16BITS_WIDTH, +}; + +/** + * enum rockchip_pwm_wave_update_mode - update mode of wave generator + * @PWM_WAVE_INCREASING: + * The wave table address will wrap back to minimum address when increase to + * maximum and then increase again. + * @PWM_WAVE_INCREASING_THEN_DECREASING: + * The wave table address will change to decreasing when increasing to the maximum + * address. it will return to increasing when decrease to the minimum value. + */ +enum rockchip_pwm_wave_update_mode { + PWM_WAVE_INCREASING, + PWM_WAVE_INCREASING_THEN_DECREASING, +}; + +/** + * struct rockchip_pwm_wave_config - wave generator config object + * @duty_table: the wave table config of duty + * @period_table: the wave table config of period + * @enable: enable or disable wave generator + * @duty_en: to update duty by duty table or not + * @period_en: to update period by period table or not + * @width_mode: the width mode of wave table + * @update_mode: the update mode of wave generator + * @duty_max: the maximum address of duty table + * @duty_min: the minimum address of duty table + * @period_max: the maximum address of period table + * @period_min: the minimum address of period table + * @offset: the initial offset address of duty and period + * @middle: the middle address of duty and period + * @max_hold: the time to stop at maximum address + * @min_hold: the time to stop at minimum address + * @middle_hold: the time to stop at middle address + */ +struct rockchip_pwm_wave_config { + struct rockchip_pwm_wave_table *duty_table; + struct rockchip_pwm_wave_table *period_table; + bool enable; + bool duty_en; + bool period_en; + u16 rpt; + u32 width_mode; + u32 update_mode; + u32 duty_max; + u32 duty_min; + u32 period_max; + u32 period_min; + u32 offset; + u32 middle; + u32 max_hold; + u32 min_hold; + u32 middle_hold; +}; + +#if IS_REACHABLE(CONFIG_PWM_ROCKCHIP) +/** + * rockchip_pwm_set_counter() - setup pwm counter mode + * @pwm: PWM device + * @enable: enable/disable counter mode + * + * Returns: 0 on success or a negative error code on failure. + */ +int rockchip_pwm_set_counter(struct pwm_device *pwm, bool enable); + +/** + * rockchip_pwm_get_counter_result() - get counter result + * @pwm: PWM device + * @counter_res: number of input waveforms + * @is_clear: clear counter result or not + * + * Returns: 0 on success or a negative error code on failure. + */ +int rockchip_pwm_get_counter_result(struct pwm_device *pwm, + unsigned long *counter_res, bool is_clear); + +/** + * rockchip_pwm_set_freq_meter() - setup pwm frequency meter mode + * @pwm: PWM device + * @delay_ms: time to wait, in milliseconds, before getting frequency meter result + * @freq_hz: parameter in Hz to fill with frequency meter result + * + * Returns: 0 on success or a negative error code on failure. + */ +int rockchip_pwm_set_freq_meter(struct pwm_device *pwm, unsigned long delay_ms, + unsigned long *freq_hz); + +/** + * rockchip_pwm_global_ctrl() - execute global control commands + * @pwm: PWM device + * @cmd: command type to execute + * + * Returns: 0 on success or a negative error code on failure. + */ +int rockchip_pwm_global_ctrl(struct pwm_device *pwm, enum rockchip_pwm_global_ctrl_cmd cmd); + +/** + * rockchip_pwm_set_wave() - setup pwm wave generator mode + * @pwm: PWM device + * @config: configs of wave generator mode + * + * Returns: 0 on success or a negative error code on failure. + */ +int rockchip_pwm_set_wave(struct pwm_device *pwm, struct rockchip_pwm_wave_config *config); +#else +static inline int rockchip_pwm_set_counter(struct pwm_device *pwm, bool enable) +{ + return 0; +} + +static inline int rockchip_pwm_get_counter_result(struct pwm_device *pwm, + unsigned long *counter_res, bool is_clear) +{ + return 0; +} + +static inline int rockchip_pwm_set_freq_meter(struct pwm_device *pwm, unsigned long delay_ms, + unsigned long *freq_hz) +{ + return 0; +} + +static inline int rockchip_pwm_global_ctrl(struct pwm_device *pwm, + enum rockchip_pwm_global_ctrl_cmd cmd) +{ + return 0; +} + +static inline int rockchip_pwm_set_wave(struct pwm_device *pwm, + struct rockchip_pwm_wave_config *config) +{ + return 0; +} +#endif + +#endif /* _PWM_ROCKCHIP_H_ */