162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * Copyright (c) 2011 Broadcom Corporation
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Permission to use, copy, modify, and/or distribute this software for any
562306a36Sopenharmony_ci * purpose with or without fee is hereby granted, provided that the above
662306a36Sopenharmony_ci * copyright notice and this permission notice appear in all copies.
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
962306a36Sopenharmony_ci * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1062306a36Sopenharmony_ci * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
1162306a36Sopenharmony_ci * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1262306a36Sopenharmony_ci * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
1362306a36Sopenharmony_ci * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
1462306a36Sopenharmony_ci * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1562306a36Sopenharmony_ci */
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci#include <linux/delay.h>
1862306a36Sopenharmony_ci#include <linux/io.h>
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci#include <brcm_hw_ids.h>
2162306a36Sopenharmony_ci#include <chipcommon.h>
2262306a36Sopenharmony_ci#include <brcmu_utils.h>
2362306a36Sopenharmony_ci#include "pub.h"
2462306a36Sopenharmony_ci#include "aiutils.h"
2562306a36Sopenharmony_ci#include "pmu.h"
2662306a36Sopenharmony_ci#include "soc.h"
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci/*
2962306a36Sopenharmony_ci * external LPO crystal frequency
3062306a36Sopenharmony_ci */
3162306a36Sopenharmony_ci#define EXT_ILP_HZ 32768
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci/*
3462306a36Sopenharmony_ci * Duration for ILP clock frequency measurment in milliseconds
3562306a36Sopenharmony_ci *
3662306a36Sopenharmony_ci * remark: 1000 must be an integer multiple of this duration
3762306a36Sopenharmony_ci */
3862306a36Sopenharmony_ci#define ILP_CALC_DUR	10
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci/* Fields in pmucontrol */
4162306a36Sopenharmony_ci#define	PCTL_ILP_DIV_MASK	0xffff0000
4262306a36Sopenharmony_ci#define	PCTL_ILP_DIV_SHIFT	16
4362306a36Sopenharmony_ci#define PCTL_PLL_PLLCTL_UPD	0x00000400	/* rev 2 */
4462306a36Sopenharmony_ci#define PCTL_NOILP_ON_WAIT	0x00000200	/* rev 1 */
4562306a36Sopenharmony_ci#define	PCTL_HT_REQ_EN		0x00000100
4662306a36Sopenharmony_ci#define	PCTL_ALP_REQ_EN		0x00000080
4762306a36Sopenharmony_ci#define	PCTL_XTALFREQ_MASK	0x0000007c
4862306a36Sopenharmony_ci#define	PCTL_XTALFREQ_SHIFT	2
4962306a36Sopenharmony_ci#define	PCTL_ILP_DIV_EN		0x00000002
5062306a36Sopenharmony_ci#define	PCTL_LPO_SEL		0x00000001
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci/* ILP clock */
5362306a36Sopenharmony_ci#define	ILP_CLOCK		32000
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci/* ALP clock on pre-PMU chips */
5662306a36Sopenharmony_ci#define	ALP_CLOCK		20000000
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci/* pmustatus */
5962306a36Sopenharmony_ci#define PST_EXTLPOAVAIL	0x0100
6062306a36Sopenharmony_ci#define PST_WDRESET	0x0080
6162306a36Sopenharmony_ci#define	PST_INTPEND	0x0040
6262306a36Sopenharmony_ci#define	PST_SBCLKST	0x0030
6362306a36Sopenharmony_ci#define	PST_SBCLKST_ILP	0x0010
6462306a36Sopenharmony_ci#define	PST_SBCLKST_ALP	0x0020
6562306a36Sopenharmony_ci#define	PST_SBCLKST_HT	0x0030
6662306a36Sopenharmony_ci#define	PST_ALPAVAIL	0x0008
6762306a36Sopenharmony_ci#define	PST_HTAVAIL	0x0004
6862306a36Sopenharmony_ci#define	PST_RESINIT	0x0003
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci/* PMU resource bit position */
7162306a36Sopenharmony_ci#define PMURES_BIT(bit)	(1 << (bit))
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci/* PMU corerev and chip specific PLL controls.
7462306a36Sopenharmony_ci * PMU<rev>_PLL<num>_XX where <rev> is PMU corerev and <num> is an arbitrary
7562306a36Sopenharmony_ci * number to differentiate different PLLs controlled by the same PMU rev.
7662306a36Sopenharmony_ci */
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci/* pmu XtalFreqRatio */
7962306a36Sopenharmony_ci#define	PMU_XTALFREQ_REG_ILPCTR_MASK	0x00001FFF
8062306a36Sopenharmony_ci#define	PMU_XTALFREQ_REG_MEASURE_MASK	0x80000000
8162306a36Sopenharmony_ci#define	PMU_XTALFREQ_REG_MEASURE_SHIFT	31
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci/* 4313 resources */
8462306a36Sopenharmony_ci#define	RES4313_BB_PU_RSRC		0
8562306a36Sopenharmony_ci#define	RES4313_ILP_REQ_RSRC		1
8662306a36Sopenharmony_ci#define	RES4313_XTAL_PU_RSRC		2
8762306a36Sopenharmony_ci#define	RES4313_ALP_AVAIL_RSRC		3
8862306a36Sopenharmony_ci#define	RES4313_RADIO_PU_RSRC		4
8962306a36Sopenharmony_ci#define	RES4313_BG_PU_RSRC		5
9062306a36Sopenharmony_ci#define	RES4313_VREG1P4_PU_RSRC		6
9162306a36Sopenharmony_ci#define	RES4313_AFE_PWRSW_RSRC		7
9262306a36Sopenharmony_ci#define	RES4313_RX_PWRSW_RSRC		8
9362306a36Sopenharmony_ci#define	RES4313_TX_PWRSW_RSRC		9
9462306a36Sopenharmony_ci#define	RES4313_BB_PWRSW_RSRC		10
9562306a36Sopenharmony_ci#define	RES4313_SYNTH_PWRSW_RSRC	11
9662306a36Sopenharmony_ci#define	RES4313_MISC_PWRSW_RSRC		12
9762306a36Sopenharmony_ci#define	RES4313_BB_PLL_PWRSW_RSRC	13
9862306a36Sopenharmony_ci#define	RES4313_HT_AVAIL_RSRC		14
9962306a36Sopenharmony_ci#define	RES4313_MACPHY_CLK_AVAIL_RSRC	15
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ciu16 si_pmu_fast_pwrup_delay(struct si_pub *sih)
10262306a36Sopenharmony_ci{
10362306a36Sopenharmony_ci	uint delay = PMU_MAX_TRANSITION_DLY;
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci	switch (ai_get_chip_id(sih)) {
10662306a36Sopenharmony_ci	case BCMA_CHIP_ID_BCM43224:
10762306a36Sopenharmony_ci	case BCMA_CHIP_ID_BCM43225:
10862306a36Sopenharmony_ci	case BCMA_CHIP_ID_BCM4313:
10962306a36Sopenharmony_ci		delay = 3700;
11062306a36Sopenharmony_ci		break;
11162306a36Sopenharmony_ci	default:
11262306a36Sopenharmony_ci		break;
11362306a36Sopenharmony_ci	}
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci	return (u16) delay;
11662306a36Sopenharmony_ci}
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ciu32 si_pmu_measure_alpclk(struct si_pub *sih)
11962306a36Sopenharmony_ci{
12062306a36Sopenharmony_ci	struct si_info *sii = container_of(sih, struct si_info, pub);
12162306a36Sopenharmony_ci	struct bcma_device *core;
12262306a36Sopenharmony_ci	u32 alp_khz;
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci	if (ai_get_pmurev(sih) < 10)
12562306a36Sopenharmony_ci		return 0;
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci	/* Remember original core before switch to chipc */
12862306a36Sopenharmony_ci	core = sii->icbus->drv_cc.core;
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci	if (bcma_read32(core, CHIPCREGOFFS(pmustatus)) & PST_EXTLPOAVAIL) {
13162306a36Sopenharmony_ci		u32 ilp_ctr, alp_hz;
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci		/*
13462306a36Sopenharmony_ci		 * Enable the reg to measure the freq,
13562306a36Sopenharmony_ci		 * in case it was disabled before
13662306a36Sopenharmony_ci		 */
13762306a36Sopenharmony_ci		bcma_write32(core, CHIPCREGOFFS(pmu_xtalfreq),
13862306a36Sopenharmony_ci			    1U << PMU_XTALFREQ_REG_MEASURE_SHIFT);
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci		/* Delay for well over 4 ILP clocks */
14162306a36Sopenharmony_ci		udelay(1000);
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci		/* Read the latched number of ALP ticks per 4 ILP ticks */
14462306a36Sopenharmony_ci		ilp_ctr = bcma_read32(core, CHIPCREGOFFS(pmu_xtalfreq)) &
14562306a36Sopenharmony_ci			  PMU_XTALFREQ_REG_ILPCTR_MASK;
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci		/*
14862306a36Sopenharmony_ci		 * Turn off the PMU_XTALFREQ_REG_MEASURE_SHIFT
14962306a36Sopenharmony_ci		 * bit to save power
15062306a36Sopenharmony_ci		 */
15162306a36Sopenharmony_ci		bcma_write32(core, CHIPCREGOFFS(pmu_xtalfreq), 0);
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci		/* Calculate ALP frequency */
15462306a36Sopenharmony_ci		alp_hz = (ilp_ctr * EXT_ILP_HZ) / 4;
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ci		/*
15762306a36Sopenharmony_ci		 * Round to nearest 100KHz, and at
15862306a36Sopenharmony_ci		 * the same time convert to KHz
15962306a36Sopenharmony_ci		 */
16062306a36Sopenharmony_ci		alp_khz = (alp_hz + 50000) / 100000 * 100;
16162306a36Sopenharmony_ci	} else
16262306a36Sopenharmony_ci		alp_khz = 0;
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ci	return alp_khz;
16562306a36Sopenharmony_ci}
166