aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd/db8500-prcmu.c
diff options
context:
space:
mode:
authorMattias Nilsson <mattias.i.nilsson@stericsson.com>2012-01-13 10:20:28 -0500
committerSamuel Ortiz <sameo@linux.intel.com>2012-03-06 12:46:32 -0500
commit6b6fae2b890826c99f9e62cceec4f859c98ee575 (patch)
treeacec177001f40c9cc21454e0b140454026f5fd60 /drivers/mfd/db8500-prcmu.c
parent0508901ca794d411efb09befb88b8194d8387428 (diff)
mfd: db8500 clock handling update
This updates the clock handling in the DB8500 PRCMU driver with the latest findings and API changes related to changes in the backing firmware in the PRCMU. - Add the necessary interfaces to get the frequencies of the clocks and set the rate of some of the clocks. - Add support for controlling the clocks PLLSOC0, PLLDSI, DSI0, DSI1 and DSI escape clocks (DSInESCCLK). - Correct the PLLSDI enable/disable sequence by using the DSIPLL_CLAMPI bit. After this we will have the interfaces and code to implement the U8500 clock framework properly. Reviewed-by: Jonas Aberg <jonas.aberg@stericsson.com> Signed-off-by: Mattias Nilsson <mattias.i.nilsson@stericsson.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/mfd/db8500-prcmu.c')
-rw-r--r--drivers/mfd/db8500-prcmu.c666
1 files changed, 587 insertions, 79 deletions
diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c
index 5179abf94729..945932719327 100644
--- a/drivers/mfd/db8500-prcmu.c
+++ b/drivers/mfd/db8500-prcmu.c
@@ -132,6 +132,8 @@
132#define PRCM_REQ_MB1_ARM_OPP (PRCM_REQ_MB1 + 0x0) 132#define PRCM_REQ_MB1_ARM_OPP (PRCM_REQ_MB1 + 0x0)
133#define PRCM_REQ_MB1_APE_OPP (PRCM_REQ_MB1 + 0x1) 133#define PRCM_REQ_MB1_APE_OPP (PRCM_REQ_MB1 + 0x1)
134#define PRCM_REQ_MB1_PLL_ON_OFF (PRCM_REQ_MB1 + 0x4) 134#define PRCM_REQ_MB1_PLL_ON_OFF (PRCM_REQ_MB1 + 0x4)
135#define PLL_SOC0_OFF 0x1
136#define PLL_SOC0_ON 0x2
135#define PLL_SOC1_OFF 0x4 137#define PLL_SOC1_OFF 0x4
136#define PLL_SOC1_ON 0x8 138#define PLL_SOC1_ON 0x8
137 139
@@ -420,43 +422,95 @@ static DEFINE_SPINLOCK(gpiocr_lock);
420static __iomem void *tcdm_base; 422static __iomem void *tcdm_base;
421 423
422struct clk_mgt { 424struct clk_mgt {
423 unsigned int offset; 425 void __iomem *reg;
424 u32 pllsw; 426 u32 pllsw;
427 int branch;
428 bool clk38div;
429};
430
431enum {
432 PLL_RAW,
433 PLL_FIX,
434 PLL_DIV
425}; 435};
426 436
427static DEFINE_SPINLOCK(clk_mgt_lock); 437static DEFINE_SPINLOCK(clk_mgt_lock);
428 438
429#define CLK_MGT_ENTRY(_name)[PRCMU_##_name] = { (PRCM_##_name##_MGT_OFF), 0 } 439#define CLK_MGT_ENTRY(_name, _branch, _clk38div)[PRCMU_##_name] = \
440 { (PRCM_##_name##_MGT), 0 , _branch, _clk38div}
430struct clk_mgt clk_mgt[PRCMU_NUM_REG_CLOCKS] = { 441struct clk_mgt clk_mgt[PRCMU_NUM_REG_CLOCKS] = {
431 CLK_MGT_ENTRY(SGACLK), 442 CLK_MGT_ENTRY(SGACLK, PLL_DIV, false),
432 CLK_MGT_ENTRY(UARTCLK), 443 CLK_MGT_ENTRY(UARTCLK, PLL_FIX, true),
433 CLK_MGT_ENTRY(MSP02CLK), 444 CLK_MGT_ENTRY(MSP02CLK, PLL_FIX, true),
434 CLK_MGT_ENTRY(MSP1CLK), 445 CLK_MGT_ENTRY(MSP1CLK, PLL_FIX, true),
435 CLK_MGT_ENTRY(I2CCLK), 446 CLK_MGT_ENTRY(I2CCLK, PLL_FIX, true),
436 CLK_MGT_ENTRY(SDMMCCLK), 447 CLK_MGT_ENTRY(SDMMCCLK, PLL_DIV, true),
437 CLK_MGT_ENTRY(SLIMCLK), 448 CLK_MGT_ENTRY(SLIMCLK, PLL_FIX, true),
438 CLK_MGT_ENTRY(PER1CLK), 449 CLK_MGT_ENTRY(PER1CLK, PLL_DIV, true),
439 CLK_MGT_ENTRY(PER2CLK), 450 CLK_MGT_ENTRY(PER2CLK, PLL_DIV, true),
440 CLK_MGT_ENTRY(PER3CLK), 451 CLK_MGT_ENTRY(PER3CLK, PLL_DIV, true),
441 CLK_MGT_ENTRY(PER5CLK), 452 CLK_MGT_ENTRY(PER5CLK, PLL_DIV, true),
442 CLK_MGT_ENTRY(PER6CLK), 453 CLK_MGT_ENTRY(PER6CLK, PLL_DIV, true),
443 CLK_MGT_ENTRY(PER7CLK), 454 CLK_MGT_ENTRY(PER7CLK, PLL_DIV, true),
444 CLK_MGT_ENTRY(LCDCLK), 455 CLK_MGT_ENTRY(LCDCLK, PLL_FIX, true),
445 CLK_MGT_ENTRY(BMLCLK), 456 CLK_MGT_ENTRY(BMLCLK, PLL_DIV, true),
446 CLK_MGT_ENTRY(HSITXCLK), 457 CLK_MGT_ENTRY(HSITXCLK, PLL_DIV, true),
447 CLK_MGT_ENTRY(HSIRXCLK), 458 CLK_MGT_ENTRY(HSIRXCLK, PLL_DIV, true),
448 CLK_MGT_ENTRY(HDMICLK), 459 CLK_MGT_ENTRY(HDMICLK, PLL_FIX, false),
449 CLK_MGT_ENTRY(APEATCLK), 460 CLK_MGT_ENTRY(APEATCLK, PLL_DIV, true),
450 CLK_MGT_ENTRY(APETRACECLK), 461 CLK_MGT_ENTRY(APETRACECLK, PLL_DIV, true),
451 CLK_MGT_ENTRY(MCDECLK), 462 CLK_MGT_ENTRY(MCDECLK, PLL_DIV, true),
452 CLK_MGT_ENTRY(IPI2CCLK), 463 CLK_MGT_ENTRY(IPI2CCLK, PLL_FIX, true),
453 CLK_MGT_ENTRY(DSIALTCLK), 464 CLK_MGT_ENTRY(DSIALTCLK, PLL_FIX, false),
454 CLK_MGT_ENTRY(DMACLK), 465 CLK_MGT_ENTRY(DMACLK, PLL_DIV, true),
455 CLK_MGT_ENTRY(B2R2CLK), 466 CLK_MGT_ENTRY(B2R2CLK, PLL_DIV, true),
456 CLK_MGT_ENTRY(TVCLK), 467 CLK_MGT_ENTRY(TVCLK, PLL_FIX, true),
457 CLK_MGT_ENTRY(SSPCLK), 468 CLK_MGT_ENTRY(SSPCLK, PLL_FIX, true),
458 CLK_MGT_ENTRY(RNGCLK), 469 CLK_MGT_ENTRY(RNGCLK, PLL_FIX, true),
459 CLK_MGT_ENTRY(UICCCLK), 470 CLK_MGT_ENTRY(UICCCLK, PLL_FIX, false),
471};
472
473struct dsiclk {
474 u32 divsel_mask;
475 u32 divsel_shift;
476 u32 divsel;
477};
478
479static struct dsiclk dsiclk[2] = {
480 {
481 .divsel_mask = PRCM_DSI_PLLOUT_SEL_DSI0_PLLOUT_DIVSEL_MASK,
482 .divsel_shift = PRCM_DSI_PLLOUT_SEL_DSI0_PLLOUT_DIVSEL_SHIFT,
483 .divsel = PRCM_DSI_PLLOUT_SEL_PHI,
484 },
485 {
486 .divsel_mask = PRCM_DSI_PLLOUT_SEL_DSI1_PLLOUT_DIVSEL_MASK,
487 .divsel_shift = PRCM_DSI_PLLOUT_SEL_DSI1_PLLOUT_DIVSEL_SHIFT,
488 .divsel = PRCM_DSI_PLLOUT_SEL_PHI,
489 }
490};
491
492struct dsiescclk {
493 u32 en;
494 u32 div_mask;
495 u32 div_shift;
496};
497
498static struct dsiescclk dsiescclk[3] = {
499 {
500 .en = PRCM_DSITVCLK_DIV_DSI0_ESC_CLK_EN,
501 .div_mask = PRCM_DSITVCLK_DIV_DSI0_ESC_CLK_DIV_MASK,
502 .div_shift = PRCM_DSITVCLK_DIV_DSI0_ESC_CLK_DIV_SHIFT,
503 },
504 {
505 .en = PRCM_DSITVCLK_DIV_DSI1_ESC_CLK_EN,
506 .div_mask = PRCM_DSITVCLK_DIV_DSI1_ESC_CLK_DIV_MASK,
507 .div_shift = PRCM_DSITVCLK_DIV_DSI1_ESC_CLK_DIV_SHIFT,
508 },
509 {
510 .en = PRCM_DSITVCLK_DIV_DSI2_ESC_CLK_EN,
511 .div_mask = PRCM_DSITVCLK_DIV_DSI2_ESC_CLK_DIV_MASK,
512 .div_shift = PRCM_DSITVCLK_DIV_DSI2_ESC_CLK_DIV_SHIFT,
513 }
460}; 514};
461 515
462static struct regulator *hwacc_regulator[NUM_HW_ACC]; 516static struct regulator *hwacc_regulator[NUM_HW_ACC];
@@ -910,6 +964,7 @@ int db8500_prcmu_set_ddr_opp(u8 opp)
910 964
911 return 0; 965 return 0;
912} 966}
967
913/** 968/**
914 * db8500_set_ape_opp - set the appropriate APE OPP 969 * db8500_set_ape_opp - set the appropriate APE OPP
915 * @opp: The new APE operating point to which transition is to be made 970 * @opp: The new APE operating point to which transition is to be made
@@ -1031,7 +1086,9 @@ static int request_pll(u8 clock, bool enable)
1031{ 1086{
1032 int r = 0; 1087 int r = 0;
1033 1088
1034 if (clock == PRCMU_PLLSOC1) 1089 if (clock == PRCMU_PLLSOC0)
1090 clock = (enable ? PLL_SOC0_ON : PLL_SOC0_OFF);
1091 else if (clock == PRCMU_PLLSOC1)
1035 clock = (enable ? PLL_SOC1_ON : PLL_SOC1_OFF); 1092 clock = (enable ? PLL_SOC1_ON : PLL_SOC1_OFF);
1036 else 1093 else
1037 return -EINVAL; 1094 return -EINVAL;
@@ -1350,7 +1407,7 @@ static int request_timclk(bool enable)
1350 return 0; 1407 return 0;
1351} 1408}
1352 1409
1353static int request_reg_clock(u8 clock, bool enable) 1410static int request_clock(u8 clock, bool enable)
1354{ 1411{
1355 u32 val; 1412 u32 val;
1356 unsigned long flags; 1413 unsigned long flags;
@@ -1361,14 +1418,14 @@ static int request_reg_clock(u8 clock, bool enable)
1361 while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0) 1418 while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0)
1362 cpu_relax(); 1419 cpu_relax();
1363 1420
1364 val = readl(_PRCMU_BASE + clk_mgt[clock].offset); 1421 val = readl(clk_mgt[clock].reg);
1365 if (enable) { 1422 if (enable) {
1366 val |= (PRCM_CLK_MGT_CLKEN | clk_mgt[clock].pllsw); 1423 val |= (PRCM_CLK_MGT_CLKEN | clk_mgt[clock].pllsw);
1367 } else { 1424 } else {
1368 clk_mgt[clock].pllsw = (val & PRCM_CLK_MGT_CLKPLLSW_MASK); 1425 clk_mgt[clock].pllsw = (val & PRCM_CLK_MGT_CLKPLLSW_MASK);
1369 val &= ~(PRCM_CLK_MGT_CLKEN | PRCM_CLK_MGT_CLKPLLSW_MASK); 1426 val &= ~(PRCM_CLK_MGT_CLKEN | PRCM_CLK_MGT_CLKPLLSW_MASK);
1370 } 1427 }
1371 writel(val, (_PRCMU_BASE + clk_mgt[clock].offset)); 1428 writel(val, clk_mgt[clock].reg);
1372 1429
1373 /* Release the HW semaphore. */ 1430 /* Release the HW semaphore. */
1374 writel(0, PRCM_SEM); 1431 writel(0, PRCM_SEM);
@@ -1388,7 +1445,7 @@ static int request_sga_clock(u8 clock, bool enable)
1388 writel(val | PRCM_CGATING_BYPASS_ICN2, PRCM_CGATING_BYPASS); 1445 writel(val | PRCM_CGATING_BYPASS_ICN2, PRCM_CGATING_BYPASS);
1389 } 1446 }
1390 1447
1391 ret = request_reg_clock(clock, enable); 1448 ret = request_clock(clock, enable);
1392 1449
1393 if (!ret && !enable) { 1450 if (!ret && !enable) {
1394 val = readl(PRCM_CGATING_BYPASS); 1451 val = readl(PRCM_CGATING_BYPASS);
@@ -1398,6 +1455,78 @@ static int request_sga_clock(u8 clock, bool enable)
1398 return ret; 1455 return ret;
1399} 1456}
1400 1457
1458static inline bool plldsi_locked(void)
1459{
1460 return (readl(PRCM_PLLDSI_LOCKP) &
1461 (PRCM_PLLDSI_LOCKP_PRCM_PLLDSI_LOCKP10 |
1462 PRCM_PLLDSI_LOCKP_PRCM_PLLDSI_LOCKP3)) ==
1463 (PRCM_PLLDSI_LOCKP_PRCM_PLLDSI_LOCKP10 |
1464 PRCM_PLLDSI_LOCKP_PRCM_PLLDSI_LOCKP3);
1465}
1466
1467static int request_plldsi(bool enable)
1468{
1469 int r = 0;
1470 u32 val;
1471
1472 writel((PRCM_MMIP_LS_CLAMP_DSIPLL_CLAMP |
1473 PRCM_MMIP_LS_CLAMP_DSIPLL_CLAMPI), (enable ?
1474 PRCM_MMIP_LS_CLAMP_CLR : PRCM_MMIP_LS_CLAMP_SET));
1475
1476 val = readl(PRCM_PLLDSI_ENABLE);
1477 if (enable)
1478 val |= PRCM_PLLDSI_ENABLE_PRCM_PLLDSI_ENABLE;
1479 else
1480 val &= ~PRCM_PLLDSI_ENABLE_PRCM_PLLDSI_ENABLE;
1481 writel(val, PRCM_PLLDSI_ENABLE);
1482
1483 if (enable) {
1484 unsigned int i;
1485 bool locked = plldsi_locked();
1486
1487 for (i = 10; !locked && (i > 0); --i) {
1488 udelay(100);
1489 locked = plldsi_locked();
1490 }
1491 if (locked) {
1492 writel(PRCM_APE_RESETN_DSIPLL_RESETN,
1493 PRCM_APE_RESETN_SET);
1494 } else {
1495 writel((PRCM_MMIP_LS_CLAMP_DSIPLL_CLAMP |
1496 PRCM_MMIP_LS_CLAMP_DSIPLL_CLAMPI),
1497 PRCM_MMIP_LS_CLAMP_SET);
1498 val &= ~PRCM_PLLDSI_ENABLE_PRCM_PLLDSI_ENABLE;
1499 writel(val, PRCM_PLLDSI_ENABLE);
1500 r = -EAGAIN;
1501 }
1502 } else {
1503 writel(PRCM_APE_RESETN_DSIPLL_RESETN, PRCM_APE_RESETN_CLR);
1504 }
1505 return r;
1506}
1507
1508static int request_dsiclk(u8 n, bool enable)
1509{
1510 u32 val;
1511
1512 val = readl(PRCM_DSI_PLLOUT_SEL);
1513 val &= ~dsiclk[n].divsel_mask;
1514 val |= ((enable ? dsiclk[n].divsel : PRCM_DSI_PLLOUT_SEL_OFF) <<
1515 dsiclk[n].divsel_shift);
1516 writel(val, PRCM_DSI_PLLOUT_SEL);
1517 return 0;
1518}
1519
1520static int request_dsiescclk(u8 n, bool enable)
1521{
1522 u32 val;
1523
1524 val = readl(PRCM_DSITVCLK_DIV);
1525 enable ? (val |= dsiescclk[n].en) : (val &= ~dsiescclk[n].en);
1526 writel(val, PRCM_DSITVCLK_DIV);
1527 return 0;
1528}
1529
1401/** 1530/**
1402 * db8500_prcmu_request_clock() - Request for a clock to be enabled or disabled. 1531 * db8500_prcmu_request_clock() - Request for a clock to be enabled or disabled.
1403 * @clock: The clock for which the request is made. 1532 * @clock: The clock for which the request is made.
@@ -1408,21 +1537,435 @@ static int request_sga_clock(u8 clock, bool enable)
1408 */ 1537 */
1409int db8500_prcmu_request_clock(u8 clock, bool enable) 1538int db8500_prcmu_request_clock(u8 clock, bool enable)
1410{ 1539{
1411 switch(clock) { 1540 if (clock == PRCMU_SGACLK)
1412 case PRCMU_SGACLK:
1413 return request_sga_clock(clock, enable); 1541 return request_sga_clock(clock, enable);
1414 case PRCMU_TIMCLK: 1542 else if (clock < PRCMU_NUM_REG_CLOCKS)
1543 return request_clock(clock, enable);
1544 else if (clock == PRCMU_TIMCLK)
1415 return request_timclk(enable); 1545 return request_timclk(enable);
1416 case PRCMU_SYSCLK: 1546 else if ((clock == PRCMU_DSI0CLK) || (clock == PRCMU_DSI1CLK))
1547 return request_dsiclk((clock - PRCMU_DSI0CLK), enable);
1548 else if ((PRCMU_DSI0ESCCLK <= clock) && (clock <= PRCMU_DSI2ESCCLK))
1549 return request_dsiescclk((clock - PRCMU_DSI0ESCCLK), enable);
1550 else if (clock == PRCMU_PLLDSI)
1551 return request_plldsi(enable);
1552 else if (clock == PRCMU_SYSCLK)
1417 return request_sysclk(enable); 1553 return request_sysclk(enable);
1418 case PRCMU_PLLSOC1: 1554 else if ((clock == PRCMU_PLLSOC0) || (clock == PRCMU_PLLSOC1))
1419 return request_pll(clock, enable); 1555 return request_pll(clock, enable);
1556 else
1557 return -EINVAL;
1558}
1559
1560static unsigned long pll_rate(void __iomem *reg, unsigned long src_rate,
1561 int branch)
1562{
1563 u64 rate;
1564 u32 val;
1565 u32 d;
1566 u32 div = 1;
1567
1568 val = readl(reg);
1569
1570 rate = src_rate;
1571 rate *= ((val & PRCM_PLL_FREQ_D_MASK) >> PRCM_PLL_FREQ_D_SHIFT);
1572
1573 d = ((val & PRCM_PLL_FREQ_N_MASK) >> PRCM_PLL_FREQ_N_SHIFT);
1574 if (d > 1)
1575 div *= d;
1576
1577 d = ((val & PRCM_PLL_FREQ_R_MASK) >> PRCM_PLL_FREQ_R_SHIFT);
1578 if (d > 1)
1579 div *= d;
1580
1581 if (val & PRCM_PLL_FREQ_SELDIV2)
1582 div *= 2;
1583
1584 if ((branch == PLL_FIX) || ((branch == PLL_DIV) &&
1585 (val & PRCM_PLL_FREQ_DIV2EN) &&
1586 ((reg == PRCM_PLLSOC0_FREQ) ||
1587 (reg == PRCM_PLLDDR_FREQ))))
1588 div *= 2;
1589
1590 (void)do_div(rate, div);
1591
1592 return (unsigned long)rate;
1593}
1594
1595#define ROOT_CLOCK_RATE 38400000
1596
1597static unsigned long clock_rate(u8 clock)
1598{
1599 u32 val;
1600 u32 pllsw;
1601 unsigned long rate = ROOT_CLOCK_RATE;
1602
1603 val = readl(clk_mgt[clock].reg);
1604
1605 if (val & PRCM_CLK_MGT_CLK38) {
1606 if (clk_mgt[clock].clk38div && (val & PRCM_CLK_MGT_CLK38DIV))
1607 rate /= 2;
1608 return rate;
1609 }
1610
1611 val |= clk_mgt[clock].pllsw;
1612 pllsw = (val & PRCM_CLK_MGT_CLKPLLSW_MASK);
1613
1614 if (pllsw == PRCM_CLK_MGT_CLKPLLSW_SOC0)
1615 rate = pll_rate(PRCM_PLLSOC0_FREQ, rate, clk_mgt[clock].branch);
1616 else if (pllsw == PRCM_CLK_MGT_CLKPLLSW_SOC1)
1617 rate = pll_rate(PRCM_PLLSOC1_FREQ, rate, clk_mgt[clock].branch);
1618 else if (pllsw == PRCM_CLK_MGT_CLKPLLSW_DDR)
1619 rate = pll_rate(PRCM_PLLDDR_FREQ, rate, clk_mgt[clock].branch);
1620 else
1621 return 0;
1622
1623 if ((clock == PRCMU_SGACLK) &&
1624 (val & PRCM_SGACLK_MGT_SGACLKDIV_BY_2_5_EN)) {
1625 u64 r = (rate * 10);
1626
1627 (void)do_div(r, 25);
1628 return (unsigned long)r;
1629 }
1630 val &= PRCM_CLK_MGT_CLKPLLDIV_MASK;
1631 if (val)
1632 return rate / val;
1633 else
1634 return 0;
1635}
1636
1637static unsigned long dsiclk_rate(u8 n)
1638{
1639 u32 divsel;
1640 u32 div = 1;
1641
1642 divsel = readl(PRCM_DSI_PLLOUT_SEL);
1643 divsel = ((divsel & dsiclk[n].divsel_mask) >> dsiclk[n].divsel_shift);
1644
1645 if (divsel == PRCM_DSI_PLLOUT_SEL_OFF)
1646 divsel = dsiclk[n].divsel;
1647
1648 switch (divsel) {
1649 case PRCM_DSI_PLLOUT_SEL_PHI_4:
1650 div *= 2;
1651 case PRCM_DSI_PLLOUT_SEL_PHI_2:
1652 div *= 2;
1653 case PRCM_DSI_PLLOUT_SEL_PHI:
1654 return pll_rate(PRCM_PLLDSI_FREQ, clock_rate(PRCMU_HDMICLK),
1655 PLL_RAW) / div;
1420 default: 1656 default:
1421 break; 1657 return 0;
1422 } 1658 }
1659}
1660
1661static unsigned long dsiescclk_rate(u8 n)
1662{
1663 u32 div;
1664
1665 div = readl(PRCM_DSITVCLK_DIV);
1666 div = ((div & dsiescclk[n].div_mask) >> (dsiescclk[n].div_shift));
1667 return clock_rate(PRCMU_TVCLK) / max((u32)1, div);
1668}
1669
1670unsigned long prcmu_clock_rate(u8 clock)
1671{
1423 if (clock < PRCMU_NUM_REG_CLOCKS) 1672 if (clock < PRCMU_NUM_REG_CLOCKS)
1424 return request_reg_clock(clock, enable); 1673 return clock_rate(clock);
1425 return -EINVAL; 1674 else if (clock == PRCMU_TIMCLK)
1675 return ROOT_CLOCK_RATE / 16;
1676 else if (clock == PRCMU_SYSCLK)
1677 return ROOT_CLOCK_RATE;
1678 else if (clock == PRCMU_PLLSOC0)
1679 return pll_rate(PRCM_PLLSOC0_FREQ, ROOT_CLOCK_RATE, PLL_RAW);
1680 else if (clock == PRCMU_PLLSOC1)
1681 return pll_rate(PRCM_PLLSOC1_FREQ, ROOT_CLOCK_RATE, PLL_RAW);
1682 else if (clock == PRCMU_PLLDDR)
1683 return pll_rate(PRCM_PLLDDR_FREQ, ROOT_CLOCK_RATE, PLL_RAW);
1684 else if (clock == PRCMU_PLLDSI)
1685 return pll_rate(PRCM_PLLDSI_FREQ, clock_rate(PRCMU_HDMICLK),
1686 PLL_RAW);
1687 else if ((clock == PRCMU_DSI0CLK) || (clock == PRCMU_DSI1CLK))
1688 return dsiclk_rate(clock - PRCMU_DSI0CLK);
1689 else if ((PRCMU_DSI0ESCCLK <= clock) && (clock <= PRCMU_DSI2ESCCLK))
1690 return dsiescclk_rate(clock - PRCMU_DSI0ESCCLK);
1691 else
1692 return 0;
1693}
1694
1695static unsigned long clock_source_rate(u32 clk_mgt_val, int branch)
1696{
1697 if (clk_mgt_val & PRCM_CLK_MGT_CLK38)
1698 return ROOT_CLOCK_RATE;
1699 clk_mgt_val &= PRCM_CLK_MGT_CLKPLLSW_MASK;
1700 if (clk_mgt_val == PRCM_CLK_MGT_CLKPLLSW_SOC0)
1701 return pll_rate(PRCM_PLLSOC0_FREQ, ROOT_CLOCK_RATE, branch);
1702 else if (clk_mgt_val == PRCM_CLK_MGT_CLKPLLSW_SOC1)
1703 return pll_rate(PRCM_PLLSOC1_FREQ, ROOT_CLOCK_RATE, branch);
1704 else if (clk_mgt_val == PRCM_CLK_MGT_CLKPLLSW_DDR)
1705 return pll_rate(PRCM_PLLDDR_FREQ, ROOT_CLOCK_RATE, branch);
1706 else
1707 return 0;
1708}
1709
1710static u32 clock_divider(unsigned long src_rate, unsigned long rate)
1711{
1712 u32 div;
1713
1714 div = (src_rate / rate);
1715 if (div == 0)
1716 return 1;
1717 if (rate < (src_rate / div))
1718 div++;
1719 return div;
1720}
1721
1722static long round_clock_rate(u8 clock, unsigned long rate)
1723{
1724 u32 val;
1725 u32 div;
1726 unsigned long src_rate;
1727 long rounded_rate;
1728
1729 val = readl(clk_mgt[clock].reg);
1730 src_rate = clock_source_rate((val | clk_mgt[clock].pllsw),
1731 clk_mgt[clock].branch);
1732 div = clock_divider(src_rate, rate);
1733 if (val & PRCM_CLK_MGT_CLK38) {
1734 if (clk_mgt[clock].clk38div) {
1735 if (div > 2)
1736 div = 2;
1737 } else {
1738 div = 1;
1739 }
1740 } else if ((clock == PRCMU_SGACLK) && (div == 3)) {
1741 u64 r = (src_rate * 10);
1742
1743 (void)do_div(r, 25);
1744 if (r <= rate)
1745 return (unsigned long)r;
1746 }
1747 rounded_rate = (src_rate / min(div, (u32)31));
1748
1749 return rounded_rate;
1750}
1751
1752#define MIN_PLL_VCO_RATE 600000000ULL
1753#define MAX_PLL_VCO_RATE 1680640000ULL
1754
1755static long round_plldsi_rate(unsigned long rate)
1756{
1757 long rounded_rate = 0;
1758 unsigned long src_rate;
1759 unsigned long rem;
1760 u32 r;
1761
1762 src_rate = clock_rate(PRCMU_HDMICLK);
1763 rem = rate;
1764
1765 for (r = 7; (rem > 0) && (r > 0); r--) {
1766 u64 d;
1767
1768 d = (r * rate);
1769 (void)do_div(d, src_rate);
1770 if (d < 6)
1771 d = 6;
1772 else if (d > 255)
1773 d = 255;
1774 d *= src_rate;
1775 if (((2 * d) < (r * MIN_PLL_VCO_RATE)) ||
1776 ((r * MAX_PLL_VCO_RATE) < (2 * d)))
1777 continue;
1778 (void)do_div(d, r);
1779 if (rate < d) {
1780 if (rounded_rate == 0)
1781 rounded_rate = (long)d;
1782 break;
1783 }
1784 if ((rate - d) < rem) {
1785 rem = (rate - d);
1786 rounded_rate = (long)d;
1787 }
1788 }
1789 return rounded_rate;
1790}
1791
1792static long round_dsiclk_rate(unsigned long rate)
1793{
1794 u32 div;
1795 unsigned long src_rate;
1796 long rounded_rate;
1797
1798 src_rate = pll_rate(PRCM_PLLDSI_FREQ, clock_rate(PRCMU_HDMICLK),
1799 PLL_RAW);
1800 div = clock_divider(src_rate, rate);
1801 rounded_rate = (src_rate / ((div > 2) ? 4 : div));
1802
1803 return rounded_rate;
1804}
1805
1806static long round_dsiescclk_rate(unsigned long rate)
1807{
1808 u32 div;
1809 unsigned long src_rate;
1810 long rounded_rate;
1811
1812 src_rate = clock_rate(PRCMU_TVCLK);
1813 div = clock_divider(src_rate, rate);
1814 rounded_rate = (src_rate / min(div, (u32)255));
1815
1816 return rounded_rate;
1817}
1818
1819long prcmu_round_clock_rate(u8 clock, unsigned long rate)
1820{
1821 if (clock < PRCMU_NUM_REG_CLOCKS)
1822 return round_clock_rate(clock, rate);
1823 else if (clock == PRCMU_PLLDSI)
1824 return round_plldsi_rate(rate);
1825 else if ((clock == PRCMU_DSI0CLK) || (clock == PRCMU_DSI1CLK))
1826 return round_dsiclk_rate(rate);
1827 else if ((PRCMU_DSI0ESCCLK <= clock) && (clock <= PRCMU_DSI2ESCCLK))
1828 return round_dsiescclk_rate(rate);
1829 else
1830 return (long)prcmu_clock_rate(clock);
1831}
1832
1833static void set_clock_rate(u8 clock, unsigned long rate)
1834{
1835 u32 val;
1836 u32 div;
1837 unsigned long src_rate;
1838 unsigned long flags;
1839
1840 spin_lock_irqsave(&clk_mgt_lock, flags);
1841
1842 /* Grab the HW semaphore. */
1843 while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0)
1844 cpu_relax();
1845
1846 val = readl(clk_mgt[clock].reg);
1847 src_rate = clock_source_rate((val | clk_mgt[clock].pllsw),
1848 clk_mgt[clock].branch);
1849 div = clock_divider(src_rate, rate);
1850 if (val & PRCM_CLK_MGT_CLK38) {
1851 if (clk_mgt[clock].clk38div) {
1852 if (div > 1)
1853 val |= PRCM_CLK_MGT_CLK38DIV;
1854 else
1855 val &= ~PRCM_CLK_MGT_CLK38DIV;
1856 }
1857 } else if (clock == PRCMU_SGACLK) {
1858 val &= ~(PRCM_CLK_MGT_CLKPLLDIV_MASK |
1859 PRCM_SGACLK_MGT_SGACLKDIV_BY_2_5_EN);
1860 if (div == 3) {
1861 u64 r = (src_rate * 10);
1862
1863 (void)do_div(r, 25);
1864 if (r <= rate) {
1865 val |= PRCM_SGACLK_MGT_SGACLKDIV_BY_2_5_EN;
1866 div = 0;
1867 }
1868 }
1869 val |= min(div, (u32)31);
1870 } else {
1871 val &= ~PRCM_CLK_MGT_CLKPLLDIV_MASK;
1872 val |= min(div, (u32)31);
1873 }
1874 writel(val, clk_mgt[clock].reg);
1875
1876 /* Release the HW semaphore. */
1877 writel(0, PRCM_SEM);
1878
1879 spin_unlock_irqrestore(&clk_mgt_lock, flags);
1880}
1881
1882static int set_plldsi_rate(unsigned long rate)
1883{
1884 unsigned long src_rate;
1885 unsigned long rem;
1886 u32 pll_freq = 0;
1887 u32 r;
1888
1889 src_rate = clock_rate(PRCMU_HDMICLK);
1890 rem = rate;
1891
1892 for (r = 7; (rem > 0) && (r > 0); r--) {
1893 u64 d;
1894 u64 hwrate;
1895
1896 d = (r * rate);
1897 (void)do_div(d, src_rate);
1898 if (d < 6)
1899 d = 6;
1900 else if (d > 255)
1901 d = 255;
1902 hwrate = (d * src_rate);
1903 if (((2 * hwrate) < (r * MIN_PLL_VCO_RATE)) ||
1904 ((r * MAX_PLL_VCO_RATE) < (2 * hwrate)))
1905 continue;
1906 (void)do_div(hwrate, r);
1907 if (rate < hwrate) {
1908 if (pll_freq == 0)
1909 pll_freq = (((u32)d << PRCM_PLL_FREQ_D_SHIFT) |
1910 (r << PRCM_PLL_FREQ_R_SHIFT));
1911 break;
1912 }
1913 if ((rate - hwrate) < rem) {
1914 rem = (rate - hwrate);
1915 pll_freq = (((u32)d << PRCM_PLL_FREQ_D_SHIFT) |
1916 (r << PRCM_PLL_FREQ_R_SHIFT));
1917 }
1918 }
1919 if (pll_freq == 0)
1920 return -EINVAL;
1921
1922 pll_freq |= (1 << PRCM_PLL_FREQ_N_SHIFT);
1923 writel(pll_freq, PRCM_PLLDSI_FREQ);
1924
1925 return 0;
1926}
1927
1928static void set_dsiclk_rate(u8 n, unsigned long rate)
1929{
1930 u32 val;
1931 u32 div;
1932
1933 div = clock_divider(pll_rate(PRCM_PLLDSI_FREQ,
1934 clock_rate(PRCMU_HDMICLK), PLL_RAW), rate);
1935
1936 dsiclk[n].divsel = (div == 1) ? PRCM_DSI_PLLOUT_SEL_PHI :
1937 (div == 2) ? PRCM_DSI_PLLOUT_SEL_PHI_2 :
1938 /* else */ PRCM_DSI_PLLOUT_SEL_PHI_4;
1939
1940 val = readl(PRCM_DSI_PLLOUT_SEL);
1941 val &= ~dsiclk[n].divsel_mask;
1942 val |= (dsiclk[n].divsel << dsiclk[n].divsel_shift);
1943 writel(val, PRCM_DSI_PLLOUT_SEL);
1944}
1945
1946static void set_dsiescclk_rate(u8 n, unsigned long rate)
1947{
1948 u32 val;
1949 u32 div;
1950
1951 div = clock_divider(clock_rate(PRCMU_TVCLK), rate);
1952 val = readl(PRCM_DSITVCLK_DIV);
1953 val &= ~dsiescclk[n].div_mask;
1954 val |= (min(div, (u32)255) << dsiescclk[n].div_shift);
1955 writel(val, PRCM_DSITVCLK_DIV);
1956}
1957
1958int prcmu_set_clock_rate(u8 clock, unsigned long rate)
1959{
1960 if (clock < PRCMU_NUM_REG_CLOCKS)
1961 set_clock_rate(clock, rate);
1962 else if (clock == PRCMU_PLLDSI)
1963 return set_plldsi_rate(rate);
1964 else if ((clock == PRCMU_DSI0CLK) || (clock == PRCMU_DSI1CLK))
1965 set_dsiclk_rate((clock - PRCMU_DSI0CLK), rate);
1966 else if ((PRCMU_DSI0ESCCLK <= clock) && (clock <= PRCMU_DSI2ESCCLK))
1967 set_dsiescclk_rate((clock - PRCMU_DSI0ESCCLK), rate);
1968 return 0;
1426} 1969}
1427 1970
1428int db8500_prcmu_config_esram0_deep_sleep(u8 state) 1971int db8500_prcmu_config_esram0_deep_sleep(u8 state)
@@ -1594,41 +2137,6 @@ int db8500_prcmu_load_a9wdog(u8 id, u32 timeout)
1594} 2137}
1595 2138
1596/** 2139/**
1597 * prcmu_set_clock_divider() - Configure the clock divider.
1598 * @clock: The clock for which the request is made.
1599 * @divider: The clock divider. (< 32)
1600 *
1601 * This function should only be used by the clock implementation.
1602 * Do not use it from any other place!
1603 */
1604int prcmu_set_clock_divider(u8 clock, u8 divider)
1605{
1606 u32 val;
1607 unsigned long flags;
1608
1609 if ((clock >= PRCMU_NUM_REG_CLOCKS) || (divider < 1) || (31 < divider))
1610 return -EINVAL;
1611
1612 spin_lock_irqsave(&clk_mgt_lock, flags);
1613
1614 /* Grab the HW semaphore. */
1615 while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0)
1616 cpu_relax();
1617
1618 val = readl(_PRCMU_BASE + clk_mgt[clock].offset);
1619 val &= ~(PRCM_CLK_MGT_CLKPLLDIV_MASK);
1620 val |= (u32)divider;
1621 writel(val, (_PRCMU_BASE + clk_mgt[clock].offset));
1622
1623 /* Release the HW semaphore. */
1624 writel(0, PRCM_SEM);
1625
1626 spin_unlock_irqrestore(&clk_mgt_lock, flags);
1627
1628 return 0;
1629}
1630
1631/**
1632 * prcmu_abb_read() - Read register value(s) from the ABB. 2140 * prcmu_abb_read() - Read register value(s) from the ABB.
1633 * @slave: The I2C slave address. 2141 * @slave: The I2C slave address.
1634 * @reg: The (start) register address. 2142 * @reg: The (start) register address.