drm/nva3/clk: Parse clock control registers more accurately
Signed-off-by: Roy Spliet <rspliet@eclipso.eu> Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
parent
17eac85a8c
commit
3d896d349e
1 changed files with 28 additions and 4 deletions
|
@ -20,6 +20,7 @@
|
||||||
* OTHER DEALINGS IN THE SOFTWARE.
|
* OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*
|
*
|
||||||
* Authors: Ben Skeggs
|
* Authors: Ben Skeggs
|
||||||
|
* Roy Spliet
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <subdev/bios.h>
|
#include <subdev/bios.h>
|
||||||
|
@ -42,9 +43,17 @@ static u32
|
||||||
read_vco(struct nva3_clock_priv *priv, int clk)
|
read_vco(struct nva3_clock_priv *priv, int clk)
|
||||||
{
|
{
|
||||||
u32 sctl = nv_rd32(priv, 0x4120 + (clk * 4));
|
u32 sctl = nv_rd32(priv, 0x4120 + (clk * 4));
|
||||||
if ((sctl & 0x00000030) != 0x00000030)
|
|
||||||
|
switch (sctl & 0x00000030) {
|
||||||
|
case 0x00000000:
|
||||||
|
return nv_device(priv)->crystal;
|
||||||
|
case 0x00000020:
|
||||||
return read_pll(priv, 0x41, 0x00e820);
|
return read_pll(priv, 0x41, 0x00e820);
|
||||||
return read_pll(priv, 0x42, 0x00e8a0);
|
case 0x00000030:
|
||||||
|
return read_pll(priv, 0x42, 0x00e8a0);
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32
|
static u32
|
||||||
|
@ -66,14 +75,25 @@ read_clk(struct nva3_clock_priv *priv, int clk, bool ignore_en)
|
||||||
if (!ignore_en && !(sctl & 0x00000100))
|
if (!ignore_en && !(sctl & 0x00000100))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
/* out_alt */
|
||||||
|
if (sctl & 0x00000400)
|
||||||
|
return 108000;
|
||||||
|
|
||||||
|
/* vco_out */
|
||||||
switch (sctl & 0x00003000) {
|
switch (sctl & 0x00003000) {
|
||||||
case 0x00000000:
|
case 0x00000000:
|
||||||
return nv_device(priv)->crystal;
|
if (!(sctl & 0x00000200))
|
||||||
|
return nv_device(priv)->crystal;
|
||||||
|
return 0;
|
||||||
case 0x00002000:
|
case 0x00002000:
|
||||||
if (sctl & 0x00000040)
|
if (sctl & 0x00000040)
|
||||||
return 108000;
|
return 108000;
|
||||||
return 100000;
|
return 100000;
|
||||||
case 0x00003000:
|
case 0x00003000:
|
||||||
|
/* vco_enable */
|
||||||
|
if (!(sctl & 0x00000001))
|
||||||
|
return 0;
|
||||||
|
|
||||||
sclk = read_vco(priv, clk);
|
sclk = read_vco(priv, clk);
|
||||||
sdiv = ((sctl & 0x003f0000) >> 16) + 2;
|
sdiv = ((sctl & 0x003f0000) >> 16) + 2;
|
||||||
return (sclk * 2) / sdiv;
|
return (sclk * 2) / sdiv;
|
||||||
|
@ -95,7 +115,9 @@ read_pll(struct nva3_clock_priv *priv, int clk, u32 pll)
|
||||||
N = (coef & 0x0000ff00) >> 8;
|
N = (coef & 0x0000ff00) >> 8;
|
||||||
P = (coef & 0x003f0000) >> 16;
|
P = (coef & 0x003f0000) >> 16;
|
||||||
|
|
||||||
/* no post-divider on these.. */
|
/* no post-divider on these..
|
||||||
|
* XXX: it looks more like two post-"dividers" that
|
||||||
|
* cross each other out in the default RPLL config */
|
||||||
if ((pll & 0x00ff00) == 0x00e800)
|
if ((pll & 0x00ff00) == 0x00e800)
|
||||||
P = 1;
|
P = 1;
|
||||||
|
|
||||||
|
@ -136,6 +158,8 @@ nva3_clock_read(struct nouveau_clock *clk, enum nv_clk_src src)
|
||||||
nv_error(clk, "invalid clock source %d\n", src);
|
nv_error(clk, "invalid clock source %d\n", src);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
Loading…
Add table
Reference in a new issue