/* * Jeff Harrell, jharrell@ti.com * Copyright (C) 2001 Texas Instruments, Inc. All rights reserved. * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. * * Texas Instruments Sangam specific setup. */ #include #include #include #include #include /*--- #include ---*/ /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ #if defined (CONFIG_MIPS_AVALANCHE_VLYNQ) || defined (CONFIG_MIPS_AVALANCHE_VLYNQ_MODULE) extern REMOTE_VLYNQ_DEV_RESET_CTRL_FN p_remote_vlynq_dev_reset_ctrl; #endif #include /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ extern int vlynq_device_type0; extern int vlynq_device_type1; extern int reset_hack; extern int vlynq_dev_init(unsigned int); /*------------------------------------------------------------------------------------------*\ This function is board specific and should be ported for each board. \*------------------------------------------------------------------------------------------*/ /*****************************************************************************\ \*****************************************************************************/ typedef struct _reset_desc_t { unsigned int * reg_addr; int reset_hack; unsigned long * gpio_reset_addr; int *p_gpio_bit; } vlynq_reset_desc_t; extern int vlynq_reset_bit_0; extern int vlynq_reset_bit_1; static vlynq_reset_desc_t vlynq_reset_desc[CONFIG_MIPS_AVALANCHE_VLYNQ_PORTS] = { { /* VLYNQ0 */ (unsigned int *) 0xa4000004, 1, (unsigned long *) AVALANCHE_GPIO_DATA_OUT, &vlynq_reset_bit_0 } #if CONFIG_MIPS_AVALANCHE_VLYNQ_PORTS > 1 , { /* VLYNQ1 */ (unsigned int *) 0xac000004, 1, (unsigned long *) AVALANCHE_GPIO_DATA_OUT, &vlynq_reset_bit_1 } #endif /*--- #if CONFIG_MIPS_AVALANCHE_VLYNQ_PORTS > 1 ---*/ } ; int remote_vlynq_dev_reset_ctrl (unsigned int module_reset_bit, AVALANCHE_RESET_CTRL_T reset_ctrl) { int unit; if (module_reset_bit >= 32) { printk ( KERN_ERR "ERROR: remote_vlynq_dev_reset_ctrl(%u, %d)\n", module_reset_bit, (int) reset_ctrl ); return 1; } else { /* * Ok, for two VLYNQs... * * VLYNQ0: module_reset_bit == 0 * VLYNQ1: anything else */ unit = module_reset_bit ? 1 : 0; } printk ( KERN_INFO "remote_vlynq_dev_reset_ctrl(%u(VLYNQ%d), %s)\n", module_reset_bit, unit, OUT_OF_RESET == reset_ctrl ? "OUT_OF_RESET" : IN_RESET == reset_ctrl ? "IN_RESET" : "unknown_RESET" ); switch ((int) reset_ctrl) { case IN_RESET: { unsigned long * gpio = vlynq_reset_desc[unit].gpio_reset_addr; unsigned int bit = *(vlynq_reset_desc[unit].p_gpio_bit); if (gpio != NULL) { printk (KERN_INFO "gpio[%p] &= ~(1 << %u);\n", gpio, bit); *gpio &= ~(1 << bit); } vlynq_delay (20000); printk (KERN_INFO "Resetting the remote device.\n"); vlynq_reset_desc[unit].reset_hack = 0; break; } case OUT_OF_RESET: { unsigned int * reg = vlynq_reset_desc[unit].reg_addr; if (vlynq_reset_desc[unit].reset_hack != 0) { printk (KERN_INFO "remote_vlynq_dev_reset_ctrl: SKIPPED!\n"); return 2; } vlynq_delay (20000); printk (KERN_INFO "Un-resetting the remote device...\n"); if (vlynq_dev_init (1 << unit)) { printk (KERN_INFO "remote_vlynq_dev_reset_ctrl: FAILED!\n"); return 3; } printk (KERN_INFO "VLYNQ re-initialized.\n"); printk (KERN_INFO "Test, reading from %p... result = 0x%x\n", reg, *reg); vlynq_reset_desc[unit].reset_hack = 2; break; } default: /* assert (0); */ break; } printk ("remote_vlynq_dev_reset_ctrl: done\n"); return 0; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ #define SYS_VLYNQ_LOCAL_INTERRUPT_VECTOR 30 /* MSB - 1 bit */ #define SYS_VLYNQ_REMOTE_INTERRUPT_VECTOR 31 /* MSB bit */ #define SYS_VLYNQ_OPTIONS 0x7F; /* all options*/ /* These defines are board specific */ #define VLYNQ0_REMOTE_WINDOW1_OFFSET (0x0C000000) #define VLYNQ0_REMOTE_WINDOW1_SIZE (0x00030000) /* 0x10500 */ #define VLYNQ1_REMOTE_WINDOW1_OFFSET (0x0C010000) #define VLYNQ1_REMOTE_WINDOW1_SIZE (0x00000500) /*------------------------------------------------------------------------------------------*\ * Defines for Config = 0, Port = 0 \*------------------------------------------------------------------------------------------*/ #define VLYNQ_ACX111_MEM_OFFSET 0xC0000000 /* Physical address of ACX111 memory */ #define VLYNQ_ACX111_MEM_SIZE 0x00040000 /* Total size of the ACX111 memory */ #define VLYNQ_ACX111_REG_OFFSET 0xF0000000 /* PHYS_ADDR of ACX111 control registers */ #define VLYNQ_ACX111_REG_SIZE 0x00022000 /* Size of ACX111 registers area, MAC+PHY */ #include "vlynq_init.h" /*------------------------------------------------------------------------------------------*\ * for debugging \*------------------------------------------------------------------------------------------*/ struct _vlynq_registers *VLYNQ0_local = (struct _vlynq_registers *) 0xa8611800; struct _vlynq_registers *VLYNQ0_remote = (struct _vlynq_registers *) 0xa4000000; struct _vlynq_registers *VLYNQ1_local = (struct _vlynq_registers *) 0xa8611C00; struct _vlynq_registers *VLYNQ1_remote = (struct _vlynq_registers *) 0xac000000; extern VLYNQ_DEV vlynqDevice0, vlynqDevice1; int vlynq_init_status[CONFIG_MIPS_AVALANCHE_VLYNQ_PORTS] = { 0 #if CONFIG_MIPS_AVALANCHE_VLYNQ_PORTS > 1 , 0 #endif /*--- #if CONFIG_MIPS_AVALANCHE_VLYNQ_PORTS > 1 ---*/ }; static int reset_hack = 1; /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int vlynq_config_dev_init (unsigned int device_index, unsigned int config_index) { VLYNQ_DEV * V; struct _vlynq_dev_config * C; int ret, bit; #if CONFIG_MIPS_OHIO == 1 if ((device_index >= 1) || (config_index >= MAX_VLYNQ_CONFIG0 )) { printk (KERN_INFO "Invalid config: device=%u, config=%u\n", device_index, config_index); return 1; } V = &vlynqDevice0; C = &vlynq_dev_config0[config_index]; #else /*--- #if CONFIG_MIPS_OHIO == 1 ---*/ if ((device_index >= 2) || (config_index >= MAX_VLYNQ_CONFIG0 )) { printk (KERN_INFO "Invalid config: device=%u, config=%u\n", device_index, config_index); return 1; } V = device_index == 0 ? &vlynqDevice0 : &vlynqDevice1; C = device_index == 0 ? &vlynq_dev_config0[config_index] : &vlynq_dev_config1[config_index]; #endif /*--- #else ---*/ /*--- #if CONFIG_MIPS_OHIO == 1 ---*/ if (NULL != vlynq_reset_desc[device_index].gpio_reset_addr) { int bit = *(vlynq_reset_desc[device_index].p_gpio_bit); printk (KERN_INFO "GPIO pin reset, bit %d\n", bit); *(unsigned long*) AVALANCHE_GPIO_ENBL |= (1 << bit); vlynq_delay(20000); *(unsigned long*) AVALANCHE_GPIO_DIR &= ~(1 << bit); vlynq_delay(20000); *(unsigned long*) AVALANCHE_GPIO_DATA_OUT &= ~(1 << bit); vlynq_delay(50000); *(unsigned long*) AVALANCHE_GPIO_DATA_OUT |= (1 << bit); vlynq_delay(50000); } printk (KERN_INFO "Setup registers for VLYNQ%d\n", device_index); V->dev_idx = C->dev_idx; V->module_base = C->module_base; V->clk_source = C->clk_source; V->clk_div = C->clk_div; V->state = C->state; V->local_mem = C->local_mem; if (V->local_mem.RxSize[0] == 0) { char * memsize_str = prom_getenv("memsize"); V->local_mem.RxSize[0] = simple_strtol(memsize_str, NULL, 0); printk(KERN_INFO "Set local_mem.RxSize to 0x%x\n", V->local_mem.RxSize[0]); } V->remote_mem = C->remote_mem; V->local_irq = C->local_irq; V->remote_irq = C->remote_irq; if (reset_hack != 1) { printk(KERN_INFO "About to re-init the VLYNQ.\n"); } /*--------------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------------*/ if ((ret = vlynq_init (V, VLYNQ_INIT_PERFORM_ALL)) == 0) { int cnt, i; /* Suraj added the following to keep the 1130 going. */ switch (C->name) { /*------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------*/ case ti_vlynq_tnetw1130: vlynq_interrupt_vector_set( V, 0 /* intr vector line running into 1130 vlynq */, 0 /* intr mapped onto the interrupt register on remote vlynq and this vlynq */, VLYNQ_REMOTE_DVC, 0 /* polarity active high */, 0 /* interrupt Level triggered */ ); /* System wide interrupt is 80 for 1130, please note. */ vlynq_init_status[device_index] = 1; vlynq_reset_desc[device_index].reset_hack = 2; printk(KERN_INFO "VLYNQ%d: init succeeded!\n", device_index); return 0; /*------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------*/ case ti_vlynq_tnetw1350: vlynq_interrupt_vector_set( V, 0 /* intr vector line running into 1350 vlynq */, 7 /* intr mapped onto the interrupt register on remote vlynq and this vlynq */, VLYNQ_REMOTE_DVC, 0 /* polarity active high */, 0 /* interrupt Level triggered */ ); /* System wide interrupt is 80 for 1130, please note. */ vlynq_init_status[device_index] = 1; vlynq_reset_desc[device_index].reset_hack = 2; printk(KERN_INFO "VLYNQ%d: init succeeded!\n", device_index); return 0; /*------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------*/ case ti_vlynq_usb: cnt = sizeof (vecmap) / sizeof (vecmap[0]); for (i = 0; i < cnt; i++) { vlynq_interrupt_vector_set ( V, vecmap[i].int_vector, vecmap[i].map_vector, vecmap[i].dev, vecmap[i].pol, vecmap[i].type ); if (vecmap[i].int_enable) { vlynq_interrupt_enable (V, vecmap[i].dev, vecmap[i].map_vector); } else { vlynq_interrupt_disable (V, vecmap[i].dev, vecmap[i].map_vector); } } vlynq_init_status[device_index] = 1; vlynq_reset_desc[device_index].reset_hack = 2; // <<<< printk(KERN_INFO "VLYNQ%d: init succeeded!\n", device_index); return 0; } } /*--------------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------------*/ if (ret != 0) { printk ( KERN_INFO "VLYNQ INIT FAILED: %s\n", /* YUK! */ ret == VLYNQ_INVALID_ARG ? "VLYNQ_INVALID_ARG" : ret == VLYNQ_INVALID_DRV_STATE ? "VLYNQ_INVALID_DRV_STATE" : ret == VLYNQ_INT_CONFIG_ERR ? "VLYNQ_INT_CONFIG_ERR" : ret == VLYNQ_LINK_DOWN ? "VLYNQ_LINK_DOWN" : ret == VLYNQ_MEMALLOC_FAIL ? "VLYNQ_MEMALLOC_FAIL" : ret == VLYNQ_SUCCESS ? "VLYNQ_SUCCESS" : "VLYNQ_unknown" ); } if (vlynq_reset_desc[device_index].reset_hack == 1) { /*--- prom_printf("VLYNQ INIT FAILED: Please try cold reboot. \n"); ---*/ printk (KERN_INFO "VLYNQ INIT FAILED: Please try cold reboot. \n"); } else { printk (KERN_INFO "Failed to initialize the VLYNQ interface at insmod.\n"); } return 1; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int vlynq_dev_init (unsigned int device_mask) { volatile unsigned int *reset_base = (unsigned int *) AVALANCHE_RESET_CONTROL_BASE; if (((device_mask & 1) != 0) && (vlynq_device_type0 != 0)) { *reset_base &= ~((1 << AVALANCHE_LOW_VLYNQ_RESET_BIT)); /* | (1 << AVALANCHE_HIGH_VLYNQ_RESET_BIT)); */ vlynq_delay(20000); /* Bring vlynq out of reset if not already done */ *reset_base |= (1 << AVALANCHE_LOW_VLYNQ_RESET_BIT); /* | (1 << AVALANCHE_HIGH_VLYNQ_RESET_BIT); */ vlynq_delay(20000); /* Allowing sufficient time to VLYNQ to settle down.*/ if (vlynq_config_dev_init(0, vlynq_device_type0 - 1)) { return 1; } } #if defined(AVALANCHE_HIGH_VLYNQ_RESET_BIT) if (((device_mask & 2) != 0) && (vlynq_device_type1 != 0)) { *reset_base &= ~((1 << AVALANCHE_HIGH_VLYNQ_RESET_BIT)); /* | (1 << AVALANCHE_HIGH_VLYNQ_RESET_BIT)); */ vlynq_delay(20000); /* Bring vlynq out of reset if not already done */ *reset_base |= (1 << AVALANCHE_HIGH_VLYNQ_RESET_BIT); /* | (1 << AVALANCHE_HIGH_VLYNQ_RESET_BIT); */ vlynq_delay(20000); /* Allowing sufficient time to VLYNQ to settle down.*/ if (vlynq_config_dev_init(1, vlynq_device_type1 - 1)) { return 1; } } #endif /*--- #if defined(AVALANCHE_HIGH_VLYNQ_RESET_BIT) ---*/ printk (KERN_INFO "vlynq init done\n"); return 0; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void vlynq_set_function_pointers(void) { extern VLYNQ_DEV vlynqDevice0; extern VLYNQ_DEV vlynqDevice1; p_vlynq_interrupt_vector_set = (p_vlynq_interrupt_vector_set_t) vlynq_interrupt_vector_set; p_vlynq_interrupt_vector_cntl = (p_vlynq_interrupt_vector_cntl_t) vlynq_interrupt_vector_cntl; p_vlynq_interrupt_get_count = (p_vlynq_interrupt_get_count_t) vlynq_interrupt_get_count; p_vlynq_install_isr = (p_vlynq_install_isr_t) vlynq_install_isr; p_vlynq_uninstall_isr = (p_vlynq_uninstall_isr_t) vlynq_uninstall_isr; p_vlynq_root_isr = (p_vlynq_root_isr_t) vlynq_root_isr; p_vlynq_delay = (p_vlynq_delay_t) vlynq_delay; p_vlynq_interrupt_vector_map = (p_vlynq_interrupt_vector_map_t) vlynq_interrupt_vector_map; p_vlynq_interrupt_set_polarity = (p_vlynq_interrupt_set_polarity_t) vlynq_interrupt_set_polarity; p_vlynq_interrupt_get_polarity = (p_vlynq_interrupt_get_polarity_t) vlynq_interrupt_get_polarity; p_vlynq_interrupt_set_type = (p_vlynq_interrupt_set_type_t) vlynq_interrupt_set_type; p_vlynq_interrupt_get_type = (p_vlynq_interrupt_get_type_t) vlynq_interrupt_get_type; p_vlynq_interrupt_enable = (p_vlynq_interrupt_enable_t) vlynq_interrupt_enable; p_vlynq_interrupt_disable = (p_vlynq_interrupt_disable_t) vlynq_interrupt_disable; p_remote_vlynq_dev_reset_ctrl = remote_vlynq_dev_reset_ctrl; p_vlynqDevice0 = &vlynqDevice0; p_vlynqDevice1 = &vlynqDevice1; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void vlynq_clear_function_pointers(void) { extern VLYNQ_DEV vlynqDevice0; extern VLYNQ_DEV vlynqDevice1; p_vlynq_interrupt_vector_set = NULL; p_vlynq_interrupt_vector_cntl = NULL; p_vlynq_interrupt_get_count = NULL; p_vlynq_install_isr = NULL; p_vlynq_uninstall_isr = NULL; p_vlynq_root_isr = NULL; p_vlynq_delay = NULL; p_vlynq_interrupt_vector_map = NULL; p_vlynq_interrupt_set_polarity = NULL; p_vlynq_interrupt_get_polarity = NULL; p_vlynq_interrupt_set_type = NULL; p_vlynq_interrupt_get_type = NULL; p_vlynq_interrupt_enable = NULL; p_vlynq_interrupt_disable = NULL; p_remote_vlynq_dev_reset_ctrl = NULL; p_vlynqDevice0 = NULL; p_vlynqDevice1 = NULL; }