| .. | .. | 
|---|
| 7 | 7 | */ | 
|---|
| 8 | 8 |  | 
|---|
| 9 | 9 | #include <linux/clk.h> | 
|---|
|  | 10 | +#include <linux/debugfs.h> | 
|---|
| 10 | 11 | #include <linux/interrupt.h> | 
|---|
| 11 | 12 | #include <linux/io.h> | 
|---|
| 12 | 13 | #include <linux/iopoll.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> | 
|---|
| 21 |  | -#include "pwm-rockchip.h" | 
|---|
|  | 23 | +#include "pwm-rockchip-irq-callbacks.h" | 
|---|
| 22 | 24 |  | 
|---|
| 23 |  | -#define PWM_MAX_CHANNEL_NUM	4 | 
|---|
|  | 25 | +#define PWM_MAX_CHANNEL_NUM	8 | 
|---|
| 24 | 26 |  | 
|---|
|  | 27 | +/* | 
|---|
|  | 28 | + * regs for pwm v1-v3 | 
|---|
|  | 29 | + */ | 
|---|
| 25 | 30 | #define PWM_CTRL_TIMER_EN	(1 << 0) | 
|---|
| 26 | 31 | #define PWM_CTRL_OUTPUT_EN	(1 << 3) | 
|---|
| 27 | 32 |  | 
|---|
| .. | .. | 
|---|
| 51 | 56 |  | 
|---|
| 52 | 57 | #define PWM_ONESHOT_COUNT_SHIFT	24 | 
|---|
| 53 | 58 | #define PWM_ONESHOT_COUNT_MASK	(0xff << PWM_ONESHOT_COUNT_SHIFT) | 
|---|
| 54 |  | -#define PWM_ONESHOT_COUNT_MAX	256 | 
|---|
| 55 | 59 |  | 
|---|
| 56 | 60 | #define PWM_REG_INTSTS(n)	((3 - (n)) * 0x10 + 0x10) | 
|---|
| 57 | 61 | #define PWM_REG_INT_EN(n)	((3 - (n)) * 0x10 + 0x14) | 
|---|
| 58 | 62 |  | 
|---|
| 59 | 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 | 
|---|
| 60 | 214 |  | 
|---|
| 61 | 215 | struct rockchip_pwm_chip { | 
|---|
| 62 | 216 | struct pwm_chip chip; | 
|---|
| .. | .. | 
|---|
| 64 | 218 | struct clk *pclk; | 
|---|
| 65 | 219 | struct pinctrl *pinctrl; | 
|---|
| 66 | 220 | struct pinctrl_state *active_state; | 
|---|
|  | 221 | +	struct delayed_work pwm_work; | 
|---|
| 67 | 222 | const struct rockchip_pwm_data *data; | 
|---|
|  | 223 | +	struct resource *res; | 
|---|
|  | 224 | +	struct dentry *debugfs; | 
|---|
| 68 | 225 | void __iomem *base; | 
|---|
| 69 | 226 | unsigned long clk_rate; | 
|---|
| 70 | 227 | bool vop_pwm_en; /* indicate voppwm mirror register state */ | 
|---|
| 71 | 228 | bool center_aligned; | 
|---|
| 72 | 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; | 
|---|
| 73 | 235 | int channel_id; | 
|---|
| 74 | 236 | int irq; | 
|---|
|  | 237 | +	u8 main_version; | 
|---|
|  | 238 | +	u8 capture_cnt; | 
|---|
| 75 | 239 | }; | 
|---|
| 76 | 240 |  | 
|---|
| 77 | 241 | struct rockchip_pwm_regs { | 
|---|
| .. | .. | 
|---|
| 79 | 243 | unsigned long period; | 
|---|
| 80 | 244 | unsigned long cntr; | 
|---|
| 81 | 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); | 
|---|
| 82 | 281 | }; | 
|---|
| 83 | 282 |  | 
|---|
| 84 | 283 | struct rockchip_pwm_data { | 
|---|
| 85 | 284 | struct rockchip_pwm_regs regs; | 
|---|
|  | 285 | +	struct rockchip_pwm_funcs funcs; | 
|---|
| 86 | 286 | unsigned int prescaler; | 
|---|
| 87 | 287 | bool supports_polarity; | 
|---|
| 88 | 288 | bool supports_lock; | 
|---|
| 89 | 289 | bool vop_pwm; | 
|---|
|  | 290 | +	u8 main_version; | 
|---|
| 90 | 291 | u32 enable_conf; | 
|---|
| 91 | 292 | u32 enable_conf_mask; | 
|---|
|  | 293 | +	u32 oneshot_cnt_max; | 
|---|
|  | 294 | +	u32 oneshot_rpt_max; | 
|---|
|  | 295 | +	u32 wave_table_max; | 
|---|
| 92 | 296 | }; | 
|---|
| 93 | 297 |  | 
|---|
| 94 | 298 | static inline struct rockchip_pwm_chip *to_rockchip_pwm_chip(struct pwm_chip *c) | 
|---|
| .. | .. | 
|---|
| 104 | 308 | u32 enable_conf = pc->data->enable_conf; | 
|---|
| 105 | 309 | u64 tmp; | 
|---|
| 106 | 310 | u32 val; | 
|---|
| 107 |  | -	u32 dclk_div; | 
|---|
|  | 311 | +	u32 dclk_div = 1; | 
|---|
| 108 | 312 | int ret; | 
|---|
| 109 | 313 |  | 
|---|
| 110 | 314 | if (!pc->oneshot_en) { | 
|---|
| .. | .. | 
|---|
| 113 | 317 | return; | 
|---|
| 114 | 318 | } | 
|---|
| 115 | 319 |  | 
|---|
| 116 |  | -	dclk_div = pc->oneshot_en ? 2 : 1; | 
|---|
|  | 320 | +	if (pc->main_version < 4) | 
|---|
|  | 321 | +		dclk_div = pc->oneshot_en ? 2 : 1; | 
|---|
| 117 | 322 |  | 
|---|
| 118 | 323 | tmp = readl_relaxed(pc->base + pc->data->regs.period); | 
|---|
| 119 | 324 | tmp *= dclk_div * pc->data->prescaler * NSEC_PER_SEC; | 
|---|
| .. | .. | 
|---|
| 123 | 328 | tmp *= dclk_div * pc->data->prescaler * NSEC_PER_SEC; | 
|---|
| 124 | 329 | state->duty_cycle =  DIV_ROUND_CLOSEST_ULL(tmp, pc->clk_rate); | 
|---|
| 125 | 330 |  | 
|---|
| 126 |  | -	val = readl_relaxed(pc->base + pc->data->regs.ctrl); | 
|---|
| 127 |  | -	if (pc->oneshot_en) | 
|---|
| 128 |  | -		enable_conf &= ~PWM_CONTINUOUS; | 
|---|
|  | 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; | 
|---|
|  | 337 | +	} | 
|---|
| 129 | 338 | state->enabled = (val & enable_conf) == enable_conf; | 
|---|
| 130 | 339 |  | 
|---|
| 131 | 340 | if (pc->data->supports_polarity && !(val & PWM_DUTY_POSITIVE)) | 
|---|
| .. | .. | 
|---|
| 137 | 346 | clk_disable(pc->pclk); | 
|---|
| 138 | 347 | } | 
|---|
| 139 | 348 |  | 
|---|
| 140 |  | -static irqreturn_t rockchip_pwm_oneshot_irq(int irq, void *data) | 
|---|
|  | 349 | +static irqreturn_t rockchip_pwm_irq_v1(int irq, void *data) | 
|---|
| 141 | 350 | { | 
|---|
| 142 | 351 | struct rockchip_pwm_chip *pc = data; | 
|---|
| 143 | 352 | struct pwm_state state; | 
|---|
| .. | .. | 
|---|
| 165 | 374 | return IRQ_HANDLED; | 
|---|
| 166 | 375 | } | 
|---|
| 167 | 376 |  | 
|---|
| 168 |  | -static void rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, | 
|---|
| 169 |  | -			       const struct pwm_state *state) | 
|---|
|  | 377 | +static void rockchip_pwm_config_v1(struct pwm_chip *chip, struct pwm_device *pwm, | 
|---|
|  | 378 | +				   const struct pwm_state *state) | 
|---|
| 170 | 379 | { | 
|---|
| 171 | 380 | struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); | 
|---|
| 172 | 381 | unsigned long period, duty, delay_ns; | 
|---|
| .. | .. | 
|---|
| 176 | 385 | u8 dclk_div = 1; | 
|---|
| 177 | 386 |  | 
|---|
| 178 | 387 | #ifdef CONFIG_PWM_ROCKCHIP_ONESHOT | 
|---|
| 179 |  | -	if (state->oneshot_count > 0 && state->oneshot_count <= PWM_ONESHOT_COUNT_MAX) | 
|---|
|  | 388 | +	if (state->oneshot_count > 0 && state->oneshot_count <= pc->data->oneshot_cnt_max) | 
|---|
| 180 | 389 | dclk_div = 2; | 
|---|
| 181 | 390 | #endif | 
|---|
| 182 | 391 |  | 
|---|
| .. | .. | 
|---|
| 207 | 416 | } | 
|---|
| 208 | 417 |  | 
|---|
| 209 | 418 | #ifdef CONFIG_PWM_ROCKCHIP_ONESHOT | 
|---|
| 210 |  | -	if (state->oneshot_count > 0 && state->oneshot_count <= PWM_ONESHOT_COUNT_MAX) { | 
|---|
|  | 419 | +	if (state->oneshot_count > 0 && state->oneshot_count <= pc->data->oneshot_cnt_max) { | 
|---|
| 211 | 420 | u32 int_ctrl; | 
|---|
| 212 | 421 |  | 
|---|
| 213 | 422 | /* | 
|---|
| .. | .. | 
|---|
| 230 | 439 | ctrl &= ~PWM_ONESHOT_COUNT_MASK; | 
|---|
| 231 | 440 | ctrl |= (state->oneshot_count - 1) << PWM_ONESHOT_COUNT_SHIFT; | 
|---|
| 232 | 441 |  | 
|---|
| 233 |  | -		int_ctrl = readl_relaxed(pc->base + PWM_REG_INT_EN(pc->channel_id)); | 
|---|
| 234 |  | -		int_ctrl |= PWM_CH_INT(pc->channel_id); | 
|---|
| 235 |  | -		writel_relaxed(int_ctrl, pc->base + PWM_REG_INT_EN(pc->channel_id)); | 
|---|
|  | 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 | +		} | 
|---|
| 236 | 447 | } else { | 
|---|
| 237 | 448 | u32 int_ctrl; | 
|---|
| 238 | 449 |  | 
|---|
| .. | .. | 
|---|
| 241 | 452 | ctrl |= PWM_SEL_NO_SCALED_CLOCK; | 
|---|
| 242 | 453 |  | 
|---|
| 243 | 454 | if (state->oneshot_count) | 
|---|
| 244 |  | -			dev_err(chip->dev, "Oneshot_count must be between 1 and 256.\n"); | 
|---|
|  | 455 | +			dev_err(chip->dev, "Oneshot_count must be between 1 and %d.\n", | 
|---|
|  | 456 | +				pc->data->oneshot_cnt_max); | 
|---|
| 245 | 457 |  | 
|---|
| 246 | 458 | pc->oneshot_en = false; | 
|---|
| 247 | 459 | ctrl &= ~PWM_MODE_MASK; | 
|---|
| .. | .. | 
|---|
| 289 | 501 | local_irq_restore(flags); | 
|---|
| 290 | 502 | } | 
|---|
| 291 | 503 |  | 
|---|
| 292 |  | -static int rockchip_pwm_enable(struct pwm_chip *chip, | 
|---|
| 293 |  | -			       struct pwm_device *pwm, | 
|---|
| 294 |  | -			       bool enable) | 
|---|
|  | 504 | +static int rockchip_pwm_enable_v1(struct pwm_chip *chip, struct pwm_device *pwm, bool enable) | 
|---|
| 295 | 505 | { | 
|---|
| 296 | 506 | struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); | 
|---|
| 297 | 507 | u32 enable_conf = pc->data->enable_conf; | 
|---|
| .. | .. | 
|---|
| 328 | 538 | clk_disable(pc->clk); | 
|---|
| 329 | 539 |  | 
|---|
| 330 | 540 | return 0; | 
|---|
|  | 541 | +} | 
|---|
|  | 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); | 
|---|
| 331 | 727 | } | 
|---|
| 332 | 728 |  | 
|---|
| 333 | 729 | static int rockchip_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, | 
|---|
| .. | .. | 
|---|
| 371 | 767 | return ret; | 
|---|
| 372 | 768 | } | 
|---|
| 373 | 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: | 
|---|
|  | 861 | +	clk_disable(pc->pclk); | 
|---|
|  | 862 | + | 
|---|
|  | 863 | +	return ret; | 
|---|
|  | 864 | +} | 
|---|
|  | 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 | + | 
|---|
| 374 | 1456 | static const struct pwm_ops rockchip_pwm_ops = { | 
|---|
| 375 |  | -	.get_state = rockchip_pwm_get_state, | 
|---|
|  | 1457 | +	.capture = rockchip_pwm_capture, | 
|---|
| 376 | 1458 | .apply = rockchip_pwm_apply, | 
|---|
|  | 1459 | +	.get_state = rockchip_pwm_get_state, | 
|---|
| 377 | 1460 | .owner = THIS_MODULE, | 
|---|
| 378 | 1461 | }; | 
|---|
| 379 | 1462 |  | 
|---|
| 380 | 1463 | static const struct rockchip_pwm_data pwm_data_v1 = { | 
|---|
|  | 1464 | +	.main_version = 0x01, | 
|---|
| 381 | 1465 | .regs = { | 
|---|
|  | 1466 | +		.version = 0x5c, | 
|---|
| 382 | 1467 | .duty = 0x04, | 
|---|
| 383 | 1468 | .period = 0x08, | 
|---|
| 384 | 1469 | .cntr = 0x00, | 
|---|
| .. | .. | 
|---|
| 390 | 1475 | .vop_pwm = false, | 
|---|
| 391 | 1476 | .enable_conf = PWM_CTRL_OUTPUT_EN | PWM_CTRL_TIMER_EN, | 
|---|
| 392 | 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 | +	}, | 
|---|
| 393 | 1483 | }; | 
|---|
| 394 | 1484 |  | 
|---|
| 395 | 1485 | static const struct rockchip_pwm_data pwm_data_v2 = { | 
|---|
|  | 1486 | +	.main_version = 0x02, | 
|---|
| 396 | 1487 | .regs = { | 
|---|
|  | 1488 | +		.version = 0x5c, | 
|---|
| 397 | 1489 | .duty = 0x08, | 
|---|
| 398 | 1490 | .period = 0x04, | 
|---|
| 399 | 1491 | .cntr = 0x00, | 
|---|
| .. | .. | 
|---|
| 406 | 1498 | .enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE | | 
|---|
| 407 | 1499 | PWM_CONTINUOUS, | 
|---|
| 408 | 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 | +	}, | 
|---|
| 409 | 1506 | }; | 
|---|
| 410 | 1507 |  | 
|---|
| 411 | 1508 | static const struct rockchip_pwm_data pwm_data_vop = { | 
|---|
|  | 1509 | +	.main_version = 0x02, | 
|---|
| 412 | 1510 | .regs = { | 
|---|
|  | 1511 | +		.version = 0x5c, | 
|---|
| 413 | 1512 | .duty = 0x08, | 
|---|
| 414 | 1513 | .period = 0x04, | 
|---|
| 415 | 1514 | .cntr = 0x0c, | 
|---|
| .. | .. | 
|---|
| 422 | 1521 | .enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE | | 
|---|
| 423 | 1522 | PWM_CONTINUOUS, | 
|---|
| 424 | 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 | +	}, | 
|---|
| 425 | 1529 | }; | 
|---|
| 426 | 1530 |  | 
|---|
| 427 | 1531 | static const struct rockchip_pwm_data pwm_data_v3 = { | 
|---|
|  | 1532 | +	.main_version = 0x03, | 
|---|
| 428 | 1533 | .regs = { | 
|---|
|  | 1534 | +		.version = 0x5c, | 
|---|
| 429 | 1535 | .duty = 0x08, | 
|---|
| 430 | 1536 | .period = 0x04, | 
|---|
| 431 | 1537 | .cntr = 0x00, | 
|---|
| .. | .. | 
|---|
| 438 | 1544 | .enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE | | 
|---|
| 439 | 1545 | PWM_CONTINUOUS, | 
|---|
| 440 | 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 | +	}, | 
|---|
| 441 | 1594 | }; | 
|---|
| 442 | 1595 |  | 
|---|
| 443 | 1596 | static const struct of_device_id rockchip_pwm_dt_ids[] = { | 
|---|
| .. | .. | 
|---|
| 461 | 1614 | const struct of_device_id *id; | 
|---|
| 462 | 1615 | struct rockchip_pwm_chip *pc; | 
|---|
| 463 | 1616 | struct resource *r; | 
|---|
| 464 |  | -	u32 enable_conf, ctrl; | 
|---|
|  | 1617 | +	u32 enable_conf, ctrl, version; | 
|---|
| 465 | 1618 | bool enabled; | 
|---|
| 466 | 1619 | int ret, count; | 
|---|
| 467 | 1620 |  | 
|---|
| .. | .. | 
|---|
| 474 | 1627 | return -ENOMEM; | 
|---|
| 475 | 1628 |  | 
|---|
| 476 | 1629 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 
|---|
| 477 |  | -	pc->base = devm_ioremap(&pdev->dev, r->start, | 
|---|
| 478 |  | -				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)); | 
|---|
| 479 | 1638 | if (IS_ERR(pc->base)) | 
|---|
| 480 | 1639 | return PTR_ERR(pc->base); | 
|---|
| 481 | 1640 |  | 
|---|
| .. | .. | 
|---|
| 513 | 1672 | goto err_clk; | 
|---|
| 514 | 1673 | } | 
|---|
| 515 | 1674 |  | 
|---|
| 516 |  | -	pc->channel_id = rockchip_pwm_get_channel_id(pdev->dev.of_node->full_name); | 
|---|
| 517 |  | -	if (pc->channel_id < 0 || pc->channel_id >= PWM_MAX_CHANNEL_NUM) { | 
|---|
| 518 |  | -		dev_err(&pdev->dev, "Channel id is out of range: %d\n", pc->channel_id); | 
|---|
| 519 |  | -		ret = -EINVAL; | 
|---|
| 520 |  | -		goto err_pclk; | 
|---|
| 521 |  | -	} | 
|---|
| 522 |  | - | 
|---|
| 523 |  | -	if (IS_ENABLED(CONFIG_PWM_ROCKCHIP_ONESHOT)) { | 
|---|
| 524 |  | -		pc->irq = platform_get_irq(pdev, 0); | 
|---|
| 525 |  | -		if (pc->irq < 0) { | 
|---|
| 526 |  | -			dev_err(&pdev->dev, "Get oneshot mode irq failed\n"); | 
|---|
| 527 |  | -			ret = pc->irq; | 
|---|
| 528 |  | -			goto err_pclk; | 
|---|
| 529 |  | -		} | 
|---|
| 530 |  | - | 
|---|
| 531 |  | -		ret = devm_request_irq(&pdev->dev, pc->irq, rockchip_pwm_oneshot_irq, | 
|---|
| 532 |  | -				       IRQF_NO_SUSPEND | IRQF_SHARED, | 
|---|
| 533 |  | -				       "rk_pwm_oneshot_irq", pc); | 
|---|
| 534 |  | -		if (ret) { | 
|---|
| 535 |  | -			dev_err(&pdev->dev, "Claim oneshot IRQ failed\n"); | 
|---|
| 536 |  | -			goto err_pclk; | 
|---|
| 537 |  | -		} | 
|---|
| 538 |  | -	} | 
|---|
| 539 |  | - | 
|---|
| 540 | 1675 | pc->pinctrl = devm_pinctrl_get(&pdev->dev); | 
|---|
| 541 | 1676 | if (IS_ERR(pc->pinctrl)) { | 
|---|
| 542 | 1677 | dev_err(&pdev->dev, "Get pinctrl failed!\n"); | 
|---|
| .. | .. | 
|---|
| 559 | 1694 | pc->chip.base = of_alias_get_id(pdev->dev.of_node, "pwm"); | 
|---|
| 560 | 1695 | pc->chip.npwm = 1; | 
|---|
| 561 | 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 | +	} | 
|---|
| 562 | 1747 |  | 
|---|
| 563 | 1748 | if (pc->data->supports_polarity) { | 
|---|
| 564 | 1749 | pc->chip.of_xlate = of_pwm_xlate_with_flags; | 
|---|
| .. | .. | 
|---|
| 566 | 1751 | } | 
|---|
| 567 | 1752 |  | 
|---|
| 568 | 1753 | enable_conf = pc->data->enable_conf; | 
|---|
| 569 |  | -	ctrl = readl_relaxed(pc->base + pc->data->regs.ctrl); | 
|---|
|  | 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); | 
|---|
| 570 | 1758 | enabled = (ctrl & enable_conf) == enable_conf; | 
|---|
| 571 | 1759 |  | 
|---|
| 572 | 1760 | pc->center_aligned = | 
|---|
| .. | .. | 
|---|
| 577 | 1765 | dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); | 
|---|
| 578 | 1766 | goto err_pclk; | 
|---|
| 579 | 1767 | } | 
|---|
|  | 1768 | + | 
|---|
|  | 1769 | +	rockchip_pwm_debugfs_init(pc); | 
|---|
| 580 | 1770 |  | 
|---|
| 581 | 1771 | /* Keep the PWM clk enabled if the PWM appears to be up and running. */ | 
|---|
| 582 | 1772 | if (!enabled) | 
|---|
| .. | .. | 
|---|
| 600 | 1790 | struct pwm_state state; | 
|---|
| 601 | 1791 | u32 val; | 
|---|
| 602 | 1792 |  | 
|---|
|  | 1793 | +	rockchip_pwm_debugfs_deinit(pc); | 
|---|
|  | 1794 | + | 
|---|
| 603 | 1795 | /* | 
|---|
| 604 | 1796 | * For oneshot mode, it is needed to wait for bit PWM_ENABLE | 
|---|
| 605 | 1797 | * to 0, which is automatic if all periods have been sent. | 
|---|