diff options
Diffstat (limited to 'drivers/clk/clk-cdce925.c')
| -rw-r--r-- | drivers/clk/clk-cdce925.c | 136 |
1 files changed, 80 insertions, 56 deletions
diff --git a/drivers/clk/clk-cdce925.c b/drivers/clk/clk-cdce925.c index 6350682f7e6d..0b2ad21e6e4d 100644 --- a/drivers/clk/clk-cdce925.c +++ b/drivers/clk/clk-cdce925.c @@ -25,25 +25,11 @@ * Model this as 2 PLL clocks which are parents to the outputs. */ -enum { - CDCE913, - CDCE925, - CDCE937, - CDCE949, -}; - struct clk_cdce925_chip_info { int num_plls; int num_outputs; }; -static const struct clk_cdce925_chip_info clk_cdce925_chip_info_tbl[] = { - [CDCE913] = { .num_plls = 1, .num_outputs = 3 }, - [CDCE925] = { .num_plls = 2, .num_outputs = 5 }, - [CDCE937] = { .num_plls = 3, .num_outputs = 7 }, - [CDCE949] = { .num_plls = 4, .num_outputs = 9 }, -}; - #define MAX_NUMBER_OF_PLLS 4 #define MAX_NUMBER_OF_OUTPUTS 9 @@ -115,7 +101,6 @@ static void cdce925_pll_find_rate(unsigned long rate, if (rate <= parent_rate) { /* Can always deliver parent_rate in bypass mode */ - rate = parent_rate; *n = 0; *m = 0; } else { @@ -143,13 +128,15 @@ static void cdce925_pll_find_rate(unsigned long rate, } } -static long cdce925_pll_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) +static int cdce925_pll_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { u16 n, m; - cdce925_pll_find_rate(rate, *parent_rate, &n, &m); - return (long)cdce925_pll_calculate_rate(*parent_rate, n, m); + cdce925_pll_find_rate(req->rate, req->best_parent_rate, &n, &m); + req->rate = (long)cdce925_pll_calculate_rate(req->best_parent_rate, n, m); + + return 0; } static int cdce925_pll_set_rate(struct clk_hw *hw, unsigned long rate, @@ -281,7 +268,7 @@ static const struct clk_ops cdce925_pll_ops = { .prepare = cdce925_pll_prepare, .unprepare = cdce925_pll_unprepare, .recalc_rate = cdce925_pll_recalc_rate, - .round_rate = cdce925_pll_round_rate, + .determine_rate = cdce925_pll_determine_rate, .set_rate = cdce925_pll_set_rate, }; @@ -435,20 +422,23 @@ static unsigned long cdce925_clk_best_parent_rate( return rate * pdiv_best; } -static long cdce925_clk_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) +static int cdce925_clk_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { - unsigned long l_parent_rate = *parent_rate; - u16 divider = cdce925_calc_divider(rate, l_parent_rate); + unsigned long l_parent_rate = req->best_parent_rate; + u16 divider = cdce925_calc_divider(req->rate, l_parent_rate); - if (l_parent_rate / divider != rate) { - l_parent_rate = cdce925_clk_best_parent_rate(hw, rate); - divider = cdce925_calc_divider(rate, l_parent_rate); - *parent_rate = l_parent_rate; + if (l_parent_rate / divider != req->rate) { + l_parent_rate = cdce925_clk_best_parent_rate(hw, req->rate); + divider = cdce925_calc_divider(req->rate, l_parent_rate); + req->best_parent_rate = l_parent_rate; } if (divider) - return (long)(l_parent_rate / divider); + req->rate = (long)(l_parent_rate / divider); + else + req->rate = 0; + return 0; } @@ -466,7 +456,7 @@ static const struct clk_ops cdce925_clk_ops = { .prepare = cdce925_clk_prepare, .unprepare = cdce925_clk_unprepare, .recalc_rate = cdce925_clk_recalc_rate, - .round_rate = cdce925_clk_round_rate, + .determine_rate = cdce925_clk_determine_rate, .set_rate = cdce925_clk_set_rate, }; @@ -488,14 +478,17 @@ static u16 cdce925_y1_calc_divider(unsigned long rate, return (u16)divider; } -static long cdce925_clk_y1_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) +static int cdce925_clk_y1_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { - unsigned long l_parent_rate = *parent_rate; - u16 divider = cdce925_y1_calc_divider(rate, l_parent_rate); + unsigned long l_parent_rate = req->best_parent_rate; + u16 divider = cdce925_y1_calc_divider(req->rate, l_parent_rate); if (divider) - return (long)(l_parent_rate / divider); + req->rate = (long)(l_parent_rate / divider); + else + req->rate = 0; + return 0; } @@ -513,7 +506,7 @@ static const struct clk_ops cdce925_clk_y1_ops = { .prepare = cdce925_clk_prepare, .unprepare = cdce925_clk_unprepare, .recalc_rate = cdce925_clk_recalc_rate, - .round_rate = cdce925_clk_y1_round_rate, + .determine_rate = cdce925_clk_y1_determine_rate, .set_rate = cdce925_clk_y1_set_rate, }; @@ -616,25 +609,15 @@ static int cdce925_regulator_enable(struct device *dev, const char *name) /* The CDCE925 uses a funky way to read/write registers. Bulk mode is * just weird, so just use the single byte mode exclusively. */ -static struct regmap_bus regmap_cdce925_bus = { +static const struct regmap_bus regmap_cdce925_bus = { .write = cdce925_regmap_i2c_write, .read = cdce925_regmap_i2c_read, }; -static const struct i2c_device_id cdce925_id[] = { - { "cdce913", CDCE913 }, - { "cdce925", CDCE925 }, - { "cdce937", CDCE937 }, - { "cdce949", CDCE949 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, cdce925_id); - static int cdce925_probe(struct i2c_client *client) { struct clk_cdce925_chip *data; struct device_node *node = client->dev.of_node; - const struct i2c_device_id *id = i2c_match_id(cdce925_id, client); const char *parent_name; const char *pll_clk_name[MAX_NUMBER_OF_PLLS] = {NULL,}; struct clk_init_data init; @@ -647,7 +630,7 @@ static int cdce925_probe(struct i2c_client *client) .name = "configuration0", .reg_bits = 8, .val_bits = 8, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, }; dev_dbg(&client->dev, "%s\n", __func__); @@ -665,7 +648,7 @@ static int cdce925_probe(struct i2c_client *client) return -ENOMEM; data->i2c_client = client; - data->chip_info = &clk_cdce925_chip_info_tbl[id->driver_data]; + data->chip_info = i2c_get_match_data(client); config.max_register = CDCE925_OFFSET_PLL + data->chip_info->num_plls * 0x10 - 1; data->regmap = devm_regmap_init(&client->dev, ®map_cdce925_bus, @@ -701,6 +684,10 @@ static int cdce925_probe(struct i2c_client *client) for (i = 0; i < data->chip_info->num_plls; ++i) { pll_clk_name[i] = kasprintf(GFP_KERNEL, "%pOFn.pll%d", client->dev.of_node, i); + if (!pll_clk_name[i]) { + err = -ENOMEM; + goto error; + } init.name = pll_clk_name[i]; data->pll[i].chip = data; data->pll[i].hw.init = &init; @@ -742,6 +729,10 @@ static int cdce925_probe(struct i2c_client *client) init.num_parents = 1; init.parent_names = &parent_name; /* Mux Y1 to input */ init.name = kasprintf(GFP_KERNEL, "%pOFn.Y1", client->dev.of_node); + if (!init.name) { + err = -ENOMEM; + goto error; + } data->clk[0].chip = data; data->clk[0].hw.init = &init; data->clk[0].index = 0; @@ -760,6 +751,10 @@ static int cdce925_probe(struct i2c_client *client) for (i = 1; i < data->chip_info->num_outputs; ++i) { init.name = kasprintf(GFP_KERNEL, "%pOFn.Y%d", client->dev.of_node, i+1); + if (!init.name) { + err = -ENOMEM; + goto error; + } data->clk[i].chip = data; data->clk[i].hw.init = &init; data->clk[i].index = i; @@ -810,21 +805,50 @@ error: return err; } +static const struct clk_cdce925_chip_info clk_cdce913_info = { + .num_plls = 1, + .num_outputs = 3, +}; + +static const struct clk_cdce925_chip_info clk_cdce925_info = { + .num_plls = 2, + .num_outputs = 5, +}; + +static const struct clk_cdce925_chip_info clk_cdce937_info = { + .num_plls = 3, + .num_outputs = 7, +}; + +static const struct clk_cdce925_chip_info clk_cdce949_info = { + .num_plls = 4, + .num_outputs = 9, +}; + +static const struct i2c_device_id cdce925_id[] = { + { "cdce913", (kernel_ulong_t)&clk_cdce913_info }, + { "cdce925", (kernel_ulong_t)&clk_cdce925_info }, + { "cdce937", (kernel_ulong_t)&clk_cdce937_info }, + { "cdce949", (kernel_ulong_t)&clk_cdce949_info }, + { } +}; +MODULE_DEVICE_TABLE(i2c, cdce925_id); + static const struct of_device_id clk_cdce925_of_match[] = { - { .compatible = "ti,cdce913" }, - { .compatible = "ti,cdce925" }, - { .compatible = "ti,cdce937" }, - { .compatible = "ti,cdce949" }, - { }, + { .compatible = "ti,cdce913", .data = &clk_cdce913_info }, + { .compatible = "ti,cdce925", .data = &clk_cdce925_info }, + { .compatible = "ti,cdce937", .data = &clk_cdce937_info }, + { .compatible = "ti,cdce949", .data = &clk_cdce949_info }, + { } }; MODULE_DEVICE_TABLE(of, clk_cdce925_of_match); static struct i2c_driver cdce925_driver = { .driver = { .name = "cdce925", - .of_match_table = of_match_ptr(clk_cdce925_of_match), + .of_match_table = clk_cdce925_of_match, }, - .probe_new = cdce925_probe, + .probe = cdce925_probe, .id_table = cdce925_id, }; module_i2c_driver(cdce925_driver); |
