diff options
Diffstat (limited to 'arch/sh/boards/overdrive/fpga.c')
-rw-r--r-- | arch/sh/boards/overdrive/fpga.c | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/arch/sh/boards/overdrive/fpga.c b/arch/sh/boards/overdrive/fpga.c new file mode 100644 index 00000000000..3a1ec940344 --- /dev/null +++ b/arch/sh/boards/overdrive/fpga.c @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2000 David J. Mckay (david.mckay@st.com) + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * This file handles programming up the Altera Flex10K that interfaces to + * the Galileo, and does the PS/2 keyboard and mouse + * + */ + + +#include <linux/config.h> +#include <linux/kernel.h> +#include <linux/smp.h> +#include <linux/smp_lock.h> +#include <linux/init.h> +#include <linux/errno.h> +#include <linux/pci.h> +#include <linux/delay.h> + + +#include <asm/overdriver/gt64111.h> +#include <asm/overdrive/overdrive.h> +#include <asm/overdrive/fpga.h> + +#define FPGA_NotConfigHigh() (*FPGA_ControlReg) = (*FPGA_ControlReg) | ENABLE_FPGA_BIT +#define FPGA_NotConfigLow() (*FPGA_ControlReg) = (*FPGA_ControlReg) & RESET_FPGA_MASK + +/* I need to find out what (if any) the real delay factor here is */ +/* The delay is definately not critical */ +#define long_delay() {int i;for(i=0;i<10000;i++);} +#define short_delay() {int i;for(i=0;i<100;i++);} + +static void __init program_overdrive_fpga(const unsigned char *fpgacode, + int size) +{ + int timeout = 0; + int i, j; + unsigned char b; + static volatile unsigned char *FPGA_ControlReg = + (volatile unsigned char *) (OVERDRIVE_CTRL); + static volatile unsigned char *FPGA_ProgramReg = + (volatile unsigned char *) (FPGA_DCLK_ADDRESS); + + printk("FPGA: Commencing FPGA Programming\n"); + + /* The PCI reset but MUST be low when programming the FPGA !!! */ + b = (*FPGA_ControlReg) & RESET_PCI_MASK; + + (*FPGA_ControlReg) = b; + + /* Prepare FPGA to program */ + + FPGA_NotConfigHigh(); + long_delay(); + + FPGA_NotConfigLow(); + short_delay(); + + while ((*FPGA_ProgramReg & FPGA_NOT_STATUS) != 0) { + printk("FPGA: Waiting for NotStatus to go Low ... \n"); + } + + FPGA_NotConfigHigh(); + + /* Wait for FPGA "ready to be programmed" signal */ + printk("FPGA: Waiting for NotStatus to go high (FPGA ready)... \n"); + + for (timeout = 0; + (((*FPGA_ProgramReg & FPGA_NOT_STATUS) == 0) + && (timeout < FPGA_TIMEOUT)); timeout++); + + /* Check if timeout condition occured - i.e. an error */ + + if (timeout == FPGA_TIMEOUT) { + printk + ("FPGA: Failed to program - Timeout waiting for notSTATUS to go high\n"); + return; + } + + printk("FPGA: Copying data to FPGA ... %d bytes\n", size); + + /* Copy array to FPGA - bit at a time */ + + for (i = 0; i < size; i++) { + volatile unsigned w = 0; + + for (j = 0; j < 8; j++) { + *FPGA_ProgramReg = (fpgacode[i] >> j) & 0x01; + short_delay(); + } + if ((i & 0x3ff) == 0) { + printk("."); + } + } + + /* Waiting for CONFDONE to go high - means the program is complete */ + + for (timeout = 0; + (((*FPGA_ProgramReg & FPGA_CONFDONE) == 0) + && (timeout < FPGA_TIMEOUT)); timeout++) { + + *FPGA_ProgramReg = 0x0; + long_delay(); + } + + if (timeout == FPGA_TIMEOUT) { + printk + ("FPGA: Failed to program - Timeout waiting for CONFDONE to go high\n"); + return; + } else { /* Clock another 10 times - gets the device into a working state */ + for (i = 0; i < 10; i++) { + *FPGA_ProgramReg = 0x0; + short_delay(); + } + } + + printk("FPGA: Programming complete\n"); +} + + +static const unsigned char __init fpgacode[] = { +#include "./overdrive.ttf" /* Code from maxplus2 compiler */ + , 0, 0 +}; + + +int __init init_overdrive_fpga(void) +{ + program_overdrive_fpga(fpgacode, sizeof(fpgacode)); + + return 0; +} |