aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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