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 "ssb_private.h" 14 15 #include <linux/serial.h> 16 #include <linux/serial_core.h> 17 #include <linux/serial_reg.h> 18 19 20 static inline u32 extif_read32(struct ssb_extif *extif, u16 offset) 21 { 22 return ssb_read32(extif->dev, offset); 23 } 24 25 static inline void extif_write32(struct ssb_extif *extif, u16 offset, u32 value) 26 { 27 ssb_write32(extif->dev, offset, value); 28 } 29 30 static 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 41 static 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 55 int 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(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 86 void 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 107 void 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 115 u32 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 122 u32 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 132 u32 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 141 void 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 148 u32 ssb_extif_gpio_in(struct ssb_extif *extif, u32 mask) 149 { 150 return extif_read32(extif, SSB_EXTIF_GPIO_IN) & mask; 151 } 152 153 u32 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 166 u32 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 179 u32 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 191 u32 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