1 /* 2 * Broadcom specific AMBA 3 * Core ops 4 * 5 * Licensed under the GNU/GPL. See COPYING for details. 6 */ 7 8 #include "bcma_private.h" 9 #include <linux/export.h> 10 #include <linux/bcma/bcma.h> 11 12 static bool bcma_core_wait_value(struct bcma_device *core, u16 reg, u32 mask, 13 u32 value, int timeout) 14 { 15 unsigned long deadline = jiffies + timeout; 16 u32 val; 17 18 do { 19 val = bcma_aread32(core, reg); 20 if ((val & mask) == value) 21 return true; 22 cpu_relax(); 23 udelay(10); 24 } while (!time_after_eq(jiffies, deadline)); 25 26 bcma_warn(core->bus, "Timeout waiting for register 0x%04X!\n", reg); 27 28 return false; 29 } 30 31 bool bcma_core_is_enabled(struct bcma_device *core) 32 { 33 if ((bcma_aread32(core, BCMA_IOCTL) & (BCMA_IOCTL_CLK | BCMA_IOCTL_FGC)) 34 != BCMA_IOCTL_CLK) 35 return false; 36 if (bcma_aread32(core, BCMA_RESET_CTL) & BCMA_RESET_CTL_RESET) 37 return false; 38 return true; 39 } 40 EXPORT_SYMBOL_GPL(bcma_core_is_enabled); 41 42 void bcma_core_disable(struct bcma_device *core, u32 flags) 43 { 44 if (bcma_aread32(core, BCMA_RESET_CTL) & BCMA_RESET_CTL_RESET) 45 return; 46 47 bcma_core_wait_value(core, BCMA_RESET_ST, ~0, 0, 300); 48 49 bcma_awrite32(core, BCMA_RESET_CTL, BCMA_RESET_CTL_RESET); 50 bcma_aread32(core, BCMA_RESET_CTL); 51 udelay(1); 52 53 bcma_awrite32(core, BCMA_IOCTL, flags); 54 bcma_aread32(core, BCMA_IOCTL); 55 udelay(10); 56 } 57 EXPORT_SYMBOL_GPL(bcma_core_disable); 58 59 int bcma_core_enable(struct bcma_device *core, u32 flags) 60 { 61 bcma_core_disable(core, flags); 62 63 bcma_awrite32(core, BCMA_IOCTL, (BCMA_IOCTL_CLK | BCMA_IOCTL_FGC | flags)); 64 bcma_aread32(core, BCMA_IOCTL); 65 66 bcma_awrite32(core, BCMA_RESET_CTL, 0); 67 bcma_aread32(core, BCMA_RESET_CTL); 68 udelay(1); 69 70 bcma_awrite32(core, BCMA_IOCTL, (BCMA_IOCTL_CLK | flags)); 71 bcma_aread32(core, BCMA_IOCTL); 72 udelay(1); 73 74 return 0; 75 } 76 EXPORT_SYMBOL_GPL(bcma_core_enable); 77 78 void bcma_core_set_clockmode(struct bcma_device *core, 79 enum bcma_clkmode clkmode) 80 { 81 u16 i; 82 83 WARN_ON(core->id.id != BCMA_CORE_CHIPCOMMON && 84 core->id.id != BCMA_CORE_PCIE && 85 core->id.id != BCMA_CORE_80211); 86 87 switch (clkmode) { 88 case BCMA_CLKMODE_FAST: 89 bcma_set32(core, BCMA_CLKCTLST, BCMA_CLKCTLST_FORCEHT); 90 usleep_range(64, 300); 91 for (i = 0; i < 1500; i++) { 92 if (bcma_read32(core, BCMA_CLKCTLST) & 93 BCMA_CLKCTLST_HAVEHT) { 94 i = 0; 95 break; 96 } 97 udelay(10); 98 } 99 if (i) 100 bcma_err(core->bus, "HT force timeout\n"); 101 break; 102 case BCMA_CLKMODE_DYNAMIC: 103 bcma_set32(core, BCMA_CLKCTLST, ~BCMA_CLKCTLST_FORCEHT); 104 break; 105 } 106 } 107 EXPORT_SYMBOL_GPL(bcma_core_set_clockmode); 108 109 void bcma_core_pll_ctl(struct bcma_device *core, u32 req, u32 status, bool on) 110 { 111 u16 i; 112 113 WARN_ON(req & ~BCMA_CLKCTLST_EXTRESREQ); 114 WARN_ON(status & ~BCMA_CLKCTLST_EXTRESST); 115 116 if (on) { 117 bcma_set32(core, BCMA_CLKCTLST, req); 118 for (i = 0; i < 10000; i++) { 119 if ((bcma_read32(core, BCMA_CLKCTLST) & status) == 120 status) { 121 i = 0; 122 break; 123 } 124 udelay(10); 125 } 126 if (i) 127 bcma_err(core->bus, "PLL enable timeout\n"); 128 } else { 129 /* 130 * Mask the PLL but don't wait for it to be disabled. PLL may be 131 * shared between cores and will be still up if there is another 132 * core using it. 133 */ 134 bcma_mask32(core, BCMA_CLKCTLST, ~req); 135 bcma_read32(core, BCMA_CLKCTLST); 136 } 137 } 138 EXPORT_SYMBOL_GPL(bcma_core_pll_ctl); 139 140 u32 bcma_core_dma_translation(struct bcma_device *core) 141 { 142 switch (core->bus->hosttype) { 143 case BCMA_HOSTTYPE_SOC: 144 return 0; 145 case BCMA_HOSTTYPE_PCI: 146 if (bcma_aread32(core, BCMA_IOST) & BCMA_IOST_DMA64) 147 return BCMA_DMA_TRANSLATION_DMA64_CMT; 148 else 149 return BCMA_DMA_TRANSLATION_DMA32_CMT; 150 default: 151 bcma_err(core->bus, "DMA translation unknown for host %d\n", 152 core->bus->hosttype); 153 } 154 return BCMA_DMA_TRANSLATION_NONE; 155 } 156 EXPORT_SYMBOL(bcma_core_dma_translation); 157