From a668f3d89eb68745e90ccbd38b9f300ca16c4726 Mon Sep 17 00:00:00 2001 From: "Landon J. Fuller" Date: Mon, 20 Mar 2017 19:27:35 +0000 Subject: [PATCH] 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) --- sys/dev/bhnd/cores/chipc/chipcreg.h | 31 +++++++- sys/dev/bhnd/cores/pmu/bhnd_pmu_subr.c | 103 ++++++++++++++++++------- sys/dev/bhnd/cores/pmu/bhnd_pmureg.h | 18 +++++ 3 files changed, 119 insertions(+), 33 deletions(-) diff --git a/sys/dev/bhnd/cores/chipc/chipcreg.h b/sys/dev/bhnd/cores/chipc/chipcreg.h index db444bbbb10f..b94adca847b4 100644 --- a/sys/dev/bhnd/cores/chipc/chipcreg.h +++ b/sys/dev/bhnd/cores/chipc/chipcreg.h @@ -1,11 +1,11 @@ /*- * Copyright (c) 2015-2016 Landon Fuller - * 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] diff --git a/sys/dev/bhnd/cores/pmu/bhnd_pmu_subr.c b/sys/dev/bhnd/cores/pmu/bhnd_pmu_subr.c index 1df24ffa9571..7eafd3cc6ff6 100644 --- a/sys/dev/bhnd/cores/pmu/bhnd_pmu_subr.c +++ b/sys/dev/bhnd/cores/pmu/bhnd_pmu_subr.c @@ -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 */ diff --git a/sys/dev/bhnd/cores/pmu/bhnd_pmureg.h b/sys/dev/bhnd/cores/pmu/bhnd_pmureg.h index d05de4de1c05..9c11ef4194a3 100644 --- a/sys/dev/bhnd/cores/pmu/bhnd_pmureg.h +++ b/sys/dev/bhnd/cores/pmu/bhnd_pmureg.h @@ -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