linux/drivers/bcma/core.c
<<
>>
Prefs
   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
  12static 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
  31bool 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}
  40EXPORT_SYMBOL_GPL(bcma_core_is_enabled);
  41
  42void 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}
  57EXPORT_SYMBOL_GPL(bcma_core_disable);
  58
  59int 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}
  76EXPORT_SYMBOL_GPL(bcma_core_enable);
  77
  78void 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}
 107EXPORT_SYMBOL_GPL(bcma_core_set_clockmode);
 108
 109void 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}
 138EXPORT_SYMBOL_GPL(bcma_core_pll_ctl);
 139
 140u32 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}
 156EXPORT_SYMBOL(bcma_core_dma_translation);
 157