aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRemi Pommarel <repk@triplefau.lt>2015-12-06 11:22:47 -0500
committerMichael Turquette <mturquette@baylibre.com>2015-12-24 23:38:30 -0500
commit6d18b8adbe679b5947aa822b676efff230acc5f6 (patch)
tree5119d5f0608992c2f7b597c491d8691d856d53c4
parent9c95b32ca09364e4687b72c4e17b78dc1c420026 (diff)
clk: bcm2835: Support for clock parent selection
Some bcm2835 clocks used by hardware (like "PWM" or "H264") can have multiple parent clocks. These clocks divide the rate of a parent which can be selected by setting the proper bits in the clock control register. Previously all these parents where handled by a mux clock. But a mux clock cannot be used because updating clock control register to select parent needs a password to be xor'd with the parent index. This patch get rid of mux clock and make these clocks handle their own parent, allowing them to select the one to use. Signed-off-by: Remi Pommarel <repk@triplefau.lt> Reviewed-by: Eric Anholt <eric@anholt.net> Signed-off-by: Michael Turquette <mturquette@baylibre.com>
-rw-r--r--drivers/clk/bcm/clk-bcm2835.c122
1 files changed, 77 insertions, 45 deletions
diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
index 9e881eef3c36..6e4dd6fa3403 100644
--- a/drivers/clk/bcm/clk-bcm2835.c
+++ b/drivers/clk/bcm/clk-bcm2835.c
@@ -1199,16 +1199,6 @@ static long bcm2835_clock_rate_from_divisor(struct bcm2835_clock *clock,
1199 return temp; 1199 return temp;
1200} 1200}
1201 1201
1202static long bcm2835_clock_round_rate(struct clk_hw *hw,
1203 unsigned long rate,
1204 unsigned long *parent_rate)
1205{
1206 struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
1207 u32 div = bcm2835_clock_choose_div(hw, rate, *parent_rate, false);
1208
1209 return bcm2835_clock_rate_from_divisor(clock, *parent_rate, div);
1210}
1211
1212static unsigned long bcm2835_clock_get_rate(struct clk_hw *hw, 1202static unsigned long bcm2835_clock_get_rate(struct clk_hw *hw,
1213 unsigned long parent_rate) 1203 unsigned long parent_rate)
1214{ 1204{
@@ -1280,13 +1270,75 @@ static int bcm2835_clock_set_rate(struct clk_hw *hw,
1280 return 0; 1270 return 0;
1281} 1271}
1282 1272
1273static int bcm2835_clock_determine_rate(struct clk_hw *hw,
1274 struct clk_rate_request *req)
1275{
1276 struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
1277 struct clk_hw *parent, *best_parent = NULL;
1278 unsigned long rate, best_rate = 0;
1279 unsigned long prate, best_prate = 0;
1280 size_t i;
1281 u32 div;
1282
1283 /*
1284 * Select parent clock that results in the closest but lower rate
1285 */
1286 for (i = 0; i < clk_hw_get_num_parents(hw); ++i) {
1287 parent = clk_hw_get_parent_by_index(hw, i);
1288 if (!parent)
1289 continue;
1290 prate = clk_hw_get_rate(parent);
1291 div = bcm2835_clock_choose_div(hw, req->rate, prate, true);
1292 rate = bcm2835_clock_rate_from_divisor(clock, prate, div);
1293 if (rate > best_rate && rate <= req->rate) {
1294 best_parent = parent;
1295 best_prate = prate;
1296 best_rate = rate;
1297 }
1298 }
1299
1300 if (!best_parent)
1301 return -EINVAL;
1302
1303 req->best_parent_hw = best_parent;
1304 req->best_parent_rate = best_prate;
1305
1306 req->rate = best_rate;
1307
1308 return 0;
1309}
1310
1311static int bcm2835_clock_set_parent(struct clk_hw *hw, u8 index)
1312{
1313 struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
1314 struct bcm2835_cprman *cprman = clock->cprman;
1315 const struct bcm2835_clock_data *data = clock->data;
1316 u8 src = (index << CM_SRC_SHIFT) & CM_SRC_MASK;
1317
1318 cprman_write(cprman, data->ctl_reg, src);
1319 return 0;
1320}
1321
1322static u8 bcm2835_clock_get_parent(struct clk_hw *hw)
1323{
1324 struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
1325 struct bcm2835_cprman *cprman = clock->cprman;
1326 const struct bcm2835_clock_data *data = clock->data;
1327 u32 src = cprman_read(cprman, data->ctl_reg);
1328
1329 return (src & CM_SRC_MASK) >> CM_SRC_SHIFT;
1330}
1331
1332
1283static const struct clk_ops bcm2835_clock_clk_ops = { 1333static const struct clk_ops bcm2835_clock_clk_ops = {
1284 .is_prepared = bcm2835_clock_is_on, 1334 .is_prepared = bcm2835_clock_is_on,
1285 .prepare = bcm2835_clock_on, 1335 .prepare = bcm2835_clock_on,
1286 .unprepare = bcm2835_clock_off, 1336 .unprepare = bcm2835_clock_off,
1287 .recalc_rate = bcm2835_clock_get_rate, 1337 .recalc_rate = bcm2835_clock_get_rate,
1288 .set_rate = bcm2835_clock_set_rate, 1338 .set_rate = bcm2835_clock_set_rate,
1289 .round_rate = bcm2835_clock_round_rate, 1339 .determine_rate = bcm2835_clock_determine_rate,
1340 .set_parent = bcm2835_clock_set_parent,
1341 .get_parent = bcm2835_clock_get_parent,
1290}; 1342};
1291 1343
1292static int bcm2835_vpu_clock_is_on(struct clk_hw *hw) 1344static int bcm2835_vpu_clock_is_on(struct clk_hw *hw)
@@ -1302,7 +1354,9 @@ static const struct clk_ops bcm2835_vpu_clock_clk_ops = {
1302 .is_prepared = bcm2835_vpu_clock_is_on, 1354 .is_prepared = bcm2835_vpu_clock_is_on,
1303 .recalc_rate = bcm2835_clock_get_rate, 1355 .recalc_rate = bcm2835_clock_get_rate,
1304 .set_rate = bcm2835_clock_set_rate, 1356 .set_rate = bcm2835_clock_set_rate,
1305 .round_rate = bcm2835_clock_round_rate, 1357 .determine_rate = bcm2835_clock_determine_rate,
1358 .set_parent = bcm2835_clock_set_parent,
1359 .get_parent = bcm2835_clock_get_parent,
1306}; 1360};
1307 1361
1308static struct clk *bcm2835_register_pll(struct bcm2835_cprman *cprman, 1362static struct clk *bcm2835_register_pll(struct bcm2835_cprman *cprman,
@@ -1396,45 +1450,23 @@ static struct clk *bcm2835_register_clock(struct bcm2835_cprman *cprman,
1396{ 1450{
1397 struct bcm2835_clock *clock; 1451 struct bcm2835_clock *clock;
1398 struct clk_init_data init; 1452 struct clk_init_data init;
1399 const char *parent; 1453 const char *parents[1 << CM_SRC_BITS];
1454 size_t i;
1400 1455
1401 /* 1456 /*
1402 * Most of the clock generators have a mux field, so we 1457 * Replace our "xosc" references with the oscillator's
1403 * instantiate a generic mux as our parent to handle it. 1458 * actual name.
1404 */ 1459 */
1405 if (data->num_mux_parents) { 1460 for (i = 0; i < data->num_mux_parents; i++) {
1406 const char *parents[1 << CM_SRC_BITS]; 1461 if (strcmp(data->parents[i], "xosc") == 0)
1407 int i; 1462 parents[i] = cprman->osc_name;
1408 1463 else
1409 parent = devm_kasprintf(cprman->dev, GFP_KERNEL, 1464 parents[i] = data->parents[i];
1410 "mux_%s", data->name);
1411 if (!parent)
1412 return NULL;
1413
1414 /*
1415 * Replace our "xosc" references with the oscillator's
1416 * actual name.
1417 */
1418 for (i = 0; i < data->num_mux_parents; i++) {
1419 if (strcmp(data->parents[i], "xosc") == 0)
1420 parents[i] = cprman->osc_name;
1421 else
1422 parents[i] = data->parents[i];
1423 }
1424
1425 clk_register_mux(cprman->dev, parent,
1426 parents, data->num_mux_parents,
1427 CLK_SET_RATE_PARENT,
1428 cprman->regs + data->ctl_reg,
1429 CM_SRC_SHIFT, CM_SRC_BITS,
1430 0, &cprman->regs_lock);
1431 } else {
1432 parent = data->parents[0];
1433 } 1465 }
1434 1466
1435 memset(&init, 0, sizeof(init)); 1467 memset(&init, 0, sizeof(init));
1436 init.parent_names = &parent; 1468 init.parent_names = parents;
1437 init.num_parents = 1; 1469 init.num_parents = data->num_mux_parents;
1438 init.name = data->name; 1470 init.name = data->name;
1439 init.flags = CLK_IGNORE_UNUSED; 1471 init.flags = CLK_IGNORE_UNUSED;
1440 1472