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 <mb@bu3sch.de>
   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
 115void ssb_extif_watchdog_timer_set(struct ssb_extif *extif,
 116                                  u32 ticks)
 117{
 118        extif_write32(extif, SSB_EXTIF_WATCHDOG, ticks);
 119}
 120
 121u32 ssb_extif_gpio_in(struct ssb_extif *extif, u32 mask)
 122{
 123        return extif_read32(extif, SSB_EXTIF_GPIO_IN) & mask;
 124}
 125
 126u32 ssb_extif_gpio_out(struct ssb_extif *extif, u32 mask, u32 value)
 127{
 128        return extif_write32_masked(extif, SSB_EXTIF_GPIO_OUT(0),
 129                                   mask, value);
 130}
 131
 132u32 ssb_extif_gpio_outen(struct ssb_extif *extif, u32 mask, u32 value)
 133{
 134        return extif_write32_masked(extif, SSB_EXTIF_GPIO_OUTEN(0),
 135                                   mask, value);
 136}
 137
 138u32 ssb_extif_gpio_polarity(struct ssb_extif *extif, u32 mask, u32 value)
 139{
 140        return extif_write32_masked(extif, SSB_EXTIF_GPIO_INTPOL, mask, value);
 141}
 142
 143u32 ssb_extif_gpio_intmask(struct ssb_extif *extif, u32 mask, u32 value)
 144{
 145        return extif_write32_masked(extif, SSB_EXTIF_GPIO_INTMASK, mask, value);
 146}
 147