161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch/* 261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch * Sonics Silicon Backplane 361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch * Broadcom EXTIF core driver 461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch * 561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch * Copyright 2005, Broadcom Corporation 6eb032b9837a958e21ca000358a5bde5e17192ddbMichael Buesch * Copyright 2006, 2007, Michael Buesch <m@bues.ch> 761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch * Copyright 2006, 2007, Felix Fietkau <nbd@openwrt.org> 861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch * Copyright 2007, Aurelien Jarno <aurelien@aurel32.net> 961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch * 1061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch * Licensed under the GNU/GPL. See COPYING for details. 1161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch */ 1261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 1361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch#include <linux/serial.h> 1461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch#include <linux/serial_core.h> 1561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch#include <linux/serial_reg.h> 1661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 1761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch#include "ssb_private.h" 1861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 1961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 2061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Bueschstatic inline u32 extif_read32(struct ssb_extif *extif, u16 offset) 2161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch{ 2261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch return ssb_read32(extif->dev, offset); 2361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch} 2461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 2561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Bueschstatic inline void extif_write32(struct ssb_extif *extif, u16 offset, u32 value) 2661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch{ 2761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch ssb_write32(extif->dev, offset, value); 2861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch} 2961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 30c2bcbe65fc88d61f9a806367ff6eab76c9eabb3aMichael Bueschstatic inline u32 extif_write32_masked(struct ssb_extif *extif, u16 offset, 31c2bcbe65fc88d61f9a806367ff6eab76c9eabb3aMichael Buesch u32 mask, u32 value) 3261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch{ 3361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch value &= mask; 3461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch value |= extif_read32(extif, offset) & ~mask; 3561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch extif_write32(extif, offset, value); 36c2bcbe65fc88d61f9a806367ff6eab76c9eabb3aMichael Buesch 37c2bcbe65fc88d61f9a806367ff6eab76c9eabb3aMichael Buesch return value; 3861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch} 3961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 4061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch#ifdef CONFIG_SSB_SERIAL 4161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Bueschstatic bool serial_exists(u8 *regs) 4261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch{ 4361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch u8 save_mcr, msr = 0; 4461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 4561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (regs) { 4661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch save_mcr = regs[UART_MCR]; 4761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch regs[UART_MCR] = (UART_MCR_LOOP | UART_MCR_OUT2 | UART_MCR_RTS); 4861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch msr = regs[UART_MSR] & (UART_MSR_DCD | UART_MSR_RI 4961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch | UART_MSR_CTS | UART_MSR_DSR); 5061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch regs[UART_MCR] = save_mcr; 5161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch } 5261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch return (msr == (UART_MSR_DCD | UART_MSR_CTS)); 5361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch} 5461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 5561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Bueschint ssb_extif_serial_init(struct ssb_extif *extif, struct ssb_serial_port *ports) 5661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch{ 5761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch u32 i, nr_ports = 0; 5861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 5961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch /* Disable GPIO interrupt initially */ 6061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch extif_write32(extif, SSB_EXTIF_GPIO_INTPOL, 0); 6161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch extif_write32(extif, SSB_EXTIF_GPIO_INTMASK, 0); 6261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 6361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch for (i = 0; i < 2; i++) { 6461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch void __iomem *uart_regs; 6561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 6661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch uart_regs = ioremap_nocache(SSB_EUART, 16); 6761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (uart_regs) { 6861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch uart_regs += (i * 8); 6961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 7061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (serial_exists(uart_regs) && ports) { 7161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch extif_write32(extif, SSB_EXTIF_GPIO_INTMASK, 2); 7261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 7361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch nr_ports++; 7461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch ports[i].regs = uart_regs; 7561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch ports[i].irq = 2; 7661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch ports[i].baud_base = 13500000; 7761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch ports[i].reg_shift = 0; 7861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch } 7961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch iounmap(uart_regs); 8061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch } 8161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch } 8261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch return nr_ports; 8361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch} 8461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch#endif /* CONFIG_SSB_SERIAL */ 8561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 8661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Bueschvoid ssb_extif_timing_init(struct ssb_extif *extif, unsigned long ns) 8761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch{ 8861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch u32 tmp; 8961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 9061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch /* Initialize extif so we can get to the LEDs and external UART */ 9161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch extif_write32(extif, SSB_EXTIF_PROG_CFG, SSB_EXTCFG_EN); 9261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 9361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch /* Set timing for the flash */ 9461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch tmp = DIV_ROUND_UP(10, ns) << SSB_PROG_WCNT_3_SHIFT; 9561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch tmp |= DIV_ROUND_UP(40, ns) << SSB_PROG_WCNT_1_SHIFT; 9661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch tmp |= DIV_ROUND_UP(120, ns); 9761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch extif_write32(extif, SSB_EXTIF_PROG_WAITCNT, tmp); 9861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 9961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch /* Set programmable interface timing for external uart */ 10061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch tmp = DIV_ROUND_UP(10, ns) << SSB_PROG_WCNT_3_SHIFT; 10161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch tmp |= DIV_ROUND_UP(20, ns) << SSB_PROG_WCNT_2_SHIFT; 10261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch tmp |= DIV_ROUND_UP(100, ns) << SSB_PROG_WCNT_1_SHIFT; 10361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch tmp |= DIV_ROUND_UP(120, ns); 10461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch extif_write32(extif, SSB_EXTIF_PROG_WAITCNT, tmp); 10561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch} 10661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 10761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Bueschvoid ssb_extif_get_clockcontrol(struct ssb_extif *extif, 10861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch u32 *pll_type, u32 *n, u32 *m) 10961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch{ 11061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch *pll_type = SSB_PLLTYPE_1; 11161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch *n = extif_read32(extif, SSB_EXTIF_CLOCK_N); 11261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch *m = extif_read32(extif, SSB_EXTIF_CLOCK_SB); 11361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch} 11461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 11542bfad4f71637c4eb4791aa8062063c4a8526522Michael Bueschvoid ssb_extif_watchdog_timer_set(struct ssb_extif *extif, 11642bfad4f71637c4eb4791aa8062063c4a8526522Michael Buesch u32 ticks) 11742bfad4f71637c4eb4791aa8062063c4a8526522Michael Buesch{ 11842bfad4f71637c4eb4791aa8062063c4a8526522Michael Buesch extif_write32(extif, SSB_EXTIF_WATCHDOG, ticks); 11942bfad4f71637c4eb4791aa8062063c4a8526522Michael Buesch} 12042bfad4f71637c4eb4791aa8062063c4a8526522Michael Buesch 12161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Bueschu32 ssb_extif_gpio_in(struct ssb_extif *extif, u32 mask) 12261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch{ 12361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch return extif_read32(extif, SSB_EXTIF_GPIO_IN) & mask; 12461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch} 12561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 126c2bcbe65fc88d61f9a806367ff6eab76c9eabb3aMichael Bueschu32 ssb_extif_gpio_out(struct ssb_extif *extif, u32 mask, u32 value) 12761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch{ 12861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch return extif_write32_masked(extif, SSB_EXTIF_GPIO_OUT(0), 12961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch mask, value); 13061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch} 13161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 132c2bcbe65fc88d61f9a806367ff6eab76c9eabb3aMichael Bueschu32 ssb_extif_gpio_outen(struct ssb_extif *extif, u32 mask, u32 value) 13361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch{ 13461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch return extif_write32_masked(extif, SSB_EXTIF_GPIO_OUTEN(0), 13561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch mask, value); 13661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch} 137c2bcbe65fc88d61f9a806367ff6eab76c9eabb3aMichael Buesch 138c2bcbe65fc88d61f9a806367ff6eab76c9eabb3aMichael Bueschu32 ssb_extif_gpio_polarity(struct ssb_extif *extif, u32 mask, u32 value) 139c2bcbe65fc88d61f9a806367ff6eab76c9eabb3aMichael Buesch{ 140c2bcbe65fc88d61f9a806367ff6eab76c9eabb3aMichael Buesch return extif_write32_masked(extif, SSB_EXTIF_GPIO_INTPOL, mask, value); 141c2bcbe65fc88d61f9a806367ff6eab76c9eabb3aMichael Buesch} 14261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 143c2bcbe65fc88d61f9a806367ff6eab76c9eabb3aMichael Bueschu32 ssb_extif_gpio_intmask(struct ssb_extif *extif, u32 mask, u32 value) 144c2bcbe65fc88d61f9a806367ff6eab76c9eabb3aMichael Buesch{ 145c2bcbe65fc88d61f9a806367ff6eab76c9eabb3aMichael Buesch return extif_write32_masked(extif, SSB_EXTIF_GPIO_INTMASK, mask, value); 146c2bcbe65fc88d61f9a806367ff6eab76c9eabb3aMichael Buesch} 147