Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'counter-updates-for-6.11' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/wbg/counter into char-misc-next

William writes:

Counter updates for 6.11

Primarily consists of cleanups and updates for ti-eqep; ti-eqep now
supports over/underflow events and can be build for K3 devices. In
addition, ftm-quaddec is updated to add a missing MODULE_DESCRIPTION()
macro.

* tag 'counter-updates-for-6.11' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/wbg/counter:
counter: ti-eqep: Allow eQEP driver to be built for K3 devices
counter/ti-eqep: Add new ti-am62-eqep compatible
dt-bindings: counter: Add new ti,am62-eqep compatible
counter: ti-eqep: remove counter_priv() wrapper
counter: ti-eqep: remove unused struct member
counter: ti-eqep: implement over/underflow events
counter: ftm-quaddec: add missing MODULE_DESCRIPTION() macro

+139 -22
+22 -5
Documentation/devicetree/bindings/counter/ti-eqep.yaml
··· 11 11 12 12 properties: 13 13 compatible: 14 - const: ti,am3352-eqep 14 + enum: 15 + - ti,am3352-eqep 16 + - ti,am62-eqep 15 17 16 18 reg: 17 19 maxItems: 1 ··· 23 21 maxItems: 1 24 22 25 23 clocks: 26 - description: The clock that determines the SYSCLKOUT rate for the eQEP 27 - peripheral. 24 + description: The functional and interface clock that determines the clock 25 + rate for the eQEP peripheral. 28 26 maxItems: 1 29 27 30 28 clock-names: 31 29 const: sysclkout 30 + 31 + power-domains: 32 + maxItems: 1 33 + 34 + allOf: 35 + - if: 36 + properties: 37 + compatible: 38 + contains: 39 + enum: 40 + - ti,am62-eqep 41 + then: 42 + properties: 43 + clock-names: false 44 + 45 + required: 46 + - power-domains 32 47 33 48 required: 34 49 - compatible 35 50 - reg 36 51 - interrupts 37 52 - clocks 38 - - clock-names 39 53 40 54 additionalProperties: false 41 55 ··· 61 43 compatible = "ti,am3352-eqep"; 62 44 reg = <0x180 0x80>; 63 45 clocks = <&l4ls_gclk>; 64 - clock-names = "sysclkout"; 65 46 interrupts = <79>; 66 47 }; 67 48
+1 -1
drivers/counter/Kconfig
··· 138 138 139 139 config TI_EQEP 140 140 tristate "TI eQEP counter driver" 141 - depends on (SOC_AM33XX || COMPILE_TEST) 141 + depends on SOC_AM33XX || ARCH_K3 || COMPILE_TEST 142 142 select REGMAP_MMIO 143 143 help 144 144 Select this option to enable the Texas Instruments Enhanced Quadrature
+1
drivers/counter/ftm-quaddec.c
··· 322 322 323 323 module_platform_driver(ftm_quaddec_driver); 324 324 325 + MODULE_DESCRIPTION("Flex Timer Module Quadrature decoder"); 325 326 MODULE_LICENSE("GPL"); 326 327 MODULE_AUTHOR("Kjeld Flarup <kfa@deif.com>"); 327 328 MODULE_AUTHOR("Patrick Havelange <patrick.havelange@essensium.com>");
+115 -16
drivers/counter/ti-eqep.c
··· 8 8 #include <linux/bitops.h> 9 9 #include <linux/clk.h> 10 10 #include <linux/counter.h> 11 + #include <linux/interrupt.h> 11 12 #include <linux/kernel.h> 12 13 #include <linux/mod_devicetable.h> 13 14 #include <linux/module.h> ··· 69 68 #define QEPCTL_UTE BIT(1) 70 69 #define QEPCTL_WDE BIT(0) 71 70 71 + #define QEINT_UTO BIT(11) 72 + #define QEINT_IEL BIT(10) 73 + #define QEINT_SEL BIT(9) 74 + #define QEINT_PCM BIT(8) 75 + #define QEINT_PCR BIT(7) 76 + #define QEINT_PCO BIT(6) 77 + #define QEINT_PCU BIT(5) 78 + #define QEINT_WTO BIT(4) 79 + #define QEINT_QDC BIT(3) 80 + #define QEINT_PHE BIT(2) 81 + #define QEINT_PCE BIT(1) 82 + 83 + #define QFLG_UTO BIT(11) 84 + #define QFLG_IEL BIT(10) 85 + #define QFLG_SEL BIT(9) 86 + #define QFLG_PCM BIT(8) 87 + #define QFLG_PCR BIT(7) 88 + #define QFLG_PCO BIT(6) 89 + #define QFLG_PCU BIT(5) 90 + #define QFLG_WTO BIT(4) 91 + #define QFLG_QDC BIT(3) 92 + #define QFLG_PHE BIT(2) 93 + #define QFLG_PCE BIT(1) 94 + #define QFLG_INT BIT(0) 95 + 96 + #define QCLR_UTO BIT(11) 97 + #define QCLR_IEL BIT(10) 98 + #define QCLR_SEL BIT(9) 99 + #define QCLR_PCM BIT(8) 100 + #define QCLR_PCR BIT(7) 101 + #define QCLR_PCO BIT(6) 102 + #define QCLR_PCU BIT(5) 103 + #define QCLR_WTO BIT(4) 104 + #define QCLR_QDC BIT(3) 105 + #define QCLR_PHE BIT(2) 106 + #define QCLR_PCE BIT(1) 107 + #define QCLR_INT BIT(0) 108 + 72 109 /* EQEP Inputs */ 73 110 enum { 74 111 TI_EQEP_SIGNAL_QEPA, /* QEPA/XCLK */ ··· 122 83 }; 123 84 124 85 struct ti_eqep_cnt { 125 - struct counter_device counter; 126 86 struct regmap *regmap32; 127 87 struct regmap *regmap16; 128 88 }; 129 89 130 - static struct ti_eqep_cnt *ti_eqep_count_from_counter(struct counter_device *counter) 131 - { 132 - return counter_priv(counter); 133 - } 134 - 135 90 static int ti_eqep_count_read(struct counter_device *counter, 136 91 struct counter_count *count, u64 *val) 137 92 { 138 - struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter); 93 + struct ti_eqep_cnt *priv = counter_priv(counter); 139 94 u32 cnt; 140 95 141 96 regmap_read(priv->regmap32, QPOSCNT, &cnt); ··· 141 108 static int ti_eqep_count_write(struct counter_device *counter, 142 109 struct counter_count *count, u64 val) 143 110 { 144 - struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter); 111 + struct ti_eqep_cnt *priv = counter_priv(counter); 145 112 u32 max; 146 113 147 114 regmap_read(priv->regmap32, QPOSMAX, &max); ··· 155 122 struct counter_count *count, 156 123 enum counter_function *function) 157 124 { 158 - struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter); 125 + struct ti_eqep_cnt *priv = counter_priv(counter); 159 126 u32 qdecctl; 160 127 161 128 regmap_read(priv->regmap16, QDECCTL, &qdecctl); ··· 182 149 struct counter_count *count, 183 150 enum counter_function function) 184 151 { 185 - struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter); 152 + struct ti_eqep_cnt *priv = counter_priv(counter); 186 153 enum ti_eqep_count_func qsrc; 187 154 188 155 switch (function) { ··· 212 179 struct counter_synapse *synapse, 213 180 enum counter_synapse_action *action) 214 181 { 215 - struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter); 182 + struct ti_eqep_cnt *priv = counter_priv(counter); 216 183 enum counter_function function; 217 184 u32 qdecctl; 218 185 int err; ··· 272 239 } 273 240 } 274 241 242 + static int ti_eqep_events_configure(struct counter_device *counter) 243 + { 244 + struct ti_eqep_cnt *priv = counter_priv(counter); 245 + struct counter_event_node *event_node; 246 + u32 qeint = 0; 247 + 248 + list_for_each_entry(event_node, &counter->events_list, l) { 249 + switch (event_node->event) { 250 + case COUNTER_EVENT_OVERFLOW: 251 + qeint |= QEINT_PCO; 252 + break; 253 + case COUNTER_EVENT_UNDERFLOW: 254 + qeint |= QEINT_PCU; 255 + break; 256 + } 257 + } 258 + 259 + return regmap_write(priv->regmap16, QEINT, qeint); 260 + } 261 + 262 + static int ti_eqep_watch_validate(struct counter_device *counter, 263 + const struct counter_watch *watch) 264 + { 265 + switch (watch->event) { 266 + case COUNTER_EVENT_OVERFLOW: 267 + case COUNTER_EVENT_UNDERFLOW: 268 + if (watch->channel != 0) 269 + return -EINVAL; 270 + 271 + return 0; 272 + default: 273 + return -EINVAL; 274 + } 275 + } 276 + 275 277 static const struct counter_ops ti_eqep_counter_ops = { 276 278 .count_read = ti_eqep_count_read, 277 279 .count_write = ti_eqep_count_write, 278 280 .function_read = ti_eqep_function_read, 279 281 .function_write = ti_eqep_function_write, 280 282 .action_read = ti_eqep_action_read, 283 + .events_configure = ti_eqep_events_configure, 284 + .watch_validate = ti_eqep_watch_validate, 281 285 }; 282 286 283 287 static int ti_eqep_position_ceiling_read(struct counter_device *counter, 284 288 struct counter_count *count, 285 289 u64 *ceiling) 286 290 { 287 - struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter); 291 + struct ti_eqep_cnt *priv = counter_priv(counter); 288 292 u32 qposmax; 289 293 290 294 regmap_read(priv->regmap32, QPOSMAX, &qposmax); ··· 335 265 struct counter_count *count, 336 266 u64 ceiling) 337 267 { 338 - struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter); 268 + struct ti_eqep_cnt *priv = counter_priv(counter); 339 269 340 270 if (ceiling != (u32)ceiling) 341 271 return -ERANGE; ··· 348 278 static int ti_eqep_position_enable_read(struct counter_device *counter, 349 279 struct counter_count *count, u8 *enable) 350 280 { 351 - struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter); 281 + struct ti_eqep_cnt *priv = counter_priv(counter); 352 282 u32 qepctl; 353 283 354 284 regmap_read(priv->regmap16, QEPCTL, &qepctl); ··· 361 291 static int ti_eqep_position_enable_write(struct counter_device *counter, 362 292 struct counter_count *count, u8 enable) 363 293 { 364 - struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter); 294 + struct ti_eqep_cnt *priv = counter_priv(counter); 365 295 366 296 regmap_write_bits(priv->regmap16, QEPCTL, QEPCTL_PHEN, enable ? -1 : 0); 367 297 ··· 425 355 }, 426 356 }; 427 357 358 + static irqreturn_t ti_eqep_irq_handler(int irq, void *dev_id) 359 + { 360 + struct counter_device *counter = dev_id; 361 + struct ti_eqep_cnt *priv = counter_priv(counter); 362 + u32 qflg; 363 + 364 + regmap_read(priv->regmap16, QFLG, &qflg); 365 + 366 + if (qflg & QFLG_PCO) 367 + counter_push_event(counter, COUNTER_EVENT_OVERFLOW, 0); 368 + 369 + if (qflg & QFLG_PCU) 370 + counter_push_event(counter, COUNTER_EVENT_UNDERFLOW, 0); 371 + 372 + regmap_write(priv->regmap16, QCLR, qflg); 373 + 374 + return IRQ_HANDLED; 375 + } 376 + 428 377 static const struct regmap_config ti_eqep_regmap32_config = { 429 378 .name = "32-bit", 430 379 .reg_bits = 32, ··· 467 378 struct ti_eqep_cnt *priv; 468 379 void __iomem *base; 469 380 struct clk *clk; 470 - int err; 381 + int err, irq; 471 382 472 383 counter = devm_counter_alloc(dev, sizeof(*priv)); 473 384 if (!counter) ··· 487 398 &ti_eqep_regmap16_config); 488 399 if (IS_ERR(priv->regmap16)) 489 400 return PTR_ERR(priv->regmap16); 401 + 402 + irq = platform_get_irq(pdev, 0); 403 + if (irq < 0) 404 + return irq; 405 + 406 + err = devm_request_threaded_irq(dev, irq, NULL, ti_eqep_irq_handler, 407 + IRQF_ONESHOT, dev_name(dev), counter); 408 + if (err < 0) 409 + return dev_err_probe(dev, err, "failed to request IRQ\n"); 490 410 491 411 counter->name = dev_name(dev); 492 412 counter->parent = dev; ··· 541 443 542 444 static const struct of_device_id ti_eqep_of_match[] = { 543 445 { .compatible = "ti,am3352-eqep", }, 446 + { .compatible = "ti,am62-eqep", }, 544 447 { }, 545 448 }; 546 449 MODULE_DEVICE_TABLE(of, ti_eqep_of_match);