162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Renesas RZ/G2L MTU3a Counter driver
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2022 Renesas Electronics Corporation
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <linux/clk.h>
962306a36Sopenharmony_ci#include <linux/counter.h>
1062306a36Sopenharmony_ci#include <linux/mfd/rz-mtu3.h>
1162306a36Sopenharmony_ci#include <linux/module.h>
1262306a36Sopenharmony_ci#include <linux/platform_device.h>
1362306a36Sopenharmony_ci#include <linux/pm_runtime.h>
1462306a36Sopenharmony_ci#include <linux/types.h>
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci/*
1762306a36Sopenharmony_ci * Register descriptions
1862306a36Sopenharmony_ci *   TSR: Timer Status Register
1962306a36Sopenharmony_ci *   TMDR1: Timer Mode Register 1
2062306a36Sopenharmony_ci *   TMDR3: Timer Mode Register 3
2162306a36Sopenharmony_ci *   TIOR: Timer I/O Control Register
2262306a36Sopenharmony_ci *   TCR: Timer Control Register
2362306a36Sopenharmony_ci *   TCNT: Timer Counter
2462306a36Sopenharmony_ci *   TGRA: Timer general register A
2562306a36Sopenharmony_ci *   TCNTLW: Timer Longword Counter
2662306a36Sopenharmony_ci *   TGRALW: Timer longword general register A
2762306a36Sopenharmony_ci */
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci#define RZ_MTU3_TSR_TCFD	BIT(7) /* Count Direction Flag */
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci#define RZ_MTU3_TMDR1_PH_CNT_MODE_1	(4) /* Phase counting mode 1 */
3262306a36Sopenharmony_ci#define RZ_MTU3_TMDR1_PH_CNT_MODE_2	(5) /* Phase counting mode 2 */
3362306a36Sopenharmony_ci#define RZ_MTU3_TMDR1_PH_CNT_MODE_3	(6) /* Phase counting mode 3 */
3462306a36Sopenharmony_ci#define RZ_MTU3_TMDR1_PH_CNT_MODE_4	(7) /* Phase counting mode 4 */
3562306a36Sopenharmony_ci#define RZ_MTU3_TMDR1_PH_CNT_MODE_5	(9) /* Phase counting mode 5 */
3662306a36Sopenharmony_ci#define RZ_MTU3_TMDR1_PH_CNT_MODE_MASK	(0xf)
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci/*
3962306a36Sopenharmony_ci * LWA: MTU1/MTU2 Combination Longword Access Control
4062306a36Sopenharmony_ci * 0: 16-bit, 1: 32-bit
4162306a36Sopenharmony_ci */
4262306a36Sopenharmony_ci#define RZ_MTU3_TMDR3_LWA	(0)
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci/*
4562306a36Sopenharmony_ci * PHCKSEL: External Input Phase Clock Select
4662306a36Sopenharmony_ci * 0: MTCLKA and MTCLKB, 1: MTCLKC and MTCLKD
4762306a36Sopenharmony_ci */
4862306a36Sopenharmony_ci#define RZ_MTU3_TMDR3_PHCKSEL	(1)
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci#define RZ_MTU3_16_BIT_MTU1_CH	(0)
5162306a36Sopenharmony_ci#define RZ_MTU3_16_BIT_MTU2_CH	(1)
5262306a36Sopenharmony_ci#define RZ_MTU3_32_BIT_CH	(2)
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci#define RZ_MTU3_TIOR_NO_OUTPUT	(0) /* Output prohibited */
5562306a36Sopenharmony_ci#define RZ_MTU3_TIOR_IC_BOTH	(10) /* Input capture at both edges */
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci#define SIGNAL_A_ID	(0)
5862306a36Sopenharmony_ci#define SIGNAL_B_ID	(1)
5962306a36Sopenharmony_ci#define SIGNAL_C_ID	(2)
6062306a36Sopenharmony_ci#define SIGNAL_D_ID	(3)
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci#define RZ_MTU3_MAX_HW_CNTR_CHANNELS	(2)
6362306a36Sopenharmony_ci#define RZ_MTU3_MAX_LOGICAL_CNTR_CHANNELS	(3)
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci/**
6662306a36Sopenharmony_ci * struct rz_mtu3_cnt - MTU3 counter private data
6762306a36Sopenharmony_ci *
6862306a36Sopenharmony_ci * @clk: MTU3 module clock
6962306a36Sopenharmony_ci * @lock: Lock to prevent concurrent access for ceiling and count
7062306a36Sopenharmony_ci * @ch: HW channels for the counters
7162306a36Sopenharmony_ci * @count_is_enabled: Enabled state of Counter value channel
7262306a36Sopenharmony_ci * @mtu_16bit_max: Cache for 16-bit counters
7362306a36Sopenharmony_ci * @mtu_32bit_max: Cache for 32-bit counters
7462306a36Sopenharmony_ci */
7562306a36Sopenharmony_cistruct rz_mtu3_cnt {
7662306a36Sopenharmony_ci	struct clk *clk;
7762306a36Sopenharmony_ci	struct mutex lock;
7862306a36Sopenharmony_ci	struct rz_mtu3_channel *ch;
7962306a36Sopenharmony_ci	bool count_is_enabled[RZ_MTU3_MAX_LOGICAL_CNTR_CHANNELS];
8062306a36Sopenharmony_ci	union {
8162306a36Sopenharmony_ci		u16 mtu_16bit_max[RZ_MTU3_MAX_HW_CNTR_CHANNELS];
8262306a36Sopenharmony_ci		u32 mtu_32bit_max;
8362306a36Sopenharmony_ci	};
8462306a36Sopenharmony_ci};
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_cistatic const enum counter_function rz_mtu3_count_functions[] = {
8762306a36Sopenharmony_ci	COUNTER_FUNCTION_QUADRATURE_X4,
8862306a36Sopenharmony_ci	COUNTER_FUNCTION_PULSE_DIRECTION,
8962306a36Sopenharmony_ci	COUNTER_FUNCTION_QUADRATURE_X2_B,
9062306a36Sopenharmony_ci};
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_cistatic inline size_t rz_mtu3_get_hw_ch(const size_t id)
9362306a36Sopenharmony_ci{
9462306a36Sopenharmony_ci	return (id == RZ_MTU3_32_BIT_CH) ? 0 : id;
9562306a36Sopenharmony_ci}
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_cistatic inline struct rz_mtu3_channel *rz_mtu3_get_ch(struct counter_device *counter, int id)
9862306a36Sopenharmony_ci{
9962306a36Sopenharmony_ci	struct rz_mtu3_cnt *const priv = counter_priv(counter);
10062306a36Sopenharmony_ci	const size_t ch_id = rz_mtu3_get_hw_ch(id);
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci	return &priv->ch[ch_id];
10362306a36Sopenharmony_ci}
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_cistatic bool rz_mtu3_is_counter_invalid(struct counter_device *counter, int id)
10662306a36Sopenharmony_ci{
10762306a36Sopenharmony_ci	struct rz_mtu3_cnt *const priv = counter_priv(counter);
10862306a36Sopenharmony_ci	unsigned long tmdr;
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci	pm_runtime_get_sync(priv->ch->dev);
11162306a36Sopenharmony_ci	tmdr = rz_mtu3_shared_reg_read(priv->ch, RZ_MTU3_TMDR3);
11262306a36Sopenharmony_ci	pm_runtime_put(priv->ch->dev);
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci	if (id == RZ_MTU3_32_BIT_CH && test_bit(RZ_MTU3_TMDR3_LWA, &tmdr))
11562306a36Sopenharmony_ci		return false;
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci	if (id != RZ_MTU3_32_BIT_CH && !test_bit(RZ_MTU3_TMDR3_LWA, &tmdr))
11862306a36Sopenharmony_ci		return false;
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci	return true;
12162306a36Sopenharmony_ci}
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_cistatic int rz_mtu3_lock_if_counter_is_valid(struct counter_device *counter,
12462306a36Sopenharmony_ci					    struct rz_mtu3_channel *const ch,
12562306a36Sopenharmony_ci					    struct rz_mtu3_cnt *const priv,
12662306a36Sopenharmony_ci					    int id)
12762306a36Sopenharmony_ci{
12862306a36Sopenharmony_ci	mutex_lock(&priv->lock);
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci	if (ch->is_busy && !priv->count_is_enabled[id]) {
13162306a36Sopenharmony_ci		mutex_unlock(&priv->lock);
13262306a36Sopenharmony_ci		return -EINVAL;
13362306a36Sopenharmony_ci	}
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci	if (rz_mtu3_is_counter_invalid(counter, id)) {
13662306a36Sopenharmony_ci		mutex_unlock(&priv->lock);
13762306a36Sopenharmony_ci		return -EBUSY;
13862306a36Sopenharmony_ci	}
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci	return 0;
14162306a36Sopenharmony_ci}
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_cistatic int rz_mtu3_lock_if_count_is_enabled(struct rz_mtu3_channel *const ch,
14462306a36Sopenharmony_ci					    struct rz_mtu3_cnt *const priv,
14562306a36Sopenharmony_ci					    int id)
14662306a36Sopenharmony_ci{
14762306a36Sopenharmony_ci	mutex_lock(&priv->lock);
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci	if (ch->is_busy && !priv->count_is_enabled[id]) {
15062306a36Sopenharmony_ci		mutex_unlock(&priv->lock);
15162306a36Sopenharmony_ci		return -EINVAL;
15262306a36Sopenharmony_ci	}
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ci	return 0;
15562306a36Sopenharmony_ci}
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_cistatic int rz_mtu3_count_read(struct counter_device *counter,
15862306a36Sopenharmony_ci			      struct counter_count *count, u64 *val)
15962306a36Sopenharmony_ci{
16062306a36Sopenharmony_ci	struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id);
16162306a36Sopenharmony_ci	struct rz_mtu3_cnt *const priv = counter_priv(counter);
16262306a36Sopenharmony_ci	int ret;
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ci	ret = rz_mtu3_lock_if_counter_is_valid(counter, ch, priv, count->id);
16562306a36Sopenharmony_ci	if (ret)
16662306a36Sopenharmony_ci		return ret;
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci	pm_runtime_get_sync(ch->dev);
16962306a36Sopenharmony_ci	if (count->id == RZ_MTU3_32_BIT_CH)
17062306a36Sopenharmony_ci		*val = rz_mtu3_32bit_ch_read(ch, RZ_MTU3_TCNTLW);
17162306a36Sopenharmony_ci	else
17262306a36Sopenharmony_ci		*val = rz_mtu3_16bit_ch_read(ch, RZ_MTU3_TCNT);
17362306a36Sopenharmony_ci	pm_runtime_put(ch->dev);
17462306a36Sopenharmony_ci	mutex_unlock(&priv->lock);
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci	return 0;
17762306a36Sopenharmony_ci}
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_cistatic int rz_mtu3_count_write(struct counter_device *counter,
18062306a36Sopenharmony_ci			       struct counter_count *count, const u64 val)
18162306a36Sopenharmony_ci{
18262306a36Sopenharmony_ci	struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id);
18362306a36Sopenharmony_ci	struct rz_mtu3_cnt *const priv = counter_priv(counter);
18462306a36Sopenharmony_ci	int ret;
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_ci	ret = rz_mtu3_lock_if_counter_is_valid(counter, ch, priv, count->id);
18762306a36Sopenharmony_ci	if (ret)
18862306a36Sopenharmony_ci		return ret;
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ci	pm_runtime_get_sync(ch->dev);
19162306a36Sopenharmony_ci	if (count->id == RZ_MTU3_32_BIT_CH)
19262306a36Sopenharmony_ci		rz_mtu3_32bit_ch_write(ch, RZ_MTU3_TCNTLW, val);
19362306a36Sopenharmony_ci	else
19462306a36Sopenharmony_ci		rz_mtu3_16bit_ch_write(ch, RZ_MTU3_TCNT, val);
19562306a36Sopenharmony_ci	pm_runtime_put(ch->dev);
19662306a36Sopenharmony_ci	mutex_unlock(&priv->lock);
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci	return 0;
19962306a36Sopenharmony_ci}
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_cistatic int rz_mtu3_count_function_read_helper(struct rz_mtu3_channel *const ch,
20262306a36Sopenharmony_ci					      struct rz_mtu3_cnt *const priv,
20362306a36Sopenharmony_ci					      enum counter_function *function)
20462306a36Sopenharmony_ci{
20562306a36Sopenharmony_ci	u8 timer_mode;
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_ci	pm_runtime_get_sync(ch->dev);
20862306a36Sopenharmony_ci	timer_mode = rz_mtu3_8bit_ch_read(ch, RZ_MTU3_TMDR1);
20962306a36Sopenharmony_ci	pm_runtime_put(ch->dev);
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ci	switch (timer_mode & RZ_MTU3_TMDR1_PH_CNT_MODE_MASK) {
21262306a36Sopenharmony_ci	case RZ_MTU3_TMDR1_PH_CNT_MODE_1:
21362306a36Sopenharmony_ci		*function = COUNTER_FUNCTION_QUADRATURE_X4;
21462306a36Sopenharmony_ci		return 0;
21562306a36Sopenharmony_ci	case RZ_MTU3_TMDR1_PH_CNT_MODE_2:
21662306a36Sopenharmony_ci		*function = COUNTER_FUNCTION_PULSE_DIRECTION;
21762306a36Sopenharmony_ci		return 0;
21862306a36Sopenharmony_ci	case RZ_MTU3_TMDR1_PH_CNT_MODE_4:
21962306a36Sopenharmony_ci		*function = COUNTER_FUNCTION_QUADRATURE_X2_B;
22062306a36Sopenharmony_ci		return 0;
22162306a36Sopenharmony_ci	default:
22262306a36Sopenharmony_ci		/*
22362306a36Sopenharmony_ci		 * TODO:
22462306a36Sopenharmony_ci		 *  - need to add RZ_MTU3_TMDR1_PH_CNT_MODE_3
22562306a36Sopenharmony_ci		 *  - need to add RZ_MTU3_TMDR1_PH_CNT_MODE_5
22662306a36Sopenharmony_ci		 */
22762306a36Sopenharmony_ci		return -EINVAL;
22862306a36Sopenharmony_ci	}
22962306a36Sopenharmony_ci}
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_cistatic int rz_mtu3_count_function_read(struct counter_device *counter,
23262306a36Sopenharmony_ci				       struct counter_count *count,
23362306a36Sopenharmony_ci				       enum counter_function *function)
23462306a36Sopenharmony_ci{
23562306a36Sopenharmony_ci	struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id);
23662306a36Sopenharmony_ci	struct rz_mtu3_cnt *const priv = counter_priv(counter);
23762306a36Sopenharmony_ci	int ret;
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_ci	ret = rz_mtu3_lock_if_count_is_enabled(ch, priv, count->id);
24062306a36Sopenharmony_ci	if (ret)
24162306a36Sopenharmony_ci		return ret;
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci	ret = rz_mtu3_count_function_read_helper(ch, priv, function);
24462306a36Sopenharmony_ci	mutex_unlock(&priv->lock);
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci	return ret;
24762306a36Sopenharmony_ci}
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_cistatic int rz_mtu3_count_function_write(struct counter_device *counter,
25062306a36Sopenharmony_ci					struct counter_count *count,
25162306a36Sopenharmony_ci					enum counter_function function)
25262306a36Sopenharmony_ci{
25362306a36Sopenharmony_ci	struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id);
25462306a36Sopenharmony_ci	struct rz_mtu3_cnt *const priv = counter_priv(counter);
25562306a36Sopenharmony_ci	u8 timer_mode;
25662306a36Sopenharmony_ci	int ret;
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci	ret = rz_mtu3_lock_if_count_is_enabled(ch, priv, count->id);
25962306a36Sopenharmony_ci	if (ret)
26062306a36Sopenharmony_ci		return ret;
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_ci	switch (function) {
26362306a36Sopenharmony_ci	case COUNTER_FUNCTION_QUADRATURE_X4:
26462306a36Sopenharmony_ci		timer_mode = RZ_MTU3_TMDR1_PH_CNT_MODE_1;
26562306a36Sopenharmony_ci		break;
26662306a36Sopenharmony_ci	case COUNTER_FUNCTION_PULSE_DIRECTION:
26762306a36Sopenharmony_ci		timer_mode = RZ_MTU3_TMDR1_PH_CNT_MODE_2;
26862306a36Sopenharmony_ci		break;
26962306a36Sopenharmony_ci	case COUNTER_FUNCTION_QUADRATURE_X2_B:
27062306a36Sopenharmony_ci		timer_mode = RZ_MTU3_TMDR1_PH_CNT_MODE_4;
27162306a36Sopenharmony_ci		break;
27262306a36Sopenharmony_ci	default:
27362306a36Sopenharmony_ci		/*
27462306a36Sopenharmony_ci		 * TODO:
27562306a36Sopenharmony_ci		 *  - need to add RZ_MTU3_TMDR1_PH_CNT_MODE_3
27662306a36Sopenharmony_ci		 *  - need to add RZ_MTU3_TMDR1_PH_CNT_MODE_5
27762306a36Sopenharmony_ci		 */
27862306a36Sopenharmony_ci		mutex_unlock(&priv->lock);
27962306a36Sopenharmony_ci		return -EINVAL;
28062306a36Sopenharmony_ci	}
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_ci	pm_runtime_get_sync(ch->dev);
28362306a36Sopenharmony_ci	rz_mtu3_8bit_ch_write(ch, RZ_MTU3_TMDR1, timer_mode);
28462306a36Sopenharmony_ci	pm_runtime_put(ch->dev);
28562306a36Sopenharmony_ci	mutex_unlock(&priv->lock);
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci	return 0;
28862306a36Sopenharmony_ci}
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_cistatic int rz_mtu3_count_direction_read(struct counter_device *counter,
29162306a36Sopenharmony_ci					struct counter_count *count,
29262306a36Sopenharmony_ci					enum counter_count_direction *direction)
29362306a36Sopenharmony_ci{
29462306a36Sopenharmony_ci	struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id);
29562306a36Sopenharmony_ci	struct rz_mtu3_cnt *const priv = counter_priv(counter);
29662306a36Sopenharmony_ci	int ret;
29762306a36Sopenharmony_ci	u8 tsr;
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci	ret = rz_mtu3_lock_if_count_is_enabled(ch, priv, count->id);
30062306a36Sopenharmony_ci	if (ret)
30162306a36Sopenharmony_ci		return ret;
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci	pm_runtime_get_sync(ch->dev);
30462306a36Sopenharmony_ci	tsr = rz_mtu3_8bit_ch_read(ch, RZ_MTU3_TSR);
30562306a36Sopenharmony_ci	pm_runtime_put(ch->dev);
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_ci	*direction = (tsr & RZ_MTU3_TSR_TCFD) ?
30862306a36Sopenharmony_ci		COUNTER_COUNT_DIRECTION_FORWARD : COUNTER_COUNT_DIRECTION_BACKWARD;
30962306a36Sopenharmony_ci	mutex_unlock(&priv->lock);
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_ci	return 0;
31262306a36Sopenharmony_ci}
31362306a36Sopenharmony_ci
31462306a36Sopenharmony_cistatic int rz_mtu3_count_ceiling_read(struct counter_device *counter,
31562306a36Sopenharmony_ci				      struct counter_count *count,
31662306a36Sopenharmony_ci				      u64 *ceiling)
31762306a36Sopenharmony_ci{
31862306a36Sopenharmony_ci	struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id);
31962306a36Sopenharmony_ci	struct rz_mtu3_cnt *const priv = counter_priv(counter);
32062306a36Sopenharmony_ci	const size_t ch_id = rz_mtu3_get_hw_ch(count->id);
32162306a36Sopenharmony_ci	int ret;
32262306a36Sopenharmony_ci
32362306a36Sopenharmony_ci	ret = rz_mtu3_lock_if_counter_is_valid(counter, ch, priv, count->id);
32462306a36Sopenharmony_ci	if (ret)
32562306a36Sopenharmony_ci		return ret;
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci	switch (count->id) {
32862306a36Sopenharmony_ci	case RZ_MTU3_16_BIT_MTU1_CH:
32962306a36Sopenharmony_ci	case RZ_MTU3_16_BIT_MTU2_CH:
33062306a36Sopenharmony_ci		*ceiling = priv->mtu_16bit_max[ch_id];
33162306a36Sopenharmony_ci		break;
33262306a36Sopenharmony_ci	case RZ_MTU3_32_BIT_CH:
33362306a36Sopenharmony_ci		*ceiling = priv->mtu_32bit_max;
33462306a36Sopenharmony_ci		break;
33562306a36Sopenharmony_ci	default:
33662306a36Sopenharmony_ci		/* should never reach this path */
33762306a36Sopenharmony_ci		mutex_unlock(&priv->lock);
33862306a36Sopenharmony_ci		return -EINVAL;
33962306a36Sopenharmony_ci	}
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ci	mutex_unlock(&priv->lock);
34262306a36Sopenharmony_ci	return 0;
34362306a36Sopenharmony_ci}
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_cistatic int rz_mtu3_count_ceiling_write(struct counter_device *counter,
34662306a36Sopenharmony_ci				       struct counter_count *count,
34762306a36Sopenharmony_ci				       u64 ceiling)
34862306a36Sopenharmony_ci{
34962306a36Sopenharmony_ci	struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id);
35062306a36Sopenharmony_ci	struct rz_mtu3_cnt *const priv = counter_priv(counter);
35162306a36Sopenharmony_ci	const size_t ch_id = rz_mtu3_get_hw_ch(count->id);
35262306a36Sopenharmony_ci	int ret;
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci	ret = rz_mtu3_lock_if_counter_is_valid(counter, ch, priv, count->id);
35562306a36Sopenharmony_ci	if (ret)
35662306a36Sopenharmony_ci		return ret;
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_ci	switch (count->id) {
35962306a36Sopenharmony_ci	case RZ_MTU3_16_BIT_MTU1_CH:
36062306a36Sopenharmony_ci	case RZ_MTU3_16_BIT_MTU2_CH:
36162306a36Sopenharmony_ci		if (ceiling > U16_MAX) {
36262306a36Sopenharmony_ci			mutex_unlock(&priv->lock);
36362306a36Sopenharmony_ci			return -ERANGE;
36462306a36Sopenharmony_ci		}
36562306a36Sopenharmony_ci		priv->mtu_16bit_max[ch_id] = ceiling;
36662306a36Sopenharmony_ci		break;
36762306a36Sopenharmony_ci	case RZ_MTU3_32_BIT_CH:
36862306a36Sopenharmony_ci		if (ceiling > U32_MAX) {
36962306a36Sopenharmony_ci			mutex_unlock(&priv->lock);
37062306a36Sopenharmony_ci			return -ERANGE;
37162306a36Sopenharmony_ci		}
37262306a36Sopenharmony_ci		priv->mtu_32bit_max = ceiling;
37362306a36Sopenharmony_ci		break;
37462306a36Sopenharmony_ci	default:
37562306a36Sopenharmony_ci		/* should never reach this path */
37662306a36Sopenharmony_ci		mutex_unlock(&priv->lock);
37762306a36Sopenharmony_ci		return -EINVAL;
37862306a36Sopenharmony_ci	}
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_ci	pm_runtime_get_sync(ch->dev);
38162306a36Sopenharmony_ci	if (count->id == RZ_MTU3_32_BIT_CH)
38262306a36Sopenharmony_ci		rz_mtu3_32bit_ch_write(ch, RZ_MTU3_TGRALW, ceiling);
38362306a36Sopenharmony_ci	else
38462306a36Sopenharmony_ci		rz_mtu3_16bit_ch_write(ch, RZ_MTU3_TGRA, ceiling);
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_ci	rz_mtu3_8bit_ch_write(ch, RZ_MTU3_TCR, RZ_MTU3_TCR_CCLR_TGRA);
38762306a36Sopenharmony_ci	pm_runtime_put(ch->dev);
38862306a36Sopenharmony_ci	mutex_unlock(&priv->lock);
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_ci	return 0;
39162306a36Sopenharmony_ci}
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_cistatic void rz_mtu3_32bit_cnt_setting(struct counter_device *counter)
39462306a36Sopenharmony_ci{
39562306a36Sopenharmony_ci	struct rz_mtu3_channel *const ch1 = rz_mtu3_get_ch(counter, 0);
39662306a36Sopenharmony_ci	struct rz_mtu3_channel *const ch2 = rz_mtu3_get_ch(counter, 1);
39762306a36Sopenharmony_ci
39862306a36Sopenharmony_ci	/* Phase counting mode 1 is used as default in initialization. */
39962306a36Sopenharmony_ci	rz_mtu3_8bit_ch_write(ch1, RZ_MTU3_TMDR1, RZ_MTU3_TMDR1_PH_CNT_MODE_1);
40062306a36Sopenharmony_ci
40162306a36Sopenharmony_ci	rz_mtu3_8bit_ch_write(ch1, RZ_MTU3_TCR, RZ_MTU3_TCR_CCLR_TGRA);
40262306a36Sopenharmony_ci	rz_mtu3_8bit_ch_write(ch1, RZ_MTU3_TIOR, RZ_MTU3_TIOR_IC_BOTH);
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_ci	rz_mtu3_enable(ch1);
40562306a36Sopenharmony_ci	rz_mtu3_enable(ch2);
40662306a36Sopenharmony_ci}
40762306a36Sopenharmony_ci
40862306a36Sopenharmony_cistatic void rz_mtu3_16bit_cnt_setting(struct counter_device *counter, int id)
40962306a36Sopenharmony_ci{
41062306a36Sopenharmony_ci	struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, id);
41162306a36Sopenharmony_ci
41262306a36Sopenharmony_ci	/* Phase counting mode 1 is used as default in initialization. */
41362306a36Sopenharmony_ci	rz_mtu3_8bit_ch_write(ch, RZ_MTU3_TMDR1, RZ_MTU3_TMDR1_PH_CNT_MODE_1);
41462306a36Sopenharmony_ci
41562306a36Sopenharmony_ci	rz_mtu3_8bit_ch_write(ch, RZ_MTU3_TCR, RZ_MTU3_TCR_CCLR_TGRA);
41662306a36Sopenharmony_ci	rz_mtu3_8bit_ch_write(ch, RZ_MTU3_TIOR, RZ_MTU3_TIOR_NO_OUTPUT);
41762306a36Sopenharmony_ci	rz_mtu3_enable(ch);
41862306a36Sopenharmony_ci}
41962306a36Sopenharmony_ci
42062306a36Sopenharmony_cistatic int rz_mtu3_initialize_counter(struct counter_device *counter, int id)
42162306a36Sopenharmony_ci{
42262306a36Sopenharmony_ci	struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, id);
42362306a36Sopenharmony_ci	struct rz_mtu3_channel *const ch1 = rz_mtu3_get_ch(counter, 0);
42462306a36Sopenharmony_ci	struct rz_mtu3_channel *const ch2 = rz_mtu3_get_ch(counter, 1);
42562306a36Sopenharmony_ci
42662306a36Sopenharmony_ci	switch (id) {
42762306a36Sopenharmony_ci	case RZ_MTU3_16_BIT_MTU1_CH:
42862306a36Sopenharmony_ci	case RZ_MTU3_16_BIT_MTU2_CH:
42962306a36Sopenharmony_ci		if (!rz_mtu3_request_channel(ch))
43062306a36Sopenharmony_ci			return -EBUSY;
43162306a36Sopenharmony_ci
43262306a36Sopenharmony_ci		rz_mtu3_16bit_cnt_setting(counter, id);
43362306a36Sopenharmony_ci		return 0;
43462306a36Sopenharmony_ci	case RZ_MTU3_32_BIT_CH:
43562306a36Sopenharmony_ci		/*
43662306a36Sopenharmony_ci		 * 32-bit phase counting need MTU1 and MTU2 to create 32-bit
43762306a36Sopenharmony_ci		 * cascade counter.
43862306a36Sopenharmony_ci		 */
43962306a36Sopenharmony_ci		if (!rz_mtu3_request_channel(ch1))
44062306a36Sopenharmony_ci			return -EBUSY;
44162306a36Sopenharmony_ci
44262306a36Sopenharmony_ci		if (!rz_mtu3_request_channel(ch2)) {
44362306a36Sopenharmony_ci			rz_mtu3_release_channel(ch1);
44462306a36Sopenharmony_ci			return -EBUSY;
44562306a36Sopenharmony_ci		}
44662306a36Sopenharmony_ci
44762306a36Sopenharmony_ci		rz_mtu3_32bit_cnt_setting(counter);
44862306a36Sopenharmony_ci		return 0;
44962306a36Sopenharmony_ci	default:
45062306a36Sopenharmony_ci		/* should never reach this path */
45162306a36Sopenharmony_ci		return -EINVAL;
45262306a36Sopenharmony_ci	}
45362306a36Sopenharmony_ci}
45462306a36Sopenharmony_ci
45562306a36Sopenharmony_cistatic void rz_mtu3_terminate_counter(struct counter_device *counter, int id)
45662306a36Sopenharmony_ci{
45762306a36Sopenharmony_ci	struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, id);
45862306a36Sopenharmony_ci	struct rz_mtu3_channel *const ch1 = rz_mtu3_get_ch(counter, 0);
45962306a36Sopenharmony_ci	struct rz_mtu3_channel *const ch2 = rz_mtu3_get_ch(counter, 1);
46062306a36Sopenharmony_ci
46162306a36Sopenharmony_ci	if (id == RZ_MTU3_32_BIT_CH) {
46262306a36Sopenharmony_ci		rz_mtu3_release_channel(ch2);
46362306a36Sopenharmony_ci		rz_mtu3_release_channel(ch1);
46462306a36Sopenharmony_ci		rz_mtu3_disable(ch2);
46562306a36Sopenharmony_ci		rz_mtu3_disable(ch1);
46662306a36Sopenharmony_ci	} else {
46762306a36Sopenharmony_ci		rz_mtu3_release_channel(ch);
46862306a36Sopenharmony_ci		rz_mtu3_disable(ch);
46962306a36Sopenharmony_ci	}
47062306a36Sopenharmony_ci}
47162306a36Sopenharmony_ci
47262306a36Sopenharmony_cistatic int rz_mtu3_count_enable_read(struct counter_device *counter,
47362306a36Sopenharmony_ci				     struct counter_count *count, u8 *enable)
47462306a36Sopenharmony_ci{
47562306a36Sopenharmony_ci	struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id);
47662306a36Sopenharmony_ci	struct rz_mtu3_channel *const ch1 = rz_mtu3_get_ch(counter, 0);
47762306a36Sopenharmony_ci	struct rz_mtu3_channel *const ch2 = rz_mtu3_get_ch(counter, 1);
47862306a36Sopenharmony_ci	struct rz_mtu3_cnt *const priv = counter_priv(counter);
47962306a36Sopenharmony_ci	int ret;
48062306a36Sopenharmony_ci
48162306a36Sopenharmony_ci	ret = rz_mtu3_lock_if_count_is_enabled(ch, priv, count->id);
48262306a36Sopenharmony_ci	if (ret)
48362306a36Sopenharmony_ci		return ret;
48462306a36Sopenharmony_ci
48562306a36Sopenharmony_ci	if (count->id == RZ_MTU3_32_BIT_CH)
48662306a36Sopenharmony_ci		*enable = rz_mtu3_is_enabled(ch1) && rz_mtu3_is_enabled(ch2);
48762306a36Sopenharmony_ci	else
48862306a36Sopenharmony_ci		*enable = rz_mtu3_is_enabled(ch);
48962306a36Sopenharmony_ci
49062306a36Sopenharmony_ci	mutex_unlock(&priv->lock);
49162306a36Sopenharmony_ci
49262306a36Sopenharmony_ci	return 0;
49362306a36Sopenharmony_ci}
49462306a36Sopenharmony_ci
49562306a36Sopenharmony_cistatic int rz_mtu3_count_enable_write(struct counter_device *counter,
49662306a36Sopenharmony_ci				      struct counter_count *count, u8 enable)
49762306a36Sopenharmony_ci{
49862306a36Sopenharmony_ci	struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id);
49962306a36Sopenharmony_ci	struct rz_mtu3_cnt *const priv = counter_priv(counter);
50062306a36Sopenharmony_ci	int ret = 0;
50162306a36Sopenharmony_ci
50262306a36Sopenharmony_ci	if (enable) {
50362306a36Sopenharmony_ci		mutex_lock(&priv->lock);
50462306a36Sopenharmony_ci		pm_runtime_get_sync(ch->dev);
50562306a36Sopenharmony_ci		ret = rz_mtu3_initialize_counter(counter, count->id);
50662306a36Sopenharmony_ci		if (ret == 0)
50762306a36Sopenharmony_ci			priv->count_is_enabled[count->id] = true;
50862306a36Sopenharmony_ci		mutex_unlock(&priv->lock);
50962306a36Sopenharmony_ci	} else {
51062306a36Sopenharmony_ci		mutex_lock(&priv->lock);
51162306a36Sopenharmony_ci		rz_mtu3_terminate_counter(counter, count->id);
51262306a36Sopenharmony_ci		priv->count_is_enabled[count->id] = false;
51362306a36Sopenharmony_ci		pm_runtime_put(ch->dev);
51462306a36Sopenharmony_ci		mutex_unlock(&priv->lock);
51562306a36Sopenharmony_ci	}
51662306a36Sopenharmony_ci
51762306a36Sopenharmony_ci	return ret;
51862306a36Sopenharmony_ci}
51962306a36Sopenharmony_ci
52062306a36Sopenharmony_cistatic int rz_mtu3_lock_if_ch0_is_enabled(struct rz_mtu3_cnt *const priv)
52162306a36Sopenharmony_ci{
52262306a36Sopenharmony_ci	mutex_lock(&priv->lock);
52362306a36Sopenharmony_ci	if (priv->ch->is_busy && !(priv->count_is_enabled[RZ_MTU3_16_BIT_MTU1_CH] ||
52462306a36Sopenharmony_ci				   priv->count_is_enabled[RZ_MTU3_32_BIT_CH])) {
52562306a36Sopenharmony_ci		mutex_unlock(&priv->lock);
52662306a36Sopenharmony_ci		return -EINVAL;
52762306a36Sopenharmony_ci	}
52862306a36Sopenharmony_ci
52962306a36Sopenharmony_ci	return 0;
53062306a36Sopenharmony_ci}
53162306a36Sopenharmony_ci
53262306a36Sopenharmony_cistatic int rz_mtu3_cascade_counts_enable_get(struct counter_device *counter,
53362306a36Sopenharmony_ci					     u8 *cascade_enable)
53462306a36Sopenharmony_ci{
53562306a36Sopenharmony_ci	struct rz_mtu3_cnt *const priv = counter_priv(counter);
53662306a36Sopenharmony_ci	unsigned long tmdr;
53762306a36Sopenharmony_ci	int ret;
53862306a36Sopenharmony_ci
53962306a36Sopenharmony_ci	ret = rz_mtu3_lock_if_ch0_is_enabled(priv);
54062306a36Sopenharmony_ci	if (ret)
54162306a36Sopenharmony_ci		return ret;
54262306a36Sopenharmony_ci
54362306a36Sopenharmony_ci	pm_runtime_get_sync(priv->ch->dev);
54462306a36Sopenharmony_ci	tmdr = rz_mtu3_shared_reg_read(priv->ch, RZ_MTU3_TMDR3);
54562306a36Sopenharmony_ci	pm_runtime_put(priv->ch->dev);
54662306a36Sopenharmony_ci	*cascade_enable = test_bit(RZ_MTU3_TMDR3_LWA, &tmdr);
54762306a36Sopenharmony_ci	mutex_unlock(&priv->lock);
54862306a36Sopenharmony_ci
54962306a36Sopenharmony_ci	return 0;
55062306a36Sopenharmony_ci}
55162306a36Sopenharmony_ci
55262306a36Sopenharmony_cistatic int rz_mtu3_cascade_counts_enable_set(struct counter_device *counter,
55362306a36Sopenharmony_ci					     u8 cascade_enable)
55462306a36Sopenharmony_ci{
55562306a36Sopenharmony_ci	struct rz_mtu3_cnt *const priv = counter_priv(counter);
55662306a36Sopenharmony_ci	int ret;
55762306a36Sopenharmony_ci
55862306a36Sopenharmony_ci	ret = rz_mtu3_lock_if_ch0_is_enabled(priv);
55962306a36Sopenharmony_ci	if (ret)
56062306a36Sopenharmony_ci		return ret;
56162306a36Sopenharmony_ci
56262306a36Sopenharmony_ci	pm_runtime_get_sync(priv->ch->dev);
56362306a36Sopenharmony_ci	rz_mtu3_shared_reg_update_bit(priv->ch, RZ_MTU3_TMDR3,
56462306a36Sopenharmony_ci				      RZ_MTU3_TMDR3_LWA, cascade_enable);
56562306a36Sopenharmony_ci	pm_runtime_put(priv->ch->dev);
56662306a36Sopenharmony_ci	mutex_unlock(&priv->lock);
56762306a36Sopenharmony_ci
56862306a36Sopenharmony_ci	return 0;
56962306a36Sopenharmony_ci}
57062306a36Sopenharmony_ci
57162306a36Sopenharmony_cistatic int rz_mtu3_ext_input_phase_clock_select_get(struct counter_device *counter,
57262306a36Sopenharmony_ci						    u32 *ext_input_phase_clock_select)
57362306a36Sopenharmony_ci{
57462306a36Sopenharmony_ci	struct rz_mtu3_cnt *const priv = counter_priv(counter);
57562306a36Sopenharmony_ci	unsigned long tmdr;
57662306a36Sopenharmony_ci	int ret;
57762306a36Sopenharmony_ci
57862306a36Sopenharmony_ci	ret = rz_mtu3_lock_if_ch0_is_enabled(priv);
57962306a36Sopenharmony_ci	if (ret)
58062306a36Sopenharmony_ci		return ret;
58162306a36Sopenharmony_ci
58262306a36Sopenharmony_ci	pm_runtime_get_sync(priv->ch->dev);
58362306a36Sopenharmony_ci	tmdr = rz_mtu3_shared_reg_read(priv->ch, RZ_MTU3_TMDR3);
58462306a36Sopenharmony_ci	pm_runtime_put(priv->ch->dev);
58562306a36Sopenharmony_ci	*ext_input_phase_clock_select = test_bit(RZ_MTU3_TMDR3_PHCKSEL, &tmdr);
58662306a36Sopenharmony_ci	mutex_unlock(&priv->lock);
58762306a36Sopenharmony_ci
58862306a36Sopenharmony_ci	return 0;
58962306a36Sopenharmony_ci}
59062306a36Sopenharmony_ci
59162306a36Sopenharmony_cistatic int rz_mtu3_ext_input_phase_clock_select_set(struct counter_device *counter,
59262306a36Sopenharmony_ci						    u32 ext_input_phase_clock_select)
59362306a36Sopenharmony_ci{
59462306a36Sopenharmony_ci	struct rz_mtu3_cnt *const priv = counter_priv(counter);
59562306a36Sopenharmony_ci	int ret;
59662306a36Sopenharmony_ci
59762306a36Sopenharmony_ci	ret = rz_mtu3_lock_if_ch0_is_enabled(priv);
59862306a36Sopenharmony_ci	if (ret)
59962306a36Sopenharmony_ci		return ret;
60062306a36Sopenharmony_ci
60162306a36Sopenharmony_ci	pm_runtime_get_sync(priv->ch->dev);
60262306a36Sopenharmony_ci	rz_mtu3_shared_reg_update_bit(priv->ch, RZ_MTU3_TMDR3,
60362306a36Sopenharmony_ci				      RZ_MTU3_TMDR3_PHCKSEL,
60462306a36Sopenharmony_ci				      ext_input_phase_clock_select);
60562306a36Sopenharmony_ci	pm_runtime_put(priv->ch->dev);
60662306a36Sopenharmony_ci	mutex_unlock(&priv->lock);
60762306a36Sopenharmony_ci
60862306a36Sopenharmony_ci	return 0;
60962306a36Sopenharmony_ci}
61062306a36Sopenharmony_ci
61162306a36Sopenharmony_cistatic struct counter_comp rz_mtu3_count_ext[] = {
61262306a36Sopenharmony_ci	COUNTER_COMP_DIRECTION(rz_mtu3_count_direction_read),
61362306a36Sopenharmony_ci	COUNTER_COMP_ENABLE(rz_mtu3_count_enable_read,
61462306a36Sopenharmony_ci			    rz_mtu3_count_enable_write),
61562306a36Sopenharmony_ci	COUNTER_COMP_CEILING(rz_mtu3_count_ceiling_read,
61662306a36Sopenharmony_ci			     rz_mtu3_count_ceiling_write),
61762306a36Sopenharmony_ci};
61862306a36Sopenharmony_ci
61962306a36Sopenharmony_cistatic const enum counter_synapse_action rz_mtu3_synapse_actions[] = {
62062306a36Sopenharmony_ci	COUNTER_SYNAPSE_ACTION_BOTH_EDGES,
62162306a36Sopenharmony_ci	COUNTER_SYNAPSE_ACTION_RISING_EDGE,
62262306a36Sopenharmony_ci	COUNTER_SYNAPSE_ACTION_NONE,
62362306a36Sopenharmony_ci};
62462306a36Sopenharmony_ci
62562306a36Sopenharmony_cistatic int rz_mtu3_action_read(struct counter_device *counter,
62662306a36Sopenharmony_ci			       struct counter_count *count,
62762306a36Sopenharmony_ci			       struct counter_synapse *synapse,
62862306a36Sopenharmony_ci			       enum counter_synapse_action *action)
62962306a36Sopenharmony_ci{
63062306a36Sopenharmony_ci	const bool is_signal_ab = (synapse->signal->id == SIGNAL_A_ID) ||
63162306a36Sopenharmony_ci				  (synapse->signal->id == SIGNAL_B_ID);
63262306a36Sopenharmony_ci	struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id);
63362306a36Sopenharmony_ci	struct rz_mtu3_cnt *const priv = counter_priv(counter);
63462306a36Sopenharmony_ci	enum counter_function function;
63562306a36Sopenharmony_ci	bool mtclkc_mtclkd;
63662306a36Sopenharmony_ci	unsigned long tmdr;
63762306a36Sopenharmony_ci	int ret;
63862306a36Sopenharmony_ci
63962306a36Sopenharmony_ci	ret = rz_mtu3_lock_if_count_is_enabled(ch, priv, count->id);
64062306a36Sopenharmony_ci	if (ret)
64162306a36Sopenharmony_ci		return ret;
64262306a36Sopenharmony_ci
64362306a36Sopenharmony_ci	ret = rz_mtu3_count_function_read_helper(ch, priv, &function);
64462306a36Sopenharmony_ci	if (ret) {
64562306a36Sopenharmony_ci		mutex_unlock(&priv->lock);
64662306a36Sopenharmony_ci		return ret;
64762306a36Sopenharmony_ci	}
64862306a36Sopenharmony_ci
64962306a36Sopenharmony_ci	/* Default action mode */
65062306a36Sopenharmony_ci	*action = COUNTER_SYNAPSE_ACTION_NONE;
65162306a36Sopenharmony_ci
65262306a36Sopenharmony_ci	if (count->id != RZ_MTU3_16_BIT_MTU1_CH) {
65362306a36Sopenharmony_ci		tmdr = rz_mtu3_shared_reg_read(priv->ch, RZ_MTU3_TMDR3);
65462306a36Sopenharmony_ci		mtclkc_mtclkd = test_bit(RZ_MTU3_TMDR3_PHCKSEL, &tmdr);
65562306a36Sopenharmony_ci		if ((mtclkc_mtclkd && is_signal_ab) ||
65662306a36Sopenharmony_ci		    (!mtclkc_mtclkd && !is_signal_ab)) {
65762306a36Sopenharmony_ci			mutex_unlock(&priv->lock);
65862306a36Sopenharmony_ci			return 0;
65962306a36Sopenharmony_ci		}
66062306a36Sopenharmony_ci	}
66162306a36Sopenharmony_ci
66262306a36Sopenharmony_ci	switch (function) {
66362306a36Sopenharmony_ci	case COUNTER_FUNCTION_PULSE_DIRECTION:
66462306a36Sopenharmony_ci		/*
66562306a36Sopenharmony_ci		 * Rising edges on signal A (signal C) updates the respective
66662306a36Sopenharmony_ci		 * count. The input level of signal B (signal D) determines
66762306a36Sopenharmony_ci		 * direction.
66862306a36Sopenharmony_ci		 */
66962306a36Sopenharmony_ci		if (synapse->signal->id == SIGNAL_A_ID ||
67062306a36Sopenharmony_ci		    synapse->signal->id == SIGNAL_C_ID)
67162306a36Sopenharmony_ci			*action = COUNTER_SYNAPSE_ACTION_RISING_EDGE;
67262306a36Sopenharmony_ci		break;
67362306a36Sopenharmony_ci	case COUNTER_FUNCTION_QUADRATURE_X2_B:
67462306a36Sopenharmony_ci		/*
67562306a36Sopenharmony_ci		 * Any state transition on quadrature pair signal B (signal D)
67662306a36Sopenharmony_ci		 * updates the respective count.
67762306a36Sopenharmony_ci		 */
67862306a36Sopenharmony_ci		if (synapse->signal->id == SIGNAL_B_ID ||
67962306a36Sopenharmony_ci		    synapse->signal->id == SIGNAL_D_ID)
68062306a36Sopenharmony_ci			*action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES;
68162306a36Sopenharmony_ci		break;
68262306a36Sopenharmony_ci	case COUNTER_FUNCTION_QUADRATURE_X4:
68362306a36Sopenharmony_ci		/* counts up/down on both edges of A (C)  and B (D) signal */
68462306a36Sopenharmony_ci		*action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES;
68562306a36Sopenharmony_ci		break;
68662306a36Sopenharmony_ci	default:
68762306a36Sopenharmony_ci		/* should never reach this path */
68862306a36Sopenharmony_ci		mutex_unlock(&priv->lock);
68962306a36Sopenharmony_ci		return -EINVAL;
69062306a36Sopenharmony_ci	}
69162306a36Sopenharmony_ci
69262306a36Sopenharmony_ci	mutex_unlock(&priv->lock);
69362306a36Sopenharmony_ci
69462306a36Sopenharmony_ci	return 0;
69562306a36Sopenharmony_ci}
69662306a36Sopenharmony_ci
69762306a36Sopenharmony_cistatic const struct counter_ops rz_mtu3_cnt_ops = {
69862306a36Sopenharmony_ci	.count_read = rz_mtu3_count_read,
69962306a36Sopenharmony_ci	.count_write = rz_mtu3_count_write,
70062306a36Sopenharmony_ci	.function_read = rz_mtu3_count_function_read,
70162306a36Sopenharmony_ci	.function_write = rz_mtu3_count_function_write,
70262306a36Sopenharmony_ci	.action_read = rz_mtu3_action_read,
70362306a36Sopenharmony_ci};
70462306a36Sopenharmony_ci
70562306a36Sopenharmony_ci#define RZ_MTU3_PHASE_SIGNAL(_id, _name) {		\
70662306a36Sopenharmony_ci	.id = (_id),				\
70762306a36Sopenharmony_ci	.name = (_name),			\
70862306a36Sopenharmony_ci}
70962306a36Sopenharmony_ci
71062306a36Sopenharmony_cistatic struct counter_signal rz_mtu3_signals[] = {
71162306a36Sopenharmony_ci	RZ_MTU3_PHASE_SIGNAL(SIGNAL_A_ID, "MTU1 MTCLKA"),
71262306a36Sopenharmony_ci	RZ_MTU3_PHASE_SIGNAL(SIGNAL_B_ID, "MTU1 MTCLKB"),
71362306a36Sopenharmony_ci	RZ_MTU3_PHASE_SIGNAL(SIGNAL_C_ID, "MTU2 MTCLKC"),
71462306a36Sopenharmony_ci	RZ_MTU3_PHASE_SIGNAL(SIGNAL_D_ID, "MTU2 MTCLKD"),
71562306a36Sopenharmony_ci};
71662306a36Sopenharmony_ci
71762306a36Sopenharmony_cistatic struct counter_synapse rz_mtu3_mtu1_count_synapses[] = {
71862306a36Sopenharmony_ci	{
71962306a36Sopenharmony_ci		.actions_list = rz_mtu3_synapse_actions,
72062306a36Sopenharmony_ci		.num_actions = ARRAY_SIZE(rz_mtu3_synapse_actions),
72162306a36Sopenharmony_ci		.signal = rz_mtu3_signals,
72262306a36Sopenharmony_ci	},
72362306a36Sopenharmony_ci	{
72462306a36Sopenharmony_ci		.actions_list = rz_mtu3_synapse_actions,
72562306a36Sopenharmony_ci		.num_actions = ARRAY_SIZE(rz_mtu3_synapse_actions),
72662306a36Sopenharmony_ci		.signal = rz_mtu3_signals + 1,
72762306a36Sopenharmony_ci	}
72862306a36Sopenharmony_ci};
72962306a36Sopenharmony_ci
73062306a36Sopenharmony_cistatic struct counter_synapse rz_mtu3_mtu2_count_synapses[] = {
73162306a36Sopenharmony_ci	{
73262306a36Sopenharmony_ci		.actions_list = rz_mtu3_synapse_actions,
73362306a36Sopenharmony_ci		.num_actions = ARRAY_SIZE(rz_mtu3_synapse_actions),
73462306a36Sopenharmony_ci		.signal = rz_mtu3_signals,
73562306a36Sopenharmony_ci	},
73662306a36Sopenharmony_ci	{
73762306a36Sopenharmony_ci		.actions_list = rz_mtu3_synapse_actions,
73862306a36Sopenharmony_ci		.num_actions = ARRAY_SIZE(rz_mtu3_synapse_actions),
73962306a36Sopenharmony_ci		.signal = rz_mtu3_signals + 1,
74062306a36Sopenharmony_ci	},
74162306a36Sopenharmony_ci	{
74262306a36Sopenharmony_ci		.actions_list = rz_mtu3_synapse_actions,
74362306a36Sopenharmony_ci		.num_actions = ARRAY_SIZE(rz_mtu3_synapse_actions),
74462306a36Sopenharmony_ci		.signal = rz_mtu3_signals + 2,
74562306a36Sopenharmony_ci	},
74662306a36Sopenharmony_ci	{
74762306a36Sopenharmony_ci		.actions_list = rz_mtu3_synapse_actions,
74862306a36Sopenharmony_ci		.num_actions = ARRAY_SIZE(rz_mtu3_synapse_actions),
74962306a36Sopenharmony_ci		.signal = rz_mtu3_signals + 3,
75062306a36Sopenharmony_ci	}
75162306a36Sopenharmony_ci};
75262306a36Sopenharmony_ci
75362306a36Sopenharmony_cistatic struct counter_count rz_mtu3_counts[] = {
75462306a36Sopenharmony_ci	{
75562306a36Sopenharmony_ci		.id = RZ_MTU3_16_BIT_MTU1_CH,
75662306a36Sopenharmony_ci		.name = "Channel 1 Count",
75762306a36Sopenharmony_ci		.functions_list = rz_mtu3_count_functions,
75862306a36Sopenharmony_ci		.num_functions = ARRAY_SIZE(rz_mtu3_count_functions),
75962306a36Sopenharmony_ci		.synapses = rz_mtu3_mtu1_count_synapses,
76062306a36Sopenharmony_ci		.num_synapses = ARRAY_SIZE(rz_mtu3_mtu1_count_synapses),
76162306a36Sopenharmony_ci		.ext = rz_mtu3_count_ext,
76262306a36Sopenharmony_ci		.num_ext = ARRAY_SIZE(rz_mtu3_count_ext),
76362306a36Sopenharmony_ci	},
76462306a36Sopenharmony_ci	{
76562306a36Sopenharmony_ci		.id = RZ_MTU3_16_BIT_MTU2_CH,
76662306a36Sopenharmony_ci		.name = "Channel 2 Count",
76762306a36Sopenharmony_ci		.functions_list = rz_mtu3_count_functions,
76862306a36Sopenharmony_ci		.num_functions = ARRAY_SIZE(rz_mtu3_count_functions),
76962306a36Sopenharmony_ci		.synapses = rz_mtu3_mtu2_count_synapses,
77062306a36Sopenharmony_ci		.num_synapses = ARRAY_SIZE(rz_mtu3_mtu2_count_synapses),
77162306a36Sopenharmony_ci		.ext = rz_mtu3_count_ext,
77262306a36Sopenharmony_ci		.num_ext = ARRAY_SIZE(rz_mtu3_count_ext),
77362306a36Sopenharmony_ci	},
77462306a36Sopenharmony_ci	{
77562306a36Sopenharmony_ci		.id = RZ_MTU3_32_BIT_CH,
77662306a36Sopenharmony_ci		.name = "Channel 1 and 2 (cascaded) Count",
77762306a36Sopenharmony_ci		.functions_list = rz_mtu3_count_functions,
77862306a36Sopenharmony_ci		.num_functions = ARRAY_SIZE(rz_mtu3_count_functions),
77962306a36Sopenharmony_ci		.synapses = rz_mtu3_mtu2_count_synapses,
78062306a36Sopenharmony_ci		.num_synapses = ARRAY_SIZE(rz_mtu3_mtu2_count_synapses),
78162306a36Sopenharmony_ci		.ext = rz_mtu3_count_ext,
78262306a36Sopenharmony_ci		.num_ext = ARRAY_SIZE(rz_mtu3_count_ext),
78362306a36Sopenharmony_ci	}
78462306a36Sopenharmony_ci};
78562306a36Sopenharmony_ci
78662306a36Sopenharmony_cistatic const char *const rz_mtu3_ext_input_phase_clock_select[] = {
78762306a36Sopenharmony_ci	"MTCLKA-MTCLKB",
78862306a36Sopenharmony_ci	"MTCLKC-MTCLKD",
78962306a36Sopenharmony_ci};
79062306a36Sopenharmony_ci
79162306a36Sopenharmony_cistatic DEFINE_COUNTER_ENUM(rz_mtu3_ext_input_phase_clock_select_enum,
79262306a36Sopenharmony_ci			   rz_mtu3_ext_input_phase_clock_select);
79362306a36Sopenharmony_ci
79462306a36Sopenharmony_cistatic struct counter_comp rz_mtu3_device_ext[] = {
79562306a36Sopenharmony_ci	COUNTER_COMP_DEVICE_BOOL("cascade_counts_enable",
79662306a36Sopenharmony_ci				 rz_mtu3_cascade_counts_enable_get,
79762306a36Sopenharmony_ci				 rz_mtu3_cascade_counts_enable_set),
79862306a36Sopenharmony_ci	COUNTER_COMP_DEVICE_ENUM("external_input_phase_clock_select",
79962306a36Sopenharmony_ci				 rz_mtu3_ext_input_phase_clock_select_get,
80062306a36Sopenharmony_ci				 rz_mtu3_ext_input_phase_clock_select_set,
80162306a36Sopenharmony_ci				 rz_mtu3_ext_input_phase_clock_select_enum),
80262306a36Sopenharmony_ci};
80362306a36Sopenharmony_ci
80462306a36Sopenharmony_cistatic int rz_mtu3_cnt_pm_runtime_suspend(struct device *dev)
80562306a36Sopenharmony_ci{
80662306a36Sopenharmony_ci	struct clk *const clk = dev_get_drvdata(dev);
80762306a36Sopenharmony_ci
80862306a36Sopenharmony_ci	clk_disable_unprepare(clk);
80962306a36Sopenharmony_ci
81062306a36Sopenharmony_ci	return 0;
81162306a36Sopenharmony_ci}
81262306a36Sopenharmony_ci
81362306a36Sopenharmony_cistatic int rz_mtu3_cnt_pm_runtime_resume(struct device *dev)
81462306a36Sopenharmony_ci{
81562306a36Sopenharmony_ci	struct clk *const clk = dev_get_drvdata(dev);
81662306a36Sopenharmony_ci
81762306a36Sopenharmony_ci	clk_prepare_enable(clk);
81862306a36Sopenharmony_ci
81962306a36Sopenharmony_ci	return 0;
82062306a36Sopenharmony_ci}
82162306a36Sopenharmony_ci
82262306a36Sopenharmony_cistatic DEFINE_RUNTIME_DEV_PM_OPS(rz_mtu3_cnt_pm_ops,
82362306a36Sopenharmony_ci				 rz_mtu3_cnt_pm_runtime_suspend,
82462306a36Sopenharmony_ci				 rz_mtu3_cnt_pm_runtime_resume, NULL);
82562306a36Sopenharmony_ci
82662306a36Sopenharmony_cistatic void rz_mtu3_cnt_pm_disable(void *data)
82762306a36Sopenharmony_ci{
82862306a36Sopenharmony_ci	struct device *dev = data;
82962306a36Sopenharmony_ci
83062306a36Sopenharmony_ci	pm_runtime_disable(dev);
83162306a36Sopenharmony_ci	pm_runtime_set_suspended(dev);
83262306a36Sopenharmony_ci}
83362306a36Sopenharmony_ci
83462306a36Sopenharmony_cistatic int rz_mtu3_cnt_probe(struct platform_device *pdev)
83562306a36Sopenharmony_ci{
83662306a36Sopenharmony_ci	struct rz_mtu3 *ddata = dev_get_drvdata(pdev->dev.parent);
83762306a36Sopenharmony_ci	struct device *dev = &pdev->dev;
83862306a36Sopenharmony_ci	struct counter_device *counter;
83962306a36Sopenharmony_ci	struct rz_mtu3_channel *ch;
84062306a36Sopenharmony_ci	struct rz_mtu3_cnt *priv;
84162306a36Sopenharmony_ci	unsigned int i;
84262306a36Sopenharmony_ci	int ret;
84362306a36Sopenharmony_ci
84462306a36Sopenharmony_ci	counter = devm_counter_alloc(dev, sizeof(*priv));
84562306a36Sopenharmony_ci	if (!counter)
84662306a36Sopenharmony_ci		return -ENOMEM;
84762306a36Sopenharmony_ci
84862306a36Sopenharmony_ci	priv = counter_priv(counter);
84962306a36Sopenharmony_ci	priv->clk = ddata->clk;
85062306a36Sopenharmony_ci	priv->mtu_32bit_max = U32_MAX;
85162306a36Sopenharmony_ci	priv->ch = &ddata->channels[RZ_MTU3_CHAN_1];
85262306a36Sopenharmony_ci	ch = &priv->ch[0];
85362306a36Sopenharmony_ci	for (i = 0; i < RZ_MTU3_MAX_HW_CNTR_CHANNELS; i++) {
85462306a36Sopenharmony_ci		ch->dev = dev;
85562306a36Sopenharmony_ci		priv->mtu_16bit_max[i] = U16_MAX;
85662306a36Sopenharmony_ci		ch++;
85762306a36Sopenharmony_ci	}
85862306a36Sopenharmony_ci
85962306a36Sopenharmony_ci	mutex_init(&priv->lock);
86062306a36Sopenharmony_ci	platform_set_drvdata(pdev, priv->clk);
86162306a36Sopenharmony_ci	clk_prepare_enable(priv->clk);
86262306a36Sopenharmony_ci	pm_runtime_set_active(&pdev->dev);
86362306a36Sopenharmony_ci	pm_runtime_enable(&pdev->dev);
86462306a36Sopenharmony_ci	ret = devm_add_action_or_reset(&pdev->dev, rz_mtu3_cnt_pm_disable, dev);
86562306a36Sopenharmony_ci	if (ret < 0)
86662306a36Sopenharmony_ci		goto disable_clock;
86762306a36Sopenharmony_ci
86862306a36Sopenharmony_ci	counter->name = dev_name(dev);
86962306a36Sopenharmony_ci	counter->parent = dev;
87062306a36Sopenharmony_ci	counter->ops = &rz_mtu3_cnt_ops;
87162306a36Sopenharmony_ci	counter->counts = rz_mtu3_counts;
87262306a36Sopenharmony_ci	counter->num_counts = ARRAY_SIZE(rz_mtu3_counts);
87362306a36Sopenharmony_ci	counter->signals = rz_mtu3_signals;
87462306a36Sopenharmony_ci	counter->num_signals = ARRAY_SIZE(rz_mtu3_signals);
87562306a36Sopenharmony_ci	counter->ext = rz_mtu3_device_ext;
87662306a36Sopenharmony_ci	counter->num_ext = ARRAY_SIZE(rz_mtu3_device_ext);
87762306a36Sopenharmony_ci
87862306a36Sopenharmony_ci	/* Register Counter device */
87962306a36Sopenharmony_ci	ret = devm_counter_add(dev, counter);
88062306a36Sopenharmony_ci	if (ret < 0) {
88162306a36Sopenharmony_ci		dev_err_probe(dev, ret, "Failed to add counter\n");
88262306a36Sopenharmony_ci		goto disable_clock;
88362306a36Sopenharmony_ci	}
88462306a36Sopenharmony_ci
88562306a36Sopenharmony_ci	return 0;
88662306a36Sopenharmony_ci
88762306a36Sopenharmony_cidisable_clock:
88862306a36Sopenharmony_ci	clk_disable_unprepare(priv->clk);
88962306a36Sopenharmony_ci
89062306a36Sopenharmony_ci	return ret;
89162306a36Sopenharmony_ci}
89262306a36Sopenharmony_ci
89362306a36Sopenharmony_cistatic struct platform_driver rz_mtu3_cnt_driver = {
89462306a36Sopenharmony_ci	.probe = rz_mtu3_cnt_probe,
89562306a36Sopenharmony_ci	.driver = {
89662306a36Sopenharmony_ci		.name = "rz-mtu3-counter",
89762306a36Sopenharmony_ci		.pm = pm_ptr(&rz_mtu3_cnt_pm_ops),
89862306a36Sopenharmony_ci	},
89962306a36Sopenharmony_ci};
90062306a36Sopenharmony_cimodule_platform_driver(rz_mtu3_cnt_driver);
90162306a36Sopenharmony_ci
90262306a36Sopenharmony_ciMODULE_AUTHOR("Biju Das <biju.das.jz@bp.renesas.com>");
90362306a36Sopenharmony_ciMODULE_ALIAS("platform:rz-mtu3-counter");
90462306a36Sopenharmony_ciMODULE_DESCRIPTION("Renesas RZ/G2L MTU3a counter driver");
90562306a36Sopenharmony_ciMODULE_LICENSE("GPL");
90662306a36Sopenharmony_ciMODULE_IMPORT_NS(COUNTER);
907