| .. | .. | 
|---|
|  | 1 | +// SPDX-License-Identifier: GPL-2.0-only | 
|---|
| 1 | 2 | /* | 
|---|
| 2 | 3 | * PWM driver for Rockchip SoCs | 
|---|
| 3 | 4 | * | 
|---|
| 4 | 5 | * Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com> | 
|---|
| 5 | 6 | * Copyright (C) 2014 ROCKCHIP, Inc. | 
|---|
| 6 |  | - * | 
|---|
| 7 |  | - * This program is free software; you can redistribute it and/or | 
|---|
| 8 |  | - * modify it under the terms of the GNU General Public License | 
|---|
| 9 |  | - * version 2 as published by the Free Software Foundation. | 
|---|
| 10 | 7 | */ | 
|---|
| 11 | 8 |  | 
|---|
| 12 | 9 | #include <linux/clk.h> | 
|---|
|  | 10 | +#include <linux/debugfs.h> | 
|---|
|  | 11 | +#include <linux/interrupt.h> | 
|---|
| 13 | 12 | #include <linux/io.h> | 
|---|
|  | 13 | +#include <linux/iopoll.h> | 
|---|
|  | 14 | +#include <linux/irq.h> | 
|---|
| 14 | 15 | #include <linux/module.h> | 
|---|
| 15 | 16 | #include <linux/of.h> | 
|---|
| 16 | 17 | #include <linux/of_device.h> | 
|---|
| 17 | 18 | #include <linux/pinctrl/consumer.h> | 
|---|
| 18 | 19 | #include <linux/platform_device.h> | 
|---|
| 19 | 20 | #include <linux/pwm.h> | 
|---|
|  | 21 | +#include <linux/pwm-rockchip.h> | 
|---|
| 20 | 22 | #include <linux/time.h> | 
|---|
|  | 23 | +#include "pwm-rockchip-irq-callbacks.h" | 
|---|
| 21 | 24 |  | 
|---|
|  | 25 | +#define PWM_MAX_CHANNEL_NUM	8 | 
|---|
|  | 26 | + | 
|---|
|  | 27 | +/* | 
|---|
|  | 28 | + * regs for pwm v1-v3 | 
|---|
|  | 29 | + */ | 
|---|
| 22 | 30 | #define PWM_CTRL_TIMER_EN	(1 << 0) | 
|---|
| 23 | 31 | #define PWM_CTRL_OUTPUT_EN	(1 << 3) | 
|---|
| 24 | 32 |  | 
|---|
| 25 | 33 | #define PWM_ENABLE		(1 << 0) | 
|---|
| 26 |  | -#define PWM_CONTINUOUS		(1 << 1) | 
|---|
|  | 34 | +#define PWM_MODE_SHIFT		1 | 
|---|
|  | 35 | +#define PWM_MODE_MASK		(0x3 << PWM_MODE_SHIFT) | 
|---|
|  | 36 | +#define PWM_ONESHOT		(0 << PWM_MODE_SHIFT) | 
|---|
|  | 37 | +#define PWM_CONTINUOUS		(1 << PWM_MODE_SHIFT) | 
|---|
|  | 38 | +#define PWM_CAPTURE		(2 << PWM_MODE_SHIFT) | 
|---|
| 27 | 39 | #define PWM_DUTY_POSITIVE	(1 << 3) | 
|---|
| 28 | 40 | #define PWM_DUTY_NEGATIVE	(0 << 3) | 
|---|
| 29 | 41 | #define PWM_INACTIVE_NEGATIVE	(0 << 4) | 
|---|
| .. | .. | 
|---|
| 33 | 45 | #define PWM_OUTPUT_CENTER	(1 << 5) | 
|---|
| 34 | 46 | #define PWM_LOCK_EN		(1 << 6) | 
|---|
| 35 | 47 | #define PWM_LP_DISABLE		(0 << 8) | 
|---|
|  | 48 | +#define PWM_CLK_SEL_SHIFT	9 | 
|---|
|  | 49 | +#define PWM_CLK_SEL_MASK	(1 << PWM_CLK_SEL_SHIFT) | 
|---|
|  | 50 | +#define PWM_SEL_NO_SCALED_CLOCK	(0 << PWM_CLK_SEL_SHIFT) | 
|---|
|  | 51 | +#define PWM_SEL_SCALED_CLOCK	(1 << PWM_CLK_SEL_SHIFT) | 
|---|
|  | 52 | +#define PWM_PRESCELE_SHIFT	12 | 
|---|
|  | 53 | +#define PWM_PRESCALE_MASK	(0x3 << PWM_PRESCELE_SHIFT) | 
|---|
|  | 54 | +#define PWM_SCALE_SHIFT		16 | 
|---|
|  | 55 | +#define PWM_SCALE_MASK		(0xff << PWM_SCALE_SHIFT) | 
|---|
| 36 | 56 |  | 
|---|
| 37 | 57 | #define PWM_ONESHOT_COUNT_SHIFT	24 | 
|---|
| 38 |  | -#define PWM_ONESHOT_COUNT_MAX	256 | 
|---|
|  | 58 | +#define PWM_ONESHOT_COUNT_MASK	(0xff << PWM_ONESHOT_COUNT_SHIFT) | 
|---|
|  | 59 | + | 
|---|
|  | 60 | +#define PWM_REG_INTSTS(n)	((3 - (n)) * 0x10 + 0x10) | 
|---|
|  | 61 | +#define PWM_REG_INT_EN(n)	((3 - (n)) * 0x10 + 0x14) | 
|---|
|  | 62 | + | 
|---|
|  | 63 | +#define PWM_CH_INT(n)		BIT(n) | 
|---|
|  | 64 | + | 
|---|
|  | 65 | +/* | 
|---|
|  | 66 | + * regs for pwm v4 | 
|---|
|  | 67 | + */ | 
|---|
|  | 68 | +#define HIWORD_UPDATE(v, l, h)	(((v) << (l)) | (GENMASK(h, l) << 16)) | 
|---|
|  | 69 | + | 
|---|
|  | 70 | +/* VERSION_ID */ | 
|---|
|  | 71 | +#define CHANNEL_NUM_SUPPORT_SHIFT	0 | 
|---|
|  | 72 | +#define CHANNEL_NUM_SUPPORT_MASK	(0xf << CHANNEL_NUM_SUPPORT_SHIFT) | 
|---|
|  | 73 | +#define CHANNLE_INDEX_SHIFT		4 | 
|---|
|  | 74 | +#define CHANNLE_INDEX_MASK		(0xf << CHANNLE_INDEX_SHIFT) | 
|---|
|  | 75 | +#define IR_TRANS_SUPPORT		BIT(8) | 
|---|
|  | 76 | +#define POWER_KEY_SUPPORT		BIT(9) | 
|---|
|  | 77 | +#define FREQ_METER_SUPPORT		BIT(10) | 
|---|
|  | 78 | +#define COUNTER_SUPPORT			BIT(11) | 
|---|
|  | 79 | +#define WAVE_SUPPORT			BIT(12) | 
|---|
|  | 80 | +#define FILTER_SUPPORT			BIT(13) | 
|---|
|  | 81 | +#define MINOR_VERSION_SHIFT		16 | 
|---|
|  | 82 | +#define MINOR_VERSION_MASK		(0xff << MINOR_VERSION_SHIFT) | 
|---|
|  | 83 | +#define MAIN_VERSION_SHIFT		24 | 
|---|
|  | 84 | +#define MAIN_VERSION_MASK		(0xff << MAIN_VERSION_SHIFT) | 
|---|
|  | 85 | +/* PWM_ENABLE */ | 
|---|
|  | 86 | +#define PWM_ENABLE_V4			(0x3 << 0) | 
|---|
|  | 87 | +#define PWM_CLK_EN(v)			HIWORD_UPDATE(v, 0, 0) | 
|---|
|  | 88 | +#define PWM_EN(v)			HIWORD_UPDATE(v, 1, 1) | 
|---|
|  | 89 | +#define PWM_CTRL_UPDATE_EN(v)		HIWORD_UPDATE(v, 2, 2) | 
|---|
|  | 90 | +#define PWM_GLOBAL_JOIN_EN(v)		HIWORD_UPDATE(v, 4, 4) | 
|---|
|  | 91 | +/* PWM_CLK_CTRL */ | 
|---|
|  | 92 | +#define CLK_PRESCALE(v)			HIWORD_UPDATE(v, 0, 2) | 
|---|
|  | 93 | +#define CLK_SCALE(v)			HIWORD_UPDATE(v, 4, 12) | 
|---|
|  | 94 | +#define CLK_SRC_SEL(v)			HIWORD_UPDATE(v, 13, 14) | 
|---|
|  | 95 | +#define CLK_GLOBAL_SEL(v)		HIWORD_UPDATE(v, 15, 15) | 
|---|
|  | 96 | +/* PWM_CTRL */ | 
|---|
|  | 97 | +#define PWM_MODE(v)			HIWORD_UPDATE(v, 0, 1) | 
|---|
|  | 98 | +#define ONESHOT_MODE			0 | 
|---|
|  | 99 | +#define CONTINUOUS_MODE			1 | 
|---|
|  | 100 | +#define CAPTURE_MODE			2 | 
|---|
|  | 101 | +#define PWM_POLARITY(v)			HIWORD_UPDATE(v, 2, 3) | 
|---|
|  | 102 | +#define DUTY_NEGATIVE			(0 << 0) | 
|---|
|  | 103 | +#define DUTY_POSITIVE			(1 << 0) | 
|---|
|  | 104 | +#define INACTIVE_NEGATIVE		(0 << 1) | 
|---|
|  | 105 | +#define INACTIVE_POSITIVE		(1 << 1) | 
|---|
|  | 106 | +#define PWM_ALIGNED_INVALID(v)		HIWORD_UPDATE(v, 5, 5) | 
|---|
|  | 107 | +#define PWM_IN_SEL(v)			HIWORD_UPDATE(v, 6, 8) | 
|---|
|  | 108 | +/* PWM_RPT */ | 
|---|
|  | 109 | +#define FIRST_DIMENSIONAL_SHIFT		0 | 
|---|
|  | 110 | +#define SECOND_DIMENSINAL_SHIFT		16 | 
|---|
|  | 111 | +/* INTSTS*/ | 
|---|
|  | 112 | +#define CAP_LPR_INTSTS_SHIFT		0 | 
|---|
|  | 113 | +#define CAP_HPR_INTSTS_SHIFT		1 | 
|---|
|  | 114 | +#define ONESHOT_END_INTSTS_SHIFT	2 | 
|---|
|  | 115 | +#define RELOAD_INTSTS_SHIFT		3 | 
|---|
|  | 116 | +#define FREQ_INTSTS_SHIFT		4 | 
|---|
|  | 117 | +#define PWR_INTSTS_SHIFT		5 | 
|---|
|  | 118 | +#define IR_TRANS_END_INTSTS_SHIFT	6 | 
|---|
|  | 119 | +#define WAVE_MAX_INT_SHIFT		7 | 
|---|
|  | 120 | +#define WAVE_MIDDLE_INT_SHIFT		8 | 
|---|
|  | 121 | +#define CAP_LPR_INT			BIT(CAP_LPR_INTSTS_SHIFT) | 
|---|
|  | 122 | +#define CAP_HPR_INT			BIT(CAP_HPR_INTSTS_SHIFT) | 
|---|
|  | 123 | +#define ONESHOT_END_INT			BIT(ONESHOT_END_INTSTS_SHIFT) | 
|---|
|  | 124 | +#define RELOAD_INT			BIT(RELOAD_INTSTS_SHIFT) | 
|---|
|  | 125 | +#define FREQ_INT			BIT(FREQ_INTSTS_SHIFT) | 
|---|
|  | 126 | +#define PWR_INT				BIT(PWR_INTSTS_SHIFT) | 
|---|
|  | 127 | +#define IR_TRANS_END_INT		BIT(IR_TRANS_END_INTSTS_SHIFT) | 
|---|
|  | 128 | +#define WAVE_MAX_INT			BIT(WAVE_MAX_INT_SHIFT) | 
|---|
|  | 129 | +#define WAVE_MIDDLE_INT			BIT(WAVE_MIDDLE_INT_SHIFT) | 
|---|
|  | 130 | +/* INT_EN */ | 
|---|
|  | 131 | +#define CAP_LPR_INT_EN(v)		HIWORD_UPDATE(v, 0, 0) | 
|---|
|  | 132 | +#define CAP_HPR_INT_EN(v)		HIWORD_UPDATE(v, 1, 1) | 
|---|
|  | 133 | +#define ONESHOT_END_INT_EN(v)		HIWORD_UPDATE(v, 2, 2) | 
|---|
|  | 134 | +#define RELOAD_INT_EN(v)		HIWORD_UPDATE(v, 3, 3) | 
|---|
|  | 135 | +#define FREQ_INT_EN(v)			HIWORD_UPDATE(v, 4, 4) | 
|---|
|  | 136 | +#define PWR_INT_EN(v)			HIWORD_UPDATE(v, 5, 5) | 
|---|
|  | 137 | +#define IR_TRANS_END_INT_EN(v)		HIWORD_UPDATE(v, 6, 6) | 
|---|
|  | 138 | +#define WAVE_MAX_INT_EN(v)		HIWORD_UPDATE(v, 7, 7) | 
|---|
|  | 139 | +#define WAVE_MIDDLE_INT_EN(v)		HIWORD_UPDATE(v, 8, 8) | 
|---|
|  | 140 | +/* WAVE_MEM_ARBITER */ | 
|---|
|  | 141 | +#define WAVE_MEM_ARBITER		0x80 | 
|---|
|  | 142 | +#define WAVE_MEM_GRANT_SHIFT		0 | 
|---|
|  | 143 | +#define WAVE_MEM_READ_LOCK_SHIFT	16 | 
|---|
|  | 144 | +/* WAVE_MEM_STATUS */ | 
|---|
|  | 145 | +#define WAVE_MEM_STATUS			0x84 | 
|---|
|  | 146 | +#define WAVE_MEM_STATUS_SHIFT		0 | 
|---|
|  | 147 | +/* WAVE_CTRL */ | 
|---|
|  | 148 | +#define WAVE_CTRL			0x88 | 
|---|
|  | 149 | +#define WAVE_DUTY_EN(v)			HIWORD_UPDATE(v, 0, 0) | 
|---|
|  | 150 | +#define WAVE_PERIOD_EN(v)		HIWORD_UPDATE(v, 1, 1) | 
|---|
|  | 151 | +#define WAVE_WIDTH_MODE(v)		HIWORD_UPDATE(v, 2, 2) | 
|---|
|  | 152 | +#define WAVE_UPDATE_MODE(v)		HIWORD_UPDATE(v, 3, 3) | 
|---|
|  | 153 | +#define WAVE_MEM_CLK_SEL(v)		HIWORD_UPDATE(v, 4, 5) | 
|---|
|  | 154 | +#define WAVE_DUTY_AMPLIFY(v)		HIWORD_UPDATE(v, 6, 10) | 
|---|
|  | 155 | +#define WAVE_PERIOD_AMPLIFY(v)		HIWORD_UPDATE(v, 11, 15) | 
|---|
|  | 156 | +/* WAVE_MAX */ | 
|---|
|  | 157 | +#define WAVE_MAX			0x8c | 
|---|
|  | 158 | +#define WAVE_DUTY_MAX_SHIFT		0 | 
|---|
|  | 159 | +#define WAVE_PERIOD_MAX_SHIFT		16 | 
|---|
|  | 160 | +/* WAVE_MIN */ | 
|---|
|  | 161 | +#define WAVE_MIN			0x90 | 
|---|
|  | 162 | +#define WAVE_DUTY_MIN_SHIFT		0 | 
|---|
|  | 163 | +#define WAVE_PERIOD_MIN_SHIFT		16 | 
|---|
|  | 164 | +/* WAVE_OFFSET */ | 
|---|
|  | 165 | +#define WAVE_OFFSET			0x94 | 
|---|
|  | 166 | +#define WAVE_OFFSET_SHIFT		0 | 
|---|
|  | 167 | +/* WAVE_MIDDLE */ | 
|---|
|  | 168 | +#define WAVE_MIDDLE			0x98 | 
|---|
|  | 169 | +#define WAVE_MIDDLE_SHIFT		0 | 
|---|
|  | 170 | +/* WAVE_HOLD */ | 
|---|
|  | 171 | +#define WAVE_HOLD			0x9c | 
|---|
|  | 172 | +#define MAX_HOLD_SHIFT			0 | 
|---|
|  | 173 | +#define MIN_HOLD_SHIFT			8 | 
|---|
|  | 174 | +#define MIDDLE_HOLD_SHIFT		16 | 
|---|
|  | 175 | +/* GLOBAL_ARBITER */ | 
|---|
|  | 176 | +#define GLOBAL_ARBITER			0xc0 | 
|---|
|  | 177 | +#define GLOBAL_GRANT_SHIFT		0 | 
|---|
|  | 178 | +#define GLOBAL_READ_LOCK_SHIFT		16 | 
|---|
|  | 179 | +/* GLOBAL_CTRL */ | 
|---|
|  | 180 | +#define GLOBAL_CTRL			0xc4 | 
|---|
|  | 181 | +#define GLOBAL_PWM_EN(v)		HIWORD_UPDATE(v, 0, 0) | 
|---|
|  | 182 | +#define GLOBAL_PWM_UPDATE_EN(v)		HIWORD_UPDATE(v, 1, 1) | 
|---|
|  | 183 | +/* FREQ_ARBITER */ | 
|---|
|  | 184 | +#define FREQ_ARBITER			0x1c0 | 
|---|
|  | 185 | +#define FREQ_GRANT_SHIFT		0 | 
|---|
|  | 186 | +#define FREQ_READ_LOCK_SHIFT		16 | 
|---|
|  | 187 | +/* FREQ_CTRL */ | 
|---|
|  | 188 | +#define FREQ_CTRL			0x1c4 | 
|---|
|  | 189 | +#define FREQ_EN(v)			HIWORD_UPDATE(v, 0, 0) | 
|---|
|  | 190 | +#define FREQ_CLK_SEL(v)			HIWORD_UPDATE(v, 1, 2) | 
|---|
|  | 191 | +#define FREQ_CHANNEL_SEL(v)		HIWORD_UPDATE(v, 3, 5) | 
|---|
|  | 192 | +#define FREQ_CLK_SWITCH_MODE(v)		HIWORD_UPDATE(v, 6, 6) | 
|---|
|  | 193 | +#define FREQ_TIMIER_CLK_SEL(v)		HIWORD_UPDATE(v, 7, 7) | 
|---|
|  | 194 | +/* FREQ_TIMER_VALUE */ | 
|---|
|  | 195 | +#define FREQ_TIMER_VALUE		0x1c8 | 
|---|
|  | 196 | +/* FREQ_RESULT_VALUE */ | 
|---|
|  | 197 | +#define FREQ_RESULT_VALUE		0x1cc | 
|---|
|  | 198 | +/* COUNTER_ARBITER */ | 
|---|
|  | 199 | +#define COUNTER_ARBITER			0x200 | 
|---|
|  | 200 | +#define COUNTER_GRANT_SHIFT		0 | 
|---|
|  | 201 | +#define COUNTER_READ_LOCK_SHIFT		16 | 
|---|
|  | 202 | +/* COUNTER_CTRL */ | 
|---|
|  | 203 | +#define COUNTER_CTRL			0x204 | 
|---|
|  | 204 | +#define COUNTER_EN(v)			HIWORD_UPDATE(v, 0, 0) | 
|---|
|  | 205 | +#define COUNTER_CLK_SEL(v)		HIWORD_UPDATE(v, 1, 2) | 
|---|
|  | 206 | +#define COUNTER_CHANNEL_SEL(v)		HIWORD_UPDATE(v, 3, 5) | 
|---|
|  | 207 | +#define COUNTER_CLR(v)			HIWORD_UPDATE(v, 6, 6) | 
|---|
|  | 208 | +/* COUNTER_LOW */ | 
|---|
|  | 209 | +#define COUNTER_LOW			0x208 | 
|---|
|  | 210 | +/* COUNTER_HIGH */ | 
|---|
|  | 211 | +#define COUNTER_HIGH			0x20c | 
|---|
|  | 212 | +/* WAVE_MEM */ | 
|---|
|  | 213 | +#define WAVE_MEM			0x400 | 
|---|
| 39 | 214 |  | 
|---|
| 40 | 215 | struct rockchip_pwm_chip { | 
|---|
| 41 | 216 | struct pwm_chip chip; | 
|---|
| .. | .. | 
|---|
| 43 | 218 | struct clk *pclk; | 
|---|
| 44 | 219 | struct pinctrl *pinctrl; | 
|---|
| 45 | 220 | struct pinctrl_state *active_state; | 
|---|
|  | 221 | +	struct delayed_work pwm_work; | 
|---|
| 46 | 222 | const struct rockchip_pwm_data *data; | 
|---|
|  | 223 | +	struct resource *res; | 
|---|
|  | 224 | +	struct dentry *debugfs; | 
|---|
| 47 | 225 | void __iomem *base; | 
|---|
| 48 | 226 | unsigned long clk_rate; | 
|---|
| 49 | 227 | bool vop_pwm_en; /* indicate voppwm mirror register state */ | 
|---|
| 50 | 228 | bool center_aligned; | 
|---|
| 51 |  | -	bool oneshot; | 
|---|
|  | 229 | +	bool oneshot_en; | 
|---|
|  | 230 | +	bool wave_en; | 
|---|
|  | 231 | +	bool global_ctrl_grant; | 
|---|
|  | 232 | +	bool freq_meter_support; | 
|---|
|  | 233 | +	bool counter_support; | 
|---|
|  | 234 | +	bool wave_support; | 
|---|
|  | 235 | +	int channel_id; | 
|---|
|  | 236 | +	int irq; | 
|---|
|  | 237 | +	u8 main_version; | 
|---|
|  | 238 | +	u8 capture_cnt; | 
|---|
| 52 | 239 | }; | 
|---|
| 53 | 240 |  | 
|---|
| 54 | 241 | struct rockchip_pwm_regs { | 
|---|
| .. | .. | 
|---|
| 56 | 243 | unsigned long period; | 
|---|
| 57 | 244 | unsigned long cntr; | 
|---|
| 58 | 245 | unsigned long ctrl; | 
|---|
|  | 246 | +	unsigned long version; | 
|---|
|  | 247 | + | 
|---|
|  | 248 | +	unsigned long enable; | 
|---|
|  | 249 | +	unsigned long clk_ctrl; | 
|---|
|  | 250 | +	unsigned long offset; | 
|---|
|  | 251 | +	unsigned long rpt; | 
|---|
|  | 252 | +	unsigned long hpr; | 
|---|
|  | 253 | +	unsigned long lpr; | 
|---|
|  | 254 | +	unsigned long intsts; | 
|---|
|  | 255 | +	unsigned long int_en; | 
|---|
|  | 256 | +	unsigned long int_mask; | 
|---|
|  | 257 | +}; | 
|---|
|  | 258 | + | 
|---|
|  | 259 | +struct rockchip_pwm_funcs { | 
|---|
|  | 260 | +	int (*enable)(struct pwm_chip *chip, struct pwm_device *pwm, bool enable); | 
|---|
|  | 261 | +	void (*config)(struct pwm_chip *chip, struct pwm_device *pwm, | 
|---|
|  | 262 | +		       const struct pwm_state *state); | 
|---|
|  | 263 | +	void (*set_capture)(struct pwm_chip *chip, struct pwm_device *pwm, bool enable); | 
|---|
|  | 264 | +	int (*get_capture_result)(struct pwm_chip *chip, struct pwm_device *pwm, | 
|---|
|  | 265 | +				  struct pwm_capture *catpure_res); | 
|---|
|  | 266 | +	int (*set_counter)(struct pwm_chip *chip, struct pwm_device *pwm, bool enable); | 
|---|
|  | 267 | +	int (*get_counter_result)(struct pwm_chip *chip, struct pwm_device *pwm, | 
|---|
|  | 268 | +				  unsigned long *counter_res, bool is_clear); | 
|---|
|  | 269 | +	int (*set_freq_meter)(struct pwm_chip *chip, struct pwm_device *pwm, | 
|---|
|  | 270 | +			      bool enable, unsigned long delay_ms); | 
|---|
|  | 271 | +	int (*get_freq_meter_result)(struct pwm_chip *chip, struct pwm_device *pwm, | 
|---|
|  | 272 | +				     unsigned long delay_ms, unsigned long *freq_hz); | 
|---|
|  | 273 | +	int (*global_ctrl)(struct pwm_chip *chip, struct pwm_device *pwm, | 
|---|
|  | 274 | +			   enum rockchip_pwm_global_ctrl_cmd cmd); | 
|---|
|  | 275 | +	int (*set_wave_table)(struct pwm_chip *chip, struct pwm_device *pwm, | 
|---|
|  | 276 | +			      struct rockchip_pwm_wave_table *table_config, | 
|---|
|  | 277 | +			      enum rockchip_pwm_wave_table_width_mode width_mode); | 
|---|
|  | 278 | +	int (*set_wave)(struct pwm_chip *chip, struct pwm_device *pwm, | 
|---|
|  | 279 | +			struct rockchip_pwm_wave_config *config); | 
|---|
|  | 280 | +	irqreturn_t (*irq_handler)(int irq, void *data); | 
|---|
| 59 | 281 | }; | 
|---|
| 60 | 282 |  | 
|---|
| 61 | 283 | struct rockchip_pwm_data { | 
|---|
| 62 | 284 | struct rockchip_pwm_regs regs; | 
|---|
|  | 285 | +	struct rockchip_pwm_funcs funcs; | 
|---|
| 63 | 286 | unsigned int prescaler; | 
|---|
| 64 | 287 | bool supports_polarity; | 
|---|
| 65 | 288 | bool supports_lock; | 
|---|
| 66 | 289 | bool vop_pwm; | 
|---|
|  | 290 | +	u8 main_version; | 
|---|
| 67 | 291 | u32 enable_conf; | 
|---|
| 68 | 292 | u32 enable_conf_mask; | 
|---|
|  | 293 | +	u32 oneshot_cnt_max; | 
|---|
|  | 294 | +	u32 oneshot_rpt_max; | 
|---|
|  | 295 | +	u32 wave_table_max; | 
|---|
| 69 | 296 | }; | 
|---|
| 70 | 297 |  | 
|---|
| 71 | 298 | static inline struct rockchip_pwm_chip *to_rockchip_pwm_chip(struct pwm_chip *c) | 
|---|
| .. | .. | 
|---|
| 81 | 308 | u32 enable_conf = pc->data->enable_conf; | 
|---|
| 82 | 309 | u64 tmp; | 
|---|
| 83 | 310 | u32 val; | 
|---|
|  | 311 | +	u32 dclk_div = 1; | 
|---|
| 84 | 312 | int ret; | 
|---|
| 85 | 313 |  | 
|---|
| 86 |  | -	ret = clk_enable(pc->pclk); | 
|---|
| 87 |  | -	if (ret) | 
|---|
| 88 |  | -		return; | 
|---|
|  | 314 | +	if (!pc->oneshot_en) { | 
|---|
|  | 315 | +		ret = clk_enable(pc->pclk); | 
|---|
|  | 316 | +		if (ret) | 
|---|
|  | 317 | +			return; | 
|---|
|  | 318 | +	} | 
|---|
|  | 319 | + | 
|---|
|  | 320 | +	if (pc->main_version < 4) | 
|---|
|  | 321 | +		dclk_div = pc->oneshot_en ? 2 : 1; | 
|---|
| 89 | 322 |  | 
|---|
| 90 | 323 | tmp = readl_relaxed(pc->base + pc->data->regs.period); | 
|---|
| 91 |  | -	tmp *= pc->data->prescaler * NSEC_PER_SEC; | 
|---|
|  | 324 | +	tmp *= dclk_div * pc->data->prescaler * NSEC_PER_SEC; | 
|---|
| 92 | 325 | state->period = DIV_ROUND_CLOSEST_ULL(tmp, pc->clk_rate); | 
|---|
| 93 | 326 |  | 
|---|
| 94 | 327 | tmp = readl_relaxed(pc->base + pc->data->regs.duty); | 
|---|
| 95 |  | -	tmp *= pc->data->prescaler * NSEC_PER_SEC; | 
|---|
|  | 328 | +	tmp *= dclk_div * pc->data->prescaler * NSEC_PER_SEC; | 
|---|
| 96 | 329 | state->duty_cycle =  DIV_ROUND_CLOSEST_ULL(tmp, pc->clk_rate); | 
|---|
| 97 | 330 |  | 
|---|
| 98 |  | -	val = readl_relaxed(pc->base + pc->data->regs.ctrl); | 
|---|
| 99 |  | -	if (pc->data->supports_polarity) | 
|---|
| 100 |  | -		state->enabled = ((val & enable_conf) != enable_conf) ? | 
|---|
| 101 |  | -				 false : true; | 
|---|
| 102 |  | -	else | 
|---|
| 103 |  | -		state->enabled = ((val & enable_conf) == enable_conf) ? | 
|---|
| 104 |  | -				 true : false; | 
|---|
| 105 |  | - | 
|---|
| 106 |  | -	if (pc->data->supports_polarity) { | 
|---|
| 107 |  | -		if (!(val & PWM_DUTY_POSITIVE)) | 
|---|
| 108 |  | -			state->polarity = PWM_POLARITY_INVERSED; | 
|---|
|  | 331 | +	if (pc->main_version >= 4) { | 
|---|
|  | 332 | +		val = readl_relaxed(pc->base + pc->data->regs.enable); | 
|---|
|  | 333 | +	} else { | 
|---|
|  | 334 | +		val = readl_relaxed(pc->base + pc->data->regs.ctrl); | 
|---|
|  | 335 | +		if (pc->oneshot_en) | 
|---|
|  | 336 | +			enable_conf &= ~PWM_CONTINUOUS; | 
|---|
| 109 | 337 | } | 
|---|
|  | 338 | +	state->enabled = (val & enable_conf) == enable_conf; | 
|---|
| 110 | 339 |  | 
|---|
| 111 |  | -	clk_disable(pc->pclk); | 
|---|
|  | 340 | +	if (pc->data->supports_polarity && !(val & PWM_DUTY_POSITIVE)) | 
|---|
|  | 341 | +		state->polarity = PWM_POLARITY_INVERSED; | 
|---|
|  | 342 | +	else | 
|---|
|  | 343 | +		state->polarity = PWM_POLARITY_NORMAL; | 
|---|
|  | 344 | + | 
|---|
|  | 345 | +	if (!pc->oneshot_en) | 
|---|
|  | 346 | +		clk_disable(pc->pclk); | 
|---|
| 112 | 347 | } | 
|---|
| 113 | 348 |  | 
|---|
| 114 |  | -static void rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, | 
|---|
| 115 |  | -				struct pwm_state *state) | 
|---|
|  | 349 | +static irqreturn_t rockchip_pwm_irq_v1(int irq, void *data) | 
|---|
|  | 350 | +{ | 
|---|
|  | 351 | +	struct rockchip_pwm_chip *pc = data; | 
|---|
|  | 352 | +	struct pwm_state state; | 
|---|
|  | 353 | +	unsigned int id = pc->channel_id; | 
|---|
|  | 354 | +	int val; | 
|---|
|  | 355 | + | 
|---|
|  | 356 | +	if (id > 3) | 
|---|
|  | 357 | +		return IRQ_NONE; | 
|---|
|  | 358 | +	val = readl_relaxed(pc->base + PWM_REG_INTSTS(id)); | 
|---|
|  | 359 | + | 
|---|
|  | 360 | +	if ((val & PWM_CH_INT(id)) == 0) | 
|---|
|  | 361 | +		return IRQ_NONE; | 
|---|
|  | 362 | + | 
|---|
|  | 363 | +	writel_relaxed(PWM_CH_INT(id), pc->base + PWM_REG_INTSTS(id)); | 
|---|
|  | 364 | + | 
|---|
|  | 365 | +	/* | 
|---|
|  | 366 | +	 * Set pwm state to disabled when the oneshot mode finished. | 
|---|
|  | 367 | +	 */ | 
|---|
|  | 368 | +	pwm_get_state(&pc->chip.pwms[0], &state); | 
|---|
|  | 369 | +	state.enabled = false; | 
|---|
|  | 370 | +	pwm_apply_state(&pc->chip.pwms[0], &state); | 
|---|
|  | 371 | + | 
|---|
|  | 372 | +	rockchip_pwm_oneshot_callback(&pc->chip.pwms[0], &state); | 
|---|
|  | 373 | + | 
|---|
|  | 374 | +	return IRQ_HANDLED; | 
|---|
|  | 375 | +} | 
|---|
|  | 376 | + | 
|---|
|  | 377 | +static void rockchip_pwm_config_v1(struct pwm_chip *chip, struct pwm_device *pwm, | 
|---|
|  | 378 | +				   const struct pwm_state *state) | 
|---|
| 116 | 379 | { | 
|---|
| 117 | 380 | struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); | 
|---|
| 118 |  | -	unsigned long period, duty; | 
|---|
|  | 381 | +	unsigned long period, duty, delay_ns; | 
|---|
| 119 | 382 | unsigned long flags; | 
|---|
| 120 | 383 | u64 div; | 
|---|
| 121 | 384 | u32 ctrl; | 
|---|
|  | 385 | +	u8 dclk_div = 1; | 
|---|
|  | 386 | + | 
|---|
|  | 387 | +#ifdef CONFIG_PWM_ROCKCHIP_ONESHOT | 
|---|
|  | 388 | +	if (state->oneshot_count > 0 && state->oneshot_count <= pc->data->oneshot_cnt_max) | 
|---|
|  | 389 | +		dclk_div = 2; | 
|---|
|  | 390 | +#endif | 
|---|
| 122 | 391 |  | 
|---|
| 123 | 392 | /* | 
|---|
| 124 | 393 | * Since period and duty cycle registers have a width of 32 | 
|---|
| .. | .. | 
|---|
| 126 | 395 | * default prescaler value for all practical clock rate values. | 
|---|
| 127 | 396 | */ | 
|---|
| 128 | 397 | div = (u64)pc->clk_rate * state->period; | 
|---|
| 129 |  | -	period = DIV_ROUND_CLOSEST_ULL(div, | 
|---|
| 130 |  | -				       pc->data->prescaler * NSEC_PER_SEC); | 
|---|
|  | 398 | +	period = DIV_ROUND_CLOSEST_ULL(div, dclk_div * pc->data->prescaler * NSEC_PER_SEC); | 
|---|
| 131 | 399 |  | 
|---|
| 132 | 400 | div = (u64)pc->clk_rate * state->duty_cycle; | 
|---|
| 133 |  | -	duty = DIV_ROUND_CLOSEST_ULL(div, pc->data->prescaler * NSEC_PER_SEC); | 
|---|
|  | 401 | +	duty = DIV_ROUND_CLOSEST_ULL(div, dclk_div * pc->data->prescaler * NSEC_PER_SEC); | 
|---|
|  | 402 | + | 
|---|
|  | 403 | +	if (pc->data->supports_lock) { | 
|---|
|  | 404 | +		div = (u64)10 * NSEC_PER_SEC * dclk_div * pc->data->prescaler; | 
|---|
|  | 405 | +		delay_ns = DIV_ROUND_UP_ULL(div, pc->clk_rate); | 
|---|
|  | 406 | +	} | 
|---|
| 134 | 407 |  | 
|---|
| 135 | 408 | local_irq_save(flags); | 
|---|
| 136 |  | -	/* | 
|---|
| 137 |  | -	 * Lock the period and duty of previous configuration, then | 
|---|
| 138 |  | -	 * change the duty and period, that would not be effective. | 
|---|
| 139 |  | -	 */ | 
|---|
|  | 409 | + | 
|---|
| 140 | 410 | ctrl = readl_relaxed(pc->base + pc->data->regs.ctrl); | 
|---|
| 141 | 411 | if (pc->data->vop_pwm) { | 
|---|
| 142 | 412 | if (pc->vop_pwm_en) | 
|---|
| .. | .. | 
|---|
| 146 | 416 | } | 
|---|
| 147 | 417 |  | 
|---|
| 148 | 418 | #ifdef CONFIG_PWM_ROCKCHIP_ONESHOT | 
|---|
| 149 |  | -	if (state->oneshot_count > PWM_ONESHOT_COUNT_MAX) { | 
|---|
| 150 |  | -		pc->oneshot = false; | 
|---|
| 151 |  | -		dev_err(chip->dev, "Oneshot_count value overflow.\n"); | 
|---|
| 152 |  | -	} else if (state->oneshot_count > 0) { | 
|---|
| 153 |  | -		pc->oneshot = true; | 
|---|
|  | 419 | +	if (state->oneshot_count > 0 && state->oneshot_count <= pc->data->oneshot_cnt_max) { | 
|---|
|  | 420 | +		u32 int_ctrl; | 
|---|
|  | 421 | + | 
|---|
|  | 422 | +		/* | 
|---|
|  | 423 | +		 * This is a workaround, an uncertain waveform will be | 
|---|
|  | 424 | +		 * generated after oneshot ends. It is needed to enable | 
|---|
|  | 425 | +		 * the dclk scale function to resolve it. It doesn't | 
|---|
|  | 426 | +		 * matter what the scale factor is, just make sure the | 
|---|
|  | 427 | +		 * scale function is turned on, for which we set scale | 
|---|
|  | 428 | +		 * factor to 2. | 
|---|
|  | 429 | +		 */ | 
|---|
|  | 430 | +		ctrl &= ~PWM_SCALE_MASK; | 
|---|
|  | 431 | +		ctrl |= (dclk_div / 2) << PWM_SCALE_SHIFT; | 
|---|
|  | 432 | +		ctrl &= ~PWM_CLK_SEL_MASK; | 
|---|
|  | 433 | +		ctrl |= PWM_SEL_SCALED_CLOCK; | 
|---|
|  | 434 | + | 
|---|
|  | 435 | +		pc->oneshot_en = true; | 
|---|
|  | 436 | +		ctrl &= ~PWM_MODE_MASK; | 
|---|
|  | 437 | +		ctrl |= PWM_ONESHOT; | 
|---|
|  | 438 | + | 
|---|
|  | 439 | +		ctrl &= ~PWM_ONESHOT_COUNT_MASK; | 
|---|
| 154 | 440 | ctrl |= (state->oneshot_count - 1) << PWM_ONESHOT_COUNT_SHIFT; | 
|---|
|  | 441 | + | 
|---|
|  | 442 | +		if (pc->irq >= 0) { | 
|---|
|  | 443 | +			int_ctrl = readl_relaxed(pc->base + PWM_REG_INT_EN(pc->channel_id)); | 
|---|
|  | 444 | +			int_ctrl |= PWM_CH_INT(pc->channel_id); | 
|---|
|  | 445 | +			writel_relaxed(int_ctrl, pc->base + PWM_REG_INT_EN(pc->channel_id)); | 
|---|
|  | 446 | +		} | 
|---|
| 155 | 447 | } else { | 
|---|
| 156 |  | -		pc->oneshot = false; | 
|---|
|  | 448 | +		u32 int_ctrl; | 
|---|
|  | 449 | + | 
|---|
|  | 450 | +		ctrl &= ~PWM_SCALE_MASK; | 
|---|
|  | 451 | +		ctrl &= ~PWM_CLK_SEL_MASK; | 
|---|
|  | 452 | +		ctrl |= PWM_SEL_NO_SCALED_CLOCK; | 
|---|
|  | 453 | + | 
|---|
|  | 454 | +		if (state->oneshot_count) | 
|---|
|  | 455 | +			dev_err(chip->dev, "Oneshot_count must be between 1 and %d.\n", | 
|---|
|  | 456 | +				pc->data->oneshot_cnt_max); | 
|---|
|  | 457 | + | 
|---|
|  | 458 | +		pc->oneshot_en = false; | 
|---|
|  | 459 | +		ctrl &= ~PWM_MODE_MASK; | 
|---|
| 157 | 460 | ctrl |= PWM_CONTINUOUS; | 
|---|
|  | 461 | + | 
|---|
|  | 462 | +		ctrl &= ~PWM_ONESHOT_COUNT_MASK; | 
|---|
|  | 463 | + | 
|---|
|  | 464 | +		int_ctrl = readl_relaxed(pc->base + PWM_REG_INT_EN(pc->channel_id)); | 
|---|
|  | 465 | +		int_ctrl &= ~PWM_CH_INT(pc->channel_id); | 
|---|
|  | 466 | +		writel_relaxed(int_ctrl, pc->base + PWM_REG_INT_EN(pc->channel_id)); | 
|---|
| 158 | 467 | } | 
|---|
| 159 | 468 | #endif | 
|---|
| 160 | 469 |  | 
|---|
|  | 470 | +	/* | 
|---|
|  | 471 | +	 * Lock the period and duty of previous configuration, then | 
|---|
|  | 472 | +	 * change the duty and period, that would not be effective. | 
|---|
|  | 473 | +	 */ | 
|---|
| 161 | 474 | if (pc->data->supports_lock) { | 
|---|
| 162 | 475 | ctrl |= PWM_LOCK_EN; | 
|---|
| 163 | 476 | writel_relaxed(ctrl, pc->base + pc->data->regs.ctrl); | 
|---|
| .. | .. | 
|---|
| 175 | 488 | } | 
|---|
| 176 | 489 |  | 
|---|
| 177 | 490 | /* | 
|---|
| 178 |  | -	 * Unlock and set polarity at the same time, | 
|---|
| 179 |  | -	 * the configuration of duty, period and polarity | 
|---|
| 180 |  | -	 * would be effective together at next period. | 
|---|
|  | 491 | +	 * Unlock and set polarity at the same time, the configuration of duty, | 
|---|
|  | 492 | +	 * period and polarity would be effective together at next period. It | 
|---|
|  | 493 | +	 * takes 10 dclk cycles to make sure lock works before unlocking. | 
|---|
| 181 | 494 | */ | 
|---|
| 182 |  | -	if (pc->data->supports_lock) | 
|---|
|  | 495 | +	if (pc->data->supports_lock) { | 
|---|
| 183 | 496 | ctrl &= ~PWM_LOCK_EN; | 
|---|
|  | 497 | +		ndelay(delay_ns); | 
|---|
|  | 498 | +	} | 
|---|
| 184 | 499 |  | 
|---|
| 185 | 500 | writel(ctrl, pc->base + pc->data->regs.ctrl); | 
|---|
| 186 | 501 | local_irq_restore(flags); | 
|---|
| 187 | 502 | } | 
|---|
| 188 | 503 |  | 
|---|
| 189 |  | -static int rockchip_pwm_enable(struct pwm_chip *chip, | 
|---|
| 190 |  | -			       struct pwm_device *pwm, | 
|---|
| 191 |  | -			       bool enable) | 
|---|
|  | 504 | +static int rockchip_pwm_enable_v1(struct pwm_chip *chip, struct pwm_device *pwm, bool enable) | 
|---|
| 192 | 505 | { | 
|---|
| 193 | 506 | struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); | 
|---|
| 194 | 507 | u32 enable_conf = pc->data->enable_conf; | 
|---|
| .. | .. | 
|---|
| 211 | 524 |  | 
|---|
| 212 | 525 | if (enable) { | 
|---|
| 213 | 526 | val |= enable_conf; | 
|---|
| 214 |  | -		if (pc->oneshot) | 
|---|
|  | 527 | +		if (pc->oneshot_en) | 
|---|
| 215 | 528 | val &= ~PWM_CONTINUOUS; | 
|---|
| 216 | 529 | } else { | 
|---|
| 217 | 530 | val &= ~enable_conf; | 
|---|
| .. | .. | 
|---|
| 227 | 540 | return 0; | 
|---|
| 228 | 541 | } | 
|---|
| 229 | 542 |  | 
|---|
|  | 543 | +static irqreturn_t rockchip_pwm_irq_v4(int irq, void *data) | 
|---|
|  | 544 | +{ | 
|---|
|  | 545 | +	struct rockchip_pwm_chip *pc = data; | 
|---|
|  | 546 | +	int val; | 
|---|
|  | 547 | +	irqreturn_t ret = IRQ_NONE; | 
|---|
|  | 548 | + | 
|---|
|  | 549 | +	val = readl_relaxed(pc->base + pc->data->regs.intsts); | 
|---|
|  | 550 | +#ifdef CONFIG_PWM_ROCKCHIP_ONESHOT | 
|---|
|  | 551 | +	if (val & ONESHOT_END_INT) { | 
|---|
|  | 552 | +		struct pwm_state state; | 
|---|
|  | 553 | + | 
|---|
|  | 554 | +		writel_relaxed(ONESHOT_END_INT, pc->base + pc->data->regs.intsts); | 
|---|
|  | 555 | + | 
|---|
|  | 556 | +		/* | 
|---|
|  | 557 | +		 * Set pwm state to disabled when the oneshot mode finished. | 
|---|
|  | 558 | +		 */ | 
|---|
|  | 559 | +		pwm_get_state(&pc->chip.pwms[0], &state); | 
|---|
|  | 560 | +		state.enabled = false; | 
|---|
|  | 561 | +		state.oneshot_count = 0; | 
|---|
|  | 562 | +		state.oneshot_repeat = 0; | 
|---|
|  | 563 | +		pwm_apply_state(&pc->chip.pwms[0], &state); | 
|---|
|  | 564 | + | 
|---|
|  | 565 | +		rockchip_pwm_oneshot_callback(&pc->chip.pwms[0], &state); | 
|---|
|  | 566 | + | 
|---|
|  | 567 | +		ret = IRQ_HANDLED; | 
|---|
|  | 568 | +	} | 
|---|
|  | 569 | +#endif | 
|---|
|  | 570 | +	if (val & CAP_LPR_INT) { | 
|---|
|  | 571 | +		writel_relaxed(CAP_LPR_INT, pc->base + pc->data->regs.intsts); | 
|---|
|  | 572 | +		pc->capture_cnt++; | 
|---|
|  | 573 | + | 
|---|
|  | 574 | +		ret = IRQ_HANDLED; | 
|---|
|  | 575 | +	} else if (val & CAP_HPR_INT) { | 
|---|
|  | 576 | +		writel_relaxed(CAP_HPR_INT, pc->base + pc->data->regs.intsts); | 
|---|
|  | 577 | +		pc->capture_cnt++; | 
|---|
|  | 578 | + | 
|---|
|  | 579 | +		ret = IRQ_HANDLED; | 
|---|
|  | 580 | +	} | 
|---|
|  | 581 | + | 
|---|
|  | 582 | +	/* | 
|---|
|  | 583 | +	 * Capture input waveform: | 
|---|
|  | 584 | +	 *    _______                 _______ | 
|---|
|  | 585 | +	 *   |       |               |       | | 
|---|
|  | 586 | +	 * __|       |_______________|       |________ | 
|---|
|  | 587 | +	 *   ^0      ^1              ^2 | 
|---|
|  | 588 | +	 * | 
|---|
|  | 589 | +	 * At position 0, the LPR interrupt comes, and PERIOD_LPR reg shows | 
|---|
|  | 590 | +	 * the low polarity cycles which should be ignored. The effective | 
|---|
|  | 591 | +	 * high and low polarity cycles will be calculated in position 1 and | 
|---|
|  | 592 | +	 * position 2, where the HPR and LPR interrupts come again. | 
|---|
|  | 593 | +	 */ | 
|---|
|  | 594 | +	if (pc->capture_cnt > 3) { | 
|---|
|  | 595 | +		writel_relaxed(CAP_LPR_INT | CAP_HPR_INT, pc->base + pc->data->regs.intsts); | 
|---|
|  | 596 | +		writel_relaxed(CAP_LPR_INT_EN(false) | CAP_HPR_INT_EN(false), | 
|---|
|  | 597 | +			       pc->base + pc->data->regs.int_en); | 
|---|
|  | 598 | +	} | 
|---|
|  | 599 | + | 
|---|
|  | 600 | +	if (val & WAVE_MIDDLE_INT) { | 
|---|
|  | 601 | +		writel_relaxed(WAVE_MIDDLE_INT, pc->base + pc->data->regs.intsts); | 
|---|
|  | 602 | + | 
|---|
|  | 603 | +		rockchip_pwm_wave_middle_callback(&pc->chip.pwms[0]); | 
|---|
|  | 604 | + | 
|---|
|  | 605 | +		ret = IRQ_HANDLED; | 
|---|
|  | 606 | +	} | 
|---|
|  | 607 | + | 
|---|
|  | 608 | +	if (val & WAVE_MAX_INT) { | 
|---|
|  | 609 | +		writel_relaxed(WAVE_MAX_INT, pc->base + pc->data->regs.intsts); | 
|---|
|  | 610 | + | 
|---|
|  | 611 | +		rockchip_pwm_wave_max_callback(&pc->chip.pwms[0]); | 
|---|
|  | 612 | + | 
|---|
|  | 613 | +		ret = IRQ_HANDLED; | 
|---|
|  | 614 | +	} | 
|---|
|  | 615 | + | 
|---|
|  | 616 | +	return ret; | 
|---|
|  | 617 | +} | 
|---|
|  | 618 | + | 
|---|
|  | 619 | +static void rockchip_pwm_config_v4(struct pwm_chip *chip, struct pwm_device *pwm, | 
|---|
|  | 620 | +				   const struct pwm_state *state) | 
|---|
|  | 621 | +{ | 
|---|
|  | 622 | +	struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); | 
|---|
|  | 623 | +	unsigned long period, duty; | 
|---|
|  | 624 | +	u64 div = 0; | 
|---|
|  | 625 | +	u32 rpt = 0; | 
|---|
|  | 626 | +	u32 offset = 0; | 
|---|
|  | 627 | + | 
|---|
|  | 628 | +	/* | 
|---|
|  | 629 | +	 * Since period and duty cycle registers have a width of 32 | 
|---|
|  | 630 | +	 * bits, every possible input period can be obtained using the | 
|---|
|  | 631 | +	 * default prescaler value for all practical clock rate values. | 
|---|
|  | 632 | +	 */ | 
|---|
|  | 633 | +	div = (u64)pc->clk_rate * state->period; | 
|---|
|  | 634 | +	period = DIV_ROUND_CLOSEST_ULL(div, pc->data->prescaler * NSEC_PER_SEC); | 
|---|
|  | 635 | + | 
|---|
|  | 636 | +	div = (u64)pc->clk_rate * state->duty_cycle; | 
|---|
|  | 637 | +	duty = DIV_ROUND_CLOSEST_ULL(div, pc->data->prescaler * NSEC_PER_SEC); | 
|---|
|  | 638 | + | 
|---|
|  | 639 | +	writel_relaxed(period, pc->base + pc->data->regs.period); | 
|---|
|  | 640 | +	writel_relaxed(duty, pc->base + pc->data->regs.duty); | 
|---|
|  | 641 | + | 
|---|
|  | 642 | +	if (pc->data->supports_polarity) { | 
|---|
|  | 643 | +		if (state->polarity == PWM_POLARITY_INVERSED) | 
|---|
|  | 644 | +			writel_relaxed(PWM_POLARITY(DUTY_NEGATIVE | INACTIVE_POSITIVE), | 
|---|
|  | 645 | +				       pc->base + pc->data->regs.ctrl); | 
|---|
|  | 646 | +		else | 
|---|
|  | 647 | +			writel_relaxed(PWM_POLARITY(DUTY_POSITIVE | INACTIVE_NEGATIVE), | 
|---|
|  | 648 | +				       pc->base + pc->data->regs.ctrl); | 
|---|
|  | 649 | +	} | 
|---|
|  | 650 | + | 
|---|
|  | 651 | +#ifdef CONFIG_PWM_ROCKCHIP_ONESHOT | 
|---|
|  | 652 | +	if ((state->oneshot_count > 0 && state->oneshot_count <= pc->data->oneshot_cnt_max) && | 
|---|
|  | 653 | +	    (state->oneshot_repeat <= pc->data->oneshot_rpt_max)) { | 
|---|
|  | 654 | +		rpt |= (state->oneshot_count - 1) << FIRST_DIMENSIONAL_SHIFT; | 
|---|
|  | 655 | +		if (state->oneshot_repeat) | 
|---|
|  | 656 | +			rpt |= (state->oneshot_repeat - 1) << SECOND_DIMENSINAL_SHIFT; | 
|---|
|  | 657 | + | 
|---|
|  | 658 | +		if (state->duty_offset > 0 && | 
|---|
|  | 659 | +		    state->duty_offset <= (state->period - state->duty_cycle)) { | 
|---|
|  | 660 | +			div = (u64)pc->clk_rate * state->duty_offset; | 
|---|
|  | 661 | +			offset = DIV_ROUND_CLOSEST_ULL(div, pc->data->prescaler * NSEC_PER_SEC); | 
|---|
|  | 662 | +		} else if (state->duty_offset > (state->period - state->duty_cycle)) { | 
|---|
|  | 663 | +			dev_err(chip->dev, "Duty_offset must be between %lld and %lld.\n", | 
|---|
|  | 664 | +				state->duty_cycle, state->period); | 
|---|
|  | 665 | +		} | 
|---|
|  | 666 | + | 
|---|
|  | 667 | +		pc->oneshot_en = true; | 
|---|
|  | 668 | +	} else { | 
|---|
|  | 669 | +		if (state->oneshot_count) | 
|---|
|  | 670 | +			dev_err(chip->dev, "Oneshot_count must be between 1 and %d.\n", | 
|---|
|  | 671 | +				pc->data->oneshot_cnt_max); | 
|---|
|  | 672 | + | 
|---|
|  | 673 | +		pc->oneshot_en = false; | 
|---|
|  | 674 | +	} | 
|---|
|  | 675 | +#endif | 
|---|
|  | 676 | + | 
|---|
|  | 677 | +	if (pc->oneshot_en) { | 
|---|
|  | 678 | +		writel_relaxed(PWM_MODE(ONESHOT_MODE) | PWM_ALIGNED_INVALID(true), | 
|---|
|  | 679 | +			       pc->base + pc->data->regs.ctrl); | 
|---|
|  | 680 | +		writel_relaxed(offset, pc->base + pc->data->regs.offset); | 
|---|
|  | 681 | +		writel_relaxed(rpt, pc->base + pc->data->regs.rpt); | 
|---|
|  | 682 | +		writel_relaxed(ONESHOT_END_INT_EN(true), pc->base + pc->data->regs.int_en); | 
|---|
|  | 683 | +	} else { | 
|---|
|  | 684 | +		writel_relaxed(PWM_MODE(CONTINUOUS_MODE) | PWM_ALIGNED_INVALID(false), | 
|---|
|  | 685 | +			       pc->base + pc->data->regs.ctrl); | 
|---|
|  | 686 | +		writel_relaxed(0, pc->base + pc->data->regs.offset); | 
|---|
|  | 687 | +		if (!pc->wave_en) | 
|---|
|  | 688 | +			writel_relaxed(0, pc->base + pc->data->regs.rpt); | 
|---|
|  | 689 | +		writel_relaxed(ONESHOT_END_INT_EN(false), pc->base + pc->data->regs.int_en); | 
|---|
|  | 690 | +	} | 
|---|
|  | 691 | + | 
|---|
|  | 692 | +	writel_relaxed(PWM_CTRL_UPDATE_EN(true), pc->base + pc->data->regs.enable); | 
|---|
|  | 693 | +} | 
|---|
|  | 694 | + | 
|---|
|  | 695 | +static int rockchip_pwm_enable_v4(struct pwm_chip *chip, struct pwm_device *pwm, bool enable) | 
|---|
|  | 696 | +{ | 
|---|
|  | 697 | +	struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); | 
|---|
|  | 698 | +	int ret; | 
|---|
|  | 699 | + | 
|---|
|  | 700 | +	if (enable) { | 
|---|
|  | 701 | +		ret = clk_enable(pc->clk); | 
|---|
|  | 702 | +		if (ret) | 
|---|
|  | 703 | +			return ret; | 
|---|
|  | 704 | +	} | 
|---|
|  | 705 | + | 
|---|
|  | 706 | +	writel_relaxed(PWM_EN(enable) | PWM_CLK_EN(enable), pc->base + pc->data->regs.enable); | 
|---|
|  | 707 | + | 
|---|
|  | 708 | +	if (!enable) | 
|---|
|  | 709 | +		clk_disable(pc->clk); | 
|---|
|  | 710 | + | 
|---|
|  | 711 | +	return 0; | 
|---|
|  | 712 | +} | 
|---|
|  | 713 | + | 
|---|
|  | 714 | +static void rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, | 
|---|
|  | 715 | +				const struct pwm_state *state) | 
|---|
|  | 716 | +{ | 
|---|
|  | 717 | +	struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); | 
|---|
|  | 718 | + | 
|---|
|  | 719 | +	pc->data->funcs.config(chip, pwm, state); | 
|---|
|  | 720 | +} | 
|---|
|  | 721 | + | 
|---|
|  | 722 | +static int rockchip_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm, bool enable) | 
|---|
|  | 723 | +{ | 
|---|
|  | 724 | +	struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); | 
|---|
|  | 725 | + | 
|---|
|  | 726 | +	return pc->data->funcs.enable(chip, pwm, enable); | 
|---|
|  | 727 | +} | 
|---|
|  | 728 | + | 
|---|
| 230 | 729 | static int rockchip_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, | 
|---|
| 231 |  | -			      struct pwm_state *state) | 
|---|
|  | 730 | +			      const struct pwm_state *state) | 
|---|
| 232 | 731 | { | 
|---|
| 233 | 732 | struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); | 
|---|
| 234 | 733 | struct pwm_state curstate; | 
|---|
| 235 | 734 | bool enabled; | 
|---|
| 236 | 735 | int ret = 0; | 
|---|
| 237 | 736 |  | 
|---|
| 238 |  | -	ret = clk_enable(pc->pclk); | 
|---|
| 239 |  | -	if (ret) | 
|---|
| 240 |  | -		return ret; | 
|---|
|  | 737 | +	if (!pc->oneshot_en) { | 
|---|
|  | 738 | +		ret = clk_enable(pc->pclk); | 
|---|
|  | 739 | +		if (ret) | 
|---|
|  | 740 | +			return ret; | 
|---|
|  | 741 | +	} | 
|---|
| 241 | 742 |  | 
|---|
| 242 | 743 | pwm_get_state(pwm, &curstate); | 
|---|
| 243 | 744 | enabled = curstate.enabled; | 
|---|
| .. | .. | 
|---|
| 257 | 758 | goto out; | 
|---|
| 258 | 759 | } | 
|---|
| 259 | 760 |  | 
|---|
| 260 |  | -	/* | 
|---|
| 261 |  | -	 * Update the state with the real hardware, which can differ a bit | 
|---|
| 262 |  | -	 * because of period/duty_cycle approximation. | 
|---|
| 263 |  | -	 */ | 
|---|
| 264 |  | -	rockchip_pwm_get_state(chip, pwm, state); | 
|---|
| 265 |  | - | 
|---|
| 266 |  | -	if (state->enabled || pc->oneshot) | 
|---|
|  | 761 | +	if (state->enabled) | 
|---|
| 267 | 762 | ret = pinctrl_select_state(pc->pinctrl, pc->active_state); | 
|---|
| 268 | 763 | out: | 
|---|
|  | 764 | +	if (!pc->oneshot_en) | 
|---|
|  | 765 | +		clk_disable(pc->pclk); | 
|---|
|  | 766 | + | 
|---|
|  | 767 | +	return ret; | 
|---|
|  | 768 | +} | 
|---|
|  | 769 | + | 
|---|
|  | 770 | +static void rockchip_pwm_set_capture_v4(struct pwm_chip *chip, struct pwm_device *pwm, | 
|---|
|  | 771 | +					bool enable) | 
|---|
|  | 772 | +{ | 
|---|
|  | 773 | +	struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); | 
|---|
|  | 774 | +	u32 channel_sel = 0; | 
|---|
|  | 775 | + | 
|---|
|  | 776 | +	if (enable) | 
|---|
|  | 777 | +		channel_sel = pc->channel_id; | 
|---|
|  | 778 | + | 
|---|
|  | 779 | +	pc->capture_cnt = 0; | 
|---|
|  | 780 | + | 
|---|
|  | 781 | +	writel_relaxed(enable ? PWM_MODE(CAPTURE_MODE) : PWM_MODE(CONTINUOUS_MODE), | 
|---|
|  | 782 | +		       pc->base + pc->data->regs.ctrl); | 
|---|
|  | 783 | +	writel_relaxed(CAP_LPR_INT_EN(enable) | CAP_HPR_INT_EN(enable) | PWM_IN_SEL(channel_sel), | 
|---|
|  | 784 | +		       pc->base + pc->data->regs.int_en); | 
|---|
|  | 785 | +} | 
|---|
|  | 786 | + | 
|---|
|  | 787 | +static int rockchip_pwm_get_capture_result_v4(struct pwm_chip *chip, struct pwm_device *pwm, | 
|---|
|  | 788 | +					      struct pwm_capture *capture_res) | 
|---|
|  | 789 | +{ | 
|---|
|  | 790 | +	struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); | 
|---|
|  | 791 | +	u64 tmp; | 
|---|
|  | 792 | + | 
|---|
|  | 793 | +	tmp = readl_relaxed(pc->base + pc->data->regs.hpr); | 
|---|
|  | 794 | +	tmp *= pc->data->prescaler * NSEC_PER_SEC; | 
|---|
|  | 795 | +	capture_res->duty_cycle = DIV_ROUND_CLOSEST_ULL(tmp, pc->clk_rate); | 
|---|
|  | 796 | + | 
|---|
|  | 797 | +	tmp = readl_relaxed(pc->base + pc->data->regs.lpr); | 
|---|
|  | 798 | +	tmp *= pc->data->prescaler * NSEC_PER_SEC; | 
|---|
|  | 799 | +	capture_res->period =  DIV_ROUND_CLOSEST_ULL(tmp, pc->clk_rate) + capture_res->duty_cycle; | 
|---|
|  | 800 | + | 
|---|
|  | 801 | +	if (!capture_res->duty_cycle || !capture_res->period) | 
|---|
|  | 802 | +		return -EINVAL; | 
|---|
|  | 803 | + | 
|---|
|  | 804 | +	writel_relaxed(0, pc->base + pc->data->regs.hpr); | 
|---|
|  | 805 | +	writel_relaxed(0, pc->base + pc->data->regs.lpr); | 
|---|
|  | 806 | + | 
|---|
|  | 807 | +	return 0; | 
|---|
|  | 808 | +} | 
|---|
|  | 809 | + | 
|---|
|  | 810 | +static u8 rockchip_pwm_get_capture_cnt(struct rockchip_pwm_chip *pc) | 
|---|
|  | 811 | +{ | 
|---|
|  | 812 | +	return pc->capture_cnt; | 
|---|
|  | 813 | +} | 
|---|
|  | 814 | + | 
|---|
|  | 815 | +static int rockchip_pwm_capture(struct pwm_chip *chip, struct pwm_device *pwm, | 
|---|
|  | 816 | +				struct pwm_capture *capture_res, unsigned long timeout_ms) | 
|---|
|  | 817 | +{ | 
|---|
|  | 818 | +	struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); | 
|---|
|  | 819 | +	struct pwm_state curstate; | 
|---|
|  | 820 | +	u8 capture_cnt; | 
|---|
|  | 821 | +	int ret = 0; | 
|---|
|  | 822 | + | 
|---|
|  | 823 | +	if (!pc->data->funcs.set_capture || !pc->data->funcs.get_capture_result) { | 
|---|
|  | 824 | +		dev_err(chip->dev, "Unsupported capture mode\n"); | 
|---|
|  | 825 | +		return -EINVAL; | 
|---|
|  | 826 | +	} | 
|---|
|  | 827 | + | 
|---|
|  | 828 | +	pwm_get_state(pwm, &curstate); | 
|---|
|  | 829 | +	if (curstate.enabled) { | 
|---|
|  | 830 | +		dev_err(chip->dev, "Failed to enable capture mode because PWM%d is busy\n", | 
|---|
|  | 831 | +			pc->channel_id); | 
|---|
|  | 832 | +		return -EBUSY; | 
|---|
|  | 833 | +	} | 
|---|
|  | 834 | + | 
|---|
|  | 835 | +	ret = clk_enable(pc->pclk); | 
|---|
|  | 836 | +	if (ret) | 
|---|
|  | 837 | +		return ret; | 
|---|
|  | 838 | + | 
|---|
|  | 839 | +	pc->data->funcs.set_capture(chip, pwm, true); | 
|---|
|  | 840 | +	ret = pc->data->funcs.enable(chip, pwm, true); | 
|---|
|  | 841 | +	if (ret) { | 
|---|
|  | 842 | +		dev_err(chip->dev, "Failed to enable capture mode\n"); | 
|---|
|  | 843 | +		goto err_disable_pclk; | 
|---|
|  | 844 | +	} | 
|---|
|  | 845 | + | 
|---|
|  | 846 | +	ret = readx_poll_timeout(rockchip_pwm_get_capture_cnt, pc, capture_cnt, | 
|---|
|  | 847 | +				 capture_cnt > 3, 0, timeout_ms * 1000); | 
|---|
|  | 848 | +	if (!ret) { | 
|---|
|  | 849 | +		dev_err(chip->dev, "Failed to wait for LPR/HPR interrupt\n"); | 
|---|
|  | 850 | +		ret = -ETIMEDOUT; | 
|---|
|  | 851 | +	} else { | 
|---|
|  | 852 | +		ret = pc->data->funcs.get_capture_result(chip, pwm, capture_res); | 
|---|
|  | 853 | +		if (ret) | 
|---|
|  | 854 | +			dev_err(chip->dev, "Failed to get capture result\n"); | 
|---|
|  | 855 | +	} | 
|---|
|  | 856 | + | 
|---|
|  | 857 | +	pc->data->funcs.enable(chip, pwm, false); | 
|---|
|  | 858 | +	pc->data->funcs.set_capture(chip, pwm, false); | 
|---|
|  | 859 | + | 
|---|
|  | 860 | +err_disable_pclk: | 
|---|
| 269 | 861 | clk_disable(pc->pclk); | 
|---|
| 270 | 862 |  | 
|---|
| 271 | 863 | return ret; | 
|---|
| 272 | 864 | } | 
|---|
| 273 | 865 |  | 
|---|
|  | 866 | +static int rockchip_pwm_set_counter_v4(struct pwm_chip *chip, struct pwm_device *pwm, | 
|---|
|  | 867 | +				       bool enable) | 
|---|
|  | 868 | +{ | 
|---|
|  | 869 | +	struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); | 
|---|
|  | 870 | +	u32 arbiter = 0; | 
|---|
|  | 871 | +	u32 channel_sel = 0; | 
|---|
|  | 872 | +	u32 val; | 
|---|
|  | 873 | + | 
|---|
|  | 874 | +	if (enable) { | 
|---|
|  | 875 | +		arbiter = BIT(pc->channel_id) << COUNTER_READ_LOCK_SHIFT | | 
|---|
|  | 876 | +			  BIT(pc->channel_id) << COUNTER_GRANT_SHIFT, | 
|---|
|  | 877 | +		channel_sel = pc->channel_id; | 
|---|
|  | 878 | +	} | 
|---|
|  | 879 | + | 
|---|
|  | 880 | +	writel_relaxed(arbiter, pc->base + COUNTER_ARBITER); | 
|---|
|  | 881 | +	if (enable) { | 
|---|
|  | 882 | +		val = readl_relaxed(pc->base + COUNTER_ARBITER); | 
|---|
|  | 883 | +		if (!(val & arbiter)) | 
|---|
|  | 884 | +			return -EINVAL; | 
|---|
|  | 885 | +	} | 
|---|
|  | 886 | + | 
|---|
|  | 887 | +	writel_relaxed(COUNTER_EN(enable) | COUNTER_CHANNEL_SEL(channel_sel), | 
|---|
|  | 888 | +		       pc->base + COUNTER_CTRL); | 
|---|
|  | 889 | + | 
|---|
|  | 890 | +	return 0; | 
|---|
|  | 891 | +} | 
|---|
|  | 892 | + | 
|---|
|  | 893 | +int rockchip_pwm_set_counter(struct pwm_device *pwm, bool enable) | 
|---|
|  | 894 | +{ | 
|---|
|  | 895 | +	struct pwm_chip *chip; | 
|---|
|  | 896 | +	struct rockchip_pwm_chip *pc; | 
|---|
|  | 897 | +	struct pwm_state curstate; | 
|---|
|  | 898 | +	int ret = 0; | 
|---|
|  | 899 | + | 
|---|
|  | 900 | +	if (!pwm) | 
|---|
|  | 901 | +		return -EINVAL; | 
|---|
|  | 902 | + | 
|---|
|  | 903 | +	chip = pwm->chip; | 
|---|
|  | 904 | +	pc = to_rockchip_pwm_chip(chip); | 
|---|
|  | 905 | + | 
|---|
|  | 906 | +	if (!pc->counter_support || | 
|---|
|  | 907 | +	    !pc->data->funcs.set_counter || !pc->data->funcs.get_counter_result) { | 
|---|
|  | 908 | +		dev_err(chip->dev, "Unsupported counter mode\n"); | 
|---|
|  | 909 | +		return -EINVAL; | 
|---|
|  | 910 | +	} | 
|---|
|  | 911 | + | 
|---|
|  | 912 | +	pwm_get_state(pwm, &curstate); | 
|---|
|  | 913 | +	if (curstate.enabled) { | 
|---|
|  | 914 | +		dev_err(chip->dev, "Failed to enable counter mode because PWM%d is busy\n", | 
|---|
|  | 915 | +			pc->channel_id); | 
|---|
|  | 916 | +		return -EBUSY; | 
|---|
|  | 917 | +	} | 
|---|
|  | 918 | + | 
|---|
|  | 919 | +	ret = clk_enable(pc->pclk); | 
|---|
|  | 920 | +	if (ret) | 
|---|
|  | 921 | +		return ret; | 
|---|
|  | 922 | + | 
|---|
|  | 923 | +	ret = pc->data->funcs.set_counter(chip, pwm, enable); | 
|---|
|  | 924 | +	if (ret) { | 
|---|
|  | 925 | +		dev_err(chip->dev, "Failed to abtain counter arbitration for PWM%d\n", | 
|---|
|  | 926 | +			pc->channel_id); | 
|---|
|  | 927 | +		goto err_disable_pclk; | 
|---|
|  | 928 | +	} | 
|---|
|  | 929 | + | 
|---|
|  | 930 | +err_disable_pclk: | 
|---|
|  | 931 | +	clk_disable(pc->pclk); | 
|---|
|  | 932 | + | 
|---|
|  | 933 | +	return ret; | 
|---|
|  | 934 | +} | 
|---|
|  | 935 | +EXPORT_SYMBOL_GPL(rockchip_pwm_set_counter); | 
|---|
|  | 936 | + | 
|---|
|  | 937 | +static int rockchip_pwm_get_counter_result_v4(struct pwm_chip *chip, struct pwm_device *pwm, | 
|---|
|  | 938 | +					      unsigned long *counter_res, bool is_clear) | 
|---|
|  | 939 | +{ | 
|---|
|  | 940 | +	struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); | 
|---|
|  | 941 | +	u64 low, high; | 
|---|
|  | 942 | + | 
|---|
|  | 943 | +	low = readl_relaxed(pc->base + COUNTER_LOW); | 
|---|
|  | 944 | +	high = readl_relaxed(pc->base + COUNTER_HIGH); | 
|---|
|  | 945 | + | 
|---|
|  | 946 | +	*counter_res = (high << 32) | low; | 
|---|
|  | 947 | +	if (!*counter_res) | 
|---|
|  | 948 | +		return -EINVAL; | 
|---|
|  | 949 | + | 
|---|
|  | 950 | +	if (is_clear) | 
|---|
|  | 951 | +		writel_relaxed(COUNTER_CLR(true), pc->base + COUNTER_CTRL); | 
|---|
|  | 952 | + | 
|---|
|  | 953 | +	return 0; | 
|---|
|  | 954 | +} | 
|---|
|  | 955 | + | 
|---|
|  | 956 | +int rockchip_pwm_get_counter_result(struct pwm_device *pwm, | 
|---|
|  | 957 | +				    unsigned long *counter_res, bool is_clear) | 
|---|
|  | 958 | +{ | 
|---|
|  | 959 | +	struct pwm_chip *chip; | 
|---|
|  | 960 | +	struct rockchip_pwm_chip *pc; | 
|---|
|  | 961 | +	int ret = 0; | 
|---|
|  | 962 | + | 
|---|
|  | 963 | +	if (!pwm || !counter_res) | 
|---|
|  | 964 | +		return -EINVAL; | 
|---|
|  | 965 | + | 
|---|
|  | 966 | +	chip = pwm->chip; | 
|---|
|  | 967 | +	pc = to_rockchip_pwm_chip(chip); | 
|---|
|  | 968 | + | 
|---|
|  | 969 | +	if (!pc->counter_support || | 
|---|
|  | 970 | +	    !pc->data->funcs.set_counter || !pc->data->funcs.get_counter_result) { | 
|---|
|  | 971 | +		dev_err(chip->dev, "Unsupported counter mode\n"); | 
|---|
|  | 972 | +		return -EINVAL; | 
|---|
|  | 973 | +	} | 
|---|
|  | 974 | + | 
|---|
|  | 975 | +	ret = clk_enable(pc->pclk); | 
|---|
|  | 976 | +	if (ret) | 
|---|
|  | 977 | +		return ret; | 
|---|
|  | 978 | + | 
|---|
|  | 979 | +	ret = pc->data->funcs.get_counter_result(chip, pwm, counter_res, is_clear); | 
|---|
|  | 980 | +	if (ret) { | 
|---|
|  | 981 | +		dev_err(chip->dev, "Failed to get counter result for PWM%d\n", | 
|---|
|  | 982 | +			pc->channel_id); | 
|---|
|  | 983 | +		goto err_disable_pclk; | 
|---|
|  | 984 | +	} | 
|---|
|  | 985 | + | 
|---|
|  | 986 | +err_disable_pclk: | 
|---|
|  | 987 | +	clk_disable(pc->pclk); | 
|---|
|  | 988 | + | 
|---|
|  | 989 | +	return ret; | 
|---|
|  | 990 | +} | 
|---|
|  | 991 | +EXPORT_SYMBOL_GPL(rockchip_pwm_get_counter_result); | 
|---|
|  | 992 | + | 
|---|
|  | 993 | +static int rockchip_pwm_set_freq_meter_v4(struct pwm_chip *chip, struct pwm_device *pwm, | 
|---|
|  | 994 | +					  bool enable, unsigned long delay_ms) | 
|---|
|  | 995 | +{ | 
|---|
|  | 996 | +	struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); | 
|---|
|  | 997 | +	u64 div = 0; | 
|---|
|  | 998 | +	u64 timer_val = 0; | 
|---|
|  | 999 | +	u32 arbiter = 0; | 
|---|
|  | 1000 | +	u32 channel_sel = 0; | 
|---|
|  | 1001 | +	u32 val; | 
|---|
|  | 1002 | + | 
|---|
|  | 1003 | +	if (enable) { | 
|---|
|  | 1004 | +		arbiter = BIT(pc->channel_id) << FREQ_READ_LOCK_SHIFT | | 
|---|
|  | 1005 | +			  BIT(pc->channel_id) << FREQ_GRANT_SHIFT; | 
|---|
|  | 1006 | +		channel_sel = pc->channel_id; | 
|---|
|  | 1007 | + | 
|---|
|  | 1008 | +		div = (u64)pc->clk_rate * delay_ms; | 
|---|
|  | 1009 | +		timer_val = DIV_ROUND_CLOSEST_ULL(div, MSEC_PER_SEC); | 
|---|
|  | 1010 | +	} | 
|---|
|  | 1011 | + | 
|---|
|  | 1012 | +	writel_relaxed(arbiter, pc->base + FREQ_ARBITER); | 
|---|
|  | 1013 | +	if (enable) { | 
|---|
|  | 1014 | +		val = readl_relaxed(pc->base + FREQ_ARBITER); | 
|---|
|  | 1015 | +		if (!(val & arbiter)) | 
|---|
|  | 1016 | +			return -EINVAL; | 
|---|
|  | 1017 | +	} | 
|---|
|  | 1018 | + | 
|---|
|  | 1019 | +	writel_relaxed(FREQ_INT_EN(enable), pc->base + pc->data->regs.int_en); | 
|---|
|  | 1020 | +	writel_relaxed(timer_val, pc->base + FREQ_TIMER_VALUE); | 
|---|
|  | 1021 | +	writel_relaxed(FREQ_EN(enable) | FREQ_CHANNEL_SEL(channel_sel), | 
|---|
|  | 1022 | +		       pc->base + FREQ_CTRL); | 
|---|
|  | 1023 | + | 
|---|
|  | 1024 | +	return 0; | 
|---|
|  | 1025 | +} | 
|---|
|  | 1026 | + | 
|---|
|  | 1027 | +static int rockchip_pwm_get_freq_meter_result_v4(struct pwm_chip *chip, struct pwm_device *pwm, | 
|---|
|  | 1028 | +						 unsigned long delay_ms, unsigned long *freq_hz) | 
|---|
|  | 1029 | +{ | 
|---|
|  | 1030 | +	struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); | 
|---|
|  | 1031 | +	int ret; | 
|---|
|  | 1032 | +	u32 val; | 
|---|
|  | 1033 | + | 
|---|
|  | 1034 | +	ret = readl_relaxed_poll_timeout(pc->base + pc->data->regs.intsts, val, val & FREQ_INT, | 
|---|
|  | 1035 | +					 0, delay_ms * 1000); | 
|---|
|  | 1036 | +	if (!ret) { | 
|---|
|  | 1037 | +		dev_err(chip->dev, "failed to wait for freq_meter interrupt\n"); | 
|---|
|  | 1038 | +		return -ETIMEDOUT; | 
|---|
|  | 1039 | +	} | 
|---|
|  | 1040 | + | 
|---|
|  | 1041 | +	*freq_hz = readl_relaxed(pc->base + FREQ_RESULT_VALUE); | 
|---|
|  | 1042 | +	if (!*freq_hz) | 
|---|
|  | 1043 | +		return -EINVAL; | 
|---|
|  | 1044 | + | 
|---|
|  | 1045 | +	return 0; | 
|---|
|  | 1046 | +} | 
|---|
|  | 1047 | + | 
|---|
|  | 1048 | +int rockchip_pwm_set_freq_meter(struct pwm_device *pwm, unsigned long delay_ms, | 
|---|
|  | 1049 | +				unsigned long *freq_hz) | 
|---|
|  | 1050 | +{ | 
|---|
|  | 1051 | +	struct pwm_chip *chip; | 
|---|
|  | 1052 | +	struct rockchip_pwm_chip *pc; | 
|---|
|  | 1053 | +	struct pwm_state curstate; | 
|---|
|  | 1054 | +	int ret = 0; | 
|---|
|  | 1055 | + | 
|---|
|  | 1056 | +	if (!pwm || !freq_hz) | 
|---|
|  | 1057 | +		return -EINVAL; | 
|---|
|  | 1058 | + | 
|---|
|  | 1059 | +	chip = pwm->chip; | 
|---|
|  | 1060 | +	pc = to_rockchip_pwm_chip(chip); | 
|---|
|  | 1061 | + | 
|---|
|  | 1062 | +	if (!pc->freq_meter_support || | 
|---|
|  | 1063 | +	    !pc->data->funcs.set_freq_meter || !pc->data->funcs.get_freq_meter_result) { | 
|---|
|  | 1064 | +		dev_err(chip->dev, "Unsupported frequency meter mode\n"); | 
|---|
|  | 1065 | +		return -EINVAL; | 
|---|
|  | 1066 | +	} | 
|---|
|  | 1067 | + | 
|---|
|  | 1068 | +	pwm_get_state(pwm, &curstate); | 
|---|
|  | 1069 | +	if (curstate.enabled) { | 
|---|
|  | 1070 | +		dev_err(chip->dev, "Failed to enable frequency meter mode because PWM%d is busy\n", | 
|---|
|  | 1071 | +			pc->channel_id); | 
|---|
|  | 1072 | +		return -EBUSY; | 
|---|
|  | 1073 | +	} | 
|---|
|  | 1074 | + | 
|---|
|  | 1075 | +	ret = clk_enable(pc->pclk); | 
|---|
|  | 1076 | +	if (ret) | 
|---|
|  | 1077 | +		return ret; | 
|---|
|  | 1078 | + | 
|---|
|  | 1079 | +	ret = pc->data->funcs.set_freq_meter(chip, pwm, true, delay_ms); | 
|---|
|  | 1080 | +	if (ret) { | 
|---|
|  | 1081 | +		dev_err(chip->dev, "Failed to abtain frequency meter arbitration for PWM%d\n", | 
|---|
|  | 1082 | +			pc->channel_id); | 
|---|
|  | 1083 | +	} else { | 
|---|
|  | 1084 | +		ret = pc->data->funcs.get_freq_meter_result(chip, pwm, delay_ms, freq_hz); | 
|---|
|  | 1085 | +		if (ret) { | 
|---|
|  | 1086 | +			dev_err(chip->dev, "Failed to get frequency meter result for PWM%d\n", | 
|---|
|  | 1087 | +				pc->channel_id); | 
|---|
|  | 1088 | +		} | 
|---|
|  | 1089 | +	} | 
|---|
|  | 1090 | +	pc->data->funcs.set_freq_meter(chip, pwm, false, 0); | 
|---|
|  | 1091 | + | 
|---|
|  | 1092 | +	clk_disable(pc->pclk); | 
|---|
|  | 1093 | + | 
|---|
|  | 1094 | +	return ret; | 
|---|
|  | 1095 | +} | 
|---|
|  | 1096 | +EXPORT_SYMBOL_GPL(rockchip_pwm_set_freq_meter); | 
|---|
|  | 1097 | + | 
|---|
|  | 1098 | +static int rockchip_pwm_global_ctrl_v4(struct pwm_chip *chip, struct pwm_device *pwm, | 
|---|
|  | 1099 | +				       enum rockchip_pwm_global_ctrl_cmd cmd) | 
|---|
|  | 1100 | +{ | 
|---|
|  | 1101 | +	struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); | 
|---|
|  | 1102 | +	u32 arbiter = 0; | 
|---|
|  | 1103 | +	u32 val = 0; | 
|---|
|  | 1104 | + | 
|---|
|  | 1105 | +	switch (cmd) { | 
|---|
|  | 1106 | +	case PWM_GLOBAL_CTRL_JOIN: | 
|---|
|  | 1107 | +		writel_relaxed(PWM_GLOBAL_JOIN_EN(true), pc->base + pc->data->regs.enable); | 
|---|
|  | 1108 | +		writel_relaxed(CLK_GLOBAL_SEL(true), pc->base + pc->data->regs.clk_ctrl); | 
|---|
|  | 1109 | +		break; | 
|---|
|  | 1110 | +	case PWM_GLOBAL_CTRL_EXIT: | 
|---|
|  | 1111 | +		writel_relaxed(PWM_GLOBAL_JOIN_EN(false), pc->base + pc->data->regs.enable); | 
|---|
|  | 1112 | +		writel_relaxed(CLK_GLOBAL_SEL(false), pc->base + pc->data->regs.clk_ctrl); | 
|---|
|  | 1113 | +		break; | 
|---|
|  | 1114 | +	case PWM_GLOBAL_CTRL_GRANT: | 
|---|
|  | 1115 | +		arbiter = BIT(pc->channel_id) << GLOBAL_READ_LOCK_SHIFT | | 
|---|
|  | 1116 | +			  BIT(pc->channel_id) << GLOBAL_GRANT_SHIFT; | 
|---|
|  | 1117 | + | 
|---|
|  | 1118 | +		writel_relaxed(arbiter, pc->base + GLOBAL_ARBITER); | 
|---|
|  | 1119 | +		val = readl_relaxed(pc->base + GLOBAL_ARBITER); | 
|---|
|  | 1120 | +		if (!(val & arbiter)) { | 
|---|
|  | 1121 | +			dev_err(chip->dev, "Failed to abtain global ctrl arbitration for PWM%d\n", | 
|---|
|  | 1122 | +				pc->channel_id); | 
|---|
|  | 1123 | +			return -EINVAL; | 
|---|
|  | 1124 | +		} | 
|---|
|  | 1125 | + | 
|---|
|  | 1126 | +		pc->global_ctrl_grant = true; | 
|---|
|  | 1127 | +		break; | 
|---|
|  | 1128 | +	case PWM_GLOBAL_CTRL_RECLAIM: | 
|---|
|  | 1129 | +		writel_relaxed(0, pc->base + GLOBAL_ARBITER); | 
|---|
|  | 1130 | + | 
|---|
|  | 1131 | +		pc->global_ctrl_grant = false; | 
|---|
|  | 1132 | +		break; | 
|---|
|  | 1133 | +	case PWM_GLOBAL_CTRL_UPDATE: | 
|---|
|  | 1134 | +		if (!pc->global_ctrl_grant) { | 
|---|
|  | 1135 | +			dev_err(chip->dev, "CMD %d: get global ctrl arbitration first for PWM%d\n", | 
|---|
|  | 1136 | +				cmd, pc->channel_id); | 
|---|
|  | 1137 | +			return -EINVAL; | 
|---|
|  | 1138 | +		} | 
|---|
|  | 1139 | + | 
|---|
|  | 1140 | +		writel_relaxed(GLOBAL_PWM_UPDATE_EN(true), pc->base + GLOBAL_CTRL); | 
|---|
|  | 1141 | +		break; | 
|---|
|  | 1142 | +	case PWM_GLOBAL_CTRL_ENABLE: | 
|---|
|  | 1143 | +		if (!pc->global_ctrl_grant) { | 
|---|
|  | 1144 | +			dev_err(chip->dev, "CMD %d: get global ctrl arbitration first for PWM%d\n", | 
|---|
|  | 1145 | +				cmd, pc->channel_id); | 
|---|
|  | 1146 | +			return -EINVAL; | 
|---|
|  | 1147 | +		} | 
|---|
|  | 1148 | + | 
|---|
|  | 1149 | +		writel_relaxed(PWM_CLK_EN(true), pc->base + pc->data->regs.enable); | 
|---|
|  | 1150 | +		writel_relaxed(GLOBAL_PWM_EN(true), pc->base + GLOBAL_CTRL); | 
|---|
|  | 1151 | +		break; | 
|---|
|  | 1152 | +	case PWM_GLOBAL_CTRL_DISABLE: | 
|---|
|  | 1153 | +		if (!pc->global_ctrl_grant) { | 
|---|
|  | 1154 | +			dev_err(chip->dev, "CMD %d: get global ctrl arbitration first for PWM%d\n", | 
|---|
|  | 1155 | +				cmd, pc->channel_id); | 
|---|
|  | 1156 | +			return -EINVAL; | 
|---|
|  | 1157 | +		} | 
|---|
|  | 1158 | + | 
|---|
|  | 1159 | +		writel_relaxed(PWM_CLK_EN(false), pc->base + pc->data->regs.enable); | 
|---|
|  | 1160 | +		writel_relaxed(GLOBAL_PWM_EN(false), pc->base + GLOBAL_CTRL); | 
|---|
|  | 1161 | +		break; | 
|---|
|  | 1162 | +	default: | 
|---|
|  | 1163 | +		dev_err(chip->dev, "Unsupported global ctrl cmd %d\n", cmd); | 
|---|
|  | 1164 | +		return -EINVAL; | 
|---|
|  | 1165 | +	} | 
|---|
|  | 1166 | + | 
|---|
|  | 1167 | +	return 0; | 
|---|
|  | 1168 | +} | 
|---|
|  | 1169 | + | 
|---|
|  | 1170 | +int rockchip_pwm_global_ctrl(struct pwm_device *pwm, enum rockchip_pwm_global_ctrl_cmd cmd) | 
|---|
|  | 1171 | +{ | 
|---|
|  | 1172 | +	struct pwm_chip *chip; | 
|---|
|  | 1173 | +	struct rockchip_pwm_chip *pc; | 
|---|
|  | 1174 | +	struct pwm_state curstate; | 
|---|
|  | 1175 | +	int ret = 0; | 
|---|
|  | 1176 | + | 
|---|
|  | 1177 | +	if (!pwm) | 
|---|
|  | 1178 | +		return -EINVAL; | 
|---|
|  | 1179 | + | 
|---|
|  | 1180 | +	chip = pwm->chip; | 
|---|
|  | 1181 | +	pc = to_rockchip_pwm_chip(chip); | 
|---|
|  | 1182 | + | 
|---|
|  | 1183 | +	if (!pc->data->funcs.global_ctrl) { | 
|---|
|  | 1184 | +		dev_err(chip->dev, "Unsupported global control\n"); | 
|---|
|  | 1185 | +		return -EINVAL; | 
|---|
|  | 1186 | +	} | 
|---|
|  | 1187 | + | 
|---|
|  | 1188 | +	pwm_get_state(pwm, &curstate); | 
|---|
|  | 1189 | +	if (curstate.enabled) { | 
|---|
|  | 1190 | +		dev_err(chip->dev, "Failed to execute global ctrl cmd %d because PWM%d is busy\n", | 
|---|
|  | 1191 | +			cmd, pc->channel_id); | 
|---|
|  | 1192 | +		return -EBUSY; | 
|---|
|  | 1193 | +	} | 
|---|
|  | 1194 | + | 
|---|
|  | 1195 | +	ret = clk_enable(pc->pclk); | 
|---|
|  | 1196 | +	if (ret) | 
|---|
|  | 1197 | +		return ret; | 
|---|
|  | 1198 | + | 
|---|
|  | 1199 | +	ret = pc->data->funcs.global_ctrl(chip, pwm, cmd); | 
|---|
|  | 1200 | +	if (ret) { | 
|---|
|  | 1201 | +		dev_err(chip->dev, "Failed to execute global ctrl cmd %d for PWM%d\n", | 
|---|
|  | 1202 | +			cmd, pc->channel_id); | 
|---|
|  | 1203 | +		goto err_disable_pclk; | 
|---|
|  | 1204 | +	} | 
|---|
|  | 1205 | + | 
|---|
|  | 1206 | +err_disable_pclk: | 
|---|
|  | 1207 | +	clk_disable(pc->pclk); | 
|---|
|  | 1208 | + | 
|---|
|  | 1209 | +	return ret; | 
|---|
|  | 1210 | +} | 
|---|
|  | 1211 | +EXPORT_SYMBOL_GPL(rockchip_pwm_global_ctrl); | 
|---|
|  | 1212 | + | 
|---|
|  | 1213 | +static int rockchip_pwm_set_wave_table_v4(struct pwm_chip *chip, struct pwm_device *pwm, | 
|---|
|  | 1214 | +					  struct rockchip_pwm_wave_table *table_config, | 
|---|
|  | 1215 | +					  enum rockchip_pwm_wave_table_width_mode width_mode) | 
|---|
|  | 1216 | +{ | 
|---|
|  | 1217 | +	struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); | 
|---|
|  | 1218 | +	u64 table_val = 0; | 
|---|
|  | 1219 | +	u64 div = 0; | 
|---|
|  | 1220 | +	u32 arbiter = 0; | 
|---|
|  | 1221 | +	u32 val; | 
|---|
|  | 1222 | +	u16 table_max; | 
|---|
|  | 1223 | +	int i; | 
|---|
|  | 1224 | + | 
|---|
|  | 1225 | +	if (width_mode == PWM_WAVE_TABLE_16BITS_WIDTH) | 
|---|
|  | 1226 | +		table_max = pc->data->wave_table_max / 2; | 
|---|
|  | 1227 | +	else | 
|---|
|  | 1228 | +		table_max = pc->data->wave_table_max; | 
|---|
|  | 1229 | + | 
|---|
|  | 1230 | +	if (!table_config->table || | 
|---|
|  | 1231 | +	    table_config->offset > table_max || table_config->len > table_max) { | 
|---|
|  | 1232 | +		dev_err(chip->dev, "The wave table to set is out of range for PWM%d\n", | 
|---|
|  | 1233 | +			pc->channel_id); | 
|---|
|  | 1234 | +		return -EINVAL; | 
|---|
|  | 1235 | +	} | 
|---|
|  | 1236 | + | 
|---|
|  | 1237 | +	arbiter = BIT(pc->channel_id) << WAVE_MEM_GRANT_SHIFT | | 
|---|
|  | 1238 | +		  BIT(pc->channel_id) << WAVE_MEM_READ_LOCK_SHIFT; | 
|---|
|  | 1239 | +	writel_relaxed(arbiter, pc->base + WAVE_MEM_ARBITER); | 
|---|
|  | 1240 | + | 
|---|
|  | 1241 | +	val = readl_relaxed(pc->base + WAVE_MEM_ARBITER); | 
|---|
|  | 1242 | +	if (!(val & arbiter)) { | 
|---|
|  | 1243 | +		dev_err(chip->dev, "Failed to abtain wave memory arbitration for PWM%d\n", | 
|---|
|  | 1244 | +			pc->channel_id); | 
|---|
|  | 1245 | +		return -EINVAL; | 
|---|
|  | 1246 | +	} | 
|---|
|  | 1247 | + | 
|---|
|  | 1248 | +	if (width_mode == PWM_WAVE_TABLE_16BITS_WIDTH) { | 
|---|
|  | 1249 | +		for (i = 0; i < table_config->len; i++) { | 
|---|
|  | 1250 | +			div = (u64)pc->clk_rate * table_config->table[i]; | 
|---|
|  | 1251 | +			table_val = DIV_ROUND_CLOSEST_ULL(div, pc->data->prescaler * NSEC_PER_SEC); | 
|---|
|  | 1252 | +			writel_relaxed(table_val & 0xff, | 
|---|
|  | 1253 | +				       pc->base + WAVE_MEM + (table_config->offset + i) * 2 * 4); | 
|---|
|  | 1254 | +			if (readl_poll_timeout(pc->base + WAVE_MEM_STATUS, | 
|---|
|  | 1255 | +					       val, (val & BIT(WAVE_MEM_STATUS_SHIFT)), | 
|---|
|  | 1256 | +					       1000, 10 * 1000)) { | 
|---|
|  | 1257 | +				dev_err(chip->dev, | 
|---|
|  | 1258 | +					"Wait for wave mem(offset 0x%08x) to update failed\n", | 
|---|
|  | 1259 | +					(table_config->offset + i) * 2 * 4); | 
|---|
|  | 1260 | +				return -ETIMEDOUT; | 
|---|
|  | 1261 | +			} | 
|---|
|  | 1262 | + | 
|---|
|  | 1263 | +			writel_relaxed((table_val >> 8) & 0xff, | 
|---|
|  | 1264 | +				       pc->base + WAVE_MEM + | 
|---|
|  | 1265 | +				       ((table_config->offset + i) * 2 + 1) * 4); | 
|---|
|  | 1266 | +			if (readl_poll_timeout(pc->base + WAVE_MEM_STATUS, | 
|---|
|  | 1267 | +					       val, (val & BIT(WAVE_MEM_STATUS_SHIFT)), | 
|---|
|  | 1268 | +					       1000, 10 * 1000)) { | 
|---|
|  | 1269 | +				dev_err(chip->dev, | 
|---|
|  | 1270 | +					"Wait for wave mem(offset 0x%08x) to update failed\n", | 
|---|
|  | 1271 | +					((table_config->offset + i) * 2 + 1) * 4); | 
|---|
|  | 1272 | +				return -ETIMEDOUT; | 
|---|
|  | 1273 | +			} | 
|---|
|  | 1274 | +		} | 
|---|
|  | 1275 | +	} else { | 
|---|
|  | 1276 | +		for (i = 0; i < table_config->len; i++) { | 
|---|
|  | 1277 | +			div = (u64)pc->clk_rate * table_config->table[i]; | 
|---|
|  | 1278 | +			table_val = DIV_ROUND_CLOSEST_ULL(div, pc->data->prescaler * NSEC_PER_SEC); | 
|---|
|  | 1279 | +			writel_relaxed(table_val, | 
|---|
|  | 1280 | +				       pc->base + WAVE_MEM + (table_config->offset + i) * 4); | 
|---|
|  | 1281 | +			if (readl_poll_timeout(pc->base + WAVE_MEM_STATUS, | 
|---|
|  | 1282 | +					       val, (val & BIT(WAVE_MEM_STATUS_SHIFT)), | 
|---|
|  | 1283 | +					       1000, 10 * 1000)) { | 
|---|
|  | 1284 | +				dev_err(chip->dev, | 
|---|
|  | 1285 | +					"Wait for wave mem(offset 0x%08x) to update failed\n", | 
|---|
|  | 1286 | +					(table_config->offset + i) * 4); | 
|---|
|  | 1287 | +				return -ETIMEDOUT; | 
|---|
|  | 1288 | +			} | 
|---|
|  | 1289 | +		} | 
|---|
|  | 1290 | +	} | 
|---|
|  | 1291 | + | 
|---|
|  | 1292 | +	writel_relaxed(0, pc->base + WAVE_MEM_ARBITER); | 
|---|
|  | 1293 | + | 
|---|
|  | 1294 | +	return 0; | 
|---|
|  | 1295 | +} | 
|---|
|  | 1296 | + | 
|---|
|  | 1297 | +static int rockchip_pwm_set_wave_v4(struct pwm_chip *chip, struct pwm_device *pwm, | 
|---|
|  | 1298 | +				    struct rockchip_pwm_wave_config *config) | 
|---|
|  | 1299 | +{ | 
|---|
|  | 1300 | +	struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); | 
|---|
|  | 1301 | +	u32 ctrl = 0; | 
|---|
|  | 1302 | +	u32 max_val = 0; | 
|---|
|  | 1303 | +	u32 min_val = 0; | 
|---|
|  | 1304 | +	u32 offset = 0; | 
|---|
|  | 1305 | +	u32 middle = 0; | 
|---|
|  | 1306 | +	u32 rpt = 0; | 
|---|
|  | 1307 | +	u8 factor = 0; | 
|---|
|  | 1308 | + | 
|---|
|  | 1309 | +	if (config->enable) { | 
|---|
|  | 1310 | +		/* | 
|---|
|  | 1311 | +		 * If the width mode is 16-bits mode, two 8-bits table units | 
|---|
|  | 1312 | +		 * are combined into one 16-bits unit. | 
|---|
|  | 1313 | +		 */ | 
|---|
|  | 1314 | +		if (config->width_mode == PWM_WAVE_TABLE_16BITS_WIDTH) | 
|---|
|  | 1315 | +			factor = 2; | 
|---|
|  | 1316 | +		else | 
|---|
|  | 1317 | +			factor = 1; | 
|---|
|  | 1318 | + | 
|---|
|  | 1319 | +		ctrl = WAVE_DUTY_EN(config->duty_en) | | 
|---|
|  | 1320 | +		       WAVE_PERIOD_EN(config->period_en) | | 
|---|
|  | 1321 | +		       WAVE_WIDTH_MODE(config->width_mode) | | 
|---|
|  | 1322 | +		       WAVE_UPDATE_MODE(config->update_mode); | 
|---|
|  | 1323 | +		max_val = config->duty_max * factor << WAVE_DUTY_MAX_SHIFT | | 
|---|
|  | 1324 | +			  config->period_max * factor << WAVE_PERIOD_MAX_SHIFT; | 
|---|
|  | 1325 | +		min_val = config->duty_min * factor << WAVE_DUTY_MIN_SHIFT | | 
|---|
|  | 1326 | +			  config->period_min * factor << WAVE_PERIOD_MIN_SHIFT; | 
|---|
|  | 1327 | +		offset = config->offset * factor << WAVE_OFFSET_SHIFT; | 
|---|
|  | 1328 | +		middle = config->middle * factor << WAVE_MIDDLE_SHIFT; | 
|---|
|  | 1329 | + | 
|---|
|  | 1330 | +		rpt = config->rpt << FIRST_DIMENSIONAL_SHIFT; | 
|---|
|  | 1331 | +	} else { | 
|---|
|  | 1332 | +		ctrl = WAVE_DUTY_EN(false) | WAVE_PERIOD_EN(false); | 
|---|
|  | 1333 | +	} | 
|---|
|  | 1334 | + | 
|---|
|  | 1335 | +	writel_relaxed(ctrl, pc->base + WAVE_CTRL); | 
|---|
|  | 1336 | +	writel_relaxed(max_val, pc->base + WAVE_MAX); | 
|---|
|  | 1337 | +	writel_relaxed(min_val, pc->base + WAVE_MIN); | 
|---|
|  | 1338 | +	writel_relaxed(offset, pc->base + WAVE_OFFSET); | 
|---|
|  | 1339 | +	writel_relaxed(middle, pc->base + WAVE_MIDDLE); | 
|---|
|  | 1340 | + | 
|---|
|  | 1341 | +	writel_relaxed(rpt, pc->base + pc->data->regs.rpt); | 
|---|
|  | 1342 | +	writel_relaxed(WAVE_MAX_INT_EN(config->enable) | WAVE_MIDDLE_INT_EN(config->enable), | 
|---|
|  | 1343 | +		       pc->base + pc->data->regs.int_en); | 
|---|
|  | 1344 | + | 
|---|
|  | 1345 | +	pc->wave_en = config->enable; | 
|---|
|  | 1346 | + | 
|---|
|  | 1347 | +	return 0; | 
|---|
|  | 1348 | +} | 
|---|
|  | 1349 | + | 
|---|
|  | 1350 | +int rockchip_pwm_set_wave(struct pwm_device *pwm, struct rockchip_pwm_wave_config *config) | 
|---|
|  | 1351 | +{ | 
|---|
|  | 1352 | +	struct pwm_chip *chip; | 
|---|
|  | 1353 | +	struct rockchip_pwm_chip *pc; | 
|---|
|  | 1354 | +	int ret = 0; | 
|---|
|  | 1355 | + | 
|---|
|  | 1356 | +	if (!pwm || !config) | 
|---|
|  | 1357 | +		return -EINVAL; | 
|---|
|  | 1358 | + | 
|---|
|  | 1359 | +	chip = pwm->chip; | 
|---|
|  | 1360 | +	pc = to_rockchip_pwm_chip(chip); | 
|---|
|  | 1361 | + | 
|---|
|  | 1362 | +	if (!pc->wave_support || | 
|---|
|  | 1363 | +	    !pc->data->funcs.set_wave_table || !pc->data->funcs.set_wave) { | 
|---|
|  | 1364 | +		dev_err(chip->dev, "Unsupported wave generator mode\n"); | 
|---|
|  | 1365 | +		return -EINVAL; | 
|---|
|  | 1366 | +	} | 
|---|
|  | 1367 | + | 
|---|
|  | 1368 | +	ret = clk_enable(pc->pclk); | 
|---|
|  | 1369 | +	if (ret) | 
|---|
|  | 1370 | +		return ret; | 
|---|
|  | 1371 | + | 
|---|
|  | 1372 | +	if (config->duty_table) { | 
|---|
|  | 1373 | +		ret = pc->data->funcs.set_wave_table(chip, pwm, config->duty_table, | 
|---|
|  | 1374 | +						     config->width_mode); | 
|---|
|  | 1375 | +		if (ret) { | 
|---|
|  | 1376 | +			dev_err(chip->dev, "Failed to set wave duty table for PWM%d\n", | 
|---|
|  | 1377 | +				pc->channel_id); | 
|---|
|  | 1378 | +			goto err_disable_pclk; | 
|---|
|  | 1379 | +		} | 
|---|
|  | 1380 | +	} | 
|---|
|  | 1381 | + | 
|---|
|  | 1382 | +	if (config->period_table) { | 
|---|
|  | 1383 | +		ret = pc->data->funcs.set_wave_table(chip, pwm, config->period_table, | 
|---|
|  | 1384 | +						     config->width_mode); | 
|---|
|  | 1385 | +		if (ret) { | 
|---|
|  | 1386 | +			dev_err(chip->dev, "Failed to set wave period table for PWM%d\n", | 
|---|
|  | 1387 | +				pc->channel_id); | 
|---|
|  | 1388 | +			goto err_disable_pclk; | 
|---|
|  | 1389 | +		} | 
|---|
|  | 1390 | +	} | 
|---|
|  | 1391 | + | 
|---|
|  | 1392 | +	ret = pc->data->funcs.set_wave(chip, pwm, config); | 
|---|
|  | 1393 | +	if (ret) { | 
|---|
|  | 1394 | +		dev_err(chip->dev, "Failed to set wave generator for PWM%d\n", pc->channel_id); | 
|---|
|  | 1395 | +		goto err_disable_pclk; | 
|---|
|  | 1396 | +	} | 
|---|
|  | 1397 | + | 
|---|
|  | 1398 | +err_disable_pclk: | 
|---|
|  | 1399 | +	clk_disable(pc->pclk); | 
|---|
|  | 1400 | + | 
|---|
|  | 1401 | +	return ret; | 
|---|
|  | 1402 | +} | 
|---|
|  | 1403 | +EXPORT_SYMBOL_GPL(rockchip_pwm_set_wave); | 
|---|
|  | 1404 | + | 
|---|
|  | 1405 | +#ifdef CONFIG_DEBUG_FS | 
|---|
|  | 1406 | +static int rockchip_pwm_debugfs_show(struct seq_file *s, void *data) | 
|---|
|  | 1407 | +{ | 
|---|
|  | 1408 | +	struct rockchip_pwm_chip *pc = s->private; | 
|---|
|  | 1409 | +	u32 regs_start; | 
|---|
|  | 1410 | +	int i; | 
|---|
|  | 1411 | +	int ret = 0; | 
|---|
|  | 1412 | + | 
|---|
|  | 1413 | +	if (!pc->oneshot_en) { | 
|---|
|  | 1414 | +		ret = clk_enable(pc->pclk); | 
|---|
|  | 1415 | +		if (ret) | 
|---|
|  | 1416 | +			return ret; | 
|---|
|  | 1417 | +	} | 
|---|
|  | 1418 | + | 
|---|
|  | 1419 | +	regs_start = (u32)pc->res->start - pc->channel_id * 0x10; | 
|---|
|  | 1420 | +	for (i = 0; i < 0x40; i += 4) { | 
|---|
|  | 1421 | +		seq_printf(s, "%08x:  %08x %08x %08x %08x\n", regs_start + i * 4, | 
|---|
|  | 1422 | +			   readl_relaxed(pc->base + (4 * i)), | 
|---|
|  | 1423 | +			   readl_relaxed(pc->base + (4 * (i + 1))), | 
|---|
|  | 1424 | +			   readl_relaxed(pc->base + (4 * (i + 2))), | 
|---|
|  | 1425 | +			   readl_relaxed(pc->base + (4 * (i + 3)))); | 
|---|
|  | 1426 | +	} | 
|---|
|  | 1427 | + | 
|---|
|  | 1428 | +	if (!pc->oneshot_en) | 
|---|
|  | 1429 | +		clk_disable(pc->pclk); | 
|---|
|  | 1430 | + | 
|---|
|  | 1431 | +	return ret; | 
|---|
|  | 1432 | +} | 
|---|
|  | 1433 | +DEFINE_SHOW_ATTRIBUTE(rockchip_pwm_debugfs); | 
|---|
|  | 1434 | + | 
|---|
|  | 1435 | +static inline void rockchip_pwm_debugfs_init(struct rockchip_pwm_chip *pc) | 
|---|
|  | 1436 | +{ | 
|---|
|  | 1437 | +	pc->debugfs = debugfs_create_file(dev_name(pc->chip.dev), | 
|---|
|  | 1438 | +					  S_IFREG | 0444, NULL, pc, | 
|---|
|  | 1439 | +					  &rockchip_pwm_debugfs_fops); | 
|---|
|  | 1440 | +} | 
|---|
|  | 1441 | + | 
|---|
|  | 1442 | +static inline void rockchip_pwm_debugfs_deinit(struct rockchip_pwm_chip *pc) | 
|---|
|  | 1443 | +{ | 
|---|
|  | 1444 | +	debugfs_remove(pc->debugfs); | 
|---|
|  | 1445 | +} | 
|---|
|  | 1446 | +#else | 
|---|
|  | 1447 | +static inline void rockchip_pwm_debugfs_init(struct rockchip_pwm_chip *pc) | 
|---|
|  | 1448 | +{ | 
|---|
|  | 1449 | +} | 
|---|
|  | 1450 | + | 
|---|
|  | 1451 | +static inline void rockchip_pwm_debugfs_deinit(struct rockchip_pwm_chip *pc) | 
|---|
|  | 1452 | +{ | 
|---|
|  | 1453 | +} | 
|---|
|  | 1454 | +#endif | 
|---|
|  | 1455 | + | 
|---|
| 274 | 1456 | static const struct pwm_ops rockchip_pwm_ops = { | 
|---|
| 275 |  | -	.get_state = rockchip_pwm_get_state, | 
|---|
|  | 1457 | +	.capture = rockchip_pwm_capture, | 
|---|
| 276 | 1458 | .apply = rockchip_pwm_apply, | 
|---|
|  | 1459 | +	.get_state = rockchip_pwm_get_state, | 
|---|
| 277 | 1460 | .owner = THIS_MODULE, | 
|---|
| 278 | 1461 | }; | 
|---|
| 279 | 1462 |  | 
|---|
| 280 | 1463 | static const struct rockchip_pwm_data pwm_data_v1 = { | 
|---|
|  | 1464 | +	.main_version = 0x01, | 
|---|
| 281 | 1465 | .regs = { | 
|---|
|  | 1466 | +		.version = 0x5c, | 
|---|
| 282 | 1467 | .duty = 0x04, | 
|---|
| 283 | 1468 | .period = 0x08, | 
|---|
| 284 | 1469 | .cntr = 0x00, | 
|---|
| .. | .. | 
|---|
| 290 | 1475 | .vop_pwm = false, | 
|---|
| 291 | 1476 | .enable_conf = PWM_CTRL_OUTPUT_EN | PWM_CTRL_TIMER_EN, | 
|---|
| 292 | 1477 | .enable_conf_mask = BIT(1) | BIT(3), | 
|---|
|  | 1478 | +	.oneshot_cnt_max = 0x100, | 
|---|
|  | 1479 | +	.funcs = { | 
|---|
|  | 1480 | +		.enable = rockchip_pwm_enable_v1, | 
|---|
|  | 1481 | +		.config = rockchip_pwm_config_v1, | 
|---|
|  | 1482 | +	}, | 
|---|
| 293 | 1483 | }; | 
|---|
| 294 | 1484 |  | 
|---|
| 295 | 1485 | static const struct rockchip_pwm_data pwm_data_v2 = { | 
|---|
|  | 1486 | +	.main_version = 0x02, | 
|---|
| 296 | 1487 | .regs = { | 
|---|
|  | 1488 | +		.version = 0x5c, | 
|---|
| 297 | 1489 | .duty = 0x08, | 
|---|
| 298 | 1490 | .period = 0x04, | 
|---|
| 299 | 1491 | .cntr = 0x00, | 
|---|
| .. | .. | 
|---|
| 306 | 1498 | .enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE | | 
|---|
| 307 | 1499 | PWM_CONTINUOUS, | 
|---|
| 308 | 1500 | .enable_conf_mask = GENMASK(2, 0) | BIT(5) | BIT(8), | 
|---|
|  | 1501 | +	.oneshot_cnt_max = 0x100, | 
|---|
|  | 1502 | +	.funcs = { | 
|---|
|  | 1503 | +		.enable = rockchip_pwm_enable_v1, | 
|---|
|  | 1504 | +		.config = rockchip_pwm_config_v1, | 
|---|
|  | 1505 | +	}, | 
|---|
| 309 | 1506 | }; | 
|---|
| 310 | 1507 |  | 
|---|
| 311 | 1508 | static const struct rockchip_pwm_data pwm_data_vop = { | 
|---|
|  | 1509 | +	.main_version = 0x02, | 
|---|
| 312 | 1510 | .regs = { | 
|---|
|  | 1511 | +		.version = 0x5c, | 
|---|
| 313 | 1512 | .duty = 0x08, | 
|---|
| 314 | 1513 | .period = 0x04, | 
|---|
| 315 | 1514 | .cntr = 0x0c, | 
|---|
| .. | .. | 
|---|
| 322 | 1521 | .enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE | | 
|---|
| 323 | 1522 | PWM_CONTINUOUS, | 
|---|
| 324 | 1523 | .enable_conf_mask = GENMASK(2, 0) | BIT(5) | BIT(8), | 
|---|
|  | 1524 | +	.oneshot_cnt_max = 0x100, | 
|---|
|  | 1525 | +	.funcs = { | 
|---|
|  | 1526 | +		.enable = rockchip_pwm_enable_v1, | 
|---|
|  | 1527 | +		.config = rockchip_pwm_config_v1, | 
|---|
|  | 1528 | +	}, | 
|---|
| 325 | 1529 | }; | 
|---|
| 326 | 1530 |  | 
|---|
| 327 | 1531 | static const struct rockchip_pwm_data pwm_data_v3 = { | 
|---|
|  | 1532 | +	.main_version = 0x03, | 
|---|
| 328 | 1533 | .regs = { | 
|---|
|  | 1534 | +		.version = 0x5c, | 
|---|
| 329 | 1535 | .duty = 0x08, | 
|---|
| 330 | 1536 | .period = 0x04, | 
|---|
| 331 | 1537 | .cntr = 0x00, | 
|---|
| .. | .. | 
|---|
| 338 | 1544 | .enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE | | 
|---|
| 339 | 1545 | PWM_CONTINUOUS, | 
|---|
| 340 | 1546 | .enable_conf_mask = GENMASK(2, 0) | BIT(5) | BIT(8), | 
|---|
|  | 1547 | +	.oneshot_cnt_max = 0x100, | 
|---|
|  | 1548 | +	.funcs = { | 
|---|
|  | 1549 | +		.enable = rockchip_pwm_enable_v1, | 
|---|
|  | 1550 | +		.config = rockchip_pwm_config_v1, | 
|---|
|  | 1551 | +		.irq_handler = rockchip_pwm_irq_v1, | 
|---|
|  | 1552 | +	}, | 
|---|
|  | 1553 | +}; | 
|---|
|  | 1554 | + | 
|---|
|  | 1555 | +static const struct rockchip_pwm_data pwm_data_v4 = { | 
|---|
|  | 1556 | +	.main_version = 0x04, | 
|---|
|  | 1557 | +	.regs = { | 
|---|
|  | 1558 | +		.version = 0x0, | 
|---|
|  | 1559 | +		.enable = 0x4, | 
|---|
|  | 1560 | +		.clk_ctrl = 0x8, | 
|---|
|  | 1561 | +		.ctrl = 0xc, | 
|---|
|  | 1562 | +		.period = 0x10, | 
|---|
|  | 1563 | +		.duty = 0x14, | 
|---|
|  | 1564 | +		.offset = 0x18, | 
|---|
|  | 1565 | +		.rpt = 0x1c, | 
|---|
|  | 1566 | +		.hpr = 0x2c, | 
|---|
|  | 1567 | +		.lpr = 0x30, | 
|---|
|  | 1568 | +		.intsts = 0x70, | 
|---|
|  | 1569 | +		.int_en = 0x74, | 
|---|
|  | 1570 | +		.int_mask = 0x78, | 
|---|
|  | 1571 | +	}, | 
|---|
|  | 1572 | +	.prescaler = 1, | 
|---|
|  | 1573 | +	.supports_polarity = true, | 
|---|
|  | 1574 | +	.supports_lock = true, | 
|---|
|  | 1575 | +	.vop_pwm = false, | 
|---|
|  | 1576 | +	.oneshot_cnt_max = 0x10000, | 
|---|
|  | 1577 | +	.oneshot_rpt_max = 0x10000, | 
|---|
|  | 1578 | +	.wave_table_max = 0x300, | 
|---|
|  | 1579 | +	.enable_conf = PWM_ENABLE_V4, | 
|---|
|  | 1580 | +	.funcs = { | 
|---|
|  | 1581 | +		.enable = rockchip_pwm_enable_v4, | 
|---|
|  | 1582 | +		.config = rockchip_pwm_config_v4, | 
|---|
|  | 1583 | +		.set_capture = rockchip_pwm_set_capture_v4, | 
|---|
|  | 1584 | +		.get_capture_result = rockchip_pwm_get_capture_result_v4, | 
|---|
|  | 1585 | +		.set_counter = rockchip_pwm_set_counter_v4, | 
|---|
|  | 1586 | +		.get_counter_result = rockchip_pwm_get_counter_result_v4, | 
|---|
|  | 1587 | +		.set_freq_meter = rockchip_pwm_set_freq_meter_v4, | 
|---|
|  | 1588 | +		.get_freq_meter_result = rockchip_pwm_get_freq_meter_result_v4, | 
|---|
|  | 1589 | +		.global_ctrl = rockchip_pwm_global_ctrl_v4, | 
|---|
|  | 1590 | +		.set_wave_table = rockchip_pwm_set_wave_table_v4, | 
|---|
|  | 1591 | +		.set_wave = rockchip_pwm_set_wave_v4, | 
|---|
|  | 1592 | +		.irq_handler = rockchip_pwm_irq_v4, | 
|---|
|  | 1593 | +	}, | 
|---|
| 341 | 1594 | }; | 
|---|
| 342 | 1595 |  | 
|---|
| 343 | 1596 | static const struct of_device_id rockchip_pwm_dt_ids[] = { | 
|---|
| .. | .. | 
|---|
| 349 | 1602 | }; | 
|---|
| 350 | 1603 | MODULE_DEVICE_TABLE(of, rockchip_pwm_dt_ids); | 
|---|
| 351 | 1604 |  | 
|---|
|  | 1605 | +static int rockchip_pwm_get_channel_id(const char *name) | 
|---|
|  | 1606 | +{ | 
|---|
|  | 1607 | +	int len = strlen(name); | 
|---|
|  | 1608 | + | 
|---|
|  | 1609 | +	return name[len - 2] - '0'; | 
|---|
|  | 1610 | +} | 
|---|
|  | 1611 | + | 
|---|
| 352 | 1612 | static int rockchip_pwm_probe(struct platform_device *pdev) | 
|---|
| 353 | 1613 | { | 
|---|
| 354 | 1614 | const struct of_device_id *id; | 
|---|
| 355 | 1615 | struct rockchip_pwm_chip *pc; | 
|---|
| 356 | 1616 | struct resource *r; | 
|---|
|  | 1617 | +	u32 enable_conf, ctrl, version; | 
|---|
|  | 1618 | +	bool enabled; | 
|---|
| 357 | 1619 | int ret, count; | 
|---|
| 358 | 1620 |  | 
|---|
| 359 | 1621 | id = of_match_device(rockchip_pwm_dt_ids, &pdev->dev); | 
|---|
| .. | .. | 
|---|
| 365 | 1627 | return -ENOMEM; | 
|---|
| 366 | 1628 |  | 
|---|
| 367 | 1629 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 
|---|
| 368 |  | -	pc->base = devm_ioremap(&pdev->dev, r->start, | 
|---|
| 369 |  | -				resource_size(r)); | 
|---|
|  | 1630 | +	if (!r) { | 
|---|
|  | 1631 | +		dev_err(&pdev->dev, "Failed to get pwm register\n"); | 
|---|
|  | 1632 | +		return -EINVAL; | 
|---|
|  | 1633 | +	} | 
|---|
|  | 1634 | +	pc->res = r; | 
|---|
|  | 1635 | + | 
|---|
|  | 1636 | +	pc->base = devm_ioremap(&pdev->dev, pc->res->start, | 
|---|
|  | 1637 | +				resource_size(pc->res)); | 
|---|
| 370 | 1638 | if (IS_ERR(pc->base)) | 
|---|
| 371 | 1639 | return PTR_ERR(pc->base); | 
|---|
| 372 | 1640 |  | 
|---|
| 373 | 1641 | pc->clk = devm_clk_get(&pdev->dev, "pwm"); | 
|---|
| 374 | 1642 | if (IS_ERR(pc->clk)) { | 
|---|
| 375 | 1643 | pc->clk = devm_clk_get(&pdev->dev, NULL); | 
|---|
| 376 |  | -		if (IS_ERR(pc->clk)) { | 
|---|
| 377 |  | -			ret = PTR_ERR(pc->clk); | 
|---|
| 378 |  | -			if (ret != -EPROBE_DEFER) | 
|---|
| 379 |  | -				dev_err(&pdev->dev, "Can't get bus clk: %d\n", | 
|---|
| 380 |  | -					ret); | 
|---|
| 381 |  | -			return ret; | 
|---|
| 382 |  | -		} | 
|---|
|  | 1644 | +		if (IS_ERR(pc->clk)) | 
|---|
|  | 1645 | +			return dev_err_probe(&pdev->dev, PTR_ERR(pc->clk), | 
|---|
|  | 1646 | +					     "Can't get bus clk\n"); | 
|---|
| 383 | 1647 | } | 
|---|
| 384 | 1648 |  | 
|---|
| 385 | 1649 | count = of_count_phandle_with_args(pdev->dev.of_node, | 
|---|
| .. | .. | 
|---|
| 402 | 1666 | return ret; | 
|---|
| 403 | 1667 | } | 
|---|
| 404 | 1668 |  | 
|---|
| 405 |  | -	ret = clk_prepare(pc->pclk); | 
|---|
|  | 1669 | +	ret = clk_prepare_enable(pc->pclk); | 
|---|
| 406 | 1670 | if (ret) { | 
|---|
| 407 |  | -		dev_err(&pdev->dev, "Can't prepare APB clk: %d\n", ret); | 
|---|
|  | 1671 | +		dev_err(&pdev->dev, "Can't prepare enable APB clk: %d\n", ret); | 
|---|
| 408 | 1672 | goto err_clk; | 
|---|
| 409 | 1673 | } | 
|---|
| 410 | 1674 |  | 
|---|
| 411 | 1675 | pc->pinctrl = devm_pinctrl_get(&pdev->dev); | 
|---|
| 412 | 1676 | if (IS_ERR(pc->pinctrl)) { | 
|---|
| 413 | 1677 | dev_err(&pdev->dev, "Get pinctrl failed!\n"); | 
|---|
| 414 |  | -		return PTR_ERR(pc->pinctrl); | 
|---|
|  | 1678 | +		ret = PTR_ERR(pc->pinctrl); | 
|---|
|  | 1679 | +		goto err_pclk; | 
|---|
| 415 | 1680 | } | 
|---|
| 416 | 1681 |  | 
|---|
| 417 | 1682 | pc->active_state = pinctrl_lookup_state(pc->pinctrl, "active"); | 
|---|
| 418 | 1683 | if (IS_ERR(pc->active_state)) { | 
|---|
| 419 | 1684 | dev_err(&pdev->dev, "No active pinctrl state\n"); | 
|---|
| 420 |  | -		return PTR_ERR(pc->active_state); | 
|---|
|  | 1685 | +		ret = PTR_ERR(pc->active_state); | 
|---|
|  | 1686 | +		goto err_pclk; | 
|---|
| 421 | 1687 | } | 
|---|
| 422 | 1688 |  | 
|---|
| 423 | 1689 | platform_set_drvdata(pdev, pc); | 
|---|
| .. | .. | 
|---|
| 425 | 1691 | pc->data = id->data; | 
|---|
| 426 | 1692 | pc->chip.dev = &pdev->dev; | 
|---|
| 427 | 1693 | pc->chip.ops = &rockchip_pwm_ops; | 
|---|
| 428 |  | -	pc->chip.base = -1; | 
|---|
|  | 1694 | +	pc->chip.base = of_alias_get_id(pdev->dev.of_node, "pwm"); | 
|---|
| 429 | 1695 | pc->chip.npwm = 1; | 
|---|
| 430 | 1696 | pc->clk_rate = clk_get_rate(pc->clk); | 
|---|
|  | 1697 | +	pc->main_version = pc->data->main_version; | 
|---|
|  | 1698 | +	if (pc->main_version >= 4) { | 
|---|
|  | 1699 | +		version = readl_relaxed(pc->base + pc->data->regs.version); | 
|---|
|  | 1700 | +		pc->channel_id = (version & CHANNLE_INDEX_MASK) >> CHANNLE_INDEX_SHIFT; | 
|---|
|  | 1701 | +		pc->freq_meter_support = !!(version & FREQ_METER_SUPPORT); | 
|---|
|  | 1702 | +		pc->counter_support = !!(version & COUNTER_SUPPORT); | 
|---|
|  | 1703 | +		pc->wave_support = !!(version & WAVE_SUPPORT); | 
|---|
|  | 1704 | +	} else { | 
|---|
|  | 1705 | +		pc->channel_id = rockchip_pwm_get_channel_id(pdev->dev.of_node->full_name); | 
|---|
|  | 1706 | +	} | 
|---|
|  | 1707 | +	if (pc->channel_id < 0 || pc->channel_id >= PWM_MAX_CHANNEL_NUM) { | 
|---|
|  | 1708 | +		dev_err(&pdev->dev, "Channel id is out of range: %d\n", pc->channel_id); | 
|---|
|  | 1709 | +		ret = -EINVAL; | 
|---|
|  | 1710 | +		goto err_pclk; | 
|---|
|  | 1711 | +	} | 
|---|
|  | 1712 | + | 
|---|
|  | 1713 | +	if (pc->data->funcs.irq_handler) { | 
|---|
|  | 1714 | +		if (pc->main_version >= 4) { | 
|---|
|  | 1715 | +			pc->irq = platform_get_irq(pdev, 0); | 
|---|
|  | 1716 | +			if (pc->irq < 0) { | 
|---|
|  | 1717 | +				dev_err(&pdev->dev, "Get irq failed\n"); | 
|---|
|  | 1718 | +				ret = pc->irq; | 
|---|
|  | 1719 | +				goto err_pclk; | 
|---|
|  | 1720 | +			} | 
|---|
|  | 1721 | + | 
|---|
|  | 1722 | +			ret = devm_request_irq(&pdev->dev, pc->irq, pc->data->funcs.irq_handler, | 
|---|
|  | 1723 | +					       IRQF_NO_SUSPEND, "rk_pwm_irq", pc); | 
|---|
|  | 1724 | +			if (ret) { | 
|---|
|  | 1725 | +				dev_err(&pdev->dev, "Claim IRQ failed\n"); | 
|---|
|  | 1726 | +				goto err_pclk; | 
|---|
|  | 1727 | +			} | 
|---|
|  | 1728 | +		} else { | 
|---|
|  | 1729 | +			if (IS_ENABLED(CONFIG_PWM_ROCKCHIP_ONESHOT)) { | 
|---|
|  | 1730 | +				pc->irq = platform_get_irq_optional(pdev, 0); | 
|---|
|  | 1731 | +				if (pc->irq < 0) { | 
|---|
|  | 1732 | +					dev_warn(&pdev->dev, | 
|---|
|  | 1733 | +						 "Can't get oneshot mode irq and oneshot interrupt is unsupported\n"); | 
|---|
|  | 1734 | +				} else { | 
|---|
|  | 1735 | +					ret = devm_request_irq(&pdev->dev, pc->irq, | 
|---|
|  | 1736 | +							       pc->data->funcs.irq_handler, | 
|---|
|  | 1737 | +							       IRQF_NO_SUSPEND | IRQF_SHARED, | 
|---|
|  | 1738 | +							       "rk_pwm_oneshot_irq", pc); | 
|---|
|  | 1739 | +					if (ret) { | 
|---|
|  | 1740 | +						dev_err(&pdev->dev, "Claim oneshot IRQ failed\n"); | 
|---|
|  | 1741 | +						goto err_pclk; | 
|---|
|  | 1742 | +					} | 
|---|
|  | 1743 | +				} | 
|---|
|  | 1744 | +			} | 
|---|
|  | 1745 | +		} | 
|---|
|  | 1746 | +	} | 
|---|
| 431 | 1747 |  | 
|---|
| 432 | 1748 | if (pc->data->supports_polarity) { | 
|---|
| 433 | 1749 | pc->chip.of_xlate = of_pwm_xlate_with_flags; | 
|---|
| 434 | 1750 | pc->chip.of_pwm_n_cells = 3; | 
|---|
| 435 | 1751 | } | 
|---|
|  | 1752 | + | 
|---|
|  | 1753 | +	enable_conf = pc->data->enable_conf; | 
|---|
|  | 1754 | +	if (pc->main_version >= 4) | 
|---|
|  | 1755 | +		ctrl = readl_relaxed(pc->base + pc->data->regs.enable); | 
|---|
|  | 1756 | +	else | 
|---|
|  | 1757 | +		ctrl = readl_relaxed(pc->base + pc->data->regs.ctrl); | 
|---|
|  | 1758 | +	enabled = (ctrl & enable_conf) == enable_conf; | 
|---|
| 436 | 1759 |  | 
|---|
| 437 | 1760 | pc->center_aligned = | 
|---|
| 438 | 1761 | device_property_read_bool(&pdev->dev, "center-aligned"); | 
|---|
| .. | .. | 
|---|
| 443 | 1766 | goto err_pclk; | 
|---|
| 444 | 1767 | } | 
|---|
| 445 | 1768 |  | 
|---|
|  | 1769 | +	rockchip_pwm_debugfs_init(pc); | 
|---|
|  | 1770 | + | 
|---|
| 446 | 1771 | /* Keep the PWM clk enabled if the PWM appears to be up and running. */ | 
|---|
| 447 |  | -	if (!pwm_is_enabled(pc->chip.pwms)) | 
|---|
|  | 1772 | +	if (!enabled) | 
|---|
| 448 | 1773 | clk_disable(pc->clk); | 
|---|
|  | 1774 | + | 
|---|
|  | 1775 | +	clk_disable(pc->pclk); | 
|---|
| 449 | 1776 |  | 
|---|
| 450 | 1777 | return 0; | 
|---|
| 451 | 1778 |  | 
|---|
| 452 | 1779 | err_pclk: | 
|---|
| 453 |  | -	clk_unprepare(pc->pclk); | 
|---|
|  | 1780 | +	clk_disable_unprepare(pc->pclk); | 
|---|
| 454 | 1781 | err_clk: | 
|---|
| 455 | 1782 | clk_disable_unprepare(pc->clk); | 
|---|
| 456 | 1783 |  | 
|---|
| .. | .. | 
|---|
| 460 | 1787 | static int rockchip_pwm_remove(struct platform_device *pdev) | 
|---|
| 461 | 1788 | { | 
|---|
| 462 | 1789 | struct rockchip_pwm_chip *pc = platform_get_drvdata(pdev); | 
|---|
|  | 1790 | +	struct pwm_state state; | 
|---|
|  | 1791 | +	u32 val; | 
|---|
| 463 | 1792 |  | 
|---|
|  | 1793 | +	rockchip_pwm_debugfs_deinit(pc); | 
|---|
|  | 1794 | + | 
|---|
|  | 1795 | +	/* | 
|---|
|  | 1796 | +	 * For oneshot mode, it is needed to wait for bit PWM_ENABLE | 
|---|
|  | 1797 | +	 * to 0, which is automatic if all periods have been sent. | 
|---|
|  | 1798 | +	 */ | 
|---|
|  | 1799 | +	pwm_get_state(&pc->chip.pwms[0], &state); | 
|---|
|  | 1800 | +	if (state.enabled) { | 
|---|
|  | 1801 | +		if (pc->oneshot_en) { | 
|---|
|  | 1802 | +			if (readl_poll_timeout(pc->base + pc->data->regs.ctrl, | 
|---|
|  | 1803 | +					       val, !(val & PWM_ENABLE), 1000, 10 * 1000)) | 
|---|
|  | 1804 | +				dev_err(&pdev->dev, "Wait for oneshot to complete failed\n"); | 
|---|
|  | 1805 | +		} else { | 
|---|
|  | 1806 | +			state.enabled = false; | 
|---|
|  | 1807 | +			pwm_apply_state(&pc->chip.pwms[0], &state); | 
|---|
|  | 1808 | +		} | 
|---|
|  | 1809 | +	} | 
|---|
|  | 1810 | + | 
|---|
|  | 1811 | +	if (pc->oneshot_en) | 
|---|
|  | 1812 | +		clk_disable(pc->pclk); | 
|---|
| 464 | 1813 | clk_unprepare(pc->pclk); | 
|---|
| 465 | 1814 | clk_unprepare(pc->clk); | 
|---|
| 466 | 1815 |  | 
|---|