linux/drivers/bcma/driver_chipcommon.c
<<
>>
Prefs
   1/*
   2 * Broadcom specific AMBA
   3 * 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 "bcma_private.h"
  13#include <linux/bcm47xx_wdt.h>
  14#include <linux/export.h>
  15#include <linux/platform_device.h>
  16#include <linux/bcma/bcma.h>
  17
  18static inline u32 bcma_cc_write32_masked(struct bcma_drv_cc *cc, u16 offset,
  19                                         u32 mask, u32 value)
  20{
  21        value &= mask;
  22        value |= bcma_cc_read32(cc, offset) & ~mask;
  23        bcma_cc_write32(cc, offset, value);
  24
  25        return value;
  26}
  27
  28u32 bcma_chipco_get_alp_clock(struct bcma_drv_cc *cc)
  29{
  30        if (cc->capabilities & BCMA_CC_CAP_PMU)
  31                return bcma_pmu_get_alp_clock(cc);
  32
  33        return 20000000;
  34}
  35EXPORT_SYMBOL_GPL(bcma_chipco_get_alp_clock);
  36
  37static bool bcma_core_cc_has_pmu_watchdog(struct bcma_drv_cc *cc)
  38{
  39        struct bcma_bus *bus = cc->core->bus;
  40
  41        if (cc->capabilities & BCMA_CC_CAP_PMU) {
  42                if (bus->chipinfo.id == BCMA_CHIP_ID_BCM53573) {
  43                        WARN(bus->chipinfo.rev <= 1, "No watchdog available\n");
  44                        /* 53573B0 and 53573B1 have bugged PMU watchdog. It can
  45                         * be enabled but timer can't be bumped. Use CC one
  46                         * instead.
  47                         */
  48                        return false;
  49                }
  50                return true;
  51        } else {
  52                return false;
  53        }
  54}
  55
  56static u32 bcma_chipco_watchdog_get_max_timer(struct bcma_drv_cc *cc)
  57{
  58        struct bcma_bus *bus = cc->core->bus;
  59        u32 nb;
  60
  61        if (bcma_core_cc_has_pmu_watchdog(cc)) {
  62                if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4706)
  63                        nb = 32;
  64                else if (cc->core->id.rev < 26)
  65                        nb = 16;
  66                else
  67                        nb = (cc->core->id.rev >= 37) ? 32 : 24;
  68        } else {
  69                nb = 28;
  70        }
  71        if (nb == 32)
  72                return 0xffffffff;
  73        else
  74                return (1 << nb) - 1;
  75}
  76
  77static u32 bcma_chipco_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt,
  78                                              u32 ticks)
  79{
  80        struct bcma_drv_cc *cc = bcm47xx_wdt_get_drvdata(wdt);
  81
  82        return bcma_chipco_watchdog_timer_set(cc, ticks);
  83}
  84
  85static u32 bcma_chipco_watchdog_timer_set_ms_wdt(struct bcm47xx_wdt *wdt,
  86                                                 u32 ms)
  87{
  88        struct bcma_drv_cc *cc = bcm47xx_wdt_get_drvdata(wdt);
  89        u32 ticks;
  90
  91        ticks = bcma_chipco_watchdog_timer_set(cc, cc->ticks_per_ms * ms);
  92        return ticks / cc->ticks_per_ms;
  93}
  94
  95static int bcma_chipco_watchdog_ticks_per_ms(struct bcma_drv_cc *cc)
  96{
  97        struct bcma_bus *bus = cc->core->bus;
  98
  99        if (cc->capabilities & BCMA_CC_CAP_PMU) {
 100                if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4706)
 101                        /* 4706 CC and PMU watchdogs are clocked at 1/4 of ALP
 102                         * clock
 103                         */
 104                        return bcma_chipco_get_alp_clock(cc) / 4000;
 105                else
 106                        /* based on 32KHz ILP clock */
 107                        return 32;
 108        } else {
 109                return bcma_chipco_get_alp_clock(cc) / 1000;
 110        }
 111}
 112
 113int bcma_chipco_watchdog_register(struct bcma_drv_cc *cc)
 114{
 115        struct bcma_bus *bus = cc->core->bus;
 116        struct bcm47xx_wdt wdt = {};
 117        struct platform_device *pdev;
 118
 119        if (bus->chipinfo.id == BCMA_CHIP_ID_BCM53573 &&
 120            bus->chipinfo.rev <= 1) {
 121                pr_debug("No watchdog on 53573A0 / 53573A1\n");
 122                return 0;
 123        }
 124
 125        wdt.driver_data = cc;
 126        wdt.timer_set = bcma_chipco_watchdog_timer_set_wdt;
 127        wdt.timer_set_ms = bcma_chipco_watchdog_timer_set_ms_wdt;
 128        wdt.max_timer_ms =
 129                bcma_chipco_watchdog_get_max_timer(cc) / cc->ticks_per_ms;
 130
 131        pdev = platform_device_register_data(NULL, "bcm47xx-wdt",
 132                                             bus->num, &wdt,
 133                                             sizeof(wdt));
 134        if (IS_ERR(pdev))
 135                return PTR_ERR(pdev);
 136
 137        cc->watchdog = pdev;
 138
 139        return 0;
 140}
 141
 142static void bcma_core_chipcommon_flash_detect(struct bcma_drv_cc *cc)
 143{
 144        struct bcma_bus *bus = cc->core->bus;
 145
 146        switch (cc->capabilities & BCMA_CC_CAP_FLASHT) {
 147        case BCMA_CC_FLASHT_STSER:
 148        case BCMA_CC_FLASHT_ATSER:
 149                bcma_debug(bus, "Found serial flash\n");
 150                bcma_sflash_init(cc);
 151                break;
 152        case BCMA_CC_FLASHT_PARA:
 153                bcma_debug(bus, "Found parallel flash\n");
 154                bcma_pflash_init(cc);
 155                break;
 156        default:
 157                bcma_err(bus, "Flash type not supported\n");
 158        }
 159
 160        if (cc->core->id.rev == 38 ||
 161            bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) {
 162                if (cc->capabilities & BCMA_CC_CAP_NFLASH) {
 163                        bcma_debug(bus, "Found NAND flash\n");
 164                        bcma_nflash_init(cc);
 165                }
 166        }
 167}
 168
 169void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc)
 170{
 171        struct bcma_bus *bus = cc->core->bus;
 172
 173        if (cc->early_setup_done)
 174                return;
 175
 176        spin_lock_init(&cc->gpio_lock);
 177
 178        if (cc->core->id.rev >= 11)
 179                cc->status = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT);
 180        cc->capabilities = bcma_cc_read32(cc, BCMA_CC_CAP);
 181        if (cc->core->id.rev >= 35)
 182                cc->capabilities_ext = bcma_cc_read32(cc, BCMA_CC_CAP_EXT);
 183
 184        if (cc->capabilities & BCMA_CC_CAP_PMU)
 185                bcma_pmu_early_init(cc);
 186
 187        if (bus->hosttype == BCMA_HOSTTYPE_SOC)
 188                bcma_core_chipcommon_flash_detect(cc);
 189
 190        cc->early_setup_done = true;
 191}
 192
 193void bcma_core_chipcommon_init(struct bcma_drv_cc *cc)
 194{
 195        u32 leddc_on = 10;
 196        u32 leddc_off = 90;
 197
 198        if (cc->setup_done)
 199                return;
 200
 201        bcma_core_chipcommon_early_init(cc);
 202
 203        if (cc->core->id.rev >= 20) {
 204                u32 pullup = 0, pulldown = 0;
 205
 206                if (cc->core->bus->chipinfo.id == BCMA_CHIP_ID_BCM43142) {
 207                        pullup = 0x402e0;
 208                        pulldown = 0x20500;
 209                }
 210
 211                bcma_cc_write32(cc, BCMA_CC_GPIOPULLUP, pullup);
 212                bcma_cc_write32(cc, BCMA_CC_GPIOPULLDOWN, pulldown);
 213        }
 214
 215        if (cc->capabilities & BCMA_CC_CAP_PMU)
 216                bcma_pmu_init(cc);
 217        if (cc->capabilities & BCMA_CC_CAP_PCTL)
 218                bcma_err(cc->core->bus, "Power control not implemented!\n");
 219
 220        if (cc->core->id.rev >= 16) {
 221                if (cc->core->bus->sprom.leddc_on_time &&
 222                    cc->core->bus->sprom.leddc_off_time) {
 223                        leddc_on = cc->core->bus->sprom.leddc_on_time;
 224                        leddc_off = cc->core->bus->sprom.leddc_off_time;
 225                }
 226                bcma_cc_write32(cc, BCMA_CC_GPIOTIMER,
 227                        ((leddc_on << BCMA_CC_GPIOTIMER_ONTIME_SHIFT) |
 228                         (leddc_off << BCMA_CC_GPIOTIMER_OFFTIME_SHIFT)));
 229        }
 230        cc->ticks_per_ms = bcma_chipco_watchdog_ticks_per_ms(cc);
 231
 232        cc->setup_done = true;
 233}
 234
 235/* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */
 236u32 bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks)
 237{
 238        u32 maxt;
 239
 240        maxt = bcma_chipco_watchdog_get_max_timer(cc);
 241        if (bcma_core_cc_has_pmu_watchdog(cc)) {
 242                if (ticks == 1)
 243                        ticks = 2;
 244                else if (ticks > maxt)
 245                        ticks = maxt;
 246                bcma_pmu_write32(cc, BCMA_CC_PMU_WATCHDOG, ticks);
 247        } else {
 248                struct bcma_bus *bus = cc->core->bus;
 249
 250                if (bus->chipinfo.id != BCMA_CHIP_ID_BCM4707 &&
 251                    bus->chipinfo.id != BCMA_CHIP_ID_BCM47094 &&
 252                    bus->chipinfo.id != BCMA_CHIP_ID_BCM53018)
 253                        bcma_core_set_clockmode(cc->core,
 254                                                ticks ? BCMA_CLKMODE_FAST : BCMA_CLKMODE_DYNAMIC);
 255
 256                if (ticks > maxt)
 257                        ticks = maxt;
 258                /* instant NMI */
 259                bcma_cc_write32(cc, BCMA_CC_WATCHDOG, ticks);
 260        }
 261        return ticks;
 262}
 263
 264void bcma_chipco_irq_mask(struct bcma_drv_cc *cc, u32 mask, u32 value)
 265{
 266        bcma_cc_write32_masked(cc, BCMA_CC_IRQMASK, mask, value);
 267}
 268
 269u32 bcma_chipco_irq_status(struct bcma_drv_cc *cc, u32 mask)
 270{
 271        return bcma_cc_read32(cc, BCMA_CC_IRQSTAT) & mask;
 272}
 273
 274u32 bcma_chipco_gpio_in(struct bcma_drv_cc *cc, u32 mask)
 275{
 276        return bcma_cc_read32(cc, BCMA_CC_GPIOIN) & mask;
 277}
 278
 279u32 bcma_chipco_gpio_out(struct bcma_drv_cc *cc, u32 mask, u32 value)
 280{
 281        unsigned long flags;
 282        u32 res;
 283
 284        spin_lock_irqsave(&cc->gpio_lock, flags);
 285        res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUT, mask, value);
 286        spin_unlock_irqrestore(&cc->gpio_lock, flags);
 287
 288        return res;
 289}
 290EXPORT_SYMBOL_GPL(bcma_chipco_gpio_out);
 291
 292u32 bcma_chipco_gpio_outen(struct bcma_drv_cc *cc, u32 mask, u32 value)
 293{
 294        unsigned long flags;
 295        u32 res;
 296
 297        spin_lock_irqsave(&cc->gpio_lock, flags);
 298        res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUTEN, mask, value);
 299        spin_unlock_irqrestore(&cc->gpio_lock, flags);
 300
 301        return res;
 302}
 303EXPORT_SYMBOL_GPL(bcma_chipco_gpio_outen);
 304
 305/*
 306 * If the bit is set to 0, chipcommon controlls this GPIO,
 307 * if the bit is set to 1, it is used by some part of the chip and not our code.
 308 */
 309u32 bcma_chipco_gpio_control(struct bcma_drv_cc *cc, u32 mask, u32 value)
 310{
 311        unsigned long flags;
 312        u32 res;
 313
 314        spin_lock_irqsave(&cc->gpio_lock, flags);
 315        res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOCTL, mask, value);
 316        spin_unlock_irqrestore(&cc->gpio_lock, flags);
 317
 318        return res;
 319}
 320EXPORT_SYMBOL_GPL(bcma_chipco_gpio_control);
 321
 322u32 bcma_chipco_gpio_intmask(struct bcma_drv_cc *cc, u32 mask, u32 value)
 323{
 324        unsigned long flags;
 325        u32 res;
 326
 327        spin_lock_irqsave(&cc->gpio_lock, flags);
 328        res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOIRQ, mask, value);
 329        spin_unlock_irqrestore(&cc->gpio_lock, flags);
 330
 331        return res;
 332}
 333
 334u32 bcma_chipco_gpio_polarity(struct bcma_drv_cc *cc, u32 mask, u32 value)
 335{
 336        unsigned long flags;
 337        u32 res;
 338
 339        spin_lock_irqsave(&cc->gpio_lock, flags);
 340        res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOPOL, mask, value);
 341        spin_unlock_irqrestore(&cc->gpio_lock, flags);
 342
 343        return res;
 344}
 345
 346u32 bcma_chipco_gpio_pullup(struct bcma_drv_cc *cc, u32 mask, u32 value)
 347{
 348        unsigned long flags;
 349        u32 res;
 350
 351        if (cc->core->id.rev < 20)
 352                return 0;
 353
 354        spin_lock_irqsave(&cc->gpio_lock, flags);
 355        res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOPULLUP, mask, value);
 356        spin_unlock_irqrestore(&cc->gpio_lock, flags);
 357
 358        return res;
 359}
 360
 361u32 bcma_chipco_gpio_pulldown(struct bcma_drv_cc *cc, u32 mask, u32 value)
 362{
 363        unsigned long flags;
 364        u32 res;
 365
 366        if (cc->core->id.rev < 20)
 367                return 0;
 368
 369        spin_lock_irqsave(&cc->gpio_lock, flags);
 370        res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOPULLDOWN, mask, value);
 371        spin_unlock_irqrestore(&cc->gpio_lock, flags);
 372
 373        return res;
 374}
 375
 376#ifdef CONFIG_BCMA_DRIVER_MIPS
 377void bcma_chipco_serial_init(struct bcma_drv_cc *cc)
 378{
 379        unsigned int irq;
 380        u32 baud_base;
 381        u32 i;
 382        unsigned int ccrev = cc->core->id.rev;
 383        struct bcma_serial_port *ports = cc->serial_ports;
 384
 385        if (ccrev >= 11 && ccrev != 15) {
 386                baud_base = bcma_chipco_get_alp_clock(cc);
 387                if (ccrev >= 21) {
 388                        /* Turn off UART clock before switching clocksource. */
 389                        bcma_cc_write32(cc, BCMA_CC_CORECTL,
 390                                       bcma_cc_read32(cc, BCMA_CC_CORECTL)
 391                                       & ~BCMA_CC_CORECTL_UARTCLKEN);
 392                }
 393                /* Set the override bit so we don't divide it */
 394                bcma_cc_write32(cc, BCMA_CC_CORECTL,
 395                               bcma_cc_read32(cc, BCMA_CC_CORECTL)
 396                               | BCMA_CC_CORECTL_UARTCLK0);
 397                if (ccrev >= 21) {
 398                        /* Re-enable the UART clock. */
 399                        bcma_cc_write32(cc, BCMA_CC_CORECTL,
 400                                       bcma_cc_read32(cc, BCMA_CC_CORECTL)
 401                                       | BCMA_CC_CORECTL_UARTCLKEN);
 402                }
 403        } else {
 404                bcma_err(cc->core->bus, "serial not supported on this device ccrev: 0x%x\n",
 405                         ccrev);
 406                return;
 407        }
 408
 409        irq = bcma_core_irq(cc->core, 0);
 410
 411        /* Determine the registers of the UARTs */
 412        cc->nr_serial_ports = (cc->capabilities & BCMA_CC_CAP_NRUART);
 413        for (i = 0; i < cc->nr_serial_ports; i++) {
 414                ports[i].regs = cc->core->io_addr + BCMA_CC_UART0_DATA +
 415                                (i * 256);
 416                ports[i].irq = irq;
 417                ports[i].baud_base = baud_base;
 418                ports[i].reg_shift = 0;
 419        }
 420}
 421#endif /* CONFIG_BCMA_DRIVER_MIPS */
 422