Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) 2019 David Lechner <david@lechnology.com>
0004  *
0005  * Counter driver for Texas Instruments Enhanced Quadrature Encoder Pulse (eQEP)
0006  */
0007 
0008 #include <linux/bitops.h>
0009 #include <linux/counter.h>
0010 #include <linux/kernel.h>
0011 #include <linux/mod_devicetable.h>
0012 #include <linux/module.h>
0013 #include <linux/platform_device.h>
0014 #include <linux/pm_runtime.h>
0015 #include <linux/regmap.h>
0016 #include <linux/types.h>
0017 
0018 /* 32-bit registers */
0019 #define QPOSCNT     0x0
0020 #define QPOSINIT    0x4
0021 #define QPOSMAX     0x8
0022 #define QPOSCMP     0xc
0023 #define QPOSILAT    0x10
0024 #define QPOSSLAT    0x14
0025 #define QPOSLAT     0x18
0026 #define QUTMR       0x1c
0027 #define QUPRD       0x20
0028 
0029 /* 16-bit registers */
0030 #define QWDTMR      0x0 /* 0x24 */
0031 #define QWDPRD      0x2 /* 0x26 */
0032 #define QDECCTL     0x4 /* 0x28 */
0033 #define QEPCTL      0x6 /* 0x2a */
0034 #define QCAPCTL     0x8 /* 0x2c */
0035 #define QPOSCTL     0xa /* 0x2e */
0036 #define QEINT       0xc /* 0x30 */
0037 #define QFLG        0xe /* 0x32 */
0038 #define QCLR        0x10    /* 0x34 */
0039 #define QFRC        0x12    /* 0x36 */
0040 #define QEPSTS      0x14    /* 0x38 */
0041 #define QCTMR       0x16    /* 0x3a */
0042 #define QCPRD       0x18    /* 0x3c */
0043 #define QCTMRLAT    0x1a    /* 0x3e */
0044 #define QCPRDLAT    0x1c    /* 0x40 */
0045 
0046 #define QDECCTL_QSRC_SHIFT  14
0047 #define QDECCTL_QSRC        GENMASK(15, 14)
0048 #define QDECCTL_SOEN        BIT(13)
0049 #define QDECCTL_SPSEL       BIT(12)
0050 #define QDECCTL_XCR     BIT(11)
0051 #define QDECCTL_SWAP        BIT(10)
0052 #define QDECCTL_IGATE       BIT(9)
0053 #define QDECCTL_QAP     BIT(8)
0054 #define QDECCTL_QBP     BIT(7)
0055 #define QDECCTL_QIP     BIT(6)
0056 #define QDECCTL_QSP     BIT(5)
0057 
0058 #define QEPCTL_FREE_SOFT    GENMASK(15, 14)
0059 #define QEPCTL_PCRM     GENMASK(13, 12)
0060 #define QEPCTL_SEI      GENMASK(11, 10)
0061 #define QEPCTL_IEI      GENMASK(9, 8)
0062 #define QEPCTL_SWI      BIT(7)
0063 #define QEPCTL_SEL      BIT(6)
0064 #define QEPCTL_IEL      GENMASK(5, 4)
0065 #define QEPCTL_PHEN     BIT(3)
0066 #define QEPCTL_QCLM     BIT(2)
0067 #define QEPCTL_UTE      BIT(1)
0068 #define QEPCTL_WDE      BIT(0)
0069 
0070 /* EQEP Inputs */
0071 enum {
0072     TI_EQEP_SIGNAL_QEPA,    /* QEPA/XCLK */
0073     TI_EQEP_SIGNAL_QEPB,    /* QEPB/XDIR */
0074 };
0075 
0076 /* Position Counter Input Modes */
0077 enum ti_eqep_count_func {
0078     TI_EQEP_COUNT_FUNC_QUAD_COUNT,
0079     TI_EQEP_COUNT_FUNC_DIR_COUNT,
0080     TI_EQEP_COUNT_FUNC_UP_COUNT,
0081     TI_EQEP_COUNT_FUNC_DOWN_COUNT,
0082 };
0083 
0084 struct ti_eqep_cnt {
0085     struct counter_device counter;
0086     struct regmap *regmap32;
0087     struct regmap *regmap16;
0088 };
0089 
0090 static struct ti_eqep_cnt *ti_eqep_count_from_counter(struct counter_device *counter)
0091 {
0092     return counter_priv(counter);
0093 }
0094 
0095 static int ti_eqep_count_read(struct counter_device *counter,
0096                   struct counter_count *count, u64 *val)
0097 {
0098     struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter);
0099     u32 cnt;
0100 
0101     regmap_read(priv->regmap32, QPOSCNT, &cnt);
0102     *val = cnt;
0103 
0104     return 0;
0105 }
0106 
0107 static int ti_eqep_count_write(struct counter_device *counter,
0108                    struct counter_count *count, u64 val)
0109 {
0110     struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter);
0111     u32 max;
0112 
0113     regmap_read(priv->regmap32, QPOSMAX, &max);
0114     if (val > max)
0115         return -EINVAL;
0116 
0117     return regmap_write(priv->regmap32, QPOSCNT, val);
0118 }
0119 
0120 static int ti_eqep_function_read(struct counter_device *counter,
0121                  struct counter_count *count,
0122                  enum counter_function *function)
0123 {
0124     struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter);
0125     u32 qdecctl;
0126 
0127     regmap_read(priv->regmap16, QDECCTL, &qdecctl);
0128 
0129     switch ((qdecctl & QDECCTL_QSRC) >> QDECCTL_QSRC_SHIFT) {
0130     case TI_EQEP_COUNT_FUNC_QUAD_COUNT:
0131         *function = COUNTER_FUNCTION_QUADRATURE_X4;
0132         break;
0133     case TI_EQEP_COUNT_FUNC_DIR_COUNT:
0134         *function = COUNTER_FUNCTION_PULSE_DIRECTION;
0135         break;
0136     case TI_EQEP_COUNT_FUNC_UP_COUNT:
0137         *function = COUNTER_FUNCTION_INCREASE;
0138         break;
0139     case TI_EQEP_COUNT_FUNC_DOWN_COUNT:
0140         *function = COUNTER_FUNCTION_DECREASE;
0141         break;
0142     }
0143 
0144     return 0;
0145 }
0146 
0147 static int ti_eqep_function_write(struct counter_device *counter,
0148                   struct counter_count *count,
0149                   enum counter_function function)
0150 {
0151     struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter);
0152     enum ti_eqep_count_func qsrc;
0153 
0154     switch (function) {
0155     case COUNTER_FUNCTION_QUADRATURE_X4:
0156         qsrc = TI_EQEP_COUNT_FUNC_QUAD_COUNT;
0157         break;
0158     case COUNTER_FUNCTION_PULSE_DIRECTION:
0159         qsrc = TI_EQEP_COUNT_FUNC_DIR_COUNT;
0160         break;
0161     case COUNTER_FUNCTION_INCREASE:
0162         qsrc = TI_EQEP_COUNT_FUNC_UP_COUNT;
0163         break;
0164     case COUNTER_FUNCTION_DECREASE:
0165         qsrc = TI_EQEP_COUNT_FUNC_DOWN_COUNT;
0166         break;
0167     default:
0168         /* should never reach this path */
0169         return -EINVAL;
0170     }
0171 
0172     return regmap_write_bits(priv->regmap16, QDECCTL, QDECCTL_QSRC,
0173                  qsrc << QDECCTL_QSRC_SHIFT);
0174 }
0175 
0176 static int ti_eqep_action_read(struct counter_device *counter,
0177                    struct counter_count *count,
0178                    struct counter_synapse *synapse,
0179                    enum counter_synapse_action *action)
0180 {
0181     struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter);
0182     enum counter_function function;
0183     u32 qdecctl;
0184     int err;
0185 
0186     err = ti_eqep_function_read(counter, count, &function);
0187     if (err)
0188         return err;
0189 
0190     switch (function) {
0191     case COUNTER_FUNCTION_QUADRATURE_X4:
0192         /* In quadrature mode, the rising and falling edge of both
0193          * QEPA and QEPB trigger QCLK.
0194          */
0195         *action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES;
0196         return 0;
0197     case COUNTER_FUNCTION_PULSE_DIRECTION:
0198         /* In direction-count mode only rising edge of QEPA is counted
0199          * and QEPB gives direction.
0200          */
0201         switch (synapse->signal->id) {
0202         case TI_EQEP_SIGNAL_QEPA:
0203             *action = COUNTER_SYNAPSE_ACTION_RISING_EDGE;
0204             return 0;
0205         case TI_EQEP_SIGNAL_QEPB:
0206             *action = COUNTER_SYNAPSE_ACTION_NONE;
0207             return 0;
0208         default:
0209             /* should never reach this path */
0210             return -EINVAL;
0211         }
0212     case COUNTER_FUNCTION_INCREASE:
0213     case COUNTER_FUNCTION_DECREASE:
0214         /* In up/down-count modes only QEPA is counted and QEPB is not
0215          * used.
0216          */
0217         switch (synapse->signal->id) {
0218         case TI_EQEP_SIGNAL_QEPA:
0219             err = regmap_read(priv->regmap16, QDECCTL, &qdecctl);
0220             if (err)
0221                 return err;
0222 
0223             if (qdecctl & QDECCTL_XCR)
0224                 *action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES;
0225             else
0226                 *action = COUNTER_SYNAPSE_ACTION_RISING_EDGE;
0227             return 0;
0228         case TI_EQEP_SIGNAL_QEPB:
0229             *action = COUNTER_SYNAPSE_ACTION_NONE;
0230             return 0;
0231         default:
0232             /* should never reach this path */
0233             return -EINVAL;
0234         }
0235     default:
0236         /* should never reach this path */
0237         return -EINVAL;
0238     }
0239 }
0240 
0241 static const struct counter_ops ti_eqep_counter_ops = {
0242     .count_read = ti_eqep_count_read,
0243     .count_write    = ti_eqep_count_write,
0244     .function_read  = ti_eqep_function_read,
0245     .function_write = ti_eqep_function_write,
0246     .action_read    = ti_eqep_action_read,
0247 };
0248 
0249 static int ti_eqep_position_ceiling_read(struct counter_device *counter,
0250                      struct counter_count *count,
0251                      u64 *ceiling)
0252 {
0253     struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter);
0254     u32 qposmax;
0255 
0256     regmap_read(priv->regmap32, QPOSMAX, &qposmax);
0257 
0258     *ceiling = qposmax;
0259 
0260     return 0;
0261 }
0262 
0263 static int ti_eqep_position_ceiling_write(struct counter_device *counter,
0264                       struct counter_count *count,
0265                       u64 ceiling)
0266 {
0267     struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter);
0268 
0269     if (ceiling != (u32)ceiling)
0270         return -ERANGE;
0271 
0272     regmap_write(priv->regmap32, QPOSMAX, ceiling);
0273 
0274     return 0;
0275 }
0276 
0277 static int ti_eqep_position_enable_read(struct counter_device *counter,
0278                     struct counter_count *count, u8 *enable)
0279 {
0280     struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter);
0281     u32 qepctl;
0282 
0283     regmap_read(priv->regmap16, QEPCTL, &qepctl);
0284 
0285     *enable = !!(qepctl & QEPCTL_PHEN);
0286 
0287     return 0;
0288 }
0289 
0290 static int ti_eqep_position_enable_write(struct counter_device *counter,
0291                      struct counter_count *count, u8 enable)
0292 {
0293     struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter);
0294 
0295     regmap_write_bits(priv->regmap16, QEPCTL, QEPCTL_PHEN, enable ? -1 : 0);
0296 
0297     return 0;
0298 }
0299 
0300 static struct counter_comp ti_eqep_position_ext[] = {
0301     COUNTER_COMP_CEILING(ti_eqep_position_ceiling_read,
0302                  ti_eqep_position_ceiling_write),
0303     COUNTER_COMP_ENABLE(ti_eqep_position_enable_read,
0304                 ti_eqep_position_enable_write),
0305 };
0306 
0307 static struct counter_signal ti_eqep_signals[] = {
0308     [TI_EQEP_SIGNAL_QEPA] = {
0309         .id = TI_EQEP_SIGNAL_QEPA,
0310         .name = "QEPA"
0311     },
0312     [TI_EQEP_SIGNAL_QEPB] = {
0313         .id = TI_EQEP_SIGNAL_QEPB,
0314         .name = "QEPB"
0315     },
0316 };
0317 
0318 static const enum counter_function ti_eqep_position_functions[] = {
0319     COUNTER_FUNCTION_QUADRATURE_X4,
0320     COUNTER_FUNCTION_PULSE_DIRECTION,
0321     COUNTER_FUNCTION_INCREASE,
0322     COUNTER_FUNCTION_DECREASE,
0323 };
0324 
0325 static const enum counter_synapse_action ti_eqep_position_synapse_actions[] = {
0326     COUNTER_SYNAPSE_ACTION_BOTH_EDGES,
0327     COUNTER_SYNAPSE_ACTION_RISING_EDGE,
0328     COUNTER_SYNAPSE_ACTION_NONE,
0329 };
0330 
0331 static struct counter_synapse ti_eqep_position_synapses[] = {
0332     {
0333         .actions_list   = ti_eqep_position_synapse_actions,
0334         .num_actions    = ARRAY_SIZE(ti_eqep_position_synapse_actions),
0335         .signal     = &ti_eqep_signals[TI_EQEP_SIGNAL_QEPA],
0336     },
0337     {
0338         .actions_list   = ti_eqep_position_synapse_actions,
0339         .num_actions    = ARRAY_SIZE(ti_eqep_position_synapse_actions),
0340         .signal     = &ti_eqep_signals[TI_EQEP_SIGNAL_QEPB],
0341     },
0342 };
0343 
0344 static struct counter_count ti_eqep_counts[] = {
0345     {
0346         .id     = 0,
0347         .name       = "QPOSCNT",
0348         .functions_list = ti_eqep_position_functions,
0349         .num_functions  = ARRAY_SIZE(ti_eqep_position_functions),
0350         .synapses   = ti_eqep_position_synapses,
0351         .num_synapses   = ARRAY_SIZE(ti_eqep_position_synapses),
0352         .ext        = ti_eqep_position_ext,
0353         .num_ext    = ARRAY_SIZE(ti_eqep_position_ext),
0354     },
0355 };
0356 
0357 static const struct regmap_config ti_eqep_regmap32_config = {
0358     .name = "32-bit",
0359     .reg_bits = 32,
0360     .val_bits = 32,
0361     .reg_stride = 4,
0362     .max_register = QUPRD,
0363 };
0364 
0365 static const struct regmap_config ti_eqep_regmap16_config = {
0366     .name = "16-bit",
0367     .reg_bits = 16,
0368     .val_bits = 16,
0369     .reg_stride = 2,
0370     .max_register = QCPRDLAT,
0371 };
0372 
0373 static int ti_eqep_probe(struct platform_device *pdev)
0374 {
0375     struct device *dev = &pdev->dev;
0376     struct counter_device *counter;
0377     struct ti_eqep_cnt *priv;
0378     void __iomem *base;
0379     int err;
0380 
0381     counter = devm_counter_alloc(dev, sizeof(*priv));
0382     if (!counter)
0383         return -ENOMEM;
0384     priv = counter_priv(counter);
0385 
0386     base = devm_platform_ioremap_resource(pdev, 0);
0387     if (IS_ERR(base))
0388         return PTR_ERR(base);
0389 
0390     priv->regmap32 = devm_regmap_init_mmio(dev, base,
0391                            &ti_eqep_regmap32_config);
0392     if (IS_ERR(priv->regmap32))
0393         return PTR_ERR(priv->regmap32);
0394 
0395     priv->regmap16 = devm_regmap_init_mmio(dev, base + 0x24,
0396                            &ti_eqep_regmap16_config);
0397     if (IS_ERR(priv->regmap16))
0398         return PTR_ERR(priv->regmap16);
0399 
0400     counter->name = dev_name(dev);
0401     counter->parent = dev;
0402     counter->ops = &ti_eqep_counter_ops;
0403     counter->counts = ti_eqep_counts;
0404     counter->num_counts = ARRAY_SIZE(ti_eqep_counts);
0405     counter->signals = ti_eqep_signals;
0406     counter->num_signals = ARRAY_SIZE(ti_eqep_signals);
0407 
0408     platform_set_drvdata(pdev, counter);
0409 
0410     /*
0411      * Need to make sure power is turned on. On AM33xx, this comes from the
0412      * parent PWMSS bus driver. On AM17xx, this comes from the PSC power
0413      * domain.
0414      */
0415     pm_runtime_enable(dev);
0416     pm_runtime_get_sync(dev);
0417 
0418     err = counter_add(counter);
0419     if (err < 0) {
0420         pm_runtime_put_sync(dev);
0421         pm_runtime_disable(dev);
0422         return err;
0423     }
0424 
0425     return 0;
0426 }
0427 
0428 static int ti_eqep_remove(struct platform_device *pdev)
0429 {
0430     struct counter_device *counter = platform_get_drvdata(pdev);
0431     struct device *dev = &pdev->dev;
0432 
0433     counter_unregister(counter);
0434     pm_runtime_put_sync(dev);
0435     pm_runtime_disable(dev);
0436 
0437     return 0;
0438 }
0439 
0440 static const struct of_device_id ti_eqep_of_match[] = {
0441     { .compatible = "ti,am3352-eqep", },
0442     { },
0443 };
0444 MODULE_DEVICE_TABLE(of, ti_eqep_of_match);
0445 
0446 static struct platform_driver ti_eqep_driver = {
0447     .probe = ti_eqep_probe,
0448     .remove = ti_eqep_remove,
0449     .driver = {
0450         .name = "ti-eqep-cnt",
0451         .of_match_table = ti_eqep_of_match,
0452     },
0453 };
0454 module_platform_driver(ti_eqep_driver);
0455 
0456 MODULE_AUTHOR("David Lechner <david@lechnology.com>");
0457 MODULE_DESCRIPTION("TI eQEP counter driver");
0458 MODULE_LICENSE("GPL v2");