| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906 |
- // SPDX-License-Identifier: GPL-2.0
- /*
- * Renesas RZ/G2L MTU3a Counter driver
- *
- * Copyright (C) 2022 Renesas Electronics Corporation
- */
- #include <linux/clk.h>
- #include <linux/counter.h>
- #include <linux/mfd/rz-mtu3.h>
- #include <linux/module.h>
- #include <linux/platform_device.h>
- #include <linux/pm_runtime.h>
- #include <linux/types.h>
- /*
- * Register descriptions
- * TSR: Timer Status Register
- * TMDR1: Timer Mode Register 1
- * TMDR3: Timer Mode Register 3
- * TIOR: Timer I/O Control Register
- * TCR: Timer Control Register
- * TCNT: Timer Counter
- * TGRA: Timer general register A
- * TCNTLW: Timer Longword Counter
- * TGRALW: Timer longword general register A
- */
- #define RZ_MTU3_TSR_TCFD BIT(7) /* Count Direction Flag */
- #define RZ_MTU3_TMDR1_PH_CNT_MODE_1 (4) /* Phase counting mode 1 */
- #define RZ_MTU3_TMDR1_PH_CNT_MODE_2 (5) /* Phase counting mode 2 */
- #define RZ_MTU3_TMDR1_PH_CNT_MODE_3 (6) /* Phase counting mode 3 */
- #define RZ_MTU3_TMDR1_PH_CNT_MODE_4 (7) /* Phase counting mode 4 */
- #define RZ_MTU3_TMDR1_PH_CNT_MODE_5 (9) /* Phase counting mode 5 */
- #define RZ_MTU3_TMDR1_PH_CNT_MODE_MASK (0xf)
- /*
- * LWA: MTU1/MTU2 Combination Longword Access Control
- * 0: 16-bit, 1: 32-bit
- */
- #define RZ_MTU3_TMDR3_LWA (0)
- /*
- * PHCKSEL: External Input Phase Clock Select
- * 0: MTCLKA and MTCLKB, 1: MTCLKC and MTCLKD
- */
- #define RZ_MTU3_TMDR3_PHCKSEL (1)
- #define RZ_MTU3_16_BIT_MTU1_CH (0)
- #define RZ_MTU3_16_BIT_MTU2_CH (1)
- #define RZ_MTU3_32_BIT_CH (2)
- #define RZ_MTU3_TIOR_NO_OUTPUT (0) /* Output prohibited */
- #define RZ_MTU3_TIOR_IC_BOTH (10) /* Input capture at both edges */
- #define SIGNAL_A_ID (0)
- #define SIGNAL_B_ID (1)
- #define SIGNAL_C_ID (2)
- #define SIGNAL_D_ID (3)
- #define RZ_MTU3_MAX_HW_CNTR_CHANNELS (2)
- #define RZ_MTU3_MAX_LOGICAL_CNTR_CHANNELS (3)
- /**
- * struct rz_mtu3_cnt - MTU3 counter private data
- *
- * @clk: MTU3 module clock
- * @lock: Lock to prevent concurrent access for ceiling and count
- * @ch: HW channels for the counters
- * @count_is_enabled: Enabled state of Counter value channel
- * @mtu_16bit_max: Cache for 16-bit counters
- * @mtu_32bit_max: Cache for 32-bit counters
- */
- struct rz_mtu3_cnt {
- struct clk *clk;
- struct mutex lock;
- struct rz_mtu3_channel *ch;
- bool count_is_enabled[RZ_MTU3_MAX_LOGICAL_CNTR_CHANNELS];
- union {
- u16 mtu_16bit_max[RZ_MTU3_MAX_HW_CNTR_CHANNELS];
- u32 mtu_32bit_max;
- };
- };
- static const enum counter_function rz_mtu3_count_functions[] = {
- COUNTER_FUNCTION_QUADRATURE_X4,
- COUNTER_FUNCTION_PULSE_DIRECTION,
- COUNTER_FUNCTION_QUADRATURE_X2_B,
- };
- static inline size_t rz_mtu3_get_hw_ch(const size_t id)
- {
- return (id == RZ_MTU3_32_BIT_CH) ? 0 : id;
- }
- static inline struct rz_mtu3_channel *rz_mtu3_get_ch(struct counter_device *counter, int id)
- {
- struct rz_mtu3_cnt *const priv = counter_priv(counter);
- const size_t ch_id = rz_mtu3_get_hw_ch(id);
- return &priv->ch[ch_id];
- }
- static bool rz_mtu3_is_counter_invalid(struct counter_device *counter, int id)
- {
- struct rz_mtu3_cnt *const priv = counter_priv(counter);
- unsigned long tmdr;
- pm_runtime_get_sync(priv->ch->dev);
- tmdr = rz_mtu3_shared_reg_read(priv->ch, RZ_MTU3_TMDR3);
- pm_runtime_put(priv->ch->dev);
- if (id == RZ_MTU3_32_BIT_CH && test_bit(RZ_MTU3_TMDR3_LWA, &tmdr))
- return false;
- if (id != RZ_MTU3_32_BIT_CH && !test_bit(RZ_MTU3_TMDR3_LWA, &tmdr))
- return false;
- return true;
- }
- static int rz_mtu3_lock_if_counter_is_valid(struct counter_device *counter,
- struct rz_mtu3_channel *const ch,
- struct rz_mtu3_cnt *const priv,
- int id)
- {
- mutex_lock(&priv->lock);
- if (ch->is_busy && !priv->count_is_enabled[id]) {
- mutex_unlock(&priv->lock);
- return -EINVAL;
- }
- if (rz_mtu3_is_counter_invalid(counter, id)) {
- mutex_unlock(&priv->lock);
- return -EBUSY;
- }
- return 0;
- }
- static int rz_mtu3_lock_if_count_is_enabled(struct rz_mtu3_channel *const ch,
- struct rz_mtu3_cnt *const priv,
- int id)
- {
- mutex_lock(&priv->lock);
- if (ch->is_busy && !priv->count_is_enabled[id]) {
- mutex_unlock(&priv->lock);
- return -EINVAL;
- }
- return 0;
- }
- static int rz_mtu3_count_read(struct counter_device *counter,
- struct counter_count *count, u64 *val)
- {
- struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id);
- struct rz_mtu3_cnt *const priv = counter_priv(counter);
- int ret;
- ret = rz_mtu3_lock_if_counter_is_valid(counter, ch, priv, count->id);
- if (ret)
- return ret;
- pm_runtime_get_sync(ch->dev);
- if (count->id == RZ_MTU3_32_BIT_CH)
- *val = rz_mtu3_32bit_ch_read(ch, RZ_MTU3_TCNTLW);
- else
- *val = rz_mtu3_16bit_ch_read(ch, RZ_MTU3_TCNT);
- pm_runtime_put(ch->dev);
- mutex_unlock(&priv->lock);
- return 0;
- }
- static int rz_mtu3_count_write(struct counter_device *counter,
- struct counter_count *count, const u64 val)
- {
- struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id);
- struct rz_mtu3_cnt *const priv = counter_priv(counter);
- int ret;
- ret = rz_mtu3_lock_if_counter_is_valid(counter, ch, priv, count->id);
- if (ret)
- return ret;
- pm_runtime_get_sync(ch->dev);
- if (count->id == RZ_MTU3_32_BIT_CH)
- rz_mtu3_32bit_ch_write(ch, RZ_MTU3_TCNTLW, val);
- else
- rz_mtu3_16bit_ch_write(ch, RZ_MTU3_TCNT, val);
- pm_runtime_put(ch->dev);
- mutex_unlock(&priv->lock);
- return 0;
- }
- static int rz_mtu3_count_function_read_helper(struct rz_mtu3_channel *const ch,
- struct rz_mtu3_cnt *const priv,
- enum counter_function *function)
- {
- u8 timer_mode;
- pm_runtime_get_sync(ch->dev);
- timer_mode = rz_mtu3_8bit_ch_read(ch, RZ_MTU3_TMDR1);
- pm_runtime_put(ch->dev);
- switch (timer_mode & RZ_MTU3_TMDR1_PH_CNT_MODE_MASK) {
- case RZ_MTU3_TMDR1_PH_CNT_MODE_1:
- *function = COUNTER_FUNCTION_QUADRATURE_X4;
- return 0;
- case RZ_MTU3_TMDR1_PH_CNT_MODE_2:
- *function = COUNTER_FUNCTION_PULSE_DIRECTION;
- return 0;
- case RZ_MTU3_TMDR1_PH_CNT_MODE_4:
- *function = COUNTER_FUNCTION_QUADRATURE_X2_B;
- return 0;
- default:
- /*
- * TODO:
- * - need to add RZ_MTU3_TMDR1_PH_CNT_MODE_3
- * - need to add RZ_MTU3_TMDR1_PH_CNT_MODE_5
- */
- return -EINVAL;
- }
- }
- static int rz_mtu3_count_function_read(struct counter_device *counter,
- struct counter_count *count,
- enum counter_function *function)
- {
- struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id);
- struct rz_mtu3_cnt *const priv = counter_priv(counter);
- int ret;
- ret = rz_mtu3_lock_if_count_is_enabled(ch, priv, count->id);
- if (ret)
- return ret;
- ret = rz_mtu3_count_function_read_helper(ch, priv, function);
- mutex_unlock(&priv->lock);
- return ret;
- }
- static int rz_mtu3_count_function_write(struct counter_device *counter,
- struct counter_count *count,
- enum counter_function function)
- {
- struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id);
- struct rz_mtu3_cnt *const priv = counter_priv(counter);
- u8 timer_mode;
- int ret;
- ret = rz_mtu3_lock_if_count_is_enabled(ch, priv, count->id);
- if (ret)
- return ret;
- switch (function) {
- case COUNTER_FUNCTION_QUADRATURE_X4:
- timer_mode = RZ_MTU3_TMDR1_PH_CNT_MODE_1;
- break;
- case COUNTER_FUNCTION_PULSE_DIRECTION:
- timer_mode = RZ_MTU3_TMDR1_PH_CNT_MODE_2;
- break;
- case COUNTER_FUNCTION_QUADRATURE_X2_B:
- timer_mode = RZ_MTU3_TMDR1_PH_CNT_MODE_4;
- break;
- default:
- /*
- * TODO:
- * - need to add RZ_MTU3_TMDR1_PH_CNT_MODE_3
- * - need to add RZ_MTU3_TMDR1_PH_CNT_MODE_5
- */
- mutex_unlock(&priv->lock);
- return -EINVAL;
- }
- pm_runtime_get_sync(ch->dev);
- rz_mtu3_8bit_ch_write(ch, RZ_MTU3_TMDR1, timer_mode);
- pm_runtime_put(ch->dev);
- mutex_unlock(&priv->lock);
- return 0;
- }
- static int rz_mtu3_count_direction_read(struct counter_device *counter,
- struct counter_count *count,
- enum counter_count_direction *direction)
- {
- struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id);
- struct rz_mtu3_cnt *const priv = counter_priv(counter);
- int ret;
- u8 tsr;
- ret = rz_mtu3_lock_if_count_is_enabled(ch, priv, count->id);
- if (ret)
- return ret;
- pm_runtime_get_sync(ch->dev);
- tsr = rz_mtu3_8bit_ch_read(ch, RZ_MTU3_TSR);
- pm_runtime_put(ch->dev);
- *direction = (tsr & RZ_MTU3_TSR_TCFD) ?
- COUNTER_COUNT_DIRECTION_FORWARD : COUNTER_COUNT_DIRECTION_BACKWARD;
- mutex_unlock(&priv->lock);
- return 0;
- }
- static int rz_mtu3_count_ceiling_read(struct counter_device *counter,
- struct counter_count *count,
- u64 *ceiling)
- {
- struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id);
- struct rz_mtu3_cnt *const priv = counter_priv(counter);
- const size_t ch_id = rz_mtu3_get_hw_ch(count->id);
- int ret;
- ret = rz_mtu3_lock_if_counter_is_valid(counter, ch, priv, count->id);
- if (ret)
- return ret;
- switch (count->id) {
- case RZ_MTU3_16_BIT_MTU1_CH:
- case RZ_MTU3_16_BIT_MTU2_CH:
- *ceiling = priv->mtu_16bit_max[ch_id];
- break;
- case RZ_MTU3_32_BIT_CH:
- *ceiling = priv->mtu_32bit_max;
- break;
- default:
- /* should never reach this path */
- mutex_unlock(&priv->lock);
- return -EINVAL;
- }
- mutex_unlock(&priv->lock);
- return 0;
- }
- static int rz_mtu3_count_ceiling_write(struct counter_device *counter,
- struct counter_count *count,
- u64 ceiling)
- {
- struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id);
- struct rz_mtu3_cnt *const priv = counter_priv(counter);
- const size_t ch_id = rz_mtu3_get_hw_ch(count->id);
- int ret;
- ret = rz_mtu3_lock_if_counter_is_valid(counter, ch, priv, count->id);
- if (ret)
- return ret;
- switch (count->id) {
- case RZ_MTU3_16_BIT_MTU1_CH:
- case RZ_MTU3_16_BIT_MTU2_CH:
- if (ceiling > U16_MAX) {
- mutex_unlock(&priv->lock);
- return -ERANGE;
- }
- priv->mtu_16bit_max[ch_id] = ceiling;
- break;
- case RZ_MTU3_32_BIT_CH:
- if (ceiling > U32_MAX) {
- mutex_unlock(&priv->lock);
- return -ERANGE;
- }
- priv->mtu_32bit_max = ceiling;
- break;
- default:
- /* should never reach this path */
- mutex_unlock(&priv->lock);
- return -EINVAL;
- }
- pm_runtime_get_sync(ch->dev);
- if (count->id == RZ_MTU3_32_BIT_CH)
- rz_mtu3_32bit_ch_write(ch, RZ_MTU3_TGRALW, ceiling);
- else
- rz_mtu3_16bit_ch_write(ch, RZ_MTU3_TGRA, ceiling);
- rz_mtu3_8bit_ch_write(ch, RZ_MTU3_TCR, RZ_MTU3_TCR_CCLR_TGRA);
- pm_runtime_put(ch->dev);
- mutex_unlock(&priv->lock);
- return 0;
- }
- static void rz_mtu3_32bit_cnt_setting(struct counter_device *counter)
- {
- struct rz_mtu3_channel *const ch1 = rz_mtu3_get_ch(counter, 0);
- struct rz_mtu3_channel *const ch2 = rz_mtu3_get_ch(counter, 1);
- /* Phase counting mode 1 is used as default in initialization. */
- rz_mtu3_8bit_ch_write(ch1, RZ_MTU3_TMDR1, RZ_MTU3_TMDR1_PH_CNT_MODE_1);
- rz_mtu3_8bit_ch_write(ch1, RZ_MTU3_TCR, RZ_MTU3_TCR_CCLR_TGRA);
- rz_mtu3_8bit_ch_write(ch1, RZ_MTU3_TIOR, RZ_MTU3_TIOR_IC_BOTH);
- rz_mtu3_enable(ch1);
- rz_mtu3_enable(ch2);
- }
- static void rz_mtu3_16bit_cnt_setting(struct counter_device *counter, int id)
- {
- struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, id);
- /* Phase counting mode 1 is used as default in initialization. */
- rz_mtu3_8bit_ch_write(ch, RZ_MTU3_TMDR1, RZ_MTU3_TMDR1_PH_CNT_MODE_1);
- rz_mtu3_8bit_ch_write(ch, RZ_MTU3_TCR, RZ_MTU3_TCR_CCLR_TGRA);
- rz_mtu3_8bit_ch_write(ch, RZ_MTU3_TIOR, RZ_MTU3_TIOR_NO_OUTPUT);
- rz_mtu3_enable(ch);
- }
- static int rz_mtu3_initialize_counter(struct counter_device *counter, int id)
- {
- struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, id);
- struct rz_mtu3_channel *const ch1 = rz_mtu3_get_ch(counter, 0);
- struct rz_mtu3_channel *const ch2 = rz_mtu3_get_ch(counter, 1);
- switch (id) {
- case RZ_MTU3_16_BIT_MTU1_CH:
- case RZ_MTU3_16_BIT_MTU2_CH:
- if (!rz_mtu3_request_channel(ch))
- return -EBUSY;
- rz_mtu3_16bit_cnt_setting(counter, id);
- return 0;
- case RZ_MTU3_32_BIT_CH:
- /*
- * 32-bit phase counting need MTU1 and MTU2 to create 32-bit
- * cascade counter.
- */
- if (!rz_mtu3_request_channel(ch1))
- return -EBUSY;
- if (!rz_mtu3_request_channel(ch2)) {
- rz_mtu3_release_channel(ch1);
- return -EBUSY;
- }
- rz_mtu3_32bit_cnt_setting(counter);
- return 0;
- default:
- /* should never reach this path */
- return -EINVAL;
- }
- }
- static void rz_mtu3_terminate_counter(struct counter_device *counter, int id)
- {
- struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, id);
- struct rz_mtu3_channel *const ch1 = rz_mtu3_get_ch(counter, 0);
- struct rz_mtu3_channel *const ch2 = rz_mtu3_get_ch(counter, 1);
- if (id == RZ_MTU3_32_BIT_CH) {
- rz_mtu3_release_channel(ch2);
- rz_mtu3_release_channel(ch1);
- rz_mtu3_disable(ch2);
- rz_mtu3_disable(ch1);
- } else {
- rz_mtu3_release_channel(ch);
- rz_mtu3_disable(ch);
- }
- }
- static int rz_mtu3_count_enable_read(struct counter_device *counter,
- struct counter_count *count, u8 *enable)
- {
- struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id);
- struct rz_mtu3_channel *const ch1 = rz_mtu3_get_ch(counter, 0);
- struct rz_mtu3_channel *const ch2 = rz_mtu3_get_ch(counter, 1);
- struct rz_mtu3_cnt *const priv = counter_priv(counter);
- int ret;
- ret = rz_mtu3_lock_if_count_is_enabled(ch, priv, count->id);
- if (ret)
- return ret;
- if (count->id == RZ_MTU3_32_BIT_CH)
- *enable = rz_mtu3_is_enabled(ch1) && rz_mtu3_is_enabled(ch2);
- else
- *enable = rz_mtu3_is_enabled(ch);
- mutex_unlock(&priv->lock);
- return 0;
- }
- static int rz_mtu3_count_enable_write(struct counter_device *counter,
- struct counter_count *count, u8 enable)
- {
- struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id);
- struct rz_mtu3_cnt *const priv = counter_priv(counter);
- int ret = 0;
- if (enable) {
- mutex_lock(&priv->lock);
- pm_runtime_get_sync(ch->dev);
- ret = rz_mtu3_initialize_counter(counter, count->id);
- if (ret == 0)
- priv->count_is_enabled[count->id] = true;
- mutex_unlock(&priv->lock);
- } else {
- mutex_lock(&priv->lock);
- rz_mtu3_terminate_counter(counter, count->id);
- priv->count_is_enabled[count->id] = false;
- pm_runtime_put(ch->dev);
- mutex_unlock(&priv->lock);
- }
- return ret;
- }
- static int rz_mtu3_lock_if_ch0_is_enabled(struct rz_mtu3_cnt *const priv)
- {
- mutex_lock(&priv->lock);
- if (priv->ch->is_busy && !(priv->count_is_enabled[RZ_MTU3_16_BIT_MTU1_CH] ||
- priv->count_is_enabled[RZ_MTU3_32_BIT_CH])) {
- mutex_unlock(&priv->lock);
- return -EINVAL;
- }
- return 0;
- }
- static int rz_mtu3_cascade_counts_enable_get(struct counter_device *counter,
- u8 *cascade_enable)
- {
- struct rz_mtu3_cnt *const priv = counter_priv(counter);
- unsigned long tmdr;
- int ret;
- ret = rz_mtu3_lock_if_ch0_is_enabled(priv);
- if (ret)
- return ret;
- pm_runtime_get_sync(priv->ch->dev);
- tmdr = rz_mtu3_shared_reg_read(priv->ch, RZ_MTU3_TMDR3);
- pm_runtime_put(priv->ch->dev);
- *cascade_enable = test_bit(RZ_MTU3_TMDR3_LWA, &tmdr);
- mutex_unlock(&priv->lock);
- return 0;
- }
- static int rz_mtu3_cascade_counts_enable_set(struct counter_device *counter,
- u8 cascade_enable)
- {
- struct rz_mtu3_cnt *const priv = counter_priv(counter);
- int ret;
- ret = rz_mtu3_lock_if_ch0_is_enabled(priv);
- if (ret)
- return ret;
- pm_runtime_get_sync(priv->ch->dev);
- rz_mtu3_shared_reg_update_bit(priv->ch, RZ_MTU3_TMDR3,
- RZ_MTU3_TMDR3_LWA, cascade_enable);
- pm_runtime_put(priv->ch->dev);
- mutex_unlock(&priv->lock);
- return 0;
- }
- static int rz_mtu3_ext_input_phase_clock_select_get(struct counter_device *counter,
- u32 *ext_input_phase_clock_select)
- {
- struct rz_mtu3_cnt *const priv = counter_priv(counter);
- unsigned long tmdr;
- int ret;
- ret = rz_mtu3_lock_if_ch0_is_enabled(priv);
- if (ret)
- return ret;
- pm_runtime_get_sync(priv->ch->dev);
- tmdr = rz_mtu3_shared_reg_read(priv->ch, RZ_MTU3_TMDR3);
- pm_runtime_put(priv->ch->dev);
- *ext_input_phase_clock_select = test_bit(RZ_MTU3_TMDR3_PHCKSEL, &tmdr);
- mutex_unlock(&priv->lock);
- return 0;
- }
- static int rz_mtu3_ext_input_phase_clock_select_set(struct counter_device *counter,
- u32 ext_input_phase_clock_select)
- {
- struct rz_mtu3_cnt *const priv = counter_priv(counter);
- int ret;
- ret = rz_mtu3_lock_if_ch0_is_enabled(priv);
- if (ret)
- return ret;
- pm_runtime_get_sync(priv->ch->dev);
- rz_mtu3_shared_reg_update_bit(priv->ch, RZ_MTU3_TMDR3,
- RZ_MTU3_TMDR3_PHCKSEL,
- ext_input_phase_clock_select);
- pm_runtime_put(priv->ch->dev);
- mutex_unlock(&priv->lock);
- return 0;
- }
- static struct counter_comp rz_mtu3_count_ext[] = {
- COUNTER_COMP_DIRECTION(rz_mtu3_count_direction_read),
- COUNTER_COMP_ENABLE(rz_mtu3_count_enable_read,
- rz_mtu3_count_enable_write),
- COUNTER_COMP_CEILING(rz_mtu3_count_ceiling_read,
- rz_mtu3_count_ceiling_write),
- };
- static const enum counter_synapse_action rz_mtu3_synapse_actions[] = {
- COUNTER_SYNAPSE_ACTION_BOTH_EDGES,
- COUNTER_SYNAPSE_ACTION_RISING_EDGE,
- COUNTER_SYNAPSE_ACTION_NONE,
- };
- static int rz_mtu3_action_read(struct counter_device *counter,
- struct counter_count *count,
- struct counter_synapse *synapse,
- enum counter_synapse_action *action)
- {
- const bool is_signal_ab = (synapse->signal->id == SIGNAL_A_ID) ||
- (synapse->signal->id == SIGNAL_B_ID);
- struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id);
- struct rz_mtu3_cnt *const priv = counter_priv(counter);
- enum counter_function function;
- bool mtclkc_mtclkd;
- unsigned long tmdr;
- int ret;
- ret = rz_mtu3_lock_if_count_is_enabled(ch, priv, count->id);
- if (ret)
- return ret;
- ret = rz_mtu3_count_function_read_helper(ch, priv, &function);
- if (ret) {
- mutex_unlock(&priv->lock);
- return ret;
- }
- /* Default action mode */
- *action = COUNTER_SYNAPSE_ACTION_NONE;
- if (count->id != RZ_MTU3_16_BIT_MTU1_CH) {
- tmdr = rz_mtu3_shared_reg_read(priv->ch, RZ_MTU3_TMDR3);
- mtclkc_mtclkd = test_bit(RZ_MTU3_TMDR3_PHCKSEL, &tmdr);
- if ((mtclkc_mtclkd && is_signal_ab) ||
- (!mtclkc_mtclkd && !is_signal_ab)) {
- mutex_unlock(&priv->lock);
- return 0;
- }
- }
- switch (function) {
- case COUNTER_FUNCTION_PULSE_DIRECTION:
- /*
- * Rising edges on signal A (signal C) updates the respective
- * count. The input level of signal B (signal D) determines
- * direction.
- */
- if (synapse->signal->id == SIGNAL_A_ID ||
- synapse->signal->id == SIGNAL_C_ID)
- *action = COUNTER_SYNAPSE_ACTION_RISING_EDGE;
- break;
- case COUNTER_FUNCTION_QUADRATURE_X2_B:
- /*
- * Any state transition on quadrature pair signal B (signal D)
- * updates the respective count.
- */
- if (synapse->signal->id == SIGNAL_B_ID ||
- synapse->signal->id == SIGNAL_D_ID)
- *action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES;
- break;
- case COUNTER_FUNCTION_QUADRATURE_X4:
- /* counts up/down on both edges of A (C) and B (D) signal */
- *action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES;
- break;
- default:
- /* should never reach this path */
- mutex_unlock(&priv->lock);
- return -EINVAL;
- }
- mutex_unlock(&priv->lock);
- return 0;
- }
- static const struct counter_ops rz_mtu3_cnt_ops = {
- .count_read = rz_mtu3_count_read,
- .count_write = rz_mtu3_count_write,
- .function_read = rz_mtu3_count_function_read,
- .function_write = rz_mtu3_count_function_write,
- .action_read = rz_mtu3_action_read,
- };
- #define RZ_MTU3_PHASE_SIGNAL(_id, _name) { \
- .id = (_id), \
- .name = (_name), \
- }
- static struct counter_signal rz_mtu3_signals[] = {
- RZ_MTU3_PHASE_SIGNAL(SIGNAL_A_ID, "MTU1 MTCLKA"),
- RZ_MTU3_PHASE_SIGNAL(SIGNAL_B_ID, "MTU1 MTCLKB"),
- RZ_MTU3_PHASE_SIGNAL(SIGNAL_C_ID, "MTU2 MTCLKC"),
- RZ_MTU3_PHASE_SIGNAL(SIGNAL_D_ID, "MTU2 MTCLKD"),
- };
- static struct counter_synapse rz_mtu3_mtu1_count_synapses[] = {
- {
- .actions_list = rz_mtu3_synapse_actions,
- .num_actions = ARRAY_SIZE(rz_mtu3_synapse_actions),
- .signal = rz_mtu3_signals,
- },
- {
- .actions_list = rz_mtu3_synapse_actions,
- .num_actions = ARRAY_SIZE(rz_mtu3_synapse_actions),
- .signal = rz_mtu3_signals + 1,
- }
- };
- static struct counter_synapse rz_mtu3_mtu2_count_synapses[] = {
- {
- .actions_list = rz_mtu3_synapse_actions,
- .num_actions = ARRAY_SIZE(rz_mtu3_synapse_actions),
- .signal = rz_mtu3_signals,
- },
- {
- .actions_list = rz_mtu3_synapse_actions,
- .num_actions = ARRAY_SIZE(rz_mtu3_synapse_actions),
- .signal = rz_mtu3_signals + 1,
- },
- {
- .actions_list = rz_mtu3_synapse_actions,
- .num_actions = ARRAY_SIZE(rz_mtu3_synapse_actions),
- .signal = rz_mtu3_signals + 2,
- },
- {
- .actions_list = rz_mtu3_synapse_actions,
- .num_actions = ARRAY_SIZE(rz_mtu3_synapse_actions),
- .signal = rz_mtu3_signals + 3,
- }
- };
- static struct counter_count rz_mtu3_counts[] = {
- {
- .id = RZ_MTU3_16_BIT_MTU1_CH,
- .name = "Channel 1 Count",
- .functions_list = rz_mtu3_count_functions,
- .num_functions = ARRAY_SIZE(rz_mtu3_count_functions),
- .synapses = rz_mtu3_mtu1_count_synapses,
- .num_synapses = ARRAY_SIZE(rz_mtu3_mtu1_count_synapses),
- .ext = rz_mtu3_count_ext,
- .num_ext = ARRAY_SIZE(rz_mtu3_count_ext),
- },
- {
- .id = RZ_MTU3_16_BIT_MTU2_CH,
- .name = "Channel 2 Count",
- .functions_list = rz_mtu3_count_functions,
- .num_functions = ARRAY_SIZE(rz_mtu3_count_functions),
- .synapses = rz_mtu3_mtu2_count_synapses,
- .num_synapses = ARRAY_SIZE(rz_mtu3_mtu2_count_synapses),
- .ext = rz_mtu3_count_ext,
- .num_ext = ARRAY_SIZE(rz_mtu3_count_ext),
- },
- {
- .id = RZ_MTU3_32_BIT_CH,
- .name = "Channel 1 and 2 (cascaded) Count",
- .functions_list = rz_mtu3_count_functions,
- .num_functions = ARRAY_SIZE(rz_mtu3_count_functions),
- .synapses = rz_mtu3_mtu2_count_synapses,
- .num_synapses = ARRAY_SIZE(rz_mtu3_mtu2_count_synapses),
- .ext = rz_mtu3_count_ext,
- .num_ext = ARRAY_SIZE(rz_mtu3_count_ext),
- }
- };
- static const char *const rz_mtu3_ext_input_phase_clock_select[] = {
- "MTCLKA-MTCLKB",
- "MTCLKC-MTCLKD",
- };
- static DEFINE_COUNTER_ENUM(rz_mtu3_ext_input_phase_clock_select_enum,
- rz_mtu3_ext_input_phase_clock_select);
- static struct counter_comp rz_mtu3_device_ext[] = {
- COUNTER_COMP_DEVICE_BOOL("cascade_counts_enable",
- rz_mtu3_cascade_counts_enable_get,
- rz_mtu3_cascade_counts_enable_set),
- COUNTER_COMP_DEVICE_ENUM("external_input_phase_clock_select",
- rz_mtu3_ext_input_phase_clock_select_get,
- rz_mtu3_ext_input_phase_clock_select_set,
- rz_mtu3_ext_input_phase_clock_select_enum),
- };
- static int rz_mtu3_cnt_pm_runtime_suspend(struct device *dev)
- {
- struct clk *const clk = dev_get_drvdata(dev);
- clk_disable_unprepare(clk);
- return 0;
- }
- static int rz_mtu3_cnt_pm_runtime_resume(struct device *dev)
- {
- struct clk *const clk = dev_get_drvdata(dev);
- clk_prepare_enable(clk);
- return 0;
- }
- static DEFINE_RUNTIME_DEV_PM_OPS(rz_mtu3_cnt_pm_ops,
- rz_mtu3_cnt_pm_runtime_suspend,
- rz_mtu3_cnt_pm_runtime_resume, NULL);
- static void rz_mtu3_cnt_pm_disable(void *data)
- {
- struct device *dev = data;
- pm_runtime_disable(dev);
- pm_runtime_set_suspended(dev);
- }
- static int rz_mtu3_cnt_probe(struct platform_device *pdev)
- {
- struct rz_mtu3 *ddata = dev_get_drvdata(pdev->dev.parent);
- struct device *dev = &pdev->dev;
- struct counter_device *counter;
- struct rz_mtu3_channel *ch;
- struct rz_mtu3_cnt *priv;
- unsigned int i;
- int ret;
- counter = devm_counter_alloc(dev, sizeof(*priv));
- if (!counter)
- return -ENOMEM;
- priv = counter_priv(counter);
- priv->clk = ddata->clk;
- priv->mtu_32bit_max = U32_MAX;
- priv->ch = &ddata->channels[RZ_MTU3_CHAN_1];
- ch = &priv->ch[0];
- for (i = 0; i < RZ_MTU3_MAX_HW_CNTR_CHANNELS; i++) {
- ch->dev = dev;
- priv->mtu_16bit_max[i] = U16_MAX;
- ch++;
- }
- mutex_init(&priv->lock);
- platform_set_drvdata(pdev, priv->clk);
- clk_prepare_enable(priv->clk);
- pm_runtime_set_active(&pdev->dev);
- pm_runtime_enable(&pdev->dev);
- ret = devm_add_action_or_reset(&pdev->dev, rz_mtu3_cnt_pm_disable, dev);
- if (ret < 0)
- goto disable_clock;
- counter->name = dev_name(dev);
- counter->parent = dev;
- counter->ops = &rz_mtu3_cnt_ops;
- counter->counts = rz_mtu3_counts;
- counter->num_counts = ARRAY_SIZE(rz_mtu3_counts);
- counter->signals = rz_mtu3_signals;
- counter->num_signals = ARRAY_SIZE(rz_mtu3_signals);
- counter->ext = rz_mtu3_device_ext;
- counter->num_ext = ARRAY_SIZE(rz_mtu3_device_ext);
- /* Register Counter device */
- ret = devm_counter_add(dev, counter);
- if (ret < 0) {
- dev_err_probe(dev, ret, "Failed to add counter\n");
- goto disable_clock;
- }
- return 0;
- disable_clock:
- clk_disable_unprepare(priv->clk);
- return ret;
- }
- static struct platform_driver rz_mtu3_cnt_driver = {
- .probe = rz_mtu3_cnt_probe,
- .driver = {
- .name = "rz-mtu3-counter",
- .pm = pm_ptr(&rz_mtu3_cnt_pm_ops),
- },
- };
- module_platform_driver(rz_mtu3_cnt_driver);
- MODULE_AUTHOR("Biju Das <biju.das.jz@bp.renesas.com>");
- MODULE_ALIAS("platform:rz-mtu3-counter");
- MODULE_DESCRIPTION("Renesas RZ/G2L MTU3a counter driver");
- MODULE_LICENSE("GPL");
- MODULE_IMPORT_NS(COUNTER);
|