forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-10 61598093bbdd283a7edc367d900f223070ead8d2
kernel/drivers/clk/ti/divider.c
....@@ -26,30 +26,6 @@
2626 #undef pr_fmt
2727 #define pr_fmt(fmt) "%s: " fmt, __func__
2828
29
-#define div_mask(d) ((1 << ((d)->width)) - 1)
30
-
31
-static unsigned int _get_table_maxdiv(const struct clk_div_table *table)
32
-{
33
- unsigned int maxdiv = 0;
34
- const struct clk_div_table *clkt;
35
-
36
- for (clkt = table; clkt->div; clkt++)
37
- if (clkt->div > maxdiv)
38
- maxdiv = clkt->div;
39
- return maxdiv;
40
-}
41
-
42
-static unsigned int _get_maxdiv(struct clk_omap_divider *divider)
43
-{
44
- if (divider->flags & CLK_DIVIDER_ONE_BASED)
45
- return div_mask(divider);
46
- if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
47
- return 1 << div_mask(divider);
48
- if (divider->table)
49
- return _get_table_maxdiv(divider->table);
50
- return div_mask(divider) + 1;
51
-}
52
-
5329 static unsigned int _get_table_div(const struct clk_div_table *table,
5430 unsigned int val)
5531 {
....@@ -59,6 +35,34 @@
5935 if (clkt->val == val)
6036 return clkt->div;
6137 return 0;
38
+}
39
+
40
+static void _setup_mask(struct clk_omap_divider *divider)
41
+{
42
+ u16 mask;
43
+ u32 max_val;
44
+ const struct clk_div_table *clkt;
45
+
46
+ if (divider->table) {
47
+ max_val = 0;
48
+
49
+ for (clkt = divider->table; clkt->div; clkt++)
50
+ if (clkt->val > max_val)
51
+ max_val = clkt->val;
52
+ } else {
53
+ max_val = divider->max;
54
+
55
+ if (!(divider->flags & CLK_DIVIDER_ONE_BASED) &&
56
+ !(divider->flags & CLK_DIVIDER_POWER_OF_TWO))
57
+ max_val--;
58
+ }
59
+
60
+ if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
61
+ mask = fls(max_val) - 1;
62
+ else
63
+ mask = max_val;
64
+
65
+ divider->mask = (1 << fls(mask)) - 1;
6266 }
6367
6468 static unsigned int _get_div(struct clk_omap_divider *divider, unsigned int val)
....@@ -101,7 +105,7 @@
101105 unsigned int div, val;
102106
103107 val = ti_clk_ll_ops->clk_readl(&divider->reg) >> divider->shift;
104
- val &= div_mask(divider);
108
+ val &= divider->mask;
105109
106110 div = _get_div(divider, val);
107111 if (!div) {
....@@ -180,7 +184,7 @@
180184 if (!rate)
181185 rate = 1;
182186
183
- maxdiv = _get_maxdiv(divider);
187
+ maxdiv = divider->max;
184188
185189 if (!(clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)) {
186190 parent_rate = *best_parent_rate;
....@@ -219,7 +223,7 @@
219223 }
220224
221225 if (!bestdiv) {
222
- bestdiv = _get_maxdiv(divider);
226
+ bestdiv = divider->max;
223227 *best_parent_rate =
224228 clk_hw_round_rate(clk_hw_get_parent(hw), 1);
225229 }
....@@ -249,17 +253,16 @@
249253 divider = to_clk_omap_divider(hw);
250254
251255 div = DIV_ROUND_UP(parent_rate, rate);
256
+
257
+ if (div > divider->max)
258
+ div = divider->max;
259
+ if (div < divider->min)
260
+ div = divider->min;
261
+
252262 value = _get_val(divider, div);
253263
254
- if (value > div_mask(divider))
255
- value = div_mask(divider);
256
-
257
- if (divider->flags & CLK_DIVIDER_HIWORD_MASK) {
258
- val = div_mask(divider) << (divider->shift + 16);
259
- } else {
260
- val = ti_clk_ll_ops->clk_readl(&divider->reg);
261
- val &= ~(div_mask(divider) << divider->shift);
262
- }
264
+ val = ti_clk_ll_ops->clk_readl(&divider->reg);
265
+ val &= ~(divider->mask << divider->shift);
263266 val |= value << divider->shift;
264267 ti_clk_ll_ops->clk_writel(val, &divider->reg);
265268
....@@ -268,53 +271,68 @@
268271 return 0;
269272 }
270273
274
+/**
275
+ * clk_divider_save_context - Save the divider value
276
+ * @hw: pointer struct clk_hw
277
+ *
278
+ * Save the divider value
279
+ */
280
+static int clk_divider_save_context(struct clk_hw *hw)
281
+{
282
+ struct clk_omap_divider *divider = to_clk_omap_divider(hw);
283
+ u32 val;
284
+
285
+ val = ti_clk_ll_ops->clk_readl(&divider->reg) >> divider->shift;
286
+ divider->context = val & divider->mask;
287
+
288
+ return 0;
289
+}
290
+
291
+/**
292
+ * clk_divider_restore_context - restore the saved the divider value
293
+ * @hw: pointer struct clk_hw
294
+ *
295
+ * Restore the saved the divider value
296
+ */
297
+static void clk_divider_restore_context(struct clk_hw *hw)
298
+{
299
+ struct clk_omap_divider *divider = to_clk_omap_divider(hw);
300
+ u32 val;
301
+
302
+ val = ti_clk_ll_ops->clk_readl(&divider->reg);
303
+ val &= ~(divider->mask << divider->shift);
304
+ val |= divider->context << divider->shift;
305
+ ti_clk_ll_ops->clk_writel(val, &divider->reg);
306
+}
307
+
271308 const struct clk_ops ti_clk_divider_ops = {
272309 .recalc_rate = ti_clk_divider_recalc_rate,
273310 .round_rate = ti_clk_divider_round_rate,
274311 .set_rate = ti_clk_divider_set_rate,
312
+ .save_context = clk_divider_save_context,
313
+ .restore_context = clk_divider_restore_context,
275314 };
276315
277
-static struct clk *_register_divider(struct device *dev, const char *name,
278
- const char *parent_name,
279
- unsigned long flags,
280
- struct clk_omap_reg *reg,
281
- u8 shift, u8 width, s8 latch,
282
- u8 clk_divider_flags,
283
- const struct clk_div_table *table)
316
+static struct clk *_register_divider(struct device_node *node,
317
+ u32 flags,
318
+ struct clk_omap_divider *div)
284319 {
285
- struct clk_omap_divider *div;
286320 struct clk *clk;
287
- struct clk_init_data init = {};
321
+ struct clk_init_data init;
322
+ const char *parent_name;
288323
289
- if (clk_divider_flags & CLK_DIVIDER_HIWORD_MASK) {
290
- if (width + shift > 16) {
291
- pr_warn("divider value exceeds LOWORD field\n");
292
- return ERR_PTR(-EINVAL);
293
- }
294
- }
324
+ parent_name = of_clk_get_parent_name(node, 0);
295325
296
- /* allocate the divider */
297
- div = kzalloc(sizeof(*div), GFP_KERNEL);
298
- if (!div)
299
- return ERR_PTR(-ENOMEM);
300
-
301
- init.name = name;
326
+ init.name = node->name;
302327 init.ops = &ti_clk_divider_ops;
303
- init.flags = flags | CLK_IS_BASIC;
328
+ init.flags = flags;
304329 init.parent_names = (parent_name ? &parent_name : NULL);
305330 init.num_parents = (parent_name ? 1 : 0);
306331
307
- /* struct clk_divider assignments */
308
- memcpy(&div->reg, reg, sizeof(*reg));
309
- div->shift = shift;
310
- div->width = width;
311
- div->latch = latch;
312
- div->flags = clk_divider_flags;
313332 div->hw.init = &init;
314
- div->table = table;
315333
316334 /* register the clock */
317
- clk = ti_clk_register(dev, &div->hw, name);
335
+ clk = ti_clk_register(NULL, &div->hw, node->name);
318336
319337 if (IS_ERR(clk))
320338 kfree(div);
....@@ -323,34 +341,17 @@
323341 }
324342
325343 int ti_clk_parse_divider_data(int *div_table, int num_dividers, int max_div,
326
- u8 flags, u8 *width,
327
- const struct clk_div_table **table)
344
+ u8 flags, struct clk_omap_divider *divider)
328345 {
329346 int valid_div = 0;
330
- u32 val;
331
- int div;
332347 int i;
333348 struct clk_div_table *tmp;
349
+ u16 min_div = 0;
334350
335351 if (!div_table) {
336
- if (flags & CLKF_INDEX_STARTS_AT_ONE)
337
- val = 1;
338
- else
339
- val = 0;
340
-
341
- div = 1;
342
-
343
- while (div < max_div) {
344
- if (flags & CLKF_INDEX_POWER_OF_TWO)
345
- div <<= 1;
346
- else
347
- div++;
348
- val++;
349
- }
350
-
351
- *width = fls(val);
352
- *table = NULL;
353
-
352
+ divider->min = 1;
353
+ divider->max = max_div;
354
+ _setup_mask(divider);
354355 return 0;
355356 }
356357
....@@ -367,115 +368,32 @@
367368 num_dividers = i;
368369
369370 tmp = kcalloc(valid_div + 1, sizeof(*tmp), GFP_KERNEL);
370
- if (!tmp) {
371
- *table = ERR_PTR(-ENOMEM);
371
+ if (!tmp)
372372 return -ENOMEM;
373
- }
374373
375374 valid_div = 0;
376
- *width = 0;
377375
378376 for (i = 0; i < num_dividers; i++)
379377 if (div_table[i] > 0) {
380378 tmp[valid_div].div = div_table[i];
381379 tmp[valid_div].val = i;
382380 valid_div++;
383
- *width = i;
381
+ if (div_table[i] > max_div)
382
+ max_div = div_table[i];
383
+ if (!min_div || div_table[i] < min_div)
384
+ min_div = div_table[i];
384385 }
385386
386
- *width = fls(*width);
387
- *table = tmp;
387
+ divider->min = min_div;
388
+ divider->max = max_div;
389
+ divider->table = tmp;
390
+ _setup_mask(divider);
388391
389392 return 0;
390393 }
391394
392
-static const struct clk_div_table *
393
-_get_div_table_from_setup(struct ti_clk_divider *setup, u8 *width)
394
-{
395
- const struct clk_div_table *table = NULL;
396
-
397
- ti_clk_parse_divider_data(setup->dividers, setup->num_dividers,
398
- setup->max_div, setup->flags, width,
399
- &table);
400
-
401
- return table;
402
-}
403
-
404
-struct clk_hw *ti_clk_build_component_div(struct ti_clk_divider *setup)
405
-{
406
- struct clk_omap_divider *div;
407
- struct clk_omap_reg *reg;
408
- int ret;
409
-
410
- if (!setup)
411
- return NULL;
412
-
413
- div = kzalloc(sizeof(*div), GFP_KERNEL);
414
- if (!div)
415
- return ERR_PTR(-ENOMEM);
416
-
417
- reg = (struct clk_omap_reg *)&div->reg;
418
- reg->index = setup->module;
419
- reg->offset = setup->reg;
420
-
421
- if (setup->flags & CLKF_INDEX_STARTS_AT_ONE)
422
- div->flags |= CLK_DIVIDER_ONE_BASED;
423
-
424
- if (setup->flags & CLKF_INDEX_POWER_OF_TWO)
425
- div->flags |= CLK_DIVIDER_POWER_OF_TWO;
426
-
427
- div->table = _get_div_table_from_setup(setup, &div->width);
428
- if (IS_ERR(div->table)) {
429
- ret = PTR_ERR(div->table);
430
- kfree(div);
431
- return ERR_PTR(ret);
432
- }
433
-
434
-
435
- div->shift = setup->bit_shift;
436
- div->latch = -EINVAL;
437
-
438
- return &div->hw;
439
-}
440
-
441
-struct clk *ti_clk_register_divider(struct ti_clk *setup)
442
-{
443
- struct ti_clk_divider *div = setup->data;
444
- struct clk_omap_reg reg = {
445
- .index = div->module,
446
- .offset = div->reg,
447
- };
448
- u8 width;
449
- u32 flags = 0;
450
- u8 div_flags = 0;
451
- const struct clk_div_table *table;
452
- struct clk *clk;
453
-
454
- if (div->flags & CLKF_INDEX_STARTS_AT_ONE)
455
- div_flags |= CLK_DIVIDER_ONE_BASED;
456
-
457
- if (div->flags & CLKF_INDEX_POWER_OF_TWO)
458
- div_flags |= CLK_DIVIDER_POWER_OF_TWO;
459
-
460
- if (div->flags & CLKF_SET_RATE_PARENT)
461
- flags |= CLK_SET_RATE_PARENT;
462
-
463
- table = _get_div_table_from_setup(div, &width);
464
- if (IS_ERR(table))
465
- return (struct clk *)table;
466
-
467
- clk = _register_divider(NULL, setup->name, div->parent,
468
- flags, &reg, div->bit_shift,
469
- width, -EINVAL, div_flags, table);
470
-
471
- if (IS_ERR(clk))
472
- kfree(table);
473
-
474
- return clk;
475
-}
476
-
477
-static struct clk_div_table *
478
-__init ti_clk_get_div_table(struct device_node *node)
395
+static int __init ti_clk_get_div_table(struct device_node *node,
396
+ struct clk_omap_divider *div)
479397 {
480398 struct clk_div_table *table;
481399 const __be32 *divspec;
....@@ -487,7 +405,7 @@
487405 divspec = of_get_property(node, "ti,dividers", &num_div);
488406
489407 if (!divspec)
490
- return NULL;
408
+ return 0;
491409
492410 num_div /= 4;
493411
....@@ -501,14 +419,13 @@
501419 }
502420
503421 if (!valid_div) {
504
- pr_err("no valid dividers for %s table\n", node->name);
505
- return ERR_PTR(-EINVAL);
422
+ pr_err("no valid dividers for %pOFn table\n", node);
423
+ return -EINVAL;
506424 }
507425
508426 table = kcalloc(valid_div + 1, sizeof(*table), GFP_KERNEL);
509
-
510427 if (!table)
511
- return ERR_PTR(-ENOMEM);
428
+ return -ENOMEM;
512429
513430 valid_div = 0;
514431
....@@ -521,96 +438,84 @@
521438 }
522439 }
523440
524
- return table;
441
+ div->table = table;
442
+
443
+ return 0;
525444 }
526445
527
-static int _get_divider_width(struct device_node *node,
528
- const struct clk_div_table *table,
529
- u8 flags)
446
+static int _populate_divider_min_max(struct device_node *node,
447
+ struct clk_omap_divider *divider)
530448 {
531
- u32 min_div;
532
- u32 max_div;
533
- u32 val = 0;
534
- u32 div;
449
+ u32 min_div = 0;
450
+ u32 max_div = 0;
451
+ u32 val;
452
+ const struct clk_div_table *clkt;
535453
536
- if (!table) {
454
+ if (!divider->table) {
537455 /* Clk divider table not provided, determine min/max divs */
538456 if (of_property_read_u32(node, "ti,min-div", &min_div))
539457 min_div = 1;
540458
541459 if (of_property_read_u32(node, "ti,max-div", &max_div)) {
542
- pr_err("no max-div for %s!\n", node->name);
460
+ pr_err("no max-div for %pOFn!\n", node);
543461 return -EINVAL;
544462 }
545
-
546
- /* Determine bit width for the field */
547
- if (flags & CLK_DIVIDER_ONE_BASED)
548
- val = 1;
549
-
550
- div = min_div;
551
-
552
- while (div < max_div) {
553
- if (flags & CLK_DIVIDER_POWER_OF_TWO)
554
- div <<= 1;
555
- else
556
- div++;
557
- val++;
558
- }
559463 } else {
560
- div = 0;
561464
562
- while (table[div].div) {
563
- val = table[div].val;
564
- div++;
465
+ for (clkt = divider->table; clkt->div; clkt++) {
466
+ val = clkt->div;
467
+ if (val > max_div)
468
+ max_div = val;
469
+ if (!min_div || val < min_div)
470
+ min_div = val;
565471 }
566472 }
567473
568
- return fls(val);
474
+ divider->min = min_div;
475
+ divider->max = max_div;
476
+ _setup_mask(divider);
477
+
478
+ return 0;
569479 }
570480
571481 static int __init ti_clk_divider_populate(struct device_node *node,
572
- struct clk_omap_reg *reg, const struct clk_div_table **table,
573
- u32 *flags, u8 *div_flags, u8 *width, u8 *shift, s8 *latch)
482
+ struct clk_omap_divider *div,
483
+ u32 *flags)
574484 {
575485 u32 val;
576486 int ret;
577487
578
- ret = ti_clk_get_reg_addr(node, 0, reg);
488
+ ret = ti_clk_get_reg_addr(node, 0, &div->reg);
579489 if (ret)
580490 return ret;
581491
582492 if (!of_property_read_u32(node, "ti,bit-shift", &val))
583
- *shift = val;
493
+ div->shift = val;
584494 else
585
- *shift = 0;
495
+ div->shift = 0;
586496
587
- if (latch) {
588
- if (!of_property_read_u32(node, "ti,latch-bit", &val))
589
- *latch = val;
590
- else
591
- *latch = -EINVAL;
592
- }
497
+ if (!of_property_read_u32(node, "ti,latch-bit", &val))
498
+ div->latch = val;
499
+ else
500
+ div->latch = -EINVAL;
593501
594502 *flags = 0;
595
- *div_flags = 0;
503
+ div->flags = 0;
596504
597505 if (of_property_read_bool(node, "ti,index-starts-at-one"))
598
- *div_flags |= CLK_DIVIDER_ONE_BASED;
506
+ div->flags |= CLK_DIVIDER_ONE_BASED;
599507
600508 if (of_property_read_bool(node, "ti,index-power-of-two"))
601
- *div_flags |= CLK_DIVIDER_POWER_OF_TWO;
509
+ div->flags |= CLK_DIVIDER_POWER_OF_TWO;
602510
603511 if (of_property_read_bool(node, "ti,set-rate-parent"))
604512 *flags |= CLK_SET_RATE_PARENT;
605513
606
- *table = ti_clk_get_div_table(node);
514
+ ret = ti_clk_get_div_table(node, div);
515
+ if (ret)
516
+ return ret;
607517
608
- if (IS_ERR(*table))
609
- return PTR_ERR(*table);
610
-
611
- *width = _get_divider_width(node, *table, *div_flags);
612
-
613
- return 0;
518
+ return _populate_divider_min_max(node, div);
614519 }
615520
616521 /**
....@@ -622,24 +527,17 @@
622527 static void __init of_ti_divider_clk_setup(struct device_node *node)
623528 {
624529 struct clk *clk;
625
- const char *parent_name;
626
- struct clk_omap_reg reg;
627
- u8 clk_divider_flags = 0;
628
- u8 width = 0;
629
- u8 shift = 0;
630
- s8 latch = -EINVAL;
631
- const struct clk_div_table *table = NULL;
632530 u32 flags = 0;
531
+ struct clk_omap_divider *div;
633532
634
- parent_name = of_clk_get_parent_name(node, 0);
533
+ div = kzalloc(sizeof(*div), GFP_KERNEL);
534
+ if (!div)
535
+ return;
635536
636
- if (ti_clk_divider_populate(node, &reg, &table, &flags,
637
- &clk_divider_flags, &width, &shift, &latch))
537
+ if (ti_clk_divider_populate(node, div, &flags))
638538 goto cleanup;
639539
640
- clk = _register_divider(NULL, node->name, parent_name, flags, &reg,
641
- shift, width, latch, clk_divider_flags, table);
642
-
540
+ clk = _register_divider(node, flags, div);
643541 if (!IS_ERR(clk)) {
644542 of_clk_add_provider(node, of_clk_src_simple_get, clk);
645543 of_ti_clk_autoidle_setup(node);
....@@ -647,22 +545,21 @@
647545 }
648546
649547 cleanup:
650
- kfree(table);
548
+ kfree(div->table);
549
+ kfree(div);
651550 }
652551 CLK_OF_DECLARE(divider_clk, "ti,divider-clock", of_ti_divider_clk_setup);
653552
654553 static void __init of_ti_composite_divider_clk_setup(struct device_node *node)
655554 {
656555 struct clk_omap_divider *div;
657
- u32 val;
556
+ u32 tmp;
658557
659558 div = kzalloc(sizeof(*div), GFP_KERNEL);
660559 if (!div)
661560 return;
662561
663
- if (ti_clk_divider_populate(node, &div->reg, &div->table, &val,
664
- &div->flags, &div->width, &div->shift,
665
- NULL) < 0)
562
+ if (ti_clk_divider_populate(node, div, &tmp))
666563 goto cleanup;
667564
668565 if (!ti_clk_add_component(node, &div->hw, CLK_COMPONENT_TYPE_DIVIDER))