1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2020 Microchip 4 * 5 * Author: Kamel Bouhara <kamel.bouhara@bootlin.com> 6 */ 7 #include <linux/clk.h> 8 #include <linux/counter.h> 9 #include <linux/interrupt.h> 10 #include <linux/mfd/syscon.h> 11 #include <linux/module.h> 12 #include <linux/mutex.h> 13 #include <linux/of.h> 14 #include <linux/of_irq.h> 15 #include <linux/platform_device.h> 16 #include <linux/regmap.h> 17 #include <uapi/linux/counter/microchip-tcb-capture.h> 18 #include <soc/at91/atmel_tcb.h> 19 20 #define ATMEL_TC_CMR_MASK (ATMEL_TC_LDRA_RISING | ATMEL_TC_LDRB_FALLING | \ 21 ATMEL_TC_ETRGEDG_RISING | ATMEL_TC_LDBDIS | \ 22 ATMEL_TC_LDBSTOP) 23 24 #define ATMEL_TC_DEF_IRQS (ATMEL_TC_ETRGS | ATMEL_TC_COVFS | \ 25 ATMEL_TC_LDRAS | ATMEL_TC_LDRBS | ATMEL_TC_CPCS) 26 27 #define ATMEL_TC_QDEN BIT(8) 28 #define ATMEL_TC_POSEN BIT(9) 29 30 struct mchp_tc_data { 31 const struct atmel_tcb_config *tc_cfg; 32 struct regmap *regmap; 33 int qdec_mode; 34 int num_channels; 35 int channel[2]; 36 }; 37 38 static const enum counter_function mchp_tc_count_functions[] = { 39 COUNTER_FUNCTION_INCREASE, 40 COUNTER_FUNCTION_QUADRATURE_X4, 41 }; 42 43 static const enum counter_synapse_action mchp_tc_synapse_actions[] = { 44 COUNTER_SYNAPSE_ACTION_NONE, 45 COUNTER_SYNAPSE_ACTION_RISING_EDGE, 46 COUNTER_SYNAPSE_ACTION_FALLING_EDGE, 47 COUNTER_SYNAPSE_ACTION_BOTH_EDGES, 48 }; 49 50 static struct counter_signal mchp_tc_count_signals[] = { 51 { 52 .id = 0, 53 .name = "Channel A", 54 }, 55 { 56 .id = 1, 57 .name = "Channel B", 58 } 59 }; 60 61 static struct counter_synapse mchp_tc_count_synapses[] = { 62 { 63 .actions_list = mchp_tc_synapse_actions, 64 .num_actions = ARRAY_SIZE(mchp_tc_synapse_actions), 65 .signal = &mchp_tc_count_signals[0] 66 }, 67 { 68 .actions_list = mchp_tc_synapse_actions, 69 .num_actions = ARRAY_SIZE(mchp_tc_synapse_actions), 70 .signal = &mchp_tc_count_signals[1] 71 } 72 }; 73 74 static int mchp_tc_count_function_read(struct counter_device *counter, 75 struct counter_count *count, 76 enum counter_function *function) 77 { 78 struct mchp_tc_data *const priv = counter_priv(counter); 79 80 if (priv->qdec_mode) 81 *function = COUNTER_FUNCTION_QUADRATURE_X4; 82 else 83 *function = COUNTER_FUNCTION_INCREASE; 84 85 return 0; 86 } 87 88 static int mchp_tc_count_function_write(struct counter_device *counter, 89 struct counter_count *count, 90 enum counter_function function) 91 { 92 struct mchp_tc_data *const priv = counter_priv(counter); 93 u32 bmr, cmr; 94 95 regmap_read(priv->regmap, ATMEL_TC_BMR, &bmr); 96 regmap_read(priv->regmap, ATMEL_TC_REG(priv->channel[0], CMR), &cmr); 97 98 /* Set capture mode */ 99 cmr &= ~ATMEL_TC_WAVE; 100 101 switch (function) { 102 case COUNTER_FUNCTION_INCREASE: 103 priv->qdec_mode = 0; 104 /* Set highest rate based on whether soc has gclk or not */ 105 bmr &= ~(ATMEL_TC_QDEN | ATMEL_TC_POSEN); 106 if (!priv->tc_cfg->has_gclk) 107 cmr |= ATMEL_TC_TIMER_CLOCK2; 108 else 109 cmr |= ATMEL_TC_TIMER_CLOCK1; 110 /* Setup the period capture mode */ 111 cmr |= ATMEL_TC_CMR_MASK; 112 cmr &= ~(ATMEL_TC_ABETRG | ATMEL_TC_XC0); 113 break; 114 case COUNTER_FUNCTION_QUADRATURE_X4: 115 if (!priv->tc_cfg->has_qdec) 116 return -EINVAL; 117 /* In QDEC mode settings both channels 0 and 1 are required */ 118 if (priv->num_channels < 2 || priv->channel[0] != 0 || 119 priv->channel[1] != 1) { 120 pr_err("Invalid channels number or id for quadrature mode\n"); 121 return -EINVAL; 122 } 123 priv->qdec_mode = 1; 124 bmr |= ATMEL_TC_QDEN | ATMEL_TC_POSEN; 125 cmr |= ATMEL_TC_ETRGEDG_RISING | ATMEL_TC_ABETRG | ATMEL_TC_XC0; 126 break; 127 default: 128 /* should never reach this path */ 129 return -EINVAL; 130 } 131 132 regmap_write(priv->regmap, ATMEL_TC_BMR, bmr); 133 regmap_write(priv->regmap, ATMEL_TC_REG(priv->channel[0], CMR), cmr); 134 135 /* Enable clock and trigger counter */ 136 regmap_write(priv->regmap, ATMEL_TC_REG(priv->channel[0], CCR), 137 ATMEL_TC_CLKEN | ATMEL_TC_SWTRG); 138 139 if (priv->qdec_mode) { 140 regmap_write(priv->regmap, 141 ATMEL_TC_REG(priv->channel[1], CMR), cmr); 142 regmap_write(priv->regmap, 143 ATMEL_TC_REG(priv->channel[1], CCR), 144 ATMEL_TC_CLKEN | ATMEL_TC_SWTRG); 145 } 146 147 return 0; 148 } 149 150 static int mchp_tc_count_signal_read(struct counter_device *counter, 151 struct counter_signal *signal, 152 enum counter_signal_level *lvl) 153 { 154 struct mchp_tc_data *const priv = counter_priv(counter); 155 bool sigstatus; 156 u32 sr; 157 158 regmap_read(priv->regmap, ATMEL_TC_REG(priv->channel[0], SR), &sr); 159 160 if (signal->id == 1) 161 sigstatus = (sr & ATMEL_TC_MTIOB); 162 else 163 sigstatus = (sr & ATMEL_TC_MTIOA); 164 165 *lvl = sigstatus ? COUNTER_SIGNAL_LEVEL_HIGH : COUNTER_SIGNAL_LEVEL_LOW; 166 167 return 0; 168 } 169 170 static int mchp_tc_count_action_read(struct counter_device *counter, 171 struct counter_count *count, 172 struct counter_synapse *synapse, 173 enum counter_synapse_action *action) 174 { 175 struct mchp_tc_data *const priv = counter_priv(counter); 176 u32 cmr; 177 178 if (priv->qdec_mode) { 179 *action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES; 180 return 0; 181 } 182 183 /* Only TIOA signal is evaluated in non-QDEC mode */ 184 if (synapse->signal->id != 0) { 185 *action = COUNTER_SYNAPSE_ACTION_NONE; 186 return 0; 187 } 188 189 regmap_read(priv->regmap, ATMEL_TC_REG(priv->channel[0], CMR), &cmr); 190 191 switch (cmr & ATMEL_TC_ETRGEDG) { 192 default: 193 *action = COUNTER_SYNAPSE_ACTION_NONE; 194 break; 195 case ATMEL_TC_ETRGEDG_RISING: 196 *action = COUNTER_SYNAPSE_ACTION_RISING_EDGE; 197 break; 198 case ATMEL_TC_ETRGEDG_FALLING: 199 *action = COUNTER_SYNAPSE_ACTION_FALLING_EDGE; 200 break; 201 case ATMEL_TC_ETRGEDG_BOTH: 202 *action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES; 203 break; 204 } 205 206 return 0; 207 } 208 209 static int mchp_tc_count_action_write(struct counter_device *counter, 210 struct counter_count *count, 211 struct counter_synapse *synapse, 212 enum counter_synapse_action action) 213 { 214 struct mchp_tc_data *const priv = counter_priv(counter); 215 u32 edge = ATMEL_TC_ETRGEDG_NONE; 216 217 /* QDEC mode is rising edge only; only TIOA handled in non-QDEC mode */ 218 if (priv->qdec_mode || synapse->signal->id != 0) 219 return -EINVAL; 220 221 switch (action) { 222 case COUNTER_SYNAPSE_ACTION_NONE: 223 edge = ATMEL_TC_ETRGEDG_NONE; 224 break; 225 case COUNTER_SYNAPSE_ACTION_RISING_EDGE: 226 edge = ATMEL_TC_ETRGEDG_RISING; 227 break; 228 case COUNTER_SYNAPSE_ACTION_FALLING_EDGE: 229 edge = ATMEL_TC_ETRGEDG_FALLING; 230 break; 231 case COUNTER_SYNAPSE_ACTION_BOTH_EDGES: 232 edge = ATMEL_TC_ETRGEDG_BOTH; 233 break; 234 default: 235 /* should never reach this path */ 236 return -EINVAL; 237 } 238 239 return regmap_write_bits(priv->regmap, 240 ATMEL_TC_REG(priv->channel[0], CMR), 241 ATMEL_TC_ETRGEDG, edge); 242 } 243 244 static int mchp_tc_count_read(struct counter_device *counter, 245 struct counter_count *count, u64 *val) 246 { 247 struct mchp_tc_data *const priv = counter_priv(counter); 248 u32 cnt; 249 250 regmap_read(priv->regmap, ATMEL_TC_REG(priv->channel[0], CV), &cnt); 251 *val = cnt; 252 253 return 0; 254 } 255 256 static int mchp_tc_count_cap_read(struct counter_device *counter, 257 struct counter_count *count, size_t idx, u64 *val) 258 { 259 struct mchp_tc_data *const priv = counter_priv(counter); 260 u32 cnt; 261 int ret; 262 263 switch (idx) { 264 case COUNTER_MCHP_EXCAP_RA: 265 ret = regmap_read(priv->regmap, ATMEL_TC_REG(priv->channel[0], RA), &cnt); 266 break; 267 case COUNTER_MCHP_EXCAP_RB: 268 ret = regmap_read(priv->regmap, ATMEL_TC_REG(priv->channel[0], RB), &cnt); 269 break; 270 default: 271 return -EINVAL; 272 } 273 274 if (ret < 0) 275 return ret; 276 277 *val = cnt; 278 279 return 0; 280 } 281 282 static int mchp_tc_count_cap_write(struct counter_device *counter, 283 struct counter_count *count, size_t idx, u64 val) 284 { 285 struct mchp_tc_data *const priv = counter_priv(counter); 286 int ret; 287 288 if (val > U32_MAX) 289 return -ERANGE; 290 291 switch (idx) { 292 case COUNTER_MCHP_EXCAP_RA: 293 ret = regmap_write(priv->regmap, ATMEL_TC_REG(priv->channel[0], RA), val); 294 break; 295 case COUNTER_MCHP_EXCAP_RB: 296 ret = regmap_write(priv->regmap, ATMEL_TC_REG(priv->channel[0], RB), val); 297 break; 298 default: 299 return -EINVAL; 300 } 301 302 return ret; 303 } 304 305 static int mchp_tc_count_compare_read(struct counter_device *counter, struct counter_count *count, 306 u64 *val) 307 { 308 struct mchp_tc_data *const priv = counter_priv(counter); 309 u32 cnt; 310 int ret; 311 312 ret = regmap_read(priv->regmap, ATMEL_TC_REG(priv->channel[0], RC), &cnt); 313 if (ret < 0) 314 return ret; 315 316 *val = cnt; 317 318 return 0; 319 } 320 321 static int mchp_tc_count_compare_write(struct counter_device *counter, struct counter_count *count, 322 u64 val) 323 { 324 struct mchp_tc_data *const priv = counter_priv(counter); 325 326 if (val > U32_MAX) 327 return -ERANGE; 328 329 return regmap_write(priv->regmap, ATMEL_TC_REG(priv->channel[0], RC), val); 330 } 331 332 static DEFINE_COUNTER_ARRAY_CAPTURE(mchp_tc_cnt_cap_array, 2); 333 334 static struct counter_comp mchp_tc_count_ext[] = { 335 COUNTER_COMP_ARRAY_CAPTURE(mchp_tc_count_cap_read, mchp_tc_count_cap_write, 336 mchp_tc_cnt_cap_array), 337 COUNTER_COMP_COMPARE(mchp_tc_count_compare_read, mchp_tc_count_compare_write), 338 }; 339 340 static struct counter_count mchp_tc_counts[] = { 341 { 342 .id = 0, 343 .name = "Timer Counter", 344 .functions_list = mchp_tc_count_functions, 345 .num_functions = ARRAY_SIZE(mchp_tc_count_functions), 346 .synapses = mchp_tc_count_synapses, 347 .num_synapses = ARRAY_SIZE(mchp_tc_count_synapses), 348 .ext = mchp_tc_count_ext, 349 .num_ext = ARRAY_SIZE(mchp_tc_count_ext), 350 }, 351 }; 352 353 static const struct counter_ops mchp_tc_ops = { 354 .signal_read = mchp_tc_count_signal_read, 355 .count_read = mchp_tc_count_read, 356 .function_read = mchp_tc_count_function_read, 357 .function_write = mchp_tc_count_function_write, 358 .action_read = mchp_tc_count_action_read, 359 .action_write = mchp_tc_count_action_write 360 }; 361 362 static const struct atmel_tcb_config tcb_rm9200_config = { 363 .counter_width = 16, 364 }; 365 366 static const struct atmel_tcb_config tcb_sam9x5_config = { 367 .counter_width = 32, 368 }; 369 370 static const struct atmel_tcb_config tcb_sama5d2_config = { 371 .counter_width = 32, 372 .has_gclk = true, 373 .has_qdec = true, 374 }; 375 376 static const struct atmel_tcb_config tcb_sama5d3_config = { 377 .counter_width = 32, 378 .has_qdec = true, 379 }; 380 381 static const struct of_device_id atmel_tc_of_match[] = { 382 { .compatible = "atmel,at91rm9200-tcb", .data = &tcb_rm9200_config, }, 383 { .compatible = "atmel,at91sam9x5-tcb", .data = &tcb_sam9x5_config, }, 384 { .compatible = "atmel,sama5d2-tcb", .data = &tcb_sama5d2_config, }, 385 { .compatible = "atmel,sama5d3-tcb", .data = &tcb_sama5d3_config, }, 386 { /* sentinel */ } 387 }; 388 389 static irqreturn_t mchp_tc_isr(int irq, void *dev_id) 390 { 391 struct counter_device *const counter = dev_id; 392 struct mchp_tc_data *const priv = counter_priv(counter); 393 u32 sr, mask; 394 395 regmap_read(priv->regmap, ATMEL_TC_REG(priv->channel[0], SR), &sr); 396 regmap_read(priv->regmap, ATMEL_TC_REG(priv->channel[0], IMR), &mask); 397 398 sr &= mask; 399 if (!(sr & ATMEL_TC_ALL_IRQ)) 400 return IRQ_NONE; 401 402 if (sr & ATMEL_TC_ETRGS) 403 counter_push_event(counter, COUNTER_EVENT_CHANGE_OF_STATE, 404 COUNTER_MCHP_EVCHN_CV); 405 if (sr & ATMEL_TC_LDRAS) 406 counter_push_event(counter, COUNTER_EVENT_CAPTURE, 407 COUNTER_MCHP_EVCHN_RA); 408 if (sr & ATMEL_TC_LDRBS) 409 counter_push_event(counter, COUNTER_EVENT_CAPTURE, 410 COUNTER_MCHP_EVCHN_RB); 411 if (sr & ATMEL_TC_CPCS) 412 counter_push_event(counter, COUNTER_EVENT_THRESHOLD, 413 COUNTER_MCHP_EVCHN_RC); 414 if (sr & ATMEL_TC_COVFS) 415 counter_push_event(counter, COUNTER_EVENT_OVERFLOW, 416 COUNTER_MCHP_EVCHN_CV); 417 418 return IRQ_HANDLED; 419 } 420 421 static void mchp_tc_irq_remove(void *ptr) 422 { 423 struct mchp_tc_data *priv = ptr; 424 425 regmap_write(priv->regmap, ATMEL_TC_REG(priv->channel[0], IDR), ATMEL_TC_DEF_IRQS); 426 } 427 428 static int mchp_tc_irq_enable(struct counter_device *const counter, int irq) 429 { 430 struct mchp_tc_data *const priv = counter_priv(counter); 431 int ret = devm_request_irq(counter->parent, irq, mchp_tc_isr, 0, 432 dev_name(counter->parent), counter); 433 434 if (ret < 0) 435 return ret; 436 437 ret = regmap_write(priv->regmap, ATMEL_TC_REG(priv->channel[0], IER), ATMEL_TC_DEF_IRQS); 438 if (ret < 0) 439 return ret; 440 441 ret = devm_add_action_or_reset(counter->parent, mchp_tc_irq_remove, priv); 442 if (ret < 0) 443 return ret; 444 445 return 0; 446 } 447 448 static void mchp_tc_clk_remove(void *ptr) 449 { 450 clk_disable_unprepare((struct clk *)ptr); 451 } 452 453 static int mchp_tc_probe(struct platform_device *pdev) 454 { 455 struct device_node *np = pdev->dev.of_node; 456 const struct atmel_tcb_config *tcb_config; 457 const struct of_device_id *match; 458 struct counter_device *counter; 459 struct mchp_tc_data *priv; 460 char clk_name[7]; 461 struct regmap *regmap; 462 struct clk *clk[3]; 463 int channel; 464 int ret, i; 465 466 counter = devm_counter_alloc(&pdev->dev, sizeof(*priv)); 467 if (!counter) 468 return -ENOMEM; 469 priv = counter_priv(counter); 470 471 match = of_match_node(atmel_tc_of_match, np->parent); 472 tcb_config = match->data; 473 if (!tcb_config) { 474 dev_err(&pdev->dev, "No matching parent node found\n"); 475 return -ENODEV; 476 } 477 478 regmap = syscon_node_to_regmap(np->parent); 479 if (IS_ERR(regmap)) 480 return PTR_ERR(regmap); 481 482 /* max. channels number is 2 when in QDEC mode */ 483 priv->num_channels = of_property_count_u32_elems(np, "reg"); 484 if (priv->num_channels < 0) { 485 dev_err(&pdev->dev, "Invalid or missing channel\n"); 486 return -EINVAL; 487 } 488 489 /* Register channels and initialize clocks */ 490 for (i = 0; i < priv->num_channels; i++) { 491 ret = of_property_read_u32_index(np, "reg", i, &channel); 492 if (ret < 0 || channel > 2) 493 return -ENODEV; 494 495 priv->channel[i] = channel; 496 497 snprintf(clk_name, sizeof(clk_name), "t%d_clk", channel); 498 499 clk[i] = of_clk_get_by_name(np->parent, clk_name); 500 if (IS_ERR(clk[i])) { 501 /* Fallback to t0_clk */ 502 clk[i] = of_clk_get_by_name(np->parent, "t0_clk"); 503 if (IS_ERR(clk[i])) 504 return PTR_ERR(clk[i]); 505 } 506 507 ret = clk_prepare_enable(clk[i]); 508 if (ret) 509 return ret; 510 511 ret = devm_add_action_or_reset(&pdev->dev, 512 mchp_tc_clk_remove, 513 clk[i]); 514 if (ret) 515 return ret; 516 517 dev_dbg(&pdev->dev, 518 "Initialized capture mode on channel %d\n", 519 channel); 520 } 521 522 /* Disable Quadrature Decoder and position measure */ 523 ret = regmap_update_bits(regmap, ATMEL_TC_BMR, ATMEL_TC_QDEN | ATMEL_TC_POSEN, 0); 524 if (ret) 525 return ret; 526 527 /* Setup the period capture mode */ 528 ret = regmap_update_bits(regmap, ATMEL_TC_REG(priv->channel[0], CMR), 529 ATMEL_TC_WAVE | ATMEL_TC_ABETRG | ATMEL_TC_CMR_MASK | 530 ATMEL_TC_TCCLKS, 531 ATMEL_TC_CMR_MASK); 532 if (ret) 533 return ret; 534 535 /* Enable clock and trigger counter */ 536 ret = regmap_write(regmap, ATMEL_TC_REG(priv->channel[0], CCR), 537 ATMEL_TC_CLKEN | ATMEL_TC_SWTRG); 538 if (ret) 539 return ret; 540 541 priv->tc_cfg = tcb_config; 542 priv->regmap = regmap; 543 counter->name = dev_name(&pdev->dev); 544 counter->parent = &pdev->dev; 545 counter->ops = &mchp_tc_ops; 546 counter->num_counts = ARRAY_SIZE(mchp_tc_counts); 547 counter->counts = mchp_tc_counts; 548 counter->num_signals = ARRAY_SIZE(mchp_tc_count_signals); 549 counter->signals = mchp_tc_count_signals; 550 551 i = of_irq_get(np->parent, 0); 552 if (i == -EPROBE_DEFER) 553 return -EPROBE_DEFER; 554 if (i > 0) { 555 ret = mchp_tc_irq_enable(counter, i); 556 if (ret < 0) 557 return dev_err_probe(&pdev->dev, ret, "Failed to set up IRQ"); 558 } 559 560 ret = devm_counter_add(&pdev->dev, counter); 561 if (ret < 0) 562 return dev_err_probe(&pdev->dev, ret, "Failed to add counter\n"); 563 564 return 0; 565 } 566 567 static const struct of_device_id mchp_tc_dt_ids[] = { 568 { .compatible = "microchip,tcb-capture", }, 569 { /* sentinel */ }, 570 }; 571 MODULE_DEVICE_TABLE(of, mchp_tc_dt_ids); 572 573 static struct platform_driver mchp_tc_driver = { 574 .probe = mchp_tc_probe, 575 .driver = { 576 .name = "microchip-tcb-capture", 577 .of_match_table = mchp_tc_dt_ids, 578 }, 579 }; 580 module_platform_driver(mchp_tc_driver); 581 582 MODULE_AUTHOR("Kamel Bouhara <kamel.bouhara@bootlin.com>"); 583 MODULE_DESCRIPTION("Microchip TCB Capture driver"); 584 MODULE_LICENSE("GPL v2"); 585 MODULE_IMPORT_NS("COUNTER"); 586