linux/drivers/ssb/driver_extif.c
<<
>>
Prefs
   1/*
   2 * Sonics Silicon Backplane
   3 * Broadcom EXTIF core driver
   4 *
   5 * Copyright 2005, Broadcom Corporation
   6 * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
   7 * Copyright 2006, 2007, Felix Fietkau <nbd@openwrt.org>
   8 * Copyright 2007, Aurelien Jarno <aurelien@aurel32.net>
   9 *
  10 * Licensed under the GNU/GPL. See COPYING for details.
  11 */
  12
  13#include <linux/serial.h>
  14#include <linux/serial_core.h>
  15#include <linux/serial_reg.h>
  16
  17#include "ssb_private.h"
  18
  19
  20static inline u32 extif_read32(struct ssb_extif *extif, u16 offset)
  21{
  22        return ssb_read32(extif->dev, offset);
  23}
  24
  25static inline void extif_write32(struct ssb_extif *extif, u16 offset, u32 value)
  26{
  27        ssb_write32(extif->dev, offset, value);
  28}
  29
  30static inline u32 extif_write32_masked(struct ssb_extif *extif, u16 offset,
  31                                       u32 mask, u32 value)
  32{
  33        value &= mask;
  34        value |= extif_read32(extif, offset) & ~mask;
  35        extif_write32(extif, offset, value);
  36
  37        return value;
  38}
  39
  40#ifdef CONFIG_SSB_SERIAL
  41static bool serial_exists(u8 *regs)
  42{
  43        u8 save_mcr, msr = 0;
  44
  45        if (regs) {
  46                save_mcr = regs[UART_MCR];
  47                regs[UART_MCR] = (UART_MCR_LOOP | UART_MCR_OUT2 | UART_MCR_RTS);
  48                msr = regs[UART_MSR] & (UART_MSR_DCD | UART_MSR_RI
  49                                        | UART_MSR_CTS | UART_MSR_DSR);
  50                regs[UART_MCR] = save_mcr;
  51        }
  52        return (msr == (UART_MSR_DCD | UART_MSR_CTS));
  53}
  54
  55int ssb_extif_serial_init(struct ssb_extif *extif, struct ssb_serial_port *ports)
  56{
  57        u32 i, nr_ports = 0;
  58
  59        /* Disable GPIO interrupt initially */
  60        extif_write32(extif, SSB_EXTIF_GPIO_INTPOL, 0);
  61        extif_write32(extif, SSB_EXTIF_GPIO_INTMASK, 0);
  62
  63        for (i = 0; i < 2; i++) {
  64                void __iomem *uart_regs;
  65
  66                uart_regs = ioremap_nocache(SSB_EUART, 16);
  67                if (uart_regs) {
  68                        uart_regs += (i * 8);
  69
  70                        if (serial_exists(uart_regs) && ports) {
  71                                extif_write32(extif, SSB_EXTIF_GPIO_INTMASK, 2);
  72
  73                                nr_ports++;
  74                                ports[i].regs = uart_regs;
  75                                ports[i].irq = 2;
  76                                ports[i].baud_base = 13500000;
  77                                ports[i].reg_shift = 0;
  78                        }
  79                        iounmap(uart_regs);
  80                }
  81        }
  82        return nr_ports;
  83}
  84#endif /* CONFIG_SSB_SERIAL */
  85
  86void ssb_extif_timing_init(struct ssb_extif *extif, unsigned long ns)
  87{
  88        u32 tmp;
  89
  90        /* Initialize extif so we can get to the LEDs and external UART */
  91        extif_write32(extif, SSB_EXTIF_PROG_CFG, SSB_EXTCFG_EN);
  92
  93        /* Set timing for the flash */
  94        tmp  = DIV_ROUND_UP(10, ns) << SSB_PROG_WCNT_3_SHIFT;
  95        tmp |= DIV_ROUND_UP(40, ns) << SSB_PROG_WCNT_1_SHIFT;
  96        tmp |= DIV_ROUND_UP(120, ns);
  97        extif_write32(extif, SSB_EXTIF_PROG_WAITCNT, tmp);
  98
  99        /* Set programmable interface timing for external uart */
 100        tmp  = DIV_ROUND_UP(10, ns) << SSB_PROG_WCNT_3_SHIFT;
 101        tmp |= DIV_ROUND_UP(20, ns) << SSB_PROG_WCNT_2_SHIFT;
 102        tmp |= DIV_ROUND_UP(100, ns) << SSB_PROG_WCNT_1_SHIFT;
 103        tmp |= DIV_ROUND_UP(120, ns);
 104        extif_write32(extif, SSB_EXTIF_PROG_WAITCNT, tmp);
 105}
 106
 107void ssb_extif_get_clockcontrol(struct ssb_extif *extif,
 108                                u32 *pll_type, u32 *n, u32 *m)
 109{
 110        *pll_type = SSB_PLLTYPE_1;
 111        *n = extif_read32(extif, SSB_EXTIF_CLOCK_N);
 112        *m = extif_read32(extif, SSB_EXTIF_CLOCK_SB);
 113}
 114
 115u32 ssb_extif_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt, u32 ticks)
 116{
 117        struct ssb_extif *extif = bcm47xx_wdt_get_drvdata(wdt);
 118
 119        return ssb_extif_watchdog_timer_set(extif, ticks);
 120}
 121
 122u32 ssb_extif_watchdog_timer_set_ms(struct bcm47xx_wdt *wdt, u32 ms)
 123{
 124        struct ssb_extif *extif = bcm47xx_wdt_get_drvdata(wdt);
 125        u32 ticks = (SSB_EXTIF_WATCHDOG_CLK / 1000) * ms;
 126
 127        ticks = ssb_extif_watchdog_timer_set(extif, ticks);
 128
 129        return (ticks * 1000) / SSB_EXTIF_WATCHDOG_CLK;
 130}
 131
 132u32 ssb_extif_watchdog_timer_set(struct ssb_extif *extif, u32 ticks)
 133{
 134        if (ticks > SSB_EXTIF_WATCHDOG_MAX_TIMER)
 135                ticks = SSB_EXTIF_WATCHDOG_MAX_TIMER;
 136        extif_write32(extif, SSB_EXTIF_WATCHDOG, ticks);
 137
 138        return ticks;
 139}
 140
 141void ssb_extif_init(struct ssb_extif *extif)
 142{
 143        if (!extif->dev)
 144                return; /* We don't have a Extif core */
 145        spin_lock_init(&extif->gpio_lock);
 146}
 147
 148u32 ssb_extif_gpio_in(struct ssb_extif *extif, u32 mask)
 149{
 150        return extif_read32(extif, SSB_EXTIF_GPIO_IN) & mask;
 151}
 152
 153u32 ssb_extif_gpio_out(struct ssb_extif *extif, u32 mask, u32 value)
 154{
 155        unsigned long flags;
 156        u32 res = 0;
 157
 158        spin_lock_irqsave(&extif->gpio_lock, flags);
 159        res = extif_write32_masked(extif, SSB_EXTIF_GPIO_OUT(0),
 160                                   mask, value);
 161        spin_unlock_irqrestore(&extif->gpio_lock, flags);
 162
 163        return res;
 164}
 165
 166u32 ssb_extif_gpio_outen(struct ssb_extif *extif, u32 mask, u32 value)
 167{
 168        unsigned long flags;
 169        u32 res = 0;
 170
 171        spin_lock_irqsave(&extif->gpio_lock, flags);
 172        res = extif_write32_masked(extif, SSB_EXTIF_GPIO_OUTEN(0),
 173                                   mask, value);
 174        spin_unlock_irqrestore(&extif->gpio_lock, flags);
 175
 176        return res;
 177}
 178
 179u32 ssb_extif_gpio_polarity(struct ssb_extif *extif, u32 mask, u32 value)
 180{
 181        unsigned long flags;
 182        u32 res = 0;
 183
 184        spin_lock_irqsave(&extif->gpio_lock, flags);
 185        res = extif_write32_masked(extif, SSB_EXTIF_GPIO_INTPOL, mask, value);
 186        spin_unlock_irqrestore(&extif->gpio_lock, flags);
 187
 188        return res;
 189}
 190
 191u32 ssb_extif_gpio_intmask(struct ssb_extif *extif, u32 mask, u32 value)
 192{
 193        unsigned long flags;
 194        u32 res = 0;
 195
 196        spin_lock_irqsave(&extif->gpio_lock, flags);
 197        res = extif_write32_masked(extif, SSB_EXTIF_GPIO_INTMASK, mask, value);
 198        spin_unlock_irqrestore(&extif->gpio_lock, flags);
 199
 200        return res;
 201}
 202