563 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (C) 2019 David Lechner <david@lechnology.com>4 *5 * Counter driver for Texas Instruments Enhanced Quadrature Encoder Pulse (eQEP)6 */7 8#include <linux/bitops.h>9#include <linux/clk.h>10#include <linux/counter.h>11#include <linux/interrupt.h>12#include <linux/kernel.h>13#include <linux/mod_devicetable.h>14#include <linux/module.h>15#include <linux/platform_device.h>16#include <linux/pm_runtime.h>17#include <linux/regmap.h>18#include <linux/types.h>19 20/* 32-bit registers */21#define QPOSCNT 0x022#define QPOSINIT 0x423#define QPOSMAX 0x824#define QPOSCMP 0xc25#define QPOSILAT 0x1026#define QPOSSLAT 0x1427#define QPOSLAT 0x1828#define QUTMR 0x1c29#define QUPRD 0x2030 31/* 16-bit registers */32#define QWDTMR 0x0 /* 0x24 */33#define QWDPRD 0x2 /* 0x26 */34#define QDECCTL 0x4 /* 0x28 */35#define QEPCTL 0x6 /* 0x2a */36#define QCAPCTL 0x8 /* 0x2c */37#define QPOSCTL 0xa /* 0x2e */38#define QEINT 0xc /* 0x30 */39#define QFLG 0xe /* 0x32 */40#define QCLR 0x10 /* 0x34 */41#define QFRC 0x12 /* 0x36 */42#define QEPSTS 0x14 /* 0x38 */43#define QCTMR 0x16 /* 0x3a */44#define QCPRD 0x18 /* 0x3c */45#define QCTMRLAT 0x1a /* 0x3e */46#define QCPRDLAT 0x1c /* 0x40 */47 48#define QDECCTL_QSRC_SHIFT 1449#define QDECCTL_QSRC GENMASK(15, 14)50#define QDECCTL_SOEN BIT(13)51#define QDECCTL_SPSEL BIT(12)52#define QDECCTL_XCR BIT(11)53#define QDECCTL_SWAP BIT(10)54#define QDECCTL_IGATE BIT(9)55#define QDECCTL_QAP BIT(8)56#define QDECCTL_QBP BIT(7)57#define QDECCTL_QIP BIT(6)58#define QDECCTL_QSP BIT(5)59 60#define QEPCTL_FREE_SOFT GENMASK(15, 14)61#define QEPCTL_PCRM GENMASK(13, 12)62#define QEPCTL_SEI GENMASK(11, 10)63#define QEPCTL_IEI GENMASK(9, 8)64#define QEPCTL_SWI BIT(7)65#define QEPCTL_SEL BIT(6)66#define QEPCTL_IEL GENMASK(5, 4)67#define QEPCTL_PHEN BIT(3)68#define QEPCTL_QCLM BIT(2)69#define QEPCTL_UTE BIT(1)70#define QEPCTL_WDE BIT(0)71 72#define QEINT_UTO BIT(11)73#define QEINT_IEL BIT(10)74#define QEINT_SEL BIT(9)75#define QEINT_PCM BIT(8)76#define QEINT_PCR BIT(7)77#define QEINT_PCO BIT(6)78#define QEINT_PCU BIT(5)79#define QEINT_WTO BIT(4)80#define QEINT_QDC BIT(3)81#define QEINT_PHE BIT(2)82#define QEINT_PCE BIT(1)83 84#define QFLG_UTO BIT(11)85#define QFLG_IEL BIT(10)86#define QFLG_SEL BIT(9)87#define QFLG_PCM BIT(8)88#define QFLG_PCR BIT(7)89#define QFLG_PCO BIT(6)90#define QFLG_PCU BIT(5)91#define QFLG_WTO BIT(4)92#define QFLG_QDC BIT(3)93#define QFLG_PHE BIT(2)94#define QFLG_PCE BIT(1)95#define QFLG_INT BIT(0)96 97#define QCLR_UTO BIT(11)98#define QCLR_IEL BIT(10)99#define QCLR_SEL BIT(9)100#define QCLR_PCM BIT(8)101#define QCLR_PCR BIT(7)102#define QCLR_PCO BIT(6)103#define QCLR_PCU BIT(5)104#define QCLR_WTO BIT(4)105#define QCLR_QDC BIT(3)106#define QCLR_PHE BIT(2)107#define QCLR_PCE BIT(1)108#define QCLR_INT BIT(0)109 110/* EQEP Inputs */111enum {112 TI_EQEP_SIGNAL_QEPA, /* QEPA/XCLK */113 TI_EQEP_SIGNAL_QEPB, /* QEPB/XDIR */114};115 116/* Position Counter Input Modes */117enum ti_eqep_count_func {118 TI_EQEP_COUNT_FUNC_QUAD_COUNT,119 TI_EQEP_COUNT_FUNC_DIR_COUNT,120 TI_EQEP_COUNT_FUNC_UP_COUNT,121 TI_EQEP_COUNT_FUNC_DOWN_COUNT,122};123 124struct ti_eqep_cnt {125 struct regmap *regmap32;126 struct regmap *regmap16;127};128 129static int ti_eqep_count_read(struct counter_device *counter,130 struct counter_count *count, u64 *val)131{132 struct ti_eqep_cnt *priv = counter_priv(counter);133 u32 cnt;134 135 regmap_read(priv->regmap32, QPOSCNT, &cnt);136 *val = cnt;137 138 return 0;139}140 141static int ti_eqep_count_write(struct counter_device *counter,142 struct counter_count *count, u64 val)143{144 struct ti_eqep_cnt *priv = counter_priv(counter);145 u32 max;146 147 regmap_read(priv->regmap32, QPOSMAX, &max);148 if (val > max)149 return -EINVAL;150 151 return regmap_write(priv->regmap32, QPOSCNT, val);152}153 154static int ti_eqep_function_read(struct counter_device *counter,155 struct counter_count *count,156 enum counter_function *function)157{158 struct ti_eqep_cnt *priv = counter_priv(counter);159 u32 qdecctl;160 161 regmap_read(priv->regmap16, QDECCTL, &qdecctl);162 163 switch ((qdecctl & QDECCTL_QSRC) >> QDECCTL_QSRC_SHIFT) {164 case TI_EQEP_COUNT_FUNC_QUAD_COUNT:165 *function = COUNTER_FUNCTION_QUADRATURE_X4;166 break;167 case TI_EQEP_COUNT_FUNC_DIR_COUNT:168 *function = COUNTER_FUNCTION_PULSE_DIRECTION;169 break;170 case TI_EQEP_COUNT_FUNC_UP_COUNT:171 *function = COUNTER_FUNCTION_INCREASE;172 break;173 case TI_EQEP_COUNT_FUNC_DOWN_COUNT:174 *function = COUNTER_FUNCTION_DECREASE;175 break;176 }177 178 return 0;179}180 181static int ti_eqep_function_write(struct counter_device *counter,182 struct counter_count *count,183 enum counter_function function)184{185 struct ti_eqep_cnt *priv = counter_priv(counter);186 enum ti_eqep_count_func qsrc;187 188 switch (function) {189 case COUNTER_FUNCTION_QUADRATURE_X4:190 qsrc = TI_EQEP_COUNT_FUNC_QUAD_COUNT;191 break;192 case COUNTER_FUNCTION_PULSE_DIRECTION:193 qsrc = TI_EQEP_COUNT_FUNC_DIR_COUNT;194 break;195 case COUNTER_FUNCTION_INCREASE:196 qsrc = TI_EQEP_COUNT_FUNC_UP_COUNT;197 break;198 case COUNTER_FUNCTION_DECREASE:199 qsrc = TI_EQEP_COUNT_FUNC_DOWN_COUNT;200 break;201 default:202 /* should never reach this path */203 return -EINVAL;204 }205 206 return regmap_write_bits(priv->regmap16, QDECCTL, QDECCTL_QSRC,207 qsrc << QDECCTL_QSRC_SHIFT);208}209 210static int ti_eqep_action_read(struct counter_device *counter,211 struct counter_count *count,212 struct counter_synapse *synapse,213 enum counter_synapse_action *action)214{215 struct ti_eqep_cnt *priv = counter_priv(counter);216 enum counter_function function;217 u32 qdecctl;218 int err;219 220 err = ti_eqep_function_read(counter, count, &function);221 if (err)222 return err;223 224 switch (function) {225 case COUNTER_FUNCTION_QUADRATURE_X4:226 /* In quadrature mode, the rising and falling edge of both227 * QEPA and QEPB trigger QCLK.228 */229 *action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES;230 return 0;231 case COUNTER_FUNCTION_PULSE_DIRECTION:232 /* In direction-count mode only rising edge of QEPA is counted233 * and QEPB gives direction.234 */235 switch (synapse->signal->id) {236 case TI_EQEP_SIGNAL_QEPA:237 *action = COUNTER_SYNAPSE_ACTION_RISING_EDGE;238 return 0;239 case TI_EQEP_SIGNAL_QEPB:240 *action = COUNTER_SYNAPSE_ACTION_NONE;241 return 0;242 default:243 /* should never reach this path */244 return -EINVAL;245 }246 case COUNTER_FUNCTION_INCREASE:247 case COUNTER_FUNCTION_DECREASE:248 /* In up/down-count modes only QEPA is counted and QEPB is not249 * used.250 */251 switch (synapse->signal->id) {252 case TI_EQEP_SIGNAL_QEPA:253 err = regmap_read(priv->regmap16, QDECCTL, &qdecctl);254 if (err)255 return err;256 257 if (qdecctl & QDECCTL_XCR)258 *action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES;259 else260 *action = COUNTER_SYNAPSE_ACTION_RISING_EDGE;261 return 0;262 case TI_EQEP_SIGNAL_QEPB:263 *action = COUNTER_SYNAPSE_ACTION_NONE;264 return 0;265 default:266 /* should never reach this path */267 return -EINVAL;268 }269 default:270 /* should never reach this path */271 return -EINVAL;272 }273}274 275static int ti_eqep_events_configure(struct counter_device *counter)276{277 struct ti_eqep_cnt *priv = counter_priv(counter);278 struct counter_event_node *event_node;279 u32 qeint = 0;280 281 list_for_each_entry(event_node, &counter->events_list, l) {282 switch (event_node->event) {283 case COUNTER_EVENT_OVERFLOW:284 qeint |= QEINT_PCO;285 break;286 case COUNTER_EVENT_UNDERFLOW:287 qeint |= QEINT_PCU;288 break;289 }290 }291 292 return regmap_write(priv->regmap16, QEINT, qeint);293}294 295static int ti_eqep_watch_validate(struct counter_device *counter,296 const struct counter_watch *watch)297{298 switch (watch->event) {299 case COUNTER_EVENT_OVERFLOW:300 case COUNTER_EVENT_UNDERFLOW:301 if (watch->channel != 0)302 return -EINVAL;303 304 return 0;305 default:306 return -EINVAL;307 }308}309 310static const struct counter_ops ti_eqep_counter_ops = {311 .count_read = ti_eqep_count_read,312 .count_write = ti_eqep_count_write,313 .function_read = ti_eqep_function_read,314 .function_write = ti_eqep_function_write,315 .action_read = ti_eqep_action_read,316 .events_configure = ti_eqep_events_configure,317 .watch_validate = ti_eqep_watch_validate,318};319 320static int ti_eqep_position_ceiling_read(struct counter_device *counter,321 struct counter_count *count,322 u64 *ceiling)323{324 struct ti_eqep_cnt *priv = counter_priv(counter);325 u32 qposmax;326 327 regmap_read(priv->regmap32, QPOSMAX, &qposmax);328 329 *ceiling = qposmax;330 331 return 0;332}333 334static int ti_eqep_position_ceiling_write(struct counter_device *counter,335 struct counter_count *count,336 u64 ceiling)337{338 struct ti_eqep_cnt *priv = counter_priv(counter);339 340 if (ceiling != (u32)ceiling)341 return -ERANGE;342 343 regmap_write(priv->regmap32, QPOSMAX, ceiling);344 345 return 0;346}347 348static int ti_eqep_position_enable_read(struct counter_device *counter,349 struct counter_count *count, u8 *enable)350{351 struct ti_eqep_cnt *priv = counter_priv(counter);352 u32 qepctl;353 354 regmap_read(priv->regmap16, QEPCTL, &qepctl);355 356 *enable = !!(qepctl & QEPCTL_PHEN);357 358 return 0;359}360 361static int ti_eqep_position_enable_write(struct counter_device *counter,362 struct counter_count *count, u8 enable)363{364 struct ti_eqep_cnt *priv = counter_priv(counter);365 366 regmap_write_bits(priv->regmap16, QEPCTL, QEPCTL_PHEN, enable ? -1 : 0);367 368 return 0;369}370 371static struct counter_comp ti_eqep_position_ext[] = {372 COUNTER_COMP_CEILING(ti_eqep_position_ceiling_read,373 ti_eqep_position_ceiling_write),374 COUNTER_COMP_ENABLE(ti_eqep_position_enable_read,375 ti_eqep_position_enable_write),376};377 378static struct counter_signal ti_eqep_signals[] = {379 [TI_EQEP_SIGNAL_QEPA] = {380 .id = TI_EQEP_SIGNAL_QEPA,381 .name = "QEPA"382 },383 [TI_EQEP_SIGNAL_QEPB] = {384 .id = TI_EQEP_SIGNAL_QEPB,385 .name = "QEPB"386 },387};388 389static const enum counter_function ti_eqep_position_functions[] = {390 COUNTER_FUNCTION_QUADRATURE_X4,391 COUNTER_FUNCTION_PULSE_DIRECTION,392 COUNTER_FUNCTION_INCREASE,393 COUNTER_FUNCTION_DECREASE,394};395 396static const enum counter_synapse_action ti_eqep_position_synapse_actions[] = {397 COUNTER_SYNAPSE_ACTION_BOTH_EDGES,398 COUNTER_SYNAPSE_ACTION_RISING_EDGE,399 COUNTER_SYNAPSE_ACTION_NONE,400};401 402static struct counter_synapse ti_eqep_position_synapses[] = {403 {404 .actions_list = ti_eqep_position_synapse_actions,405 .num_actions = ARRAY_SIZE(ti_eqep_position_synapse_actions),406 .signal = &ti_eqep_signals[TI_EQEP_SIGNAL_QEPA],407 },408 {409 .actions_list = ti_eqep_position_synapse_actions,410 .num_actions = ARRAY_SIZE(ti_eqep_position_synapse_actions),411 .signal = &ti_eqep_signals[TI_EQEP_SIGNAL_QEPB],412 },413};414 415static struct counter_count ti_eqep_counts[] = {416 {417 .id = 0,418 .name = "QPOSCNT",419 .functions_list = ti_eqep_position_functions,420 .num_functions = ARRAY_SIZE(ti_eqep_position_functions),421 .synapses = ti_eqep_position_synapses,422 .num_synapses = ARRAY_SIZE(ti_eqep_position_synapses),423 .ext = ti_eqep_position_ext,424 .num_ext = ARRAY_SIZE(ti_eqep_position_ext),425 },426};427 428static irqreturn_t ti_eqep_irq_handler(int irq, void *dev_id)429{430 struct counter_device *counter = dev_id;431 struct ti_eqep_cnt *priv = counter_priv(counter);432 u32 qflg;433 434 regmap_read(priv->regmap16, QFLG, &qflg);435 436 if (qflg & QFLG_PCO)437 counter_push_event(counter, COUNTER_EVENT_OVERFLOW, 0);438 439 if (qflg & QFLG_PCU)440 counter_push_event(counter, COUNTER_EVENT_UNDERFLOW, 0);441 442 regmap_write(priv->regmap16, QCLR, qflg);443 444 return IRQ_HANDLED;445}446 447static const struct regmap_config ti_eqep_regmap32_config = {448 .name = "32-bit",449 .reg_bits = 32,450 .val_bits = 32,451 .reg_stride = 4,452 .max_register = QUPRD,453};454 455static const struct regmap_config ti_eqep_regmap16_config = {456 .name = "16-bit",457 .reg_bits = 16,458 .val_bits = 16,459 .reg_stride = 2,460 .max_register = QCPRDLAT,461};462 463static int ti_eqep_probe(struct platform_device *pdev)464{465 struct device *dev = &pdev->dev;466 struct counter_device *counter;467 struct ti_eqep_cnt *priv;468 void __iomem *base;469 struct clk *clk;470 int err, irq;471 472 counter = devm_counter_alloc(dev, sizeof(*priv));473 if (!counter)474 return -ENOMEM;475 priv = counter_priv(counter);476 477 base = devm_platform_ioremap_resource(pdev, 0);478 if (IS_ERR(base))479 return PTR_ERR(base);480 481 priv->regmap32 = devm_regmap_init_mmio(dev, base,482 &ti_eqep_regmap32_config);483 if (IS_ERR(priv->regmap32))484 return PTR_ERR(priv->regmap32);485 486 priv->regmap16 = devm_regmap_init_mmio(dev, base + 0x24,487 &ti_eqep_regmap16_config);488 if (IS_ERR(priv->regmap16))489 return PTR_ERR(priv->regmap16);490 491 irq = platform_get_irq(pdev, 0);492 if (irq < 0)493 return irq;494 495 err = devm_request_threaded_irq(dev, irq, NULL, ti_eqep_irq_handler,496 IRQF_ONESHOT, dev_name(dev), counter);497 if (err < 0)498 return dev_err_probe(dev, err, "failed to request IRQ\n");499 500 counter->name = dev_name(dev);501 counter->parent = dev;502 counter->ops = &ti_eqep_counter_ops;503 counter->counts = ti_eqep_counts;504 counter->num_counts = ARRAY_SIZE(ti_eqep_counts);505 counter->signals = ti_eqep_signals;506 counter->num_signals = ARRAY_SIZE(ti_eqep_signals);507 508 platform_set_drvdata(pdev, counter);509 510 /*511 * Need to make sure power is turned on. On AM33xx, this comes from the512 * parent PWMSS bus driver. On AM17xx, this comes from the PSC power513 * domain.514 */515 pm_runtime_enable(dev);516 pm_runtime_get_sync(dev);517 518 clk = devm_clk_get_enabled(dev, NULL);519 if (IS_ERR(clk))520 return dev_err_probe(dev, PTR_ERR(clk), "failed to enable clock\n");521 522 err = counter_add(counter);523 if (err < 0) {524 pm_runtime_put_sync(dev);525 pm_runtime_disable(dev);526 return err;527 }528 529 return 0;530}531 532static void ti_eqep_remove(struct platform_device *pdev)533{534 struct counter_device *counter = platform_get_drvdata(pdev);535 struct device *dev = &pdev->dev;536 537 counter_unregister(counter);538 pm_runtime_put_sync(dev);539 pm_runtime_disable(dev);540}541 542static const struct of_device_id ti_eqep_of_match[] = {543 { .compatible = "ti,am3352-eqep", },544 { .compatible = "ti,am62-eqep", },545 { },546};547MODULE_DEVICE_TABLE(of, ti_eqep_of_match);548 549static struct platform_driver ti_eqep_driver = {550 .probe = ti_eqep_probe,551 .remove_new = ti_eqep_remove,552 .driver = {553 .name = "ti-eqep-cnt",554 .of_match_table = ti_eqep_of_match,555 },556};557module_platform_driver(ti_eqep_driver);558 559MODULE_AUTHOR("David Lechner <david@lechnology.com>");560MODULE_DESCRIPTION("TI eQEP counter driver");561MODULE_LICENSE("GPL v2");562MODULE_IMPORT_NS(COUNTER);563