Skip to content

Commit f54d2cd

Browse files
Tero Kristobebarino
authored andcommitted
clk: keystone: sci-clk: Fix sci_clk_get
Currently a bug in the sci_clk_get implementation causes it to always return a clock belonging to the last device in the static list of clock data. This is due to a bug in the init code that causes the array used by sci_clk_get to only be populated with the clocks for the last device, as each device overwrites the entire array with its own clocks. Fix this by calculating the actual number of clocks for the SoC, and allocating the whole array in one go. Also, we don't need the handle to the init data array anymore after doing this, instead we can just compare the dev_id / clk_id against the registered clocks and use binary search for speed. Signed-off-by: Tero Kristo <t-kristo@ti.com> Reported-by: Dave Gerlach <d-gerlach@ti.com> Fixes: b745c07 ("clk: keystone: Add sci-clk driver support") Cc: Nishanth Menon <nm@ti.com> Tested-by: Franklin Cooper <fcooper@ti.com> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
1 parent 5c0858f commit f54d2cd

File tree

1 file changed

+42
-24
lines changed

1 file changed

+42
-24
lines changed

drivers/clk/keystone/sci-clk.c

Lines changed: 42 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <linux/platform_device.h>
2323
#include <linux/slab.h>
2424
#include <linux/soc/ti/ti_sci_protocol.h>
25+
#include <linux/bsearch.h>
2526

2627
#define SCI_CLK_SSC_ENABLE BIT(0)
2728
#define SCI_CLK_ALLOW_FREQ_CHANGE BIT(1)
@@ -44,29 +45,29 @@ struct sci_clk_data {
4445
* @dev: Device pointer for the clock provider
4546
* @clk_data: Clock data
4647
* @clocks: Clocks array for this device
48+
* @num_clocks: Total number of clocks for this provider
4749
*/
4850
struct sci_clk_provider {
4951
const struct ti_sci_handle *sci;
5052
const struct ti_sci_clk_ops *ops;
5153
struct device *dev;
5254
const struct sci_clk_data *clk_data;
5355
struct clk_hw **clocks;
56+
int num_clocks;
5457
};
5558

5659
/**
5760
* struct sci_clk - TI SCI clock representation
5861
* @hw: Hardware clock cookie for common clock framework
5962
* @dev_id: Device index
6063
* @clk_id: Clock index
61-
* @node: Clocks list link
6264
* @provider: Master clock provider
6365
* @flags: Flags for the clock
6466
*/
6567
struct sci_clk {
6668
struct clk_hw hw;
6769
u16 dev_id;
6870
u8 clk_id;
69-
struct list_head node;
7071
struct sci_clk_provider *provider;
7172
u8 flags;
7273
};
@@ -367,6 +368,19 @@ static struct clk_hw *_sci_clk_build(struct sci_clk_provider *provider,
367368
return &sci_clk->hw;
368369
}
369370

371+
static int _cmp_sci_clk(const void *a, const void *b)
372+
{
373+
const struct sci_clk *ca = a;
374+
const struct sci_clk *cb = *(struct sci_clk **)b;
375+
376+
if (ca->dev_id == cb->dev_id && ca->clk_id == cb->clk_id)
377+
return 0;
378+
if (ca->dev_id > cb->dev_id ||
379+
(ca->dev_id == cb->dev_id && ca->clk_id > cb->clk_id))
380+
return 1;
381+
return -1;
382+
}
383+
370384
/**
371385
* sci_clk_get - Xlate function for getting clock handles
372386
* @clkspec: device tree clock specifier
@@ -380,48 +394,52 @@ static struct clk_hw *_sci_clk_build(struct sci_clk_provider *provider,
380394
static struct clk_hw *sci_clk_get(struct of_phandle_args *clkspec, void *data)
381395
{
382396
struct sci_clk_provider *provider = data;
383-
u16 dev_id;
384-
u8 clk_id;
385-
const struct sci_clk_data *clks = provider->clk_data;
386-
struct clk_hw **clocks = provider->clocks;
397+
struct sci_clk **clk;
398+
struct sci_clk key;
387399

388400
if (clkspec->args_count != 2)
389401
return ERR_PTR(-EINVAL);
390402

391-
dev_id = clkspec->args[0];
392-
clk_id = clkspec->args[1];
403+
key.dev_id = clkspec->args[0];
404+
key.clk_id = clkspec->args[1];
393405

394-
while (clks->num_clks) {
395-
if (clks->dev == dev_id) {
396-
if (clk_id >= clks->num_clks)
397-
return ERR_PTR(-EINVAL);
398-
399-
return clocks[clk_id];
400-
}
406+
clk = bsearch(&key, provider->clocks, provider->num_clocks,
407+
sizeof(clk), _cmp_sci_clk);
401408

402-
clks++;
403-
}
409+
if (!clk)
410+
return ERR_PTR(-ENODEV);
404411

405-
return ERR_PTR(-ENODEV);
412+
return &(*clk)->hw;
406413
}
407414

408415
static int ti_sci_init_clocks(struct sci_clk_provider *p)
409416
{
410417
const struct sci_clk_data *data = p->clk_data;
411418
struct clk_hw *hw;
412419
int i;
420+
int num_clks = 0;
413421

414422
while (data->num_clks) {
415-
p->clocks = devm_kcalloc(p->dev, data->num_clks,
416-
sizeof(struct sci_clk),
417-
GFP_KERNEL);
418-
if (!p->clocks)
419-
return -ENOMEM;
423+
num_clks += data->num_clks;
424+
data++;
425+
}
420426

427+
p->num_clocks = num_clks;
428+
429+
p->clocks = devm_kcalloc(p->dev, num_clks, sizeof(struct sci_clk),
430+
GFP_KERNEL);
431+
if (!p->clocks)
432+
return -ENOMEM;
433+
434+
num_clks = 0;
435+
436+
data = p->clk_data;
437+
438+
while (data->num_clks) {
421439
for (i = 0; i < data->num_clks; i++) {
422440
hw = _sci_clk_build(p, data->dev, i);
423441
if (!IS_ERR(hw)) {
424-
p->clocks[i] = hw;
442+
p->clocks[num_clks++] = hw;
425443
continue;
426444
}
427445

0 commit comments

Comments
 (0)