xref: /openbmc/linux/drivers/bcma/core.c (revision 972da7ec)
18369ae33SRafał Miłecki /*
28369ae33SRafał Miłecki  * Broadcom specific AMBA
38369ae33SRafał Miłecki  * Core ops
48369ae33SRafał Miłecki  *
58369ae33SRafał Miłecki  * Licensed under the GNU/GPL. See COPYING for details.
68369ae33SRafał Miłecki  */
78369ae33SRafał Miłecki 
88369ae33SRafał Miłecki #include "bcma_private.h"
944a8e377SPaul Gortmaker #include <linux/export.h>
108369ae33SRafał Miłecki #include <linux/bcma/bcma.h>
118369ae33SRafał Miłecki 
bcma_core_wait_value(struct bcma_device * core,u16 reg,u32 mask,u32 value,int timeout)12972da7ecSRafał Miłecki static bool bcma_core_wait_value(struct bcma_device *core, u16 reg, u32 mask,
13972da7ecSRafał Miłecki 				 u32 value, int timeout)
14972da7ecSRafał Miłecki {
15972da7ecSRafał Miłecki 	unsigned long deadline = jiffies + timeout;
16972da7ecSRafał Miłecki 	u32 val;
17972da7ecSRafał Miłecki 
18972da7ecSRafał Miłecki 	do {
19972da7ecSRafał Miłecki 		val = bcma_aread32(core, reg);
20972da7ecSRafał Miłecki 		if ((val & mask) == value)
21972da7ecSRafał Miłecki 			return true;
22972da7ecSRafał Miłecki 		cpu_relax();
23972da7ecSRafał Miłecki 		udelay(10);
24972da7ecSRafał Miłecki 	} while (!time_after_eq(jiffies, deadline));
25972da7ecSRafał Miłecki 
26972da7ecSRafał Miłecki 	bcma_warn(core->bus, "Timeout waiting for register 0x%04X!\n", reg);
27972da7ecSRafał Miłecki 
28972da7ecSRafał Miłecki 	return false;
29972da7ecSRafał Miłecki }
30972da7ecSRafał Miłecki 
bcma_core_is_enabled(struct bcma_device * core)318369ae33SRafał Miłecki bool bcma_core_is_enabled(struct bcma_device *core)
328369ae33SRafał Miłecki {
338369ae33SRafał Miłecki 	if ((bcma_aread32(core, BCMA_IOCTL) & (BCMA_IOCTL_CLK | BCMA_IOCTL_FGC))
348369ae33SRafał Miłecki 	    != BCMA_IOCTL_CLK)
358369ae33SRafał Miłecki 		return false;
368369ae33SRafał Miłecki 	if (bcma_aread32(core, BCMA_RESET_CTL) & BCMA_RESET_CTL_RESET)
378369ae33SRafał Miłecki 		return false;
388369ae33SRafał Miłecki 	return true;
398369ae33SRafał Miłecki }
408369ae33SRafał Miłecki EXPORT_SYMBOL_GPL(bcma_core_is_enabled);
418369ae33SRafał Miłecki 
bcma_core_disable(struct bcma_device * core,u32 flags)42e3ae0cacSArend van Spriel void bcma_core_disable(struct bcma_device *core, u32 flags)
438369ae33SRafał Miłecki {
448369ae33SRafał Miłecki 	if (bcma_aread32(core, BCMA_RESET_CTL) & BCMA_RESET_CTL_RESET)
458369ae33SRafał Miłecki 		return;
468369ae33SRafał Miłecki 
47972da7ecSRafał Miłecki 	bcma_core_wait_value(core, BCMA_RESET_ST, ~0, 0, 300);
488369ae33SRafał Miłecki 
498369ae33SRafał Miłecki 	bcma_awrite32(core, BCMA_RESET_CTL, BCMA_RESET_CTL_RESET);
50044e68c0SNathan Hintz 	bcma_aread32(core, BCMA_RESET_CTL);
518369ae33SRafał Miłecki 	udelay(1);
52972da7ecSRafał Miłecki 
53972da7ecSRafał Miłecki 	bcma_awrite32(core, BCMA_IOCTL, flags);
54972da7ecSRafał Miłecki 	bcma_aread32(core, BCMA_IOCTL);
55972da7ecSRafał Miłecki 	udelay(10);
568369ae33SRafał Miłecki }
57e3ae0cacSArend van Spriel EXPORT_SYMBOL_GPL(bcma_core_disable);
588369ae33SRafał Miłecki 
bcma_core_enable(struct bcma_device * core,u32 flags)598369ae33SRafał Miłecki int bcma_core_enable(struct bcma_device *core, u32 flags)
608369ae33SRafał Miłecki {
618369ae33SRafał Miłecki 	bcma_core_disable(core, flags);
628369ae33SRafał Miłecki 
638369ae33SRafał Miłecki 	bcma_awrite32(core, BCMA_IOCTL, (BCMA_IOCTL_CLK | BCMA_IOCTL_FGC | flags));
648369ae33SRafał Miłecki 	bcma_aread32(core, BCMA_IOCTL);
658369ae33SRafał Miłecki 
668369ae33SRafał Miłecki 	bcma_awrite32(core, BCMA_RESET_CTL, 0);
67972da7ecSRafał Miłecki 	bcma_aread32(core, BCMA_RESET_CTL);
688369ae33SRafał Miłecki 	udelay(1);
698369ae33SRafał Miłecki 
708369ae33SRafał Miłecki 	bcma_awrite32(core, BCMA_IOCTL, (BCMA_IOCTL_CLK | flags));
718369ae33SRafał Miłecki 	bcma_aread32(core, BCMA_IOCTL);
728369ae33SRafał Miłecki 	udelay(1);
738369ae33SRafał Miłecki 
748369ae33SRafał Miłecki 	return 0;
758369ae33SRafał Miłecki }
768369ae33SRafał Miłecki EXPORT_SYMBOL_GPL(bcma_core_enable);
777424dd0dSRafał Miłecki 
bcma_core_set_clockmode(struct bcma_device * core,enum bcma_clkmode clkmode)787424dd0dSRafał Miłecki void bcma_core_set_clockmode(struct bcma_device *core,
797424dd0dSRafał Miłecki 			     enum bcma_clkmode clkmode)
807424dd0dSRafał Miłecki {
817424dd0dSRafał Miłecki 	u16 i;
827424dd0dSRafał Miłecki 
837424dd0dSRafał Miłecki 	WARN_ON(core->id.id != BCMA_CORE_CHIPCOMMON &&
847424dd0dSRafał Miłecki 		core->id.id != BCMA_CORE_PCIE &&
857424dd0dSRafał Miłecki 		core->id.id != BCMA_CORE_80211);
867424dd0dSRafał Miłecki 
877424dd0dSRafał Miłecki 	switch (clkmode) {
887424dd0dSRafał Miłecki 	case BCMA_CLKMODE_FAST:
897424dd0dSRafał Miłecki 		bcma_set32(core, BCMA_CLKCTLST, BCMA_CLKCTLST_FORCEHT);
901fd41a65SRafał Miłecki 		usleep_range(64, 300);
917424dd0dSRafał Miłecki 		for (i = 0; i < 1500; i++) {
927424dd0dSRafał Miłecki 			if (bcma_read32(core, BCMA_CLKCTLST) &
937424dd0dSRafał Miłecki 			    BCMA_CLKCTLST_HAVEHT) {
947424dd0dSRafał Miłecki 				i = 0;
957424dd0dSRafał Miłecki 				break;
967424dd0dSRafał Miłecki 			}
977424dd0dSRafał Miłecki 			udelay(10);
987424dd0dSRafał Miłecki 		}
997424dd0dSRafał Miłecki 		if (i)
1003d9d8af3SRafał Miłecki 			bcma_err(core->bus, "HT force timeout\n");
1017424dd0dSRafał Miłecki 		break;
1027424dd0dSRafał Miłecki 	case BCMA_CLKMODE_DYNAMIC:
1030b2948eeSHauke Mehrtens 		bcma_set32(core, BCMA_CLKCTLST, ~BCMA_CLKCTLST_FORCEHT);
1047424dd0dSRafał Miłecki 		break;
1057424dd0dSRafał Miłecki 	}
1067424dd0dSRafał Miłecki }
1077424dd0dSRafał Miłecki EXPORT_SYMBOL_GPL(bcma_core_set_clockmode);
1086f53912fSRafał Miłecki 
bcma_core_pll_ctl(struct bcma_device * core,u32 req,u32 status,bool on)1096f53912fSRafał Miłecki void bcma_core_pll_ctl(struct bcma_device *core, u32 req, u32 status, bool on)
1106f53912fSRafał Miłecki {
1116f53912fSRafał Miłecki 	u16 i;
1126f53912fSRafał Miłecki 
1136f53912fSRafał Miłecki 	WARN_ON(req & ~BCMA_CLKCTLST_EXTRESREQ);
1146f53912fSRafał Miłecki 	WARN_ON(status & ~BCMA_CLKCTLST_EXTRESST);
1156f53912fSRafał Miłecki 
1166f53912fSRafał Miłecki 	if (on) {
1176f53912fSRafał Miłecki 		bcma_set32(core, BCMA_CLKCTLST, req);
1186f53912fSRafał Miłecki 		for (i = 0; i < 10000; i++) {
1196f53912fSRafał Miłecki 			if ((bcma_read32(core, BCMA_CLKCTLST) & status) ==
1206f53912fSRafał Miłecki 			    status) {
1216f53912fSRafał Miłecki 				i = 0;
1226f53912fSRafał Miłecki 				break;
1236f53912fSRafał Miłecki 			}
1246f53912fSRafał Miłecki 			udelay(10);
1256f53912fSRafał Miłecki 		}
1266f53912fSRafał Miłecki 		if (i)
1273d9d8af3SRafał Miłecki 			bcma_err(core->bus, "PLL enable timeout\n");
1286f53912fSRafał Miłecki 	} else {
129c722839cSRafał Miłecki 		/*
130c722839cSRafał Miłecki 		 * Mask the PLL but don't wait for it to be disabled. PLL may be
131c722839cSRafał Miłecki 		 * shared between cores and will be still up if there is another
132c722839cSRafał Miłecki 		 * core using it.
133c722839cSRafał Miłecki 		 */
134c722839cSRafał Miłecki 		bcma_mask32(core, BCMA_CLKCTLST, ~req);
135c722839cSRafał Miłecki 		bcma_read32(core, BCMA_CLKCTLST);
1366f53912fSRafał Miłecki 	}
1376f53912fSRafał Miłecki }
1386f53912fSRafał Miłecki EXPORT_SYMBOL_GPL(bcma_core_pll_ctl);
13905aec233SRafał Miłecki 
bcma_core_dma_translation(struct bcma_device * core)14005aec233SRafał Miłecki u32 bcma_core_dma_translation(struct bcma_device *core)
14105aec233SRafał Miłecki {
14205aec233SRafał Miłecki 	switch (core->bus->hosttype) {
143ecd177c2SHauke Mehrtens 	case BCMA_HOSTTYPE_SOC:
144ecd177c2SHauke Mehrtens 		return 0;
14505aec233SRafał Miłecki 	case BCMA_HOSTTYPE_PCI:
14605aec233SRafał Miłecki 		if (bcma_aread32(core, BCMA_IOST) & BCMA_IOST_DMA64)
14705aec233SRafał Miłecki 			return BCMA_DMA_TRANSLATION_DMA64_CMT;
14805aec233SRafał Miłecki 		else
14905aec233SRafał Miłecki 			return BCMA_DMA_TRANSLATION_DMA32_CMT;
15005aec233SRafał Miłecki 	default:
1513d9d8af3SRafał Miłecki 		bcma_err(core->bus, "DMA translation unknown for host %d\n",
15205aec233SRafał Miłecki 			 core->bus->hosttype);
15305aec233SRafał Miłecki 	}
15405aec233SRafał Miłecki 	return BCMA_DMA_TRANSLATION_NONE;
15505aec233SRafał Miłecki }
15605aec233SRafał Miłecki EXPORT_SYMBOL(bcma_core_dma_translation);
157