Integrate BCM4706 PMU (rev6) support, derived from the ISC-licensed Broadcom

sbchipc.h and hndpmu.c sources included in the RT-N16 and later firmware
source drops.

Approved by:	adrian (mentor, implicit)
This commit is contained in:
Landon J. Fuller 2017-03-20 19:27:35 +00:00
parent b4fca5d4a7
commit a668f3d89e
3 changed files with 119 additions and 33 deletions

View File

@ -1,11 +1,11 @@
/*-
* Copyright (c) 2015-2016 Landon Fuller <landon@landonf.org>
* Copyright (c) 2010 Broadcom Corporation
* Copyright (c) 2010-2015 Broadcom Corporation
* All rights reserved.
*
* This file is derived from the sbchipc.h header distributed with
* Broadcom's initial brcm80211 Linux driver release, as
* contributed to the Linux staging repository.
* This file is derived from the sbchipc.h header contributed by Broadcom
* to to the Linux staging repository, as well as later revisions of sbchipc.h
* distributed with the Asus RT-N16 firmware source code release.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -928,6 +928,29 @@ enum {
#define CHIPC_CST43228_SDIO_OTP_PRESENT 0x10
#define CHIPC_CST43228_SDIO_RESET 0x20
/* 4706 chipstatus reg bits */
#define CHIPC_CST4706_LOWCOST_PKG (1<<0) /* 0: full-featured package 1: low-cost package */
#define CHIPC_CST4706_SFLASH_PRESENT (1<<1) /* 0: parallel, 1: serial flash is present */
#define CHIPC_CST4706_SFLASH_TYPE (1<<2) /* 0: 8b-p/ST-s flash, 1: 16b-p/Atmal-s flash */
#define CHIPC_CST4706_MIPS_BENDIAN (1<<3) /* 0: little, 1: big endian */
#define CHIPC_CST4706_PCIE1_DISABLE (1<<5) /* PCIE1 enable strap pin */
/* 4706 flashstrconfig reg bits */
#define CHIPC_FLSTRCF4706_MASK 0x000000ff
#define CHIPC_FLSTRCF4706_SF1 0x00000001 /* 2nd serial flash present */
#define CHIPC_FLSTRCF4706_PF1 0x00000002 /* 2nd parallel flash present */
#define CHIPC_FLSTRCF4706_SF1_TYPE 0x00000004 /* 2nd serial flash type : 0 : ST, 1 : Atmel */
#define CHIPC_FLSTRCF4706_NF1 0x00000008 /* 2nd NAND flash present */
#define CHIPC_FLSTRCF4706_1ST_MADDR_SEG_MASK 0x000000f0 /* Valid value mask */
#define CHIPC_FLSTRCF4706_1ST_MADDR_SEG_SHIFT 4
#define CHIPC_FLSTRCF4706_1ST_MADDR_SEG_4MB 0x1 /* 4MB */
#define CHIPC_FLSTRCF4706_1ST_MADDR_SEG_8MB 0x2 /* 8MB */
#define CHIPC_FLSTRCF4706_1ST_MADDR_SEG_16MB 0x3 /* 16MB */
#define CHIPC_FLSTRCF4706_1ST_MADDR_SEG_32MB 0x4 /* 32MB */
#define CHIPC_FLSTRCF4706_1ST_MADDR_SEG_64MB 0x5 /* 64MB */
#define CHIPC_FLSTRCF4706_1ST_MADDR_SEG_128MB 0x6 /* 128MB */
#define CHIPC_FLSTRCF4706_1ST_MADDR_SEG_256MB 0x7 /* 256MB */
/*
* Register eci_inputlo bitfield values.
* - BT packet type information bits [7:0]

View File

@ -69,6 +69,9 @@ static uint32_t bhnd_pmu1_alpclk0(struct bhnd_pmu_query *sc);
static uint32_t bhnd_pmu5_clock(struct bhnd_pmu_query *sc, u_int pll0, u_int m);
static uint32_t bhnd_pmu6_4706_clock(struct bhnd_pmu_query *sc, u_int pll0,
u_int m);
/* PMU resources */
static bool bhnd_pmu_res_depfltr_bb(struct bhnd_pmu_softc *sc);
static bool bhnd_pmu_res_depfltr_ncb(struct bhnd_pmu_softc *sc);
@ -2329,6 +2332,47 @@ bhnd_pmu5_clock(struct bhnd_pmu_query *sc, u_int pll0, u_int m)
return ((fc / div) * 1000000);
}
static uint32_t
bhnd_pmu6_4706_clock(struct bhnd_pmu_query *sc, u_int pll0, u_int m)
{
uint32_t chipst, clock;
uint32_t ndiv, p1div, p2div, tmp;
/* Get N, P1 and P2 dividers to determine CPU clock */
BHND_PMU_WRITE_4(sc, BHND_PMU_PLL_CONTROL_ADDR,
pll0 + BHND_PMU6_4706_PROCPLL_OFF);
BHND_PMU_READ_4(sc, BHND_PMU_PLL_CONTROL_ADDR);
tmp = BHND_PMU_READ_4(sc, BHND_PMU_PLL_CONTROL_DATA);
ndiv = BHND_PMU_GET_BITS(tmp, BHND_PMU6_4706_PROC_NDIV_INT);
p1div = BHND_PMU_GET_BITS(tmp, BHND_PMU6_4706_PROC_P1DIV);
p2div = BHND_PMU_GET_BITS(tmp, BHND_PMU6_4706_PROC_P2DIV);
/* Fixed 25MHz reference clock */
clock = 25 * 1000 * 1000;
/* The low-cost bonding uses an input divider of 4; otherwise, 2 */
chipst = sc->io->rd_chipst(sc->io_ctx);
if (chipst & CHIPC_CST4706_LOWCOST_PKG)
clock /= 4;
else
clock /= 2;
clock *= ndiv * p2div / p1div;
switch (m) {
case BHND_PMU6_MAINPLL_CPU:
return (clock);
case BHND_PMU6_MAINPLL_MEM:
return (clock / 2);
case BHND_PMU6_MAINPLL_SI:
return (clock / 4);
default:
PMU_LOG(sc, "bad m divider: %d", m);
return (0);
}
}
/**
* Return the backplane clock frequency, in Hz.
*
@ -2425,6 +2469,10 @@ bhnd_pmu_si_clock(struct bhnd_pmu_query *sc)
clock = bhnd_pmu5_clock(sc, BHND_PMU5357_MAINPLL_PLL0,
BHND_PMU5_MAINPLL_SI);
break;
case BHND_CHIPID_BCM4706:
clock = bhnd_pmu6_4706_clock(sc, BHND_PMU4706_MAINPLL_PLL0,
BHND_PMU6_MAINPLL_SI);
break;
case BHND_CHIPID_BCM53572:
clock = 75000000;
break;
@ -2446,8 +2494,6 @@ bhnd_pmu_si_clock(struct bhnd_pmu_query *sc)
uint32_t
bhnd_pmu_cpu_clock(struct bhnd_pmu_query *sc)
{
uint32_t clock;
/* 5354 chip uses a non programmable PLL of frequency 240MHz */
if (sc->cid.chip_id == BHND_CHIPID_BCM5354)
return (240 * 1000 * 1000); /* 240MHz */
@ -2466,27 +2512,27 @@ bhnd_pmu_cpu_clock(struct bhnd_pmu_query *sc)
sc->cid.chip_id != BHND_CHIPID_BCM4336 &&
sc->cid.chip_id != BHND_CHIPID_BCM4330)
{
u_int pll;
switch (sc->cid.chip_id) {
case BHND_CHIPID_BCM5356:
pll = BHND_PMU5356_MAINPLL_PLL0;
break;
return (bhnd_pmu5_clock(sc, BHND_PMU5356_MAINPLL_PLL0,
BHND_PMU5_MAINPLL_CPU));
case BHND_CHIPID_BCM5357:
case BHND_CHIPID_BCM4749:
pll = BHND_PMU5357_MAINPLL_PLL0;
break;
return (bhnd_pmu5_clock(sc, BHND_PMU5357_MAINPLL_PLL0,
BHND_PMU5_MAINPLL_CPU));
case BHND_CHIPID_BCM4706:
return (bhnd_pmu6_4706_clock(sc,
BHND_PMU4706_MAINPLL_PLL0, BHND_PMU6_MAINPLL_CPU));
default:
pll = BHND_PMU4716_MAINPLL_PLL0;
break;
return (bhnd_pmu5_clock(sc, BHND_PMU4716_MAINPLL_PLL0,
BHND_PMU5_MAINPLL_CPU));
}
clock = bhnd_pmu5_clock(sc, pll, BHND_PMU5_MAINPLL_CPU);
} else {
clock = bhnd_pmu_si_clock(sc);
return (bhnd_pmu_si_clock(sc));
}
return (clock);
}
/**
@ -2497,8 +2543,6 @@ bhnd_pmu_cpu_clock(struct bhnd_pmu_query *sc)
uint32_t
bhnd_pmu_mem_clock(struct bhnd_pmu_query *sc)
{
uint32_t clock;
if (BHND_PMU_REV(sc) >= 5 &&
sc->cid.chip_id != BHND_CHIPID_BCM4329 &&
sc->cid.chip_id != BHND_CHIPID_BCM4319 &&
@ -2510,27 +2554,28 @@ bhnd_pmu_mem_clock(struct bhnd_pmu_query *sc)
sc->cid.chip_id != BHND_CHIPID_BCM4336 &&
sc->cid.chip_id != BHND_CHIPID_BCM4330)
{
u_int pll;
switch (sc->cid.chip_id) {
case BHND_CHIPID_BCM5356:
pll = BHND_PMU5356_MAINPLL_PLL0;
break;
return (bhnd_pmu5_clock(sc, BHND_PMU5356_MAINPLL_PLL0,
BHND_PMU5_MAINPLL_MEM));
case BHND_CHIPID_BCM5357:
case BHND_CHIPID_BCM4749:
pll = BHND_PMU5357_MAINPLL_PLL0;
break;
return (bhnd_pmu5_clock(sc, BHND_PMU5357_MAINPLL_PLL0,
BHND_PMU5_MAINPLL_MEM));
case BHND_CHIPID_BCM4706:
return (bhnd_pmu6_4706_clock(sc,
BHND_PMU4706_MAINPLL_PLL0, BHND_PMU6_MAINPLL_MEM));
default:
pll = BHND_PMU4716_MAINPLL_PLL0;
break;
return (bhnd_pmu5_clock(sc, BHND_PMU4716_MAINPLL_PLL0,
BHND_PMU5_MAINPLL_MEM));
}
clock = bhnd_pmu5_clock(sc, pll, BHND_PMU5_MAINPLL_MEM);
} else {
clock = bhnd_pmu_si_clock(sc);
return (bhnd_pmu_si_clock(sc));
}
return (clock);
}
/* Measure ILP clock frequency */

View File

@ -370,6 +370,24 @@
#define BHND_PMU5_MAINPLL_MEM 2
#define BHND_PMU5_MAINPLL_SI 3
/* PMU rev 6 (BCM4706/Northstar) */
#define BHND_PMU4706_MAINPLL_PLL0 0
#define BHND_PMU6_4706_PROCPLL_OFF 4 /* The CPU PLL */
#define BHND_PMU6_4706_PROC_P1DIV_MASK 0x000f0000
#define BHND_PMU6_4706_PROC_P1DIV_SHIFT 16
#define BHND_PMU6_4706_PROC_P2DIV_MASK 0x0000f000
#define BHND_PMU6_4706_PROC_P2DIV_SHIFT 12
#define BHND_PMU6_4706_PROC_NDIV_INT_MASK 0x00000ff8
#define BHND_PMU6_4706_PROC_NDIV_INT_SHIFT 3
#define BHND_PMU6_4706_PROC_NDIV_MODE_MASK 0x00000007
#define BHND_PMU6_4706_PROC_NDIV_MODE_SHIFT 0
/* Divider allocation in 4706 */
#define BHND_PMU6_MAINPLL_CPU 1
#define BHND_PMU6_MAINPLL_MEM 2
#define BHND_PMU6_MAINPLL_SI 3
/* PMU7 (?) */
#define BHND_PMU7_PLL_PLLCTL7 7
#define BHND_PMU7_PLL_PLLCTL8 8
#define BHND_PMU7_PLL_PLLCTL11 11