linux/drivers/ssb/driver_chipcommon.c
<<
>>
Prefs
   1/*
   2 * Sonics Silicon Backplane
   3 * Broadcom ChipCommon core driver
   4 *
   5 * Copyright 2005, Broadcom Corporation
   6 * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
   7 * Copyright 2012, Hauke Mehrtens <hauke@hauke-m.de>
   8 *
   9 * Licensed under the GNU/GPL. See COPYING for details.
  10 */
  11
  12#include <linux/ssb/ssb.h>
  13#include <linux/ssb/ssb_regs.h>
  14#include <linux/export.h>
  15#include <linux/pci.h>
  16#include <linux/bcm47xx_wdt.h>
  17
  18#include "ssb_private.h"
  19
  20
  21/* Clock sources */
  22enum ssb_clksrc {
  23        /* PCI clock */
  24        SSB_CHIPCO_CLKSRC_PCI,
  25        /* Crystal slow clock oscillator */
  26        SSB_CHIPCO_CLKSRC_XTALOS,
  27        /* Low power oscillator */
  28        SSB_CHIPCO_CLKSRC_LOPWROS,
  29};
  30
  31
  32static inline u32 chipco_write32_masked(struct ssb_chipcommon *cc, u16 offset,
  33                                        u32 mask, u32 value)
  34{
  35        value &= mask;
  36        value |= chipco_read32(cc, offset) & ~mask;
  37        chipco_write32(cc, offset, value);
  38
  39        return value;
  40}
  41
  42void ssb_chipco_set_clockmode(struct ssb_chipcommon *cc,
  43                              enum ssb_clkmode mode)
  44{
  45        struct ssb_device *ccdev = cc->dev;
  46        struct ssb_bus *bus;
  47        u32 tmp;
  48
  49        if (!ccdev)
  50                return;
  51        bus = ccdev->bus;
  52
  53        /* We support SLOW only on 6..9 */
  54        if (ccdev->id.revision >= 10 && mode == SSB_CLKMODE_SLOW)
  55                mode = SSB_CLKMODE_DYNAMIC;
  56
  57        if (cc->capabilities & SSB_CHIPCO_CAP_PMU)
  58                return; /* PMU controls clockmode, separated function needed */
  59        SSB_WARN_ON(ccdev->id.revision >= 20);
  60
  61        /* chipcommon cores prior to rev6 don't support dynamic clock control */
  62        if (ccdev->id.revision < 6)
  63                return;
  64
  65        /* ChipCommon cores rev10+ need testing */
  66        if (ccdev->id.revision >= 10)
  67                return;
  68
  69        if (!(cc->capabilities & SSB_CHIPCO_CAP_PCTL))
  70                return;
  71
  72        switch (mode) {
  73        case SSB_CLKMODE_SLOW: /* For revs 6..9 only */
  74                tmp = chipco_read32(cc, SSB_CHIPCO_SLOWCLKCTL);
  75                tmp |= SSB_CHIPCO_SLOWCLKCTL_FSLOW;
  76                chipco_write32(cc, SSB_CHIPCO_SLOWCLKCTL, tmp);
  77                break;
  78        case SSB_CLKMODE_FAST:
  79                if (ccdev->id.revision < 10) {
  80                        ssb_pci_xtal(bus, SSB_GPIO_XTAL, 1); /* Force crystal on */
  81                        tmp = chipco_read32(cc, SSB_CHIPCO_SLOWCLKCTL);
  82                        tmp &= ~SSB_CHIPCO_SLOWCLKCTL_FSLOW;
  83                        tmp |= SSB_CHIPCO_SLOWCLKCTL_IPLL;
  84                        chipco_write32(cc, SSB_CHIPCO_SLOWCLKCTL, tmp);
  85                } else {
  86                        chipco_write32(cc, SSB_CHIPCO_SYSCLKCTL,
  87                                (chipco_read32(cc, SSB_CHIPCO_SYSCLKCTL) |
  88                                 SSB_CHIPCO_SYSCLKCTL_FORCEHT));
  89                        /* udelay(150); TODO: not available in early init */
  90                }
  91                break;
  92        case SSB_CLKMODE_DYNAMIC:
  93                if (ccdev->id.revision < 10) {
  94                        tmp = chipco_read32(cc, SSB_CHIPCO_SLOWCLKCTL);
  95                        tmp &= ~SSB_CHIPCO_SLOWCLKCTL_FSLOW;
  96                        tmp &= ~SSB_CHIPCO_SLOWCLKCTL_IPLL;
  97                        tmp &= ~SSB_CHIPCO_SLOWCLKCTL_ENXTAL;
  98                        if ((tmp & SSB_CHIPCO_SLOWCLKCTL_SRC) !=
  99                            SSB_CHIPCO_SLOWCLKCTL_SRC_XTAL)
 100                                tmp |= SSB_CHIPCO_SLOWCLKCTL_ENXTAL;
 101                        chipco_write32(cc, SSB_CHIPCO_SLOWCLKCTL, tmp);
 102
 103                        /* For dynamic control, we have to release our xtal_pu
 104                         * "force on" */
 105                        if (tmp & SSB_CHIPCO_SLOWCLKCTL_ENXTAL)
 106                                ssb_pci_xtal(bus, SSB_GPIO_XTAL, 0);
 107                } else {
 108                        chipco_write32(cc, SSB_CHIPCO_SYSCLKCTL,
 109                                (chipco_read32(cc, SSB_CHIPCO_SYSCLKCTL) &
 110                                 ~SSB_CHIPCO_SYSCLKCTL_FORCEHT));
 111                }
 112                break;
 113        default:
 114                SSB_WARN_ON(1);
 115        }
 116}
 117
 118/* Get the Slow Clock Source */
 119static enum ssb_clksrc chipco_pctl_get_slowclksrc(struct ssb_chipcommon *cc)
 120{
 121        struct ssb_bus *bus = cc->dev->bus;
 122        u32 uninitialized_var(tmp);
 123
 124        if (cc->dev->id.revision < 6) {
 125                if (bus->bustype == SSB_BUSTYPE_SSB ||
 126                    bus->bustype == SSB_BUSTYPE_PCMCIA)
 127                        return SSB_CHIPCO_CLKSRC_XTALOS;
 128                if (bus->bustype == SSB_BUSTYPE_PCI) {
 129                        pci_read_config_dword(bus->host_pci, SSB_GPIO_OUT, &tmp);
 130                        if (tmp & 0x10)
 131                                return SSB_CHIPCO_CLKSRC_PCI;
 132                        return SSB_CHIPCO_CLKSRC_XTALOS;
 133                }
 134        }
 135        if (cc->dev->id.revision < 10) {
 136                tmp = chipco_read32(cc, SSB_CHIPCO_SLOWCLKCTL);
 137                tmp &= 0x7;
 138                if (tmp == 0)
 139                        return SSB_CHIPCO_CLKSRC_LOPWROS;
 140                if (tmp == 1)
 141                        return SSB_CHIPCO_CLKSRC_XTALOS;
 142                if (tmp == 2)
 143                        return SSB_CHIPCO_CLKSRC_PCI;
 144        }
 145
 146        return SSB_CHIPCO_CLKSRC_XTALOS;
 147}
 148
 149/* Get maximum or minimum (depending on get_max flag) slowclock frequency. */
 150static int chipco_pctl_clockfreqlimit(struct ssb_chipcommon *cc, int get_max)
 151{
 152        int uninitialized_var(limit);
 153        enum ssb_clksrc clocksrc;
 154        int divisor = 1;
 155        u32 tmp;
 156
 157        clocksrc = chipco_pctl_get_slowclksrc(cc);
 158        if (cc->dev->id.revision < 6) {
 159                switch (clocksrc) {
 160                case SSB_CHIPCO_CLKSRC_PCI:
 161                        divisor = 64;
 162                        break;
 163                case SSB_CHIPCO_CLKSRC_XTALOS:
 164                        divisor = 32;
 165                        break;
 166                default:
 167                        SSB_WARN_ON(1);
 168                }
 169        } else if (cc->dev->id.revision < 10) {
 170                switch (clocksrc) {
 171                case SSB_CHIPCO_CLKSRC_LOPWROS:
 172                        break;
 173                case SSB_CHIPCO_CLKSRC_XTALOS:
 174                case SSB_CHIPCO_CLKSRC_PCI:
 175                        tmp = chipco_read32(cc, SSB_CHIPCO_SLOWCLKCTL);
 176                        divisor = (tmp >> 16) + 1;
 177                        divisor *= 4;
 178                        break;
 179                }
 180        } else {
 181                tmp = chipco_read32(cc, SSB_CHIPCO_SYSCLKCTL);
 182                divisor = (tmp >> 16) + 1;
 183                divisor *= 4;
 184        }
 185
 186        switch (clocksrc) {
 187        case SSB_CHIPCO_CLKSRC_LOPWROS:
 188                if (get_max)
 189                        limit = 43000;
 190                else
 191                        limit = 25000;
 192                break;
 193        case SSB_CHIPCO_CLKSRC_XTALOS:
 194                if (get_max)
 195                        limit = 20200000;
 196                else
 197                        limit = 19800000;
 198                break;
 199        case SSB_CHIPCO_CLKSRC_PCI:
 200                if (get_max)
 201                        limit = 34000000;
 202                else
 203                        limit = 25000000;
 204                break;
 205        }
 206        limit /= divisor;
 207
 208        return limit;
 209}
 210
 211static void chipco_powercontrol_init(struct ssb_chipcommon *cc)
 212{
 213        struct ssb_bus *bus = cc->dev->bus;
 214
 215        if (bus->chip_id == 0x4321) {
 216                if (bus->chip_rev == 0)
 217                        chipco_write32(cc, SSB_CHIPCO_CHIPCTL, 0x3A4);
 218                else if (bus->chip_rev == 1)
 219                        chipco_write32(cc, SSB_CHIPCO_CHIPCTL, 0xA4);
 220        }
 221
 222        if (!(cc->capabilities & SSB_CHIPCO_CAP_PCTL))
 223                return;
 224
 225        if (cc->dev->id.revision >= 10) {
 226                /* Set Idle Power clock rate to 1Mhz */
 227                chipco_write32(cc, SSB_CHIPCO_SYSCLKCTL,
 228                               (chipco_read32(cc, SSB_CHIPCO_SYSCLKCTL) &
 229                                0x0000FFFF) | 0x00040000);
 230        } else {
 231                int maxfreq;
 232
 233                maxfreq = chipco_pctl_clockfreqlimit(cc, 1);
 234                chipco_write32(cc, SSB_CHIPCO_PLLONDELAY,
 235                               (maxfreq * 150 + 999999) / 1000000);
 236                chipco_write32(cc, SSB_CHIPCO_FREFSELDELAY,
 237                               (maxfreq * 15 + 999999) / 1000000);
 238        }
 239}
 240
 241/* http://bcm-v4.sipsolutions.net/802.11/PmuFastPwrupDelay */
 242static u16 pmu_fast_powerup_delay(struct ssb_chipcommon *cc)
 243{
 244        struct ssb_bus *bus = cc->dev->bus;
 245
 246        switch (bus->chip_id) {
 247        case 0x4312:
 248        case 0x4322:
 249        case 0x4328:
 250                return 7000;
 251        case 0x4325:
 252                /* TODO: */
 253        default:
 254                return 15000;
 255        }
 256}
 257
 258/* http://bcm-v4.sipsolutions.net/802.11/ClkctlFastPwrupDelay */
 259static void calc_fast_powerup_delay(struct ssb_chipcommon *cc)
 260{
 261        struct ssb_bus *bus = cc->dev->bus;
 262        int minfreq;
 263        unsigned int tmp;
 264        u32 pll_on_delay;
 265
 266        if (bus->bustype != SSB_BUSTYPE_PCI)
 267                return;
 268
 269        if (cc->capabilities & SSB_CHIPCO_CAP_PMU) {
 270                cc->fast_pwrup_delay = pmu_fast_powerup_delay(cc);
 271                return;
 272        }
 273
 274        if (!(cc->capabilities & SSB_CHIPCO_CAP_PCTL))
 275                return;
 276
 277        minfreq = chipco_pctl_clockfreqlimit(cc, 0);
 278        pll_on_delay = chipco_read32(cc, SSB_CHIPCO_PLLONDELAY);
 279        tmp = (((pll_on_delay + 2) * 1000000) + (minfreq - 1)) / minfreq;
 280        SSB_WARN_ON(tmp & ~0xFFFF);
 281
 282        cc->fast_pwrup_delay = tmp;
 283}
 284
 285static u32 ssb_chipco_alp_clock(struct ssb_chipcommon *cc)
 286{
 287        if (cc->capabilities & SSB_CHIPCO_CAP_PMU)
 288                return ssb_pmu_get_alp_clock(cc);
 289
 290        return 20000000;
 291}
 292
 293static u32 ssb_chipco_watchdog_get_max_timer(struct ssb_chipcommon *cc)
 294{
 295        u32 nb;
 296
 297        if (cc->capabilities & SSB_CHIPCO_CAP_PMU) {
 298                if (cc->dev->id.revision < 26)
 299                        nb = 16;
 300                else
 301                        nb = (cc->dev->id.revision >= 37) ? 32 : 24;
 302        } else {
 303                nb = 28;
 304        }
 305        if (nb == 32)
 306                return 0xffffffff;
 307        else
 308                return (1 << nb) - 1;
 309}
 310
 311u32 ssb_chipco_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt, u32 ticks)
 312{
 313        struct ssb_chipcommon *cc = bcm47xx_wdt_get_drvdata(wdt);
 314
 315        if (cc->dev->bus->bustype != SSB_BUSTYPE_SSB)
 316                return 0;
 317
 318        return ssb_chipco_watchdog_timer_set(cc, ticks);
 319}
 320
 321u32 ssb_chipco_watchdog_timer_set_ms(struct bcm47xx_wdt *wdt, u32 ms)
 322{
 323        struct ssb_chipcommon *cc = bcm47xx_wdt_get_drvdata(wdt);
 324        u32 ticks;
 325
 326        if (cc->dev->bus->bustype != SSB_BUSTYPE_SSB)
 327                return 0;
 328
 329        ticks = ssb_chipco_watchdog_timer_set(cc, cc->ticks_per_ms * ms);
 330        return ticks / cc->ticks_per_ms;
 331}
 332
 333static int ssb_chipco_watchdog_ticks_per_ms(struct ssb_chipcommon *cc)
 334{
 335        struct ssb_bus *bus = cc->dev->bus;
 336
 337        if (cc->capabilities & SSB_CHIPCO_CAP_PMU) {
 338                        /* based on 32KHz ILP clock */
 339                        return 32;
 340        } else {
 341                if (cc->dev->id.revision < 18)
 342                        return ssb_clockspeed(bus) / 1000;
 343                else
 344                        return ssb_chipco_alp_clock(cc) / 1000;
 345        }
 346}
 347
 348void ssb_chipcommon_init(struct ssb_chipcommon *cc)
 349{
 350        if (!cc->dev)
 351                return; /* We don't have a ChipCommon */
 352
 353        spin_lock_init(&cc->gpio_lock);
 354
 355        if (cc->dev->id.revision >= 11)
 356                cc->status = chipco_read32(cc, SSB_CHIPCO_CHIPSTAT);
 357        ssb_dbg("chipcommon status is 0x%x\n", cc->status);
 358
 359        if (cc->dev->id.revision >= 20) {
 360                chipco_write32(cc, SSB_CHIPCO_GPIOPULLUP, 0);
 361                chipco_write32(cc, SSB_CHIPCO_GPIOPULLDOWN, 0);
 362        }
 363
 364        ssb_pmu_init(cc);
 365        chipco_powercontrol_init(cc);
 366        ssb_chipco_set_clockmode(cc, SSB_CLKMODE_FAST);
 367        calc_fast_powerup_delay(cc);
 368
 369        if (cc->dev->bus->bustype == SSB_BUSTYPE_SSB) {
 370                cc->ticks_per_ms = ssb_chipco_watchdog_ticks_per_ms(cc);
 371                cc->max_timer_ms = ssb_chipco_watchdog_get_max_timer(cc) / cc->ticks_per_ms;
 372        }
 373}
 374
 375void ssb_chipco_suspend(struct ssb_chipcommon *cc)
 376{
 377        if (!cc->dev)
 378                return;
 379        ssb_chipco_set_clockmode(cc, SSB_CLKMODE_SLOW);
 380}
 381
 382void ssb_chipco_resume(struct ssb_chipcommon *cc)
 383{
 384        if (!cc->dev)
 385                return;
 386        chipco_powercontrol_init(cc);
 387        ssb_chipco_set_clockmode(cc, SSB_CLKMODE_FAST);
 388}
 389
 390/* Get the processor clock */
 391void ssb_chipco_get_clockcpu(struct ssb_chipcommon *cc,
 392                             u32 *plltype, u32 *n, u32 *m)
 393{
 394        *n = chipco_read32(cc, SSB_CHIPCO_CLOCK_N);
 395        *plltype = (cc->capabilities & SSB_CHIPCO_CAP_PLLT);
 396        switch (*plltype) {
 397        case SSB_PLLTYPE_2:
 398        case SSB_PLLTYPE_4:
 399        case SSB_PLLTYPE_6:
 400        case SSB_PLLTYPE_7:
 401                *m = chipco_read32(cc, SSB_CHIPCO_CLOCK_MIPS);
 402                break;
 403        case SSB_PLLTYPE_3:
 404                /* 5350 uses m2 to control mips */
 405                *m = chipco_read32(cc, SSB_CHIPCO_CLOCK_M2);
 406                break;
 407        default:
 408                *m = chipco_read32(cc, SSB_CHIPCO_CLOCK_SB);
 409                break;
 410        }
 411}
 412
 413/* Get the bus clock */
 414void ssb_chipco_get_clockcontrol(struct ssb_chipcommon *cc,
 415                                 u32 *plltype, u32 *n, u32 *m)
 416{
 417        *n = chipco_read32(cc, SSB_CHIPCO_CLOCK_N);
 418        *plltype = (cc->capabilities & SSB_CHIPCO_CAP_PLLT);
 419        switch (*plltype) {
 420        case SSB_PLLTYPE_6: /* 100/200 or 120/240 only */
 421                *m = chipco_read32(cc, SSB_CHIPCO_CLOCK_MIPS);
 422                break;
 423        case SSB_PLLTYPE_3: /* 25Mhz, 2 dividers */
 424                if (cc->dev->bus->chip_id != 0x5365) {
 425                        *m = chipco_read32(cc, SSB_CHIPCO_CLOCK_M2);
 426                        break;
 427                }
 428                /* Fallthough */
 429        default:
 430                *m = chipco_read32(cc, SSB_CHIPCO_CLOCK_SB);
 431        }
 432}
 433
 434void ssb_chipco_timing_init(struct ssb_chipcommon *cc,
 435                            unsigned long ns)
 436{
 437        struct ssb_device *dev = cc->dev;
 438        struct ssb_bus *bus = dev->bus;
 439        u32 tmp;
 440
 441        /* set register for external IO to control LED. */
 442        chipco_write32(cc, SSB_CHIPCO_PROG_CFG, 0x11);
 443        tmp = DIV_ROUND_UP(10, ns) << SSB_PROG_WCNT_3_SHIFT;            /* Waitcount-3 = 10ns */
 444        tmp |= DIV_ROUND_UP(40, ns) << SSB_PROG_WCNT_1_SHIFT;   /* Waitcount-1 = 40ns */
 445        tmp |= DIV_ROUND_UP(240, ns);                           /* Waitcount-0 = 240ns */
 446        chipco_write32(cc, SSB_CHIPCO_PROG_WAITCNT, tmp);       /* 0x01020a0c for a 100Mhz clock */
 447
 448        /* Set timing for the flash */
 449        tmp = DIV_ROUND_UP(10, ns) << SSB_FLASH_WCNT_3_SHIFT;   /* Waitcount-3 = 10nS */
 450        tmp |= DIV_ROUND_UP(10, ns) << SSB_FLASH_WCNT_1_SHIFT;  /* Waitcount-1 = 10nS */
 451        tmp |= DIV_ROUND_UP(120, ns);                           /* Waitcount-0 = 120nS */
 452        if ((bus->chip_id == 0x5365) ||
 453            (dev->id.revision < 9))
 454                chipco_write32(cc, SSB_CHIPCO_FLASH_WAITCNT, tmp);
 455        if ((bus->chip_id == 0x5365) ||
 456            (dev->id.revision < 9) ||
 457            ((bus->chip_id == 0x5350) && (bus->chip_rev == 0)))
 458                chipco_write32(cc, SSB_CHIPCO_PCMCIA_MEMWAIT, tmp);
 459
 460        if (bus->chip_id == 0x5350) {
 461                /* Enable EXTIF */
 462                tmp = DIV_ROUND_UP(10, ns) << SSB_PROG_WCNT_3_SHIFT;      /* Waitcount-3 = 10ns */
 463                tmp |= DIV_ROUND_UP(20, ns) << SSB_PROG_WCNT_2_SHIFT;  /* Waitcount-2 = 20ns */
 464                tmp |= DIV_ROUND_UP(100, ns) << SSB_PROG_WCNT_1_SHIFT; /* Waitcount-1 = 100ns */
 465                tmp |= DIV_ROUND_UP(120, ns);                     /* Waitcount-0 = 120ns */
 466                chipco_write32(cc, SSB_CHIPCO_PROG_WAITCNT, tmp); /* 0x01020a0c for a 100Mhz clock */
 467        }
 468}
 469
 470/* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */
 471u32 ssb_chipco_watchdog_timer_set(struct ssb_chipcommon *cc, u32 ticks)
 472{
 473        u32 maxt;
 474        enum ssb_clkmode clkmode;
 475
 476        maxt = ssb_chipco_watchdog_get_max_timer(cc);
 477        if (cc->capabilities & SSB_CHIPCO_CAP_PMU) {
 478                if (ticks == 1)
 479                        ticks = 2;
 480                else if (ticks > maxt)
 481                        ticks = maxt;
 482                chipco_write32(cc, SSB_CHIPCO_PMU_WATCHDOG, ticks);
 483        } else {
 484                clkmode = ticks ? SSB_CLKMODE_FAST : SSB_CLKMODE_DYNAMIC;
 485                ssb_chipco_set_clockmode(cc, clkmode);
 486                if (ticks > maxt)
 487                        ticks = maxt;
 488                /* instant NMI */
 489                chipco_write32(cc, SSB_CHIPCO_WATCHDOG, ticks);
 490        }
 491        return ticks;
 492}
 493
 494void ssb_chipco_irq_mask(struct ssb_chipcommon *cc, u32 mask, u32 value)
 495{
 496        chipco_write32_masked(cc, SSB_CHIPCO_IRQMASK, mask, value);
 497}
 498
 499u32 ssb_chipco_irq_status(struct ssb_chipcommon *cc, u32 mask)
 500{
 501        return chipco_read32(cc, SSB_CHIPCO_IRQSTAT) & mask;
 502}
 503
 504u32 ssb_chipco_gpio_in(struct ssb_chipcommon *cc, u32 mask)
 505{
 506        return chipco_read32(cc, SSB_CHIPCO_GPIOIN) & mask;
 507}
 508
 509u32 ssb_chipco_gpio_out(struct ssb_chipcommon *cc, u32 mask, u32 value)
 510{
 511        unsigned long flags;
 512        u32 res = 0;
 513
 514        spin_lock_irqsave(&cc->gpio_lock, flags);
 515        res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUT, mask, value);
 516        spin_unlock_irqrestore(&cc->gpio_lock, flags);
 517
 518        return res;
 519}
 520
 521u32 ssb_chipco_gpio_outen(struct ssb_chipcommon *cc, u32 mask, u32 value)
 522{
 523        unsigned long flags;
 524        u32 res = 0;
 525
 526        spin_lock_irqsave(&cc->gpio_lock, flags);
 527        res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUTEN, mask, value);
 528        spin_unlock_irqrestore(&cc->gpio_lock, flags);
 529
 530        return res;
 531}
 532
 533u32 ssb_chipco_gpio_control(struct ssb_chipcommon *cc, u32 mask, u32 value)
 534{
 535        unsigned long flags;
 536        u32 res = 0;
 537
 538        spin_lock_irqsave(&cc->gpio_lock, flags);
 539        res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOCTL, mask, value);
 540        spin_unlock_irqrestore(&cc->gpio_lock, flags);
 541
 542        return res;
 543}
 544EXPORT_SYMBOL(ssb_chipco_gpio_control);
 545
 546u32 ssb_chipco_gpio_intmask(struct ssb_chipcommon *cc, u32 mask, u32 value)
 547{
 548        unsigned long flags;
 549        u32 res = 0;
 550
 551        spin_lock_irqsave(&cc->gpio_lock, flags);
 552        res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOIRQ, mask, value);
 553        spin_unlock_irqrestore(&cc->gpio_lock, flags);
 554
 555        return res;
 556}
 557
 558u32 ssb_chipco_gpio_polarity(struct ssb_chipcommon *cc, u32 mask, u32 value)
 559{
 560        unsigned long flags;
 561        u32 res = 0;
 562
 563        spin_lock_irqsave(&cc->gpio_lock, flags);
 564        res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOPOL, mask, value);
 565        spin_unlock_irqrestore(&cc->gpio_lock, flags);
 566
 567        return res;
 568}
 569
 570u32 ssb_chipco_gpio_pullup(struct ssb_chipcommon *cc, u32 mask, u32 value)
 571{
 572        unsigned long flags;
 573        u32 res = 0;
 574
 575        if (cc->dev->id.revision < 20)
 576                return 0xffffffff;
 577
 578        spin_lock_irqsave(&cc->gpio_lock, flags);
 579        res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOPULLUP, mask, value);
 580        spin_unlock_irqrestore(&cc->gpio_lock, flags);
 581
 582        return res;
 583}
 584
 585u32 ssb_chipco_gpio_pulldown(struct ssb_chipcommon *cc, u32 mask, u32 value)
 586{
 587        unsigned long flags;
 588        u32 res = 0;
 589
 590        if (cc->dev->id.revision < 20)
 591                return 0xffffffff;
 592
 593        spin_lock_irqsave(&cc->gpio_lock, flags);
 594        res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOPULLDOWN, mask, value);
 595        spin_unlock_irqrestore(&cc->gpio_lock, flags);
 596
 597        return res;
 598}
 599
 600#ifdef CONFIG_SSB_SERIAL
 601int ssb_chipco_serial_init(struct ssb_chipcommon *cc,
 602                           struct ssb_serial_port *ports)
 603{
 604        struct ssb_bus *bus = cc->dev->bus;
 605        int nr_ports = 0;
 606        u32 plltype;
 607        unsigned int irq;
 608        u32 baud_base, div;
 609        u32 i, n;
 610        unsigned int ccrev = cc->dev->id.revision;
 611
 612        plltype = (cc->capabilities & SSB_CHIPCO_CAP_PLLT);
 613        irq = ssb_mips_irq(cc->dev);
 614
 615        if (plltype == SSB_PLLTYPE_1) {
 616                /* PLL clock */
 617                baud_base = ssb_calc_clock_rate(plltype,
 618                                                chipco_read32(cc, SSB_CHIPCO_CLOCK_N),
 619                                                chipco_read32(cc, SSB_CHIPCO_CLOCK_M2));
 620                div = 1;
 621        } else {
 622                if (ccrev == 20) {
 623                        /* BCM5354 uses constant 25MHz clock */
 624                        baud_base = 25000000;
 625                        div = 48;
 626                        /* Set the override bit so we don't divide it */
 627                        chipco_write32(cc, SSB_CHIPCO_CORECTL,
 628                                       chipco_read32(cc, SSB_CHIPCO_CORECTL)
 629                                       | SSB_CHIPCO_CORECTL_UARTCLK0);
 630                } else if ((ccrev >= 11) && (ccrev != 15)) {
 631                        baud_base = ssb_chipco_alp_clock(cc);
 632                        div = 1;
 633                        if (ccrev >= 21) {
 634                                /* Turn off UART clock before switching clocksource. */
 635                                chipco_write32(cc, SSB_CHIPCO_CORECTL,
 636                                               chipco_read32(cc, SSB_CHIPCO_CORECTL)
 637                                               & ~SSB_CHIPCO_CORECTL_UARTCLKEN);
 638                        }
 639                        /* Set the override bit so we don't divide it */
 640                        chipco_write32(cc, SSB_CHIPCO_CORECTL,
 641                                       chipco_read32(cc, SSB_CHIPCO_CORECTL)
 642                                       | SSB_CHIPCO_CORECTL_UARTCLK0);
 643                        if (ccrev >= 21) {
 644                                /* Re-enable the UART clock. */
 645                                chipco_write32(cc, SSB_CHIPCO_CORECTL,
 646                                               chipco_read32(cc, SSB_CHIPCO_CORECTL)
 647                                               | SSB_CHIPCO_CORECTL_UARTCLKEN);
 648                        }
 649                } else if (ccrev >= 3) {
 650                        /* Internal backplane clock */
 651                        baud_base = ssb_clockspeed(bus);
 652                        div = chipco_read32(cc, SSB_CHIPCO_CLKDIV)
 653                              & SSB_CHIPCO_CLKDIV_UART;
 654                } else {
 655                        /* Fixed internal backplane clock */
 656                        baud_base = 88000000;
 657                        div = 48;
 658                }
 659
 660                /* Clock source depends on strapping if UartClkOverride is unset */
 661                if ((ccrev > 0) &&
 662                    !(chipco_read32(cc, SSB_CHIPCO_CORECTL) & SSB_CHIPCO_CORECTL_UARTCLK0)) {
 663                        if ((cc->capabilities & SSB_CHIPCO_CAP_UARTCLK) ==
 664                            SSB_CHIPCO_CAP_UARTCLK_INT) {
 665                                /* Internal divided backplane clock */
 666                                baud_base /= div;
 667                        } else {
 668                                /* Assume external clock of 1.8432 MHz */
 669                                baud_base = 1843200;
 670                        }
 671                }
 672        }
 673
 674        /* Determine the registers of the UARTs */
 675        n = (cc->capabilities & SSB_CHIPCO_CAP_NRUART);
 676        for (i = 0; i < n; i++) {
 677                void __iomem *cc_mmio;
 678                void __iomem *uart_regs;
 679
 680                cc_mmio = cc->dev->bus->mmio + (cc->dev->core_index * SSB_CORE_SIZE);
 681                uart_regs = cc_mmio + SSB_CHIPCO_UART0_DATA;
 682                /* Offset changed at after rev 0 */
 683                if (ccrev == 0)
 684                        uart_regs += (i * 8);
 685                else
 686                        uart_regs += (i * 256);
 687
 688                nr_ports++;
 689                ports[i].regs = uart_regs;
 690                ports[i].irq = irq;
 691                ports[i].baud_base = baud_base;
 692                ports[i].reg_shift = 0;
 693        }
 694
 695        return nr_ports;
 696}
 697#endif /* CONFIG_SSB_SERIAL */
 698
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.