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)12*972da7ecSRafał Miłecki static bool bcma_core_wait_value(struct bcma_device *core, u16 reg, u32 mask,
13*972da7ecSRafał Miłecki u32 value, int timeout)
14*972da7ecSRafał Miłecki {
15*972da7ecSRafał Miłecki unsigned long deadline = jiffies + timeout;
16*972da7ecSRafał Miłecki u32 val;
17*972da7ecSRafał Miłecki
18*972da7ecSRafał Miłecki do {
19*972da7ecSRafał Miłecki val = bcma_aread32(core, reg);
20*972da7ecSRafał Miłecki if ((val & mask) == value)
21*972da7ecSRafał Miłecki return true;
22*972da7ecSRafał Miłecki cpu_relax();
23*972da7ecSRafał Miłecki udelay(10);
24*972da7ecSRafał Miłecki } while (!time_after_eq(jiffies, deadline));
25*972da7ecSRafał Miłecki
26*972da7ecSRafał Miłecki bcma_warn(core->bus, "Timeout waiting for register 0x%04X!\n", reg);
27*972da7ecSRafał Miłecki
28*972da7ecSRafał Miłecki return false;
29*972da7ecSRafał Miłecki }
30*972da7ecSRafał 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
47*972da7ecSRafał 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);
52*972da7ecSRafał Miłecki
53*972da7ecSRafał Miłecki bcma_awrite32(core, BCMA_IOCTL, flags);
54*972da7ecSRafał Miłecki bcma_aread32(core, BCMA_IOCTL);
55*972da7ecSRafał 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);
67*972da7ecSRafał 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