^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Flex Timer Module Quadrature decoder
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * This module implements a driver for decoding the FTM quadrature
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * of ex. a LS1021A
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/fsl/ftm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/counter.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/bitfield.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #define FTM_FIELD_UPDATE(ftm, offset, mask, val) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) ({ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) uint32_t flags; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) ftm_read(ftm, offset, &flags); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) flags &= ~mask; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) flags |= FIELD_PREP(mask, val); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) ftm_write(ftm, offset, flags); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) })
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) struct ftm_quaddec {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) struct counter_device counter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) struct platform_device *pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) void __iomem *ftm_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) bool big_endian;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) struct mutex ftm_quaddec_mutex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) static void ftm_read(struct ftm_quaddec *ftm, uint32_t offset, uint32_t *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) if (ftm->big_endian)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) *data = ioread32be(ftm->ftm_base + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) *data = ioread32(ftm->ftm_base + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) static void ftm_write(struct ftm_quaddec *ftm, uint32_t offset, uint32_t data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) if (ftm->big_endian)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) iowrite32be(data, ftm->ftm_base + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) iowrite32(data, ftm->ftm_base + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) /* Hold mutex before modifying write protection state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) static void ftm_clear_write_protection(struct ftm_quaddec *ftm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) uint32_t flag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) /* First see if it is enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) ftm_read(ftm, FTM_FMS, &flag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) if (flag & FTM_FMS_WPEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) FTM_FIELD_UPDATE(ftm, FTM_MODE, FTM_MODE_WPDIS, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) static void ftm_set_write_protection(struct ftm_quaddec *ftm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) FTM_FIELD_UPDATE(ftm, FTM_FMS, FTM_FMS_WPEN, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) static void ftm_reset_counter(struct ftm_quaddec *ftm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) /* Reset hardware counter to CNTIN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) ftm_write(ftm, FTM_CNT, 0x0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) static void ftm_quaddec_init(struct ftm_quaddec *ftm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) ftm_clear_write_protection(ftm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * Do not write in the region from the CNTIN register through the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * PWMLOAD register when FTMEN = 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) * Also reset other fields to zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) ftm_write(ftm, FTM_MODE, FTM_MODE_FTMEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) ftm_write(ftm, FTM_CNTIN, 0x0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) ftm_write(ftm, FTM_MOD, 0xffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) ftm_write(ftm, FTM_CNT, 0x0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) /* Set prescaler, reset other fields to zero */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) ftm_write(ftm, FTM_SC, FTM_SC_PS_1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) /* Select quad mode, reset other fields to zero */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) ftm_write(ftm, FTM_QDCTRL, FTM_QDCTRL_QUADEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) /* Unused features and reset to default section */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) ftm_write(ftm, FTM_POL, 0x0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) ftm_write(ftm, FTM_FLTCTRL, 0x0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) ftm_write(ftm, FTM_SYNCONF, 0x0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) ftm_write(ftm, FTM_SYNC, 0xffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) /* Lock the FTM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) ftm_set_write_protection(ftm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) static void ftm_quaddec_disable(void *ftm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) struct ftm_quaddec *ftm_qua = ftm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) ftm_clear_write_protection(ftm_qua);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) ftm_write(ftm_qua, FTM_MODE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) ftm_write(ftm_qua, FTM_QDCTRL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) * This is enough to disable the counter. No clock has been
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * selected by writing to FTM_SC in init()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) ftm_set_write_protection(ftm_qua);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) static int ftm_quaddec_get_prescaler(struct counter_device *counter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) struct counter_count *count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) size_t *cnt_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) struct ftm_quaddec *ftm = counter->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) uint32_t scflags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) ftm_read(ftm, FTM_SC, &scflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) *cnt_mode = FIELD_GET(FTM_SC_PS_MASK, scflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) static int ftm_quaddec_set_prescaler(struct counter_device *counter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) struct counter_count *count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) size_t cnt_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) struct ftm_quaddec *ftm = counter->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) mutex_lock(&ftm->ftm_quaddec_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) ftm_clear_write_protection(ftm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) FTM_FIELD_UPDATE(ftm, FTM_SC, FTM_SC_PS_MASK, cnt_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) ftm_set_write_protection(ftm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) /* Also resets the counter as it is undefined anyway now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) ftm_reset_counter(ftm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) mutex_unlock(&ftm->ftm_quaddec_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) static const char * const ftm_quaddec_prescaler[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) "1", "2", "4", "8", "16", "32", "64", "128"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) static struct counter_count_enum_ext ftm_quaddec_prescaler_enum = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) .items = ftm_quaddec_prescaler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) .num_items = ARRAY_SIZE(ftm_quaddec_prescaler),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) .get = ftm_quaddec_get_prescaler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) .set = ftm_quaddec_set_prescaler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) enum ftm_quaddec_synapse_action {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) FTM_QUADDEC_SYNAPSE_ACTION_BOTH_EDGES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) static enum counter_synapse_action ftm_quaddec_synapse_actions[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) [FTM_QUADDEC_SYNAPSE_ACTION_BOTH_EDGES] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) COUNTER_SYNAPSE_ACTION_BOTH_EDGES
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) enum ftm_quaddec_count_function {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) FTM_QUADDEC_COUNT_ENCODER_MODE_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) static const enum counter_count_function ftm_quaddec_count_functions[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) [FTM_QUADDEC_COUNT_ENCODER_MODE_1] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) COUNTER_COUNT_FUNCTION_QUADRATURE_X4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) static int ftm_quaddec_count_read(struct counter_device *counter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) struct counter_count *count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) unsigned long *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) struct ftm_quaddec *const ftm = counter->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) uint32_t cntval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) ftm_read(ftm, FTM_CNT, &cntval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) *val = cntval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) static int ftm_quaddec_count_write(struct counter_device *counter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) struct counter_count *count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) const unsigned long val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) struct ftm_quaddec *const ftm = counter->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) if (val != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) dev_warn(&ftm->pdev->dev, "Can only accept '0' as new counter value\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) ftm_reset_counter(ftm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) static int ftm_quaddec_count_function_get(struct counter_device *counter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) struct counter_count *count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) size_t *function)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) *function = FTM_QUADDEC_COUNT_ENCODER_MODE_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) static int ftm_quaddec_action_get(struct counter_device *counter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) struct counter_count *count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) struct counter_synapse *synapse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) size_t *action)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) *action = FTM_QUADDEC_SYNAPSE_ACTION_BOTH_EDGES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) static const struct counter_ops ftm_quaddec_cnt_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) .count_read = ftm_quaddec_count_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) .count_write = ftm_quaddec_count_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) .function_get = ftm_quaddec_count_function_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) .action_get = ftm_quaddec_action_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) static struct counter_signal ftm_quaddec_signals[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) .id = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) .name = "Channel 1 Phase A"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) .id = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) .name = "Channel 1 Phase B"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) static struct counter_synapse ftm_quaddec_count_synapses[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) .actions_list = ftm_quaddec_synapse_actions,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) .num_actions = ARRAY_SIZE(ftm_quaddec_synapse_actions),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) .signal = &ftm_quaddec_signals[0]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) .actions_list = ftm_quaddec_synapse_actions,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) .num_actions = ARRAY_SIZE(ftm_quaddec_synapse_actions),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) .signal = &ftm_quaddec_signals[1]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) static const struct counter_count_ext ftm_quaddec_count_ext[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) COUNTER_COUNT_ENUM("prescaler", &ftm_quaddec_prescaler_enum),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) COUNTER_COUNT_ENUM_AVAILABLE("prescaler", &ftm_quaddec_prescaler_enum),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) static struct counter_count ftm_quaddec_counts = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) .id = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) .name = "Channel 1 Count",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) .functions_list = ftm_quaddec_count_functions,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) .num_functions = ARRAY_SIZE(ftm_quaddec_count_functions),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) .synapses = ftm_quaddec_count_synapses,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) .num_synapses = ARRAY_SIZE(ftm_quaddec_count_synapses),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) .ext = ftm_quaddec_count_ext,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) .num_ext = ARRAY_SIZE(ftm_quaddec_count_ext)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) static int ftm_quaddec_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) struct ftm_quaddec *ftm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) struct device_node *node = pdev->dev.of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) struct resource *io;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) ftm = devm_kzalloc(&pdev->dev, sizeof(*ftm), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) if (!ftm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) platform_set_drvdata(pdev, ftm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) if (!io) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) dev_err(&pdev->dev, "Failed to get memory region\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) ftm->pdev = pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) ftm->big_endian = of_property_read_bool(node, "big-endian");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) ftm->ftm_base = devm_ioremap(&pdev->dev, io->start, resource_size(io));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) if (!ftm->ftm_base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) dev_err(&pdev->dev, "Failed to map memory region\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) ftm->counter.name = dev_name(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) ftm->counter.parent = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) ftm->counter.ops = &ftm_quaddec_cnt_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) ftm->counter.counts = &ftm_quaddec_counts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) ftm->counter.num_counts = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) ftm->counter.signals = ftm_quaddec_signals;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) ftm->counter.num_signals = ARRAY_SIZE(ftm_quaddec_signals);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) ftm->counter.priv = ftm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) mutex_init(&ftm->ftm_quaddec_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) ftm_quaddec_init(ftm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) ret = devm_add_action_or_reset(&pdev->dev, ftm_quaddec_disable, ftm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) ret = devm_counter_register(&pdev->dev, &ftm->counter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) static const struct of_device_id ftm_quaddec_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) { .compatible = "fsl,ftm-quaddec" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) {},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) static struct platform_driver ftm_quaddec_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) .name = "ftm-quaddec",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) .of_match_table = ftm_quaddec_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) .probe = ftm_quaddec_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) module_platform_driver(ftm_quaddec_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) MODULE_AUTHOR("Kjeld Flarup <kfa@deif.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) MODULE_AUTHOR("Patrick Havelange <patrick.havelange@essensium.com>");