From 73646217186aa17afc8e305c5f06f06dd335eaad Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Tue, 20 Nov 2007 20:33:09 +0100 Subject: drivers/pcmcia : move pcmcia drivers to drivers/pcmcia Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD --- drivers/Makefile | 9 - drivers/i82365.c | 1014 ---------------------------------------- drivers/mpc8xx_pcmcia.c | 304 ------------ drivers/pcmcia/Makefile | 50 ++ drivers/pcmcia/i82365.c | 1014 ++++++++++++++++++++++++++++++++++++++++ drivers/pcmcia/mpc8xx_pcmcia.c | 304 ++++++++++++ drivers/pcmcia/pxa_pcmcia.c | 95 ++++ drivers/pcmcia/rpx_pcmcia.c | 73 +++ drivers/pcmcia/ti_pci1410a.c | 665 ++++++++++++++++++++++++++ drivers/pcmcia/tqm8xx_pcmcia.c | 330 +++++++++++++ drivers/pxa_pcmcia.c | 95 ---- drivers/rpx_pcmcia.c | 73 --- drivers/ti_pci1410a.c | 665 -------------------------- drivers/tqm8xx_pcmcia.c | 330 ------------- 14 files changed, 2531 insertions(+), 2490 deletions(-) delete mode 100644 drivers/i82365.c delete mode 100644 drivers/mpc8xx_pcmcia.c create mode 100644 drivers/pcmcia/Makefile create mode 100644 drivers/pcmcia/i82365.c create mode 100644 drivers/pcmcia/mpc8xx_pcmcia.c create mode 100644 drivers/pcmcia/pxa_pcmcia.c create mode 100644 drivers/pcmcia/rpx_pcmcia.c create mode 100644 drivers/pcmcia/ti_pci1410a.c create mode 100644 drivers/pcmcia/tqm8xx_pcmcia.c delete mode 100644 drivers/pxa_pcmcia.c delete mode 100644 drivers/rpx_pcmcia.c delete mode 100644 drivers/ti_pci1410a.c delete mode 100644 drivers/tqm8xx_pcmcia.c (limited to 'drivers') diff --git a/drivers/Makefile b/drivers/Makefile index f775371c0b..5e31304139 100755 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -102,15 +102,6 @@ COBJS-y += tsec.o COBJS-y += tsi108_eth.o COBJS-y += uli526x.o -# -# PCI/PCMCIA device drivers -# -COBJS-y += mpc8xx_pcmcia.o -COBJS-y += pxa_pcmcia.o -COBJS-y += rpx_pcmcia.o -COBJS-y += ti_pci1410a.o -COBJS-y += tqm8xx_pcmcia.o - # # USB Drivers # diff --git a/drivers/i82365.c b/drivers/i82365.c deleted file mode 100644 index a40fcf41c9..0000000000 --- a/drivers/i82365.c +++ /dev/null @@ -1,1014 +0,0 @@ -/* - * (C) Copyright 2003-2005 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that 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 - * - ******************************************************************** - * - * Lots of code copied from: - * - * i82365.c 1.352 - Linux driver for Intel 82365 and compatible - * PC Card controllers, and Yenta-compatible PCI-to-CardBus controllers. - * (C) 1999 David A. Hinds - */ - -#include - -#ifdef CONFIG_I82365 - -#include -#include -#include -#include - -#include -#include -#include -#ifdef CONFIG_CPC45 -#include -#else -#include -#endif - -static struct pci_device_id supported[] = { -#ifdef CONFIG_CPC45 - {PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_6729}, -#else - {PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1510}, -#endif - {0, 0} -}; - -#define CYCLE_TIME 120 - -#ifdef CONFIG_CPC45 -extern int SPD67290Init (void); -#endif - -#ifdef DEBUG -static void i82365_dump_regions (pci_dev_t dev); -#endif - -typedef struct socket_info_t { - pci_dev_t dev; - u_short bcr; - u_char pci_lat, cb_lat, sub_bus, cache; - u_int cb_phys; - - socket_cap_t cap; - u_short type; - u_int flags; -#ifdef CONFIG_CPC45 - cirrus_state_t c_state; -#else - ti113x_state_t state; -#endif -} socket_info_t; - -#ifdef CONFIG_CPC45 -/* These definitions must match the pcic table! */ -typedef enum pcic_id { - IS_PD6710, IS_PD672X, IS_VT83C469 -} pcic_id; - -typedef struct pcic_t { - char *name; -} pcic_t; - -static pcic_t pcic[] = { - {" Cirrus PD6710: "}, - {" Cirrus PD672x: "}, - {" VIA VT83C469: "}, -}; -#endif - -static socket_info_t socket; -static socket_state_t state; -static struct pccard_mem_map mem; -static struct pccard_io_map io; - -/*====================================================================*/ - -/* Some PCI shortcuts */ - -static int pci_readb (socket_info_t * s, int r, u_char * v) -{ - return pci_read_config_byte (s->dev, r, v); -} -static int pci_writeb (socket_info_t * s, int r, u_char v) -{ - return pci_write_config_byte (s->dev, r, v); -} -static int pci_readw (socket_info_t * s, int r, u_short * v) -{ - return pci_read_config_word (s->dev, r, v); -} -static int pci_writew (socket_info_t * s, int r, u_short v) -{ - return pci_write_config_word (s->dev, r, v); -} -#ifndef CONFIG_CPC45 -static int pci_readl (socket_info_t * s, int r, u_int * v) -{ - return pci_read_config_dword (s->dev, r, v); -} -static int pci_writel (socket_info_t * s, int r, u_int v) -{ - return pci_write_config_dword (s->dev, r, v); -} -#endif /* !CONFIG_CPC45 */ - -/*====================================================================*/ - -#ifdef CONFIG_CPC45 - -#define cb_readb(s) readb((s)->cb_phys + 1) -#define cb_writeb(s, v) writeb(v, (s)->cb_phys) -#define cb_writeb2(s, v) writeb(v, (s)->cb_phys + 1) -#define cb_readl(s, r) readl((s)->cb_phys + (r)) -#define cb_writel(s, r, v) writel(v, (s)->cb_phys + (r)) - - -static u_char i365_get (socket_info_t * s, u_short reg) -{ - u_char val; -#ifdef CONFIG_PCMCIA_SLOT_A - int slot = 0; -#else - int slot = 1; -#endif - - val = I365_REG (slot, reg); - - cb_writeb (s, val); - val = cb_readb (s); - - debug ("i365_get slot:%x reg: %x val: %x\n", slot, reg, val); - return val; -} - -static void i365_set (socket_info_t * s, u_short reg, u_char data) -{ -#ifdef CONFIG_PCMCIA_SLOT_A - int slot = 0; -#else - int slot = 1; -#endif - u_char val; - - val = I365_REG (slot, reg); - - cb_writeb (s, val); - cb_writeb2 (s, data); - - debug ("i365_set slot:%x reg: %x data:%x\n", slot, reg, data); -} - -#else /* ! CONFIG_CPC45 */ - -#define cb_readb(s, r) readb((s)->cb_phys + (r)) -#define cb_readl(s, r) readl((s)->cb_phys + (r)) -#define cb_writeb(s, r, v) writeb(v, (s)->cb_phys + (r)) -#define cb_writel(s, r, v) writel(v, (s)->cb_phys + (r)) - -static u_char i365_get (socket_info_t * s, u_short reg) -{ - return cb_readb (s, 0x0800 + reg); -} - -static void i365_set (socket_info_t * s, u_short reg, u_char data) -{ - cb_writeb (s, 0x0800 + reg, data); -} -#endif /* CONFIG_CPC45 */ - -static void i365_bset (socket_info_t * s, u_short reg, u_char mask) -{ - i365_set (s, reg, i365_get (s, reg) | mask); -} - -static void i365_bclr (socket_info_t * s, u_short reg, u_char mask) -{ - i365_set (s, reg, i365_get (s, reg) & ~mask); -} - -#if 0 /* not used */ -static void i365_bflip (socket_info_t * s, u_short reg, u_char mask, int b) -{ - u_char d = i365_get (s, reg); - - i365_set (s, reg, (b) ? (d | mask) : (d & ~mask)); -} - -static u_short i365_get_pair (socket_info_t * s, u_short reg) -{ - return (i365_get (s, reg) + (i365_get (s, reg + 1) << 8)); -} -#endif /* not used */ - -static void i365_set_pair (socket_info_t * s, u_short reg, u_short data) -{ - i365_set (s, reg, data & 0xff); - i365_set (s, reg + 1, data >> 8); -} - -#ifdef CONFIG_CPC45 -/*====================================================================== - - Code to save and restore global state information for Cirrus - PD67xx controllers, and to set and report global configuration - options. - -======================================================================*/ - -#define flip(v,b,f) (v = ((f)<0) ? v : ((f) ? ((v)|(b)) : ((v)&(~b)))) - -static void cirrus_get_state (socket_info_t * s) -{ - int i; - cirrus_state_t *p = &s->c_state; - - p->misc1 = i365_get (s, PD67_MISC_CTL_1); - p->misc1 &= (PD67_MC1_MEDIA_ENA | PD67_MC1_INPACK_ENA); - p->misc2 = i365_get (s, PD67_MISC_CTL_2); - for (i = 0; i < 6; i++) - p->timer[i] = i365_get (s, PD67_TIME_SETUP (0) + i); - -} - -static void cirrus_set_state (socket_info_t * s) -{ - int i; - u_char misc; - cirrus_state_t *p = &s->c_state; - - misc = i365_get (s, PD67_MISC_CTL_2); - i365_set (s, PD67_MISC_CTL_2, p->misc2); - if (misc & PD67_MC2_SUSPEND) - udelay (50000); - misc = i365_get (s, PD67_MISC_CTL_1); - misc &= ~(PD67_MC1_MEDIA_ENA | PD67_MC1_INPACK_ENA); - i365_set (s, PD67_MISC_CTL_1, misc | p->misc1); - for (i = 0; i < 6; i++) - i365_set (s, PD67_TIME_SETUP (0) + i, p->timer[i]); -} - -static u_int cirrus_set_opts (socket_info_t * s) -{ - cirrus_state_t *p = &s->c_state; - u_int mask = 0xffff; -#if DEBUG - char buf[200]; - - memset (buf, 0, 200); -#endif - - if (has_ring == -1) - has_ring = 1; - flip (p->misc2, PD67_MC2_IRQ15_RI, has_ring); - flip (p->misc2, PD67_MC2_DYNAMIC_MODE, dynamic_mode); -#if DEBUG - if (p->misc2 & PD67_MC2_IRQ15_RI) - strcat (buf, " [ring]"); - if (p->misc2 & PD67_MC2_DYNAMIC_MODE) - strcat (buf, " [dyn mode]"); - if (p->misc1 & PD67_MC1_INPACK_ENA) - strcat (buf, " [inpack]"); -#endif - - if (p->misc2 & PD67_MC2_IRQ15_RI) - mask &= ~0x8000; - if (has_led > 0) { -#if DEBUG - strcat (buf, " [led]"); -#endif - mask &= ~0x1000; - } - if (has_dma > 0) { -#if DEBUG - strcat (buf, " [dma]"); -#endif - mask &= ~0x0600; - flip (p->misc2, PD67_MC2_FREQ_BYPASS, freq_bypass); -#if DEBUG - if (p->misc2 & PD67_MC2_FREQ_BYPASS) - strcat (buf, " [freq bypass]"); -#endif - } - - if (setup_time >= 0) - p->timer[0] = p->timer[3] = setup_time; - if (cmd_time > 0) { - p->timer[1] = cmd_time; - p->timer[4] = cmd_time * 2 + 4; - } - if (p->timer[1] == 0) { - p->timer[1] = 6; - p->timer[4] = 16; - if (p->timer[0] == 0) - p->timer[0] = p->timer[3] = 1; - } - if (recov_time >= 0) - p->timer[2] = p->timer[5] = recov_time; - - debug ("i82365 Opt: %s [%d/%d/%d] [%d/%d/%d]\n", - buf, - p->timer[0], p->timer[1], p->timer[2], - p->timer[3], p->timer[4], p->timer[5]); - - return mask; -} - -#else /* !CONFIG_CPC45 */ - -/*====================================================================== - - Code to save and restore global state information for TI 1130 and - TI 1131 controllers, and to set and report global configuration - options. - -======================================================================*/ - -static void ti113x_get_state (socket_info_t * s) -{ - ti113x_state_t *p = &s->state; - - pci_readl (s, TI113X_SYSTEM_CONTROL, &p->sysctl); - pci_readb (s, TI113X_CARD_CONTROL, &p->cardctl); - pci_readb (s, TI113X_DEVICE_CONTROL, &p->devctl); - pci_readb (s, TI1250_DIAGNOSTIC, &p->diag); - pci_readl (s, TI12XX_IRQMUX, &p->irqmux); -} - -static void ti113x_set_state (socket_info_t * s) -{ - ti113x_state_t *p = &s->state; - - pci_writel (s, TI113X_SYSTEM_CONTROL, p->sysctl); - pci_writeb (s, TI113X_CARD_CONTROL, p->cardctl); - pci_writeb (s, TI113X_DEVICE_CONTROL, p->devctl); - pci_writeb (s, TI1250_MULTIMEDIA_CTL, 0); - pci_writeb (s, TI1250_DIAGNOSTIC, p->diag); - pci_writel (s, TI12XX_IRQMUX, p->irqmux); - i365_set_pair (s, TI113X_IO_OFFSET (0), 0); - i365_set_pair (s, TI113X_IO_OFFSET (1), 0); -} - -static u_int ti113x_set_opts (socket_info_t * s) -{ - ti113x_state_t *p = &s->state; - u_int mask = 0xffff; - - p->cardctl &= ~TI113X_CCR_ZVENABLE; - p->cardctl |= TI113X_CCR_SPKROUTEN; - - return mask; -} -#endif /* CONFIG_CPC45 */ - -/*====================================================================== - - Routines to handle common CardBus options - -======================================================================*/ - -/* Default settings for PCI command configuration register */ -#define CMD_DFLT (PCI_COMMAND_IO|PCI_COMMAND_MEMORY| \ - PCI_COMMAND_MASTER|PCI_COMMAND_WAIT) - -static void cb_get_state (socket_info_t * s) -{ - pci_readb (s, PCI_CACHE_LINE_SIZE, &s->cache); - pci_readb (s, PCI_LATENCY_TIMER, &s->pci_lat); - pci_readb (s, CB_LATENCY_TIMER, &s->cb_lat); - pci_readb (s, CB_CARDBUS_BUS, &s->cap.cardbus); - pci_readb (s, CB_SUBORD_BUS, &s->sub_bus); - pci_readw (s, CB_BRIDGE_CONTROL, &s->bcr); -} - -static void cb_set_state (socket_info_t * s) -{ -#ifndef CONFIG_CPC45 - pci_writel (s, CB_LEGACY_MODE_BASE, 0); - pci_writel (s, PCI_BASE_ADDRESS_0, s->cb_phys); -#endif - pci_writew (s, PCI_COMMAND, CMD_DFLT); - pci_writeb (s, PCI_CACHE_LINE_SIZE, s->cache); - pci_writeb (s, PCI_LATENCY_TIMER, s->pci_lat); - pci_writeb (s, CB_LATENCY_TIMER, s->cb_lat); - pci_writeb (s, CB_CARDBUS_BUS, s->cap.cardbus); - pci_writeb (s, CB_SUBORD_BUS, s->sub_bus); - pci_writew (s, CB_BRIDGE_CONTROL, s->bcr); -} - -static void cb_set_opts (socket_info_t * s) -{ -#ifndef CONFIG_CPC45 - if (s->cache == 0) - s->cache = 8; - if (s->pci_lat == 0) - s->pci_lat = 0xa8; - if (s->cb_lat == 0) - s->cb_lat = 0xb0; -#endif -} - -/*====================================================================== - - Power control for Cardbus controllers: used both for 16-bit and - Cardbus cards. - -======================================================================*/ - -static int cb_set_power (socket_info_t * s, socket_state_t * state) -{ - u_int reg = 0; - -#ifdef CONFIG_CPC45 - - reg = I365_PWR_NORESET; - if (state->flags & SS_PWR_AUTO) - reg |= I365_PWR_AUTO; - if (state->flags & SS_OUTPUT_ENA) - reg |= I365_PWR_OUT; - if (state->Vpp != 0) { - if (state->Vpp == 120) { - reg |= I365_VPP1_12V; - puts (" 12V card found: "); - } else if (state->Vpp == state->Vcc) { - reg |= I365_VPP1_5V; - } else { - puts (" power not found: "); - return -1; - } - } - if (state->Vcc != 0) { - reg |= I365_VCC_5V; - if (state->Vcc == 33) { - puts (" 3.3V card found: "); - i365_bset (s, PD67_MISC_CTL_1, PD67_MC1_VCC_3V); - } else if (state->Vcc == 50) { - puts (" 5V card found: "); - i365_bclr (s, PD67_MISC_CTL_1, PD67_MC1_VCC_3V); - } else { - puts (" power not found: "); - return -1; - } - } - - if (reg != i365_get (s, I365_POWER)) { - reg = (I365_PWR_OUT | I365_PWR_NORESET | I365_VCC_5V | I365_VPP1_5V); - i365_set (s, I365_POWER, reg); - } - -#else /* ! CONFIG_CPC45 */ - - /* restart card voltage detection if it seems appropriate */ - if ((state->Vcc == 0) && (state->Vpp == 0) && - !(cb_readl (s, CB_SOCKET_STATE) & CB_SS_VSENSE)) - cb_writel (s, CB_SOCKET_FORCE, CB_SF_CVSTEST); - switch (state->Vcc) { - case 0: - reg = 0; - break; - case 33: - reg = CB_SC_VCC_3V; - break; - case 50: - reg = CB_SC_VCC_5V; - break; - default: - return -1; - } - switch (state->Vpp) { - case 0: - break; - case 33: - reg |= CB_SC_VPP_3V; - break; - case 50: - reg |= CB_SC_VPP_5V; - break; - case 120: - reg |= CB_SC_VPP_12V; - break; - default: - return -1; - } - if (reg != cb_readl (s, CB_SOCKET_CONTROL)) - cb_writel (s, CB_SOCKET_CONTROL, reg); -#endif /* CONFIG_CPC45 */ - return 0; -} - -/*====================================================================== - - Generic routines to get and set controller options - -======================================================================*/ - -static void get_bridge_state (socket_info_t * s) -{ -#ifdef CONFIG_CPC45 - cirrus_get_state (s); -#else - ti113x_get_state (s); -#endif - cb_get_state (s); -} - -static void set_bridge_state (socket_info_t * s) -{ - cb_set_state (s); - i365_set (s, I365_GBLCTL, 0x00); - i365_set (s, I365_GENCTL, 0x00); -#ifdef CONFIG_CPC45 - cirrus_set_state (s); -#else - ti113x_set_state (s); -#endif -} - -static void set_bridge_opts (socket_info_t * s) -{ -#ifdef CONFIG_CPC45 - cirrus_set_opts (s); -#else - ti113x_set_opts (s); -#endif - cb_set_opts (s); -} - -/*====================================================================*/ -#define PD67_EXT_INDEX 0x2e /* Extension index */ -#define PD67_EXT_DATA 0x2f /* Extension data */ -#define PD67_EXD_VS1(s) (0x01 << ((s)<<1)) - -#define pd67_ext_get(s, r) \ - (i365_set(s, PD67_EXT_INDEX, r), i365_get(s, PD67_EXT_DATA)) - -static int i365_get_status (socket_info_t * s, u_int * value) -{ - u_int status; -#ifdef CONFIG_CPC45 - u_char val; - u_char power, vcc, vpp; - u_int powerstate; -#endif - - status = i365_get (s, I365_IDENT); - status = i365_get (s, I365_STATUS); - *value = ((status & I365_CS_DETECT) == I365_CS_DETECT) ? SS_DETECT : 0; - if (i365_get (s, I365_INTCTL) & I365_PC_IOCARD) { - *value |= (status & I365_CS_STSCHG) ? 0 : SS_STSCHG; - } else { - *value |= (status & I365_CS_BVD1) ? 0 : SS_BATDEAD; - *value |= (status & I365_CS_BVD2) ? 0 : SS_BATWARN; - } - *value |= (status & I365_CS_WRPROT) ? SS_WRPROT : 0; - *value |= (status & I365_CS_READY) ? SS_READY : 0; - *value |= (status & I365_CS_POWERON) ? SS_POWERON : 0; - -#ifdef CONFIG_CPC45 - /* Check for Cirrus CL-PD67xx chips */ - i365_set (s, PD67_CHIP_INFO, 0); - val = i365_get (s, PD67_CHIP_INFO); - s->type = -1; - if ((val & PD67_INFO_CHIP_ID) == PD67_INFO_CHIP_ID) { - val = i365_get (s, PD67_CHIP_INFO); - if ((val & PD67_INFO_CHIP_ID) == 0) { - s->type = (val & PD67_INFO_SLOTS) ? IS_PD672X : IS_PD6710; - i365_set (s, PD67_EXT_INDEX, 0xe5); - if (i365_get (s, PD67_EXT_INDEX) != 0xe5) - s->type = IS_VT83C469; - } - } else { - printf ("no Cirrus Chip found\n"); - *value = 0; - return -1; - } - - power = i365_get (s, I365_POWER); - state.flags |= (power & I365_PWR_AUTO) ? SS_PWR_AUTO : 0; - state.flags |= (power & I365_PWR_OUT) ? SS_OUTPUT_ENA : 0; - vcc = power & I365_VCC_MASK; - vpp = power & I365_VPP1_MASK; - state.Vcc = state.Vpp = 0; - if((vcc== 0) || (vpp == 0)) { - /* - * On the Cirrus we get the info which card voltage - * we have in EXTERN DATA and write it to MISC_CTL1 - */ - powerstate = pd67_ext_get(s, PD67_EXTERN_DATA); - if (powerstate & PD67_EXD_VS1(0)) { - /* 5V Card */ - i365_bclr (s, PD67_MISC_CTL_1, PD67_MC1_VCC_3V); - } else { - /* 3.3V Card */ - i365_bset (s, PD67_MISC_CTL_1, PD67_MC1_VCC_3V); - } - i365_set (s, I365_POWER, (I365_PWR_OUT | I365_PWR_NORESET | I365_VCC_5V | I365_VPP1_5V)); - power = i365_get (s, I365_POWER); - } - if (power & I365_VCC_5V) { - state.Vcc = (i365_get(s, PD67_MISC_CTL_1) & PD67_MC1_VCC_3V) ? 33 : 50; - } - - if (power == I365_VPP1_12V) - state.Vpp = 120; - - /* IO card, RESET flags, IO interrupt */ - power = i365_get (s, I365_INTCTL); - state.flags |= (power & I365_PC_RESET) ? 0 : SS_RESET; - if (power & I365_PC_IOCARD) - state.flags |= SS_IOCARD; - state.io_irq = power & I365_IRQ_MASK; - - /* Card status change mask */ - power = i365_get (s, I365_CSCINT); - state.csc_mask = (power & I365_CSC_DETECT) ? SS_DETECT : 0; - if (state.flags & SS_IOCARD) - state.csc_mask |= (power & I365_CSC_STSCHG) ? SS_STSCHG : 0; - else { - state.csc_mask |= (power & I365_CSC_BVD1) ? SS_BATDEAD : 0; - state.csc_mask |= (power & I365_CSC_BVD2) ? SS_BATWARN : 0; - state.csc_mask |= (power & I365_CSC_READY) ? SS_READY : 0; - } - debug ("i82365: GetStatus(0) = flags %#3.3x, Vcc %d, Vpp %d, " - "io_irq %d, csc_mask %#2.2x\n", state.flags, - state.Vcc, state.Vpp, state.io_irq, state.csc_mask); - -#else /* !CONFIG_CPC45 */ - - status = cb_readl (s, CB_SOCKET_STATE); - *value |= (status & CB_SS_32BIT) ? SS_CARDBUS : 0; - *value |= (status & CB_SS_3VCARD) ? SS_3VCARD : 0; - *value |= (status & CB_SS_XVCARD) ? SS_XVCARD : 0; - *value |= (status & CB_SS_VSENSE) ? 0 : SS_PENDING; - /* For now, ignore cards with unsupported voltage keys */ - if (*value & SS_XVCARD) - *value &= ~(SS_DETECT | SS_3VCARD | SS_XVCARD); -#endif /* CONFIG_CPC45 */ - return 0; -} /* i365_get_status */ - -static int i365_set_socket (socket_info_t * s, socket_state_t * state) -{ - u_char reg; - - set_bridge_state (s); - - /* IO card, RESET flag */ - reg = 0; - reg |= (state->flags & SS_RESET) ? 0 : I365_PC_RESET; - reg |= (state->flags & SS_IOCARD) ? I365_PC_IOCARD : 0; - i365_set (s, I365_INTCTL, reg); - -#ifdef CONFIG_CPC45 - cb_set_power (s, state); - -#if 0 - /* Card status change interrupt mask */ - reg = s->cs_irq << 4; - if (state->csc_mask & SS_DETECT) - reg |= I365_CSC_DETECT; - if (state->flags & SS_IOCARD) { - if (state->csc_mask & SS_STSCHG) - reg |= I365_CSC_STSCHG; - } else { - if (state->csc_mask & SS_BATDEAD) - reg |= I365_CSC_BVD1; - if (state->csc_mask & SS_BATWARN) - reg |= I365_CSC_BVD2; - if (state->csc_mask & SS_READY) - reg |= I365_CSC_READY; - } - i365_set (s, I365_CSCINT, reg); - i365_get (s, I365_CSC); -#endif /* 0 */ - -#else /* !CONFIG_CPC45 */ - - reg = I365_PWR_NORESET; - if (state->flags & SS_PWR_AUTO) - reg |= I365_PWR_AUTO; - if (state->flags & SS_OUTPUT_ENA) - reg |= I365_PWR_OUT; - - cb_set_power (s, state); - reg |= i365_get (s, I365_POWER) & (I365_VCC_MASK | I365_VPP1_MASK); - - if (reg != i365_get (s, I365_POWER)) - i365_set (s, I365_POWER, reg); -#endif /* CONFIG_CPC45 */ - - return 0; -} /* i365_set_socket */ - -/*====================================================================*/ - -static int i365_set_mem_map (socket_info_t * s, struct pccard_mem_map *mem) -{ - u_short base, i; - u_char map; - - debug ("i82365: SetMemMap(%d, %#2.2x, %d ns, %#5.5lx-%#5.5lx, %#5.5x)\n", - mem->map, mem->flags, mem->speed, - mem->sys_start, mem->sys_stop, mem->card_start); - - map = mem->map; - if ((map > 4) || - (mem->card_start > 0x3ffffff) || - (mem->sys_start > mem->sys_stop) || - (mem->speed > 1000)) { - return -1; - } - - /* Turn off the window before changing anything */ - if (i365_get (s, I365_ADDRWIN) & I365_ENA_MEM (map)) - i365_bclr (s, I365_ADDRWIN, I365_ENA_MEM (map)); - - /* Take care of high byte, for PCI controllers */ - i365_set (s, CB_MEM_PAGE (map), mem->sys_start >> 24); - - base = I365_MEM (map); - i = (mem->sys_start >> 12) & 0x0fff; - if (mem->flags & MAP_16BIT) - i |= I365_MEM_16BIT; - if (mem->flags & MAP_0WS) - i |= I365_MEM_0WS; - i365_set_pair (s, base + I365_W_START, i); - - i = (mem->sys_stop >> 12) & 0x0fff; - switch (mem->speed / CYCLE_TIME) { - case 0: - break; - case 1: - i |= I365_MEM_WS0; - break; - case 2: - i |= I365_MEM_WS1; - break; - default: - i |= I365_MEM_WS1 | I365_MEM_WS0; - break; - } - i365_set_pair (s, base + I365_W_STOP, i); - -#ifdef CONFIG_CPC45 - i = 0; -#else - i = ((mem->card_start - mem->sys_start) >> 12) & 0x3fff; -#endif - if (mem->flags & MAP_WRPROT) - i |= I365_MEM_WRPROT; - if (mem->flags & MAP_ATTRIB) - i |= I365_MEM_REG; - i365_set_pair (s, base + I365_W_OFF, i); - -#ifdef CONFIG_CPC45 - /* set System Memory map Upper Adress */ - i365_set(s, PD67_EXT_INDEX, PD67_MEM_PAGE(map)); - i365_set(s, PD67_EXT_DATA, ((mem->sys_start >> 24) & 0xff)); -#endif - - /* Turn on the window if necessary */ - if (mem->flags & MAP_ACTIVE) - i365_bset (s, I365_ADDRWIN, I365_ENA_MEM (map)); - return 0; -} /* i365_set_mem_map */ - -static int i365_set_io_map (socket_info_t * s, struct pccard_io_map *io) -{ - u_char map, ioctl; - - map = io->map; - /* comment out: comparison is always false due to limited range of data type */ - if ((map > 1) || /* (io->start > 0xffff) || (io->stop > 0xffff) || */ - (io->stop < io->start)) - return -1; - /* Turn off the window before changing anything */ - if (i365_get (s, I365_ADDRWIN) & I365_ENA_IO (map)) - i365_bclr (s, I365_ADDRWIN, I365_ENA_IO (map)); - i365_set_pair (s, I365_IO (map) + I365_W_START, io->start); - i365_set_pair (s, I365_IO (map) + I365_W_STOP, io->stop); - ioctl = i365_get (s, I365_IOCTL) & ~I365_IOCTL_MASK (map); - if (io->speed) - ioctl |= I365_IOCTL_WAIT (map); - if (io->flags & MAP_0WS) - ioctl |= I365_IOCTL_0WS (map); - if (io->flags & MAP_16BIT) - ioctl |= I365_IOCTL_16BIT (map); - if (io->flags & MAP_AUTOSZ) - ioctl |= I365_IOCTL_IOCS16 (map); - i365_set (s, I365_IOCTL, ioctl); - /* Turn on the window if necessary */ - if (io->flags & MAP_ACTIVE) - i365_bset (s, I365_ADDRWIN, I365_ENA_IO (map)); - return 0; -} /* i365_set_io_map */ - -/*====================================================================*/ - -int i82365_init (void) -{ - u_int val; - int i; - -#ifdef CONFIG_CPC45 - if (SPD67290Init () != 0) - return 1; -#endif - if ((socket.dev = pci_find_devices (supported, 0)) < 0) { - /* Controller not found */ - return 1; - } - debug ("i82365 Device Found!\n"); - - pci_read_config_dword (socket.dev, PCI_BASE_ADDRESS_0, &socket.cb_phys); - socket.cb_phys &= ~0xf; - -#ifdef CONFIG_CPC45 - /* + 0xfe000000 see MPC 8245 Users Manual Adress Map B */ - socket.cb_phys += 0xfe000000; -#endif - - get_bridge_state (&socket); - set_bridge_opts (&socket); - - i = i365_get_status (&socket, &val); - -#ifdef CONFIG_CPC45 - if (i > -1) { - puts (pcic[socket.type].name); - } else { - printf ("i82365: Controller not found.\n"); - return 1; - } - if((val & SS_DETECT) != SS_DETECT){ - puts ("No card\n"); - return 1; - } -#else /* !CONFIG_CPC45 */ - if (val & SS_DETECT) { - if (val & SS_3VCARD) { - state.Vcc = state.Vpp = 33; - puts (" 3.3V card found: "); - } else if (!(val & SS_XVCARD)) { - state.Vcc = state.Vpp = 50; - puts (" 5.0V card found: "); - } else { - puts ("i82365: unsupported voltage key\n"); - state.Vcc = state.Vpp = 0; - } - } else { - /* No card inserted */ - puts ("No card\n"); - return 1; - } -#endif /* CONFIG_CPC45 */ - -#ifdef CONFIG_CPC45 - state.flags |= SS_OUTPUT_ENA; -#else - state.flags = SS_IOCARD | SS_OUTPUT_ENA; - state.csc_mask = 0; - state.io_irq = 0; -#endif - - i365_set_socket (&socket, &state); - - for (i = 500; i; i--) { - if ((i365_get (&socket, I365_STATUS) & I365_CS_READY)) - break; - udelay (1000); - } - - if (i == 0) { - /* PC Card not ready for data transfer */ - puts ("i82365 PC Card not ready for data transfer\n"); - return 1; - } - debug (" PC Card ready for data transfer: "); - - mem.map = 0; - mem.flags = MAP_ATTRIB | MAP_ACTIVE; - mem.speed = 300; - mem.sys_start = CFG_PCMCIA_MEM_ADDR; - mem.sys_stop = CFG_PCMCIA_MEM_ADDR + CFG_PCMCIA_MEM_SIZE - 1; - mem.card_start = 0; - i365_set_mem_map (&socket, &mem); - -#ifdef CONFIG_CPC45 - mem.map = 1; - mem.flags = MAP_ACTIVE; - mem.speed = 300; - mem.sys_start = CFG_PCMCIA_MEM_ADDR + CFG_PCMCIA_MEM_SIZE; - mem.sys_stop = CFG_PCMCIA_MEM_ADDR + (2 * CFG_PCMCIA_MEM_SIZE) - 1; - mem.card_start = 0; - i365_set_mem_map (&socket, &mem); - -#else /* !CONFIG_CPC45 */ - - io.map = 0; - io.flags = MAP_AUTOSZ | MAP_ACTIVE; - io.speed = 0; - io.start = 0x0100; - io.stop = 0x010F; - i365_set_io_map (&socket, &io); - -#endif /* CONFIG_CPC45 */ - -#ifdef DEBUG - i82365_dump_regions (socket.dev); -#endif - - return 0; -} - -void i82365_exit (void) -{ - io.map = 0; - io.flags = 0; - io.speed = 0; - io.start = 0; - io.stop = 0x1; - - i365_set_io_map (&socket, &io); - - mem.map = 0; - mem.flags = 0; - mem.speed = 0; - mem.sys_start = 0; - mem.sys_stop = 0x1000; - mem.card_start = 0; - - i365_set_mem_map (&socket, &mem); - -#ifdef CONFIG_CPC45 - mem.map = 1; - mem.flags = 0; - mem.speed = 0; - mem.sys_start = 0; - mem.sys_stop = 0x1000; - mem.card_start = 0; - - i365_set_mem_map (&socket, &mem); -#else /* !CONFIG_CPC45 */ - socket.state.sysctl &= 0xFFFF00FF; -#endif - state.Vcc = state.Vpp = 0; - - i365_set_socket (&socket, &state); -} - -/*====================================================================== - - Debug stuff - -======================================================================*/ - -#ifdef DEBUG -static void i82365_dump_regions (pci_dev_t dev) -{ - u_int tmp[2]; - u_int *mem = (void *) socket.cb_phys; - u_char *cis = (void *) CFG_PCMCIA_MEM_ADDR; - u_char *ide = (void *) (CFG_ATA_BASE_ADDR + CFG_ATA_REG_OFFSET); - - pci_read_config_dword (dev, 0x00, tmp + 0); - pci_read_config_dword (dev, 0x80, tmp + 1); - - printf ("PCI CONF: %08X ... %08X\n", - tmp[0], tmp[1]); - printf ("PCI MEM: ... %08X ... %08X\n", - mem[0x8 / 4], mem[0x800 / 4]); - printf ("CIS: ...%c%c%c%c%c%c%c%c...\n", - cis[0x38], cis[0x3a], cis[0x3c], cis[0x3e], - cis[0x40], cis[0x42], cis[0x44], cis[0x48]); - printf ("CIS CONF: %02X %02X %02X ...\n", - cis[0x200], cis[0x202], cis[0x204]); - printf ("IDE: %02X %02X %02X %02X %02X %02X %02X %02X\n", - ide[0], ide[1], ide[2], ide[3], - ide[4], ide[5], ide[6], ide[7]); -} -#endif /* DEBUG */ - -#endif /* CONFIG_I82365 */ diff --git a/drivers/mpc8xx_pcmcia.c b/drivers/mpc8xx_pcmcia.c deleted file mode 100644 index 8a34cd3054..0000000000 --- a/drivers/mpc8xx_pcmcia.c +++ /dev/null @@ -1,304 +0,0 @@ -#include -#if defined(CONFIG_8xx) -#include -#endif -#include - -#undef CONFIG_PCMCIA - -#if defined(CONFIG_CMD_PCMCIA) -#define CONFIG_PCMCIA -#endif - -#if defined(CONFIG_CMD_IDE) && defined(CONFIG_IDE_8xx_PCCARD) -#define CONFIG_PCMCIA -#endif - -#if defined(CONFIG_8xx) && defined(CONFIG_PCMCIA) - -#if defined(CONFIG_IDE_8xx_PCCARD) -extern int check_ide_device (int slot); -#endif - -extern int pcmcia_hardware_enable (int slot); -extern int pcmcia_voltage_set(int slot, int vcc, int vpp); - -#if defined(CONFIG_CMD_PCMCIA) -extern int pcmcia_hardware_disable(int slot); -#endif - -static u_int m8xx_get_graycode(u_int size); -#if 0 /* Disabled */ -static u_int m8xx_get_speed(u_int ns, u_int is_io); -#endif - -/* look up table for pgcrx registers */ -u_int *pcmcia_pgcrx[2] = { - &((immap_t *)CFG_IMMR)->im_pcmcia.pcmc_pgcra, - &((immap_t *)CFG_IMMR)->im_pcmcia.pcmc_pgcrb, -}; - -/* - * Search this table to see if the windowsize is - * supported... - */ - -#define M8XX_SIZES_NO 32 - -static const u_int m8xx_size_to_gray[M8XX_SIZES_NO] = -{ 0x00000001, 0x00000002, 0x00000008, 0x00000004, - 0x00000080, 0x00000040, 0x00000010, 0x00000020, - 0x00008000, 0x00004000, 0x00001000, 0x00002000, - 0x00000100, 0x00000200, 0x00000800, 0x00000400, - - 0x0fffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0x01000000, 0x02000000, 0xffffffff, 0x04000000, - 0x00010000, 0x00020000, 0x00080000, 0x00040000, - 0x00800000, 0x00400000, 0x00100000, 0x00200000 }; - - -/* -------------------------------------------------------------------- */ - -#ifdef CONFIG_HMI10 -#define HMI10_FRAM_TIMING ( PCMCIA_SHT(2) \ - | PCMCIA_SST(2) \ - | PCMCIA_SL(4)) -#endif - -#if defined(CONFIG_LWMON) || defined(CONFIG_NSCU) -#define CFG_PCMCIA_TIMING ( PCMCIA_SHT(9) \ - | PCMCIA_SST(3) \ - | PCMCIA_SL(12)) -#else -#define CFG_PCMCIA_TIMING ( PCMCIA_SHT(2) \ - | PCMCIA_SST(4) \ - | PCMCIA_SL(9)) -#endif - -/* -------------------------------------------------------------------- */ - -int pcmcia_on (void) -{ - u_long reg, base; - pcmcia_win_t *win; - u_int slotbit; - u_int rc, slot; - int i; - - debug ("Enable PCMCIA " PCMCIA_SLOT_MSG "\n"); - - /* intialize the fixed memory windows */ - win = (pcmcia_win_t *)(&((immap_t *)CFG_IMMR)->im_pcmcia.pcmc_pbr0); - base = CFG_PCMCIA_MEM_ADDR; - - if((reg = m8xx_get_graycode(CFG_PCMCIA_MEM_SIZE)) == -1) { - printf ("Cannot set window size to 0x%08x\n", - CFG_PCMCIA_MEM_SIZE); - return (1); - } - - slotbit = PCMCIA_SLOT_x; - for (i=0; ibr = base; - -#if (PCMCIA_SOCKETS_NO == 2) - if (i == 4) /* Another slot starting from win 4 */ - slotbit = (slotbit ? PCMCIA_PSLOT_A : PCMCIA_PSLOT_B); -#endif - switch (i) { -#ifdef CONFIG_IDE_8xx_PCCARD - case 4: -#ifdef CONFIG_HMI10 - { /* map FRAM area */ - win->or = ( PCMCIA_BSIZE_256K - | PCMCIA_PPS_8 - | PCMCIA_PRS_ATTR - | slotbit - | PCMCIA_PV - | HMI10_FRAM_TIMING ); - break; - } -#endif - case 0: { /* map attribute memory */ - win->or = ( PCMCIA_BSIZE_64M - | PCMCIA_PPS_8 - | PCMCIA_PRS_ATTR - | slotbit - | PCMCIA_PV - | CFG_PCMCIA_TIMING ); - break; - } - case 5: - case 1: { /* map I/O window for data reg */ - win->or = ( PCMCIA_BSIZE_1K - | PCMCIA_PPS_16 - | PCMCIA_PRS_IO - | slotbit - | PCMCIA_PV - | CFG_PCMCIA_TIMING ); - break; - } - case 6: - case 2: { /* map I/O window for cmd/ctrl reg block */ - win->or = ( PCMCIA_BSIZE_1K - | PCMCIA_PPS_8 - | PCMCIA_PRS_IO - | slotbit - | PCMCIA_PV - | CFG_PCMCIA_TIMING ); - break; - } -#endif /* CONFIG_IDE_8xx_PCCARD */ -#ifdef CONFIG_HMI10 - case 3: { /* map I/O window for 4xUART data/ctrl */ - win->br += 0x40000; - win->or = ( PCMCIA_BSIZE_256K - | PCMCIA_PPS_8 - | PCMCIA_PRS_IO - | slotbit - | PCMCIA_PV - | CFG_PCMCIA_TIMING ); - break; - } -#endif /* CONFIG_HMI10 */ - default: /* set to not valid */ - win->or = 0; - break; - } - - debug ("MemWin %d: PBR 0x%08lX POR %08lX\n", - i, win->br, win->or); - base += CFG_PCMCIA_MEM_SIZE; - ++win; - } - - for (i=0, rc=0, slot=_slot_; iim_pcmcia.pcmc_pscr = PCMCIA_MASK(_slot_); - ((immap_t *)CFG_IMMR)->im_pcmcia.pcmc_per &= ~PCMCIA_MASK(_slot_); - - /* turn off interrupt and disable CxOE */ - PCMCIA_PGCRX(_slot_) = __MY_PCMCIA_GCRX_CXOE; - - /* turn off memory windows */ - win = (pcmcia_win_t *)(&((immap_t *)CFG_IMMR)->im_pcmcia.pcmc_pbr0); - - for (i=0; ior = 0; - ++win; - } - - /* turn off voltage */ - pcmcia_voltage_set(_slot_, 0, 0); - - /* disable external hardware */ - printf ("Shutdown and Poweroff " PCMCIA_SLOT_MSG "\n"); - pcmcia_hardware_disable(_slot_); - return 0; -} -#endif - - -static u_int m8xx_get_graycode(u_int size) -{ - u_int k; - - for (k = 0; k < M8XX_SIZES_NO; k++) { - if(m8xx_size_to_gray[k] == size) - break; - } - - if((k == M8XX_SIZES_NO) || (m8xx_size_to_gray[k] == -1)) - k = -1; - - return k; -} - -#if 0 - -#if defined(CONFIG_RPXCLASSIC) || defined(CONFIG_RPXLITE) - -/* The RPX boards seems to have it's bus monitor timeout set to 6*8 clocks. - * SYPCR is write once only, therefore must the slowest memory be faster - * than the bus monitor or we will get a machine check due to the bus timeout. - */ -#undef PCMCIA_BMT_LIMIT -#define PCMCIA_BMT_LIMIT (6*8) -#endif - -static u_int m8xx_get_speed(u_int ns, u_int is_io) -{ - u_int reg, clocks, psst, psl, psht; - - if(!ns) { - - /* - * We get called with IO maps setup to 0ns - * if not specified by the user. - * They should be 255ns. - */ - - if(is_io) - ns = 255; - else - ns = 100; /* fast memory if 0 */ - } - - /* - * In PSST, PSL, PSHT fields we tell the controller - * timing parameters in CLKOUT clock cycles. - * CLKOUT is the same as GCLK2_50. - */ - - /* how we want to adjust the timing - in percent */ - -#define ADJ 180 /* 80 % longer accesstime - to be sure */ - - clocks = ((M8XX_BUSFREQ / 1000) * ns) / 1000; - clocks = (clocks * ADJ) / (100*1000); - - if(clocks >= PCMCIA_BMT_LIMIT) { - DEBUG(0, "Max access time limit reached\n"); - clocks = PCMCIA_BMT_LIMIT-1; - } - - psst = clocks / 7; /* setup time */ - psht = clocks / 7; /* hold time */ - psl = (clocks * 5) / 7; /* strobe length */ - - psst += clocks - (psst + psht + psl); - - reg = psst << 12; - reg |= psl << 7; - reg |= psht << 16; - - return reg; -} -#endif /* 0 */ - -#endif /* CONFIG_8xx && CONFIG_PCMCIA */ diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile new file mode 100644 index 0000000000..55528c889e --- /dev/null +++ b/drivers/pcmcia/Makefile @@ -0,0 +1,50 @@ +# +# (C) Copyright 2000-2007 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that 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 +# + +include $(TOPDIR)/config.mk + +LIB := $(obj)libpcmcia.a + +COBJS-y += mpc8xx_pcmcia.o +COBJS-y += pxa_pcmcia.o +COBJS-y += rpx_pcmcia.o +COBJS-y += ti_pci1410a.o +COBJS-y += tqm8xx_pcmcia.o + +COBJS := $(COBJS-y) +SRCS := $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) + +all: $(LIB) + +$(LIB): $(obj).depend $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c new file mode 100644 index 0000000000..a40fcf41c9 --- /dev/null +++ b/drivers/pcmcia/i82365.c @@ -0,0 +1,1014 @@ +/* + * (C) Copyright 2003-2005 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that 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 + * + ******************************************************************** + * + * Lots of code copied from: + * + * i82365.c 1.352 - Linux driver for Intel 82365 and compatible + * PC Card controllers, and Yenta-compatible PCI-to-CardBus controllers. + * (C) 1999 David A. Hinds + */ + +#include + +#ifdef CONFIG_I82365 + +#include +#include +#include +#include + +#include +#include +#include +#ifdef CONFIG_CPC45 +#include +#else +#include +#endif + +static struct pci_device_id supported[] = { +#ifdef CONFIG_CPC45 + {PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_6729}, +#else + {PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1510}, +#endif + {0, 0} +}; + +#define CYCLE_TIME 120 + +#ifdef CONFIG_CPC45 +extern int SPD67290Init (void); +#endif + +#ifdef DEBUG +static void i82365_dump_regions (pci_dev_t dev); +#endif + +typedef struct socket_info_t { + pci_dev_t dev; + u_short bcr; + u_char pci_lat, cb_lat, sub_bus, cache; + u_int cb_phys; + + socket_cap_t cap; + u_short type; + u_int flags; +#ifdef CONFIG_CPC45 + cirrus_state_t c_state; +#else + ti113x_state_t state; +#endif +} socket_info_t; + +#ifdef CONFIG_CPC45 +/* These definitions must match the pcic table! */ +typedef enum pcic_id { + IS_PD6710, IS_PD672X, IS_VT83C469 +} pcic_id; + +typedef struct pcic_t { + char *name; +} pcic_t; + +static pcic_t pcic[] = { + {" Cirrus PD6710: "}, + {" Cirrus PD672x: "}, + {" VIA VT83C469: "}, +}; +#endif + +static socket_info_t socket; +static socket_state_t state; +static struct pccard_mem_map mem; +static struct pccard_io_map io; + +/*====================================================================*/ + +/* Some PCI shortcuts */ + +static int pci_readb (socket_info_t * s, int r, u_char * v) +{ + return pci_read_config_byte (s->dev, r, v); +} +static int pci_writeb (socket_info_t * s, int r, u_char v) +{ + return pci_write_config_byte (s->dev, r, v); +} +static int pci_readw (socket_info_t * s, int r, u_short * v) +{ + return pci_read_config_word (s->dev, r, v); +} +static int pci_writew (socket_info_t * s, int r, u_short v) +{ + return pci_write_config_word (s->dev, r, v); +} +#ifndef CONFIG_CPC45 +static int pci_readl (socket_info_t * s, int r, u_int * v) +{ + return pci_read_config_dword (s->dev, r, v); +} +static int pci_writel (socket_info_t * s, int r, u_int v) +{ + return pci_write_config_dword (s->dev, r, v); +} +#endif /* !CONFIG_CPC45 */ + +/*====================================================================*/ + +#ifdef CONFIG_CPC45 + +#define cb_readb(s) readb((s)->cb_phys + 1) +#define cb_writeb(s, v) writeb(v, (s)->cb_phys) +#define cb_writeb2(s, v) writeb(v, (s)->cb_phys + 1) +#define cb_readl(s, r) readl((s)->cb_phys + (r)) +#define cb_writel(s, r, v) writel(v, (s)->cb_phys + (r)) + + +static u_char i365_get (socket_info_t * s, u_short reg) +{ + u_char val; +#ifdef CONFIG_PCMCIA_SLOT_A + int slot = 0; +#else + int slot = 1; +#endif + + val = I365_REG (slot, reg); + + cb_writeb (s, val); + val = cb_readb (s); + + debug ("i365_get slot:%x reg: %x val: %x\n", slot, reg, val); + return val; +} + +static void i365_set (socket_info_t * s, u_short reg, u_char data) +{ +#ifdef CONFIG_PCMCIA_SLOT_A + int slot = 0; +#else + int slot = 1; +#endif + u_char val; + + val = I365_REG (slot, reg); + + cb_writeb (s, val); + cb_writeb2 (s, data); + + debug ("i365_set slot:%x reg: %x data:%x\n", slot, reg, data); +} + +#else /* ! CONFIG_CPC45 */ + +#define cb_readb(s, r) readb((s)->cb_phys + (r)) +#define cb_readl(s, r) readl((s)->cb_phys + (r)) +#define cb_writeb(s, r, v) writeb(v, (s)->cb_phys + (r)) +#define cb_writel(s, r, v) writel(v, (s)->cb_phys + (r)) + +static u_char i365_get (socket_info_t * s, u_short reg) +{ + return cb_readb (s, 0x0800 + reg); +} + +static void i365_set (socket_info_t * s, u_short reg, u_char data) +{ + cb_writeb (s, 0x0800 + reg, data); +} +#endif /* CONFIG_CPC45 */ + +static void i365_bset (socket_info_t * s, u_short reg, u_char mask) +{ + i365_set (s, reg, i365_get (s, reg) | mask); +} + +static void i365_bclr (socket_info_t * s, u_short reg, u_char mask) +{ + i365_set (s, reg, i365_get (s, reg) & ~mask); +} + +#if 0 /* not used */ +static void i365_bflip (socket_info_t * s, u_short reg, u_char mask, int b) +{ + u_char d = i365_get (s, reg); + + i365_set (s, reg, (b) ? (d | mask) : (d & ~mask)); +} + +static u_short i365_get_pair (socket_info_t * s, u_short reg) +{ + return (i365_get (s, reg) + (i365_get (s, reg + 1) << 8)); +} +#endif /* not used */ + +static void i365_set_pair (socket_info_t * s, u_short reg, u_short data) +{ + i365_set (s, reg, data & 0xff); + i365_set (s, reg + 1, data >> 8); +} + +#ifdef CONFIG_CPC45 +/*====================================================================== + + Code to save and restore global state information for Cirrus + PD67xx controllers, and to set and report global configuration + options. + +======================================================================*/ + +#define flip(v,b,f) (v = ((f)<0) ? v : ((f) ? ((v)|(b)) : ((v)&(~b)))) + +static void cirrus_get_state (socket_info_t * s) +{ + int i; + cirrus_state_t *p = &s->c_state; + + p->misc1 = i365_get (s, PD67_MISC_CTL_1); + p->misc1 &= (PD67_MC1_MEDIA_ENA | PD67_MC1_INPACK_ENA); + p->misc2 = i365_get (s, PD67_MISC_CTL_2); + for (i = 0; i < 6; i++) + p->timer[i] = i365_get (s, PD67_TIME_SETUP (0) + i); + +} + +static void cirrus_set_state (socket_info_t * s) +{ + int i; + u_char misc; + cirrus_state_t *p = &s->c_state; + + misc = i365_get (s, PD67_MISC_CTL_2); + i365_set (s, PD67_MISC_CTL_2, p->misc2); + if (misc & PD67_MC2_SUSPEND) + udelay (50000); + misc = i365_get (s, PD67_MISC_CTL_1); + misc &= ~(PD67_MC1_MEDIA_ENA | PD67_MC1_INPACK_ENA); + i365_set (s, PD67_MISC_CTL_1, misc | p->misc1); + for (i = 0; i < 6; i++) + i365_set (s, PD67_TIME_SETUP (0) + i, p->timer[i]); +} + +static u_int cirrus_set_opts (socket_info_t * s) +{ + cirrus_state_t *p = &s->c_state; + u_int mask = 0xffff; +#if DEBUG + char buf[200]; + + memset (buf, 0, 200); +#endif + + if (has_ring == -1) + has_ring = 1; + flip (p->misc2, PD67_MC2_IRQ15_RI, has_ring); + flip (p->misc2, PD67_MC2_DYNAMIC_MODE, dynamic_mode); +#if DEBUG + if (p->misc2 & PD67_MC2_IRQ15_RI) + strcat (buf, " [ring]"); + if (p->misc2 & PD67_MC2_DYNAMIC_MODE) + strcat (buf, " [dyn mode]"); + if (p->misc1 & PD67_MC1_INPACK_ENA) + strcat (buf, " [inpack]"); +#endif + + if (p->misc2 & PD67_MC2_IRQ15_RI) + mask &= ~0x8000; + if (has_led > 0) { +#if DEBUG + strcat (buf, " [led]"); +#endif + mask &= ~0x1000; + } + if (has_dma > 0) { +#if DEBUG + strcat (buf, " [dma]"); +#endif + mask &= ~0x0600; + flip (p->misc2, PD67_MC2_FREQ_BYPASS, freq_bypass); +#if DEBUG + if (p->misc2 & PD67_MC2_FREQ_BYPASS) + strcat (buf, " [freq bypass]"); +#endif + } + + if (setup_time >= 0) + p->timer[0] = p->timer[3] = setup_time; + if (cmd_time > 0) { + p->timer[1] = cmd_time; + p->timer[4] = cmd_time * 2 + 4; + } + if (p->timer[1] == 0) { + p->timer[1] = 6; + p->timer[4] = 16; + if (p->timer[0] == 0) + p->timer[0] = p->timer[3] = 1; + } + if (recov_time >= 0) + p->timer[2] = p->timer[5] = recov_time; + + debug ("i82365 Opt: %s [%d/%d/%d] [%d/%d/%d]\n", + buf, + p->timer[0], p->timer[1], p->timer[2], + p->timer[3], p->timer[4], p->timer[5]); + + return mask; +} + +#else /* !CONFIG_CPC45 */ + +/*====================================================================== + + Code to save and restore global state information for TI 1130 and + TI 1131 controllers, and to set and report global configuration + options. + +======================================================================*/ + +static void ti113x_get_state (socket_info_t * s) +{ + ti113x_state_t *p = &s->state; + + pci_readl (s, TI113X_SYSTEM_CONTROL, &p->sysctl); + pci_readb (s, TI113X_CARD_CONTROL, &p->cardctl); + pci_readb (s, TI113X_DEVICE_CONTROL, &p->devctl); + pci_readb (s, TI1250_DIAGNOSTIC, &p->diag); + pci_readl (s, TI12XX_IRQMUX, &p->irqmux); +} + +static void ti113x_set_state (socket_info_t * s) +{ + ti113x_state_t *p = &s->state; + + pci_writel (s, TI113X_SYSTEM_CONTROL, p->sysctl); + pci_writeb (s, TI113X_CARD_CONTROL, p->cardctl); + pci_writeb (s, TI113X_DEVICE_CONTROL, p->devctl); + pci_writeb (s, TI1250_MULTIMEDIA_CTL, 0); + pci_writeb (s, TI1250_DIAGNOSTIC, p->diag); + pci_writel (s, TI12XX_IRQMUX, p->irqmux); + i365_set_pair (s, TI113X_IO_OFFSET (0), 0); + i365_set_pair (s, TI113X_IO_OFFSET (1), 0); +} + +static u_int ti113x_set_opts (socket_info_t * s) +{ + ti113x_state_t *p = &s->state; + u_int mask = 0xffff; + + p->cardctl &= ~TI113X_CCR_ZVENABLE; + p->cardctl |= TI113X_CCR_SPKROUTEN; + + return mask; +} +#endif /* CONFIG_CPC45 */ + +/*====================================================================== + + Routines to handle common CardBus options + +======================================================================*/ + +/* Default settings for PCI command configuration register */ +#define CMD_DFLT (PCI_COMMAND_IO|PCI_COMMAND_MEMORY| \ + PCI_COMMAND_MASTER|PCI_COMMAND_WAIT) + +static void cb_get_state (socket_info_t * s) +{ + pci_readb (s, PCI_CACHE_LINE_SIZE, &s->cache); + pci_readb (s, PCI_LATENCY_TIMER, &s->pci_lat); + pci_readb (s, CB_LATENCY_TIMER, &s->cb_lat); + pci_readb (s, CB_CARDBUS_BUS, &s->cap.cardbus); + pci_readb (s, CB_SUBORD_BUS, &s->sub_bus); + pci_readw (s, CB_BRIDGE_CONTROL, &s->bcr); +} + +static void cb_set_state (socket_info_t * s) +{ +#ifndef CONFIG_CPC45 + pci_writel (s, CB_LEGACY_MODE_BASE, 0); + pci_writel (s, PCI_BASE_ADDRESS_0, s->cb_phys); +#endif + pci_writew (s, PCI_COMMAND, CMD_DFLT); + pci_writeb (s, PCI_CACHE_LINE_SIZE, s->cache); + pci_writeb (s, PCI_LATENCY_TIMER, s->pci_lat); + pci_writeb (s, CB_LATENCY_TIMER, s->cb_lat); + pci_writeb (s, CB_CARDBUS_BUS, s->cap.cardbus); + pci_writeb (s, CB_SUBORD_BUS, s->sub_bus); + pci_writew (s, CB_BRIDGE_CONTROL, s->bcr); +} + +static void cb_set_opts (socket_info_t * s) +{ +#ifndef CONFIG_CPC45 + if (s->cache == 0) + s->cache = 8; + if (s->pci_lat == 0) + s->pci_lat = 0xa8; + if (s->cb_lat == 0) + s->cb_lat = 0xb0; +#endif +} + +/*====================================================================== + + Power control for Cardbus controllers: used both for 16-bit and + Cardbus cards. + +======================================================================*/ + +static int cb_set_power (socket_info_t * s, socket_state_t * state) +{ + u_int reg = 0; + +#ifdef CONFIG_CPC45 + + reg = I365_PWR_NORESET; + if (state->flags & SS_PWR_AUTO) + reg |= I365_PWR_AUTO; + if (state->flags & SS_OUTPUT_ENA) + reg |= I365_PWR_OUT; + if (state->Vpp != 0) { + if (state->Vpp == 120) { + reg |= I365_VPP1_12V; + puts (" 12V card found: "); + } else if (state->Vpp == state->Vcc) { + reg |= I365_VPP1_5V; + } else { + puts (" power not found: "); + return -1; + } + } + if (state->Vcc != 0) { + reg |= I365_VCC_5V; + if (state->Vcc == 33) { + puts (" 3.3V card found: "); + i365_bset (s, PD67_MISC_CTL_1, PD67_MC1_VCC_3V); + } else if (state->Vcc == 50) { + puts (" 5V card found: "); + i365_bclr (s, PD67_MISC_CTL_1, PD67_MC1_VCC_3V); + } else { + puts (" power not found: "); + return -1; + } + } + + if (reg != i365_get (s, I365_POWER)) { + reg = (I365_PWR_OUT | I365_PWR_NORESET | I365_VCC_5V | I365_VPP1_5V); + i365_set (s, I365_POWER, reg); + } + +#else /* ! CONFIG_CPC45 */ + + /* restart card voltage detection if it seems appropriate */ + if ((state->Vcc == 0) && (state->Vpp == 0) && + !(cb_readl (s, CB_SOCKET_STATE) & CB_SS_VSENSE)) + cb_writel (s, CB_SOCKET_FORCE, CB_SF_CVSTEST); + switch (state->Vcc) { + case 0: + reg = 0; + break; + case 33: + reg = CB_SC_VCC_3V; + break; + case 50: + reg = CB_SC_VCC_5V; + break; + default: + return -1; + } + switch (state->Vpp) { + case 0: + break; + case 33: + reg |= CB_SC_VPP_3V; + break; + case 50: + reg |= CB_SC_VPP_5V; + break; + case 120: + reg |= CB_SC_VPP_12V; + break; + default: + return -1; + } + if (reg != cb_readl (s, CB_SOCKET_CONTROL)) + cb_writel (s, CB_SOCKET_CONTROL, reg); +#endif /* CONFIG_CPC45 */ + return 0; +} + +/*====================================================================== + + Generic routines to get and set controller options + +======================================================================*/ + +static void get_bridge_state (socket_info_t * s) +{ +#ifdef CONFIG_CPC45 + cirrus_get_state (s); +#else + ti113x_get_state (s); +#endif + cb_get_state (s); +} + +static void set_bridge_state (socket_info_t * s) +{ + cb_set_state (s); + i365_set (s, I365_GBLCTL, 0x00); + i365_set (s, I365_GENCTL, 0x00); +#ifdef CONFIG_CPC45 + cirrus_set_state (s); +#else + ti113x_set_state (s); +#endif +} + +static void set_bridge_opts (socket_info_t * s) +{ +#ifdef CONFIG_CPC45 + cirrus_set_opts (s); +#else + ti113x_set_opts (s); +#endif + cb_set_opts (s); +} + +/*====================================================================*/ +#define PD67_EXT_INDEX 0x2e /* Extension index */ +#define PD67_EXT_DATA 0x2f /* Extension data */ +#define PD67_EXD_VS1(s) (0x01 << ((s)<<1)) + +#define pd67_ext_get(s, r) \ + (i365_set(s, PD67_EXT_INDEX, r), i365_get(s, PD67_EXT_DATA)) + +static int i365_get_status (socket_info_t * s, u_int * value) +{ + u_int status; +#ifdef CONFIG_CPC45 + u_char val; + u_char power, vcc, vpp; + u_int powerstate; +#endif + + status = i365_get (s, I365_IDENT); + status = i365_get (s, I365_STATUS); + *value = ((status & I365_CS_DETECT) == I365_CS_DETECT) ? SS_DETECT : 0; + if (i365_get (s, I365_INTCTL) & I365_PC_IOCARD) { + *value |= (status & I365_CS_STSCHG) ? 0 : SS_STSCHG; + } else { + *value |= (status & I365_CS_BVD1) ? 0 : SS_BATDEAD; + *value |= (status & I365_CS_BVD2) ? 0 : SS_BATWARN; + } + *value |= (status & I365_CS_WRPROT) ? SS_WRPROT : 0; + *value |= (status & I365_CS_READY) ? SS_READY : 0; + *value |= (status & I365_CS_POWERON) ? SS_POWERON : 0; + +#ifdef CONFIG_CPC45 + /* Check for Cirrus CL-PD67xx chips */ + i365_set (s, PD67_CHIP_INFO, 0); + val = i365_get (s, PD67_CHIP_INFO); + s->type = -1; + if ((val & PD67_INFO_CHIP_ID) == PD67_INFO_CHIP_ID) { + val = i365_get (s, PD67_CHIP_INFO); + if ((val & PD67_INFO_CHIP_ID) == 0) { + s->type = (val & PD67_INFO_SLOTS) ? IS_PD672X : IS_PD6710; + i365_set (s, PD67_EXT_INDEX, 0xe5); + if (i365_get (s, PD67_EXT_INDEX) != 0xe5) + s->type = IS_VT83C469; + } + } else { + printf ("no Cirrus Chip found\n"); + *value = 0; + return -1; + } + + power = i365_get (s, I365_POWER); + state.flags |= (power & I365_PWR_AUTO) ? SS_PWR_AUTO : 0; + state.flags |= (power & I365_PWR_OUT) ? SS_OUTPUT_ENA : 0; + vcc = power & I365_VCC_MASK; + vpp = power & I365_VPP1_MASK; + state.Vcc = state.Vpp = 0; + if((vcc== 0) || (vpp == 0)) { + /* + * On the Cirrus we get the info which card voltage + * we have in EXTERN DATA and write it to MISC_CTL1 + */ + powerstate = pd67_ext_get(s, PD67_EXTERN_DATA); + if (powerstate & PD67_EXD_VS1(0)) { + /* 5V Card */ + i365_bclr (s, PD67_MISC_CTL_1, PD67_MC1_VCC_3V); + } else { + /* 3.3V Card */ + i365_bset (s, PD67_MISC_CTL_1, PD67_MC1_VCC_3V); + } + i365_set (s, I365_POWER, (I365_PWR_OUT | I365_PWR_NORESET | I365_VCC_5V | I365_VPP1_5V)); + power = i365_get (s, I365_POWER); + } + if (power & I365_VCC_5V) { + state.Vcc = (i365_get(s, PD67_MISC_CTL_1) & PD67_MC1_VCC_3V) ? 33 : 50; + } + + if (power == I365_VPP1_12V) + state.Vpp = 120; + + /* IO card, RESET flags, IO interrupt */ + power = i365_get (s, I365_INTCTL); + state.flags |= (power & I365_PC_RESET) ? 0 : SS_RESET; + if (power & I365_PC_IOCARD) + state.flags |= SS_IOCARD; + state.io_irq = power & I365_IRQ_MASK; + + /* Card status change mask */ + power = i365_get (s, I365_CSCINT); + state.csc_mask = (power & I365_CSC_DETECT) ? SS_DETECT : 0; + if (state.flags & SS_IOCARD) + state.csc_mask |= (power & I365_CSC_STSCHG) ? SS_STSCHG : 0; + else { + state.csc_mask |= (power & I365_CSC_BVD1) ? SS_BATDEAD : 0; + state.csc_mask |= (power & I365_CSC_BVD2) ? SS_BATWARN : 0; + state.csc_mask |= (power & I365_CSC_READY) ? SS_READY : 0; + } + debug ("i82365: GetStatus(0) = flags %#3.3x, Vcc %d, Vpp %d, " + "io_irq %d, csc_mask %#2.2x\n", state.flags, + state.Vcc, state.Vpp, state.io_irq, state.csc_mask); + +#else /* !CONFIG_CPC45 */ + + status = cb_readl (s, CB_SOCKET_STATE); + *value |= (status & CB_SS_32BIT) ? SS_CARDBUS : 0; + *value |= (status & CB_SS_3VCARD) ? SS_3VCARD : 0; + *value |= (status & CB_SS_XVCARD) ? SS_XVCARD : 0; + *value |= (status & CB_SS_VSENSE) ? 0 : SS_PENDING; + /* For now, ignore cards with unsupported voltage keys */ + if (*value & SS_XVCARD) + *value &= ~(SS_DETECT | SS_3VCARD | SS_XVCARD); +#endif /* CONFIG_CPC45 */ + return 0; +} /* i365_get_status */ + +static int i365_set_socket (socket_info_t * s, socket_state_t * state) +{ + u_char reg; + + set_bridge_state (s); + + /* IO card, RESET flag */ + reg = 0; + reg |= (state->flags & SS_RESET) ? 0 : I365_PC_RESET; + reg |= (state->flags & SS_IOCARD) ? I365_PC_IOCARD : 0; + i365_set (s, I365_INTCTL, reg); + +#ifdef CONFIG_CPC45 + cb_set_power (s, state); + +#if 0 + /* Card status change interrupt mask */ + reg = s->cs_irq << 4; + if (state->csc_mask & SS_DETECT) + reg |= I365_CSC_DETECT; + if (state->flags & SS_IOCARD) { + if (state->csc_mask & SS_STSCHG) + reg |= I365_CSC_STSCHG; + } else { + if (state->csc_mask & SS_BATDEAD) + reg |= I365_CSC_BVD1; + if (state->csc_mask & SS_BATWARN) + reg |= I365_CSC_BVD2; + if (state->csc_mask & SS_READY) + reg |= I365_CSC_READY; + } + i365_set (s, I365_CSCINT, reg); + i365_get (s, I365_CSC); +#endif /* 0 */ + +#else /* !CONFIG_CPC45 */ + + reg = I365_PWR_NORESET; + if (state->flags & SS_PWR_AUTO) + reg |= I365_PWR_AUTO; + if (state->flags & SS_OUTPUT_ENA) + reg |= I365_PWR_OUT; + + cb_set_power (s, state); + reg |= i365_get (s, I365_POWER) & (I365_VCC_MASK | I365_VPP1_MASK); + + if (reg != i365_get (s, I365_POWER)) + i365_set (s, I365_POWER, reg); +#endif /* CONFIG_CPC45 */ + + return 0; +} /* i365_set_socket */ + +/*====================================================================*/ + +static int i365_set_mem_map (socket_info_t * s, struct pccard_mem_map *mem) +{ + u_short base, i; + u_char map; + + debug ("i82365: SetMemMap(%d, %#2.2x, %d ns, %#5.5lx-%#5.5lx, %#5.5x)\n", + mem->map, mem->flags, mem->speed, + mem->sys_start, mem->sys_stop, mem->card_start); + + map = mem->map; + if ((map > 4) || + (mem->card_start > 0x3ffffff) || + (mem->sys_start > mem->sys_stop) || + (mem->speed > 1000)) { + return -1; + } + + /* Turn off the window before changing anything */ + if (i365_get (s, I365_ADDRWIN) & I365_ENA_MEM (map)) + i365_bclr (s, I365_ADDRWIN, I365_ENA_MEM (map)); + + /* Take care of high byte, for PCI controllers */ + i365_set (s, CB_MEM_PAGE (map), mem->sys_start >> 24); + + base = I365_MEM (map); + i = (mem->sys_start >> 12) & 0x0fff; + if (mem->flags & MAP_16BIT) + i |= I365_MEM_16BIT; + if (mem->flags & MAP_0WS) + i |= I365_MEM_0WS; + i365_set_pair (s, base + I365_W_START, i); + + i = (mem->sys_stop >> 12) & 0x0fff; + switch (mem->speed / CYCLE_TIME) { + case 0: + break; + case 1: + i |= I365_MEM_WS0; + break; + case 2: + i |= I365_MEM_WS1; + break; + default: + i |= I365_MEM_WS1 | I365_MEM_WS0; + break; + } + i365_set_pair (s, base + I365_W_STOP, i); + +#ifdef CONFIG_CPC45 + i = 0; +#else + i = ((mem->card_start - mem->sys_start) >> 12) & 0x3fff; +#endif + if (mem->flags & MAP_WRPROT) + i |= I365_MEM_WRPROT; + if (mem->flags & MAP_ATTRIB) + i |= I365_MEM_REG; + i365_set_pair (s, base + I365_W_OFF, i); + +#ifdef CONFIG_CPC45 + /* set System Memory map Upper Adress */ + i365_set(s, PD67_EXT_INDEX, PD67_MEM_PAGE(map)); + i365_set(s, PD67_EXT_DATA, ((mem->sys_start >> 24) & 0xff)); +#endif + + /* Turn on the window if necessary */ + if (mem->flags & MAP_ACTIVE) + i365_bset (s, I365_ADDRWIN, I365_ENA_MEM (map)); + return 0; +} /* i365_set_mem_map */ + +static int i365_set_io_map (socket_info_t * s, struct pccard_io_map *io) +{ + u_char map, ioctl; + + map = io->map; + /* comment out: comparison is always false due to limited range of data type */ + if ((map > 1) || /* (io->start > 0xffff) || (io->stop > 0xffff) || */ + (io->stop < io->start)) + return -1; + /* Turn off the window before changing anything */ + if (i365_get (s, I365_ADDRWIN) & I365_ENA_IO (map)) + i365_bclr (s, I365_ADDRWIN, I365_ENA_IO (map)); + i365_set_pair (s, I365_IO (map) + I365_W_START, io->start); + i365_set_pair (s, I365_IO (map) + I365_W_STOP, io->stop); + ioctl = i365_get (s, I365_IOCTL) & ~I365_IOCTL_MASK (map); + if (io->speed) + ioctl |= I365_IOCTL_WAIT (map); + if (io->flags & MAP_0WS) + ioctl |= I365_IOCTL_0WS (map); + if (io->flags & MAP_16BIT) + ioctl |= I365_IOCTL_16BIT (map); + if (io->flags & MAP_AUTOSZ) + ioctl |= I365_IOCTL_IOCS16 (map); + i365_set (s, I365_IOCTL, ioctl); + /* Turn on the window if necessary */ + if (io->flags & MAP_ACTIVE) + i365_bset (s, I365_ADDRWIN, I365_ENA_IO (map)); + return 0; +} /* i365_set_io_map */ + +/*====================================================================*/ + +int i82365_init (void) +{ + u_int val; + int i; + +#ifdef CONFIG_CPC45 + if (SPD67290Init () != 0) + return 1; +#endif + if ((socket.dev = pci_find_devices (supported, 0)) < 0) { + /* Controller not found */ + return 1; + } + debug ("i82365 Device Found!\n"); + + pci_read_config_dword (socket.dev, PCI_BASE_ADDRESS_0, &socket.cb_phys); + socket.cb_phys &= ~0xf; + +#ifdef CONFIG_CPC45 + /* + 0xfe000000 see MPC 8245 Users Manual Adress Map B */ + socket.cb_phys += 0xfe000000; +#endif + + get_bridge_state (&socket); + set_bridge_opts (&socket); + + i = i365_get_status (&socket, &val); + +#ifdef CONFIG_CPC45 + if (i > -1) { + puts (pcic[socket.type].name); + } else { + printf ("i82365: Controller not found.\n"); + return 1; + } + if((val & SS_DETECT) != SS_DETECT){ + puts ("No card\n"); + return 1; + } +#else /* !CONFIG_CPC45 */ + if (val & SS_DETECT) { + if (val & SS_3VCARD) { + state.Vcc = state.Vpp = 33; + puts (" 3.3V card found: "); + } else if (!(val & SS_XVCARD)) { + state.Vcc = state.Vpp = 50; + puts (" 5.0V card found: "); + } else { + puts ("i82365: unsupported voltage key\n"); + state.Vcc = state.Vpp = 0; + } + } else { + /* No card inserted */ + puts ("No card\n"); + return 1; + } +#endif /* CONFIG_CPC45 */ + +#ifdef CONFIG_CPC45 + state.flags |= SS_OUTPUT_ENA; +#else + state.flags = SS_IOCARD | SS_OUTPUT_ENA; + state.csc_mask = 0; + state.io_irq = 0; +#endif + + i365_set_socket (&socket, &state); + + for (i = 500; i; i--) { + if ((i365_get (&socket, I365_STATUS) & I365_CS_READY)) + break; + udelay (1000); + } + + if (i == 0) { + /* PC Card not ready for data transfer */ + puts ("i82365 PC Card not ready for data transfer\n"); + return 1; + } + debug (" PC Card ready for data transfer: "); + + mem.map = 0; + mem.flags = MAP_ATTRIB | MAP_ACTIVE; + mem.speed = 300; + mem.sys_start = CFG_PCMCIA_MEM_ADDR; + mem.sys_stop = CFG_PCMCIA_MEM_ADDR + CFG_PCMCIA_MEM_SIZE - 1; + mem.card_start = 0; + i365_set_mem_map (&socket, &mem); + +#ifdef CONFIG_CPC45 + mem.map = 1; + mem.flags = MAP_ACTIVE; + mem.speed = 300; + mem.sys_start = CFG_PCMCIA_MEM_ADDR + CFG_PCMCIA_MEM_SIZE; + mem.sys_stop = CFG_PCMCIA_MEM_ADDR + (2 * CFG_PCMCIA_MEM_SIZE) - 1; + mem.card_start = 0; + i365_set_mem_map (&socket, &mem); + +#else /* !CONFIG_CPC45 */ + + io.map = 0; + io.flags = MAP_AUTOSZ | MAP_ACTIVE; + io.speed = 0; + io.start = 0x0100; + io.stop = 0x010F; + i365_set_io_map (&socket, &io); + +#endif /* CONFIG_CPC45 */ + +#ifdef DEBUG + i82365_dump_regions (socket.dev); +#endif + + return 0; +} + +void i82365_exit (void) +{ + io.map = 0; + io.flags = 0; + io.speed = 0; + io.start = 0; + io.stop = 0x1; + + i365_set_io_map (&socket, &io); + + mem.map = 0; + mem.flags = 0; + mem.speed = 0; + mem.sys_start = 0; + mem.sys_stop = 0x1000; + mem.card_start = 0; + + i365_set_mem_map (&socket, &mem); + +#ifdef CONFIG_CPC45 + mem.map = 1; + mem.flags = 0; + mem.speed = 0; + mem.sys_start = 0; + mem.sys_stop = 0x1000; + mem.card_start = 0; + + i365_set_mem_map (&socket, &mem); +#else /* !CONFIG_CPC45 */ + socket.state.sysctl &= 0xFFFF00FF; +#endif + state.Vcc = state.Vpp = 0; + + i365_set_socket (&socket, &state); +} + +/*====================================================================== + + Debug stuff + +======================================================================*/ + +#ifdef DEBUG +static void i82365_dump_regions (pci_dev_t dev) +{ + u_int tmp[2]; + u_int *mem = (void *) socket.cb_phys; + u_char *cis = (void *) CFG_PCMCIA_MEM_ADDR; + u_char *ide = (void *) (CFG_ATA_BASE_ADDR + CFG_ATA_REG_OFFSET); + + pci_read_config_dword (dev, 0x00, tmp + 0); + pci_read_config_dword (dev, 0x80, tmp + 1); + + printf ("PCI CONF: %08X ... %08X\n", + tmp[0], tmp[1]); + printf ("PCI MEM: ... %08X ... %08X\n", + mem[0x8 / 4], mem[0x800 / 4]); + printf ("CIS: ...%c%c%c%c%c%c%c%c...\n", + cis[0x38], cis[0x3a], cis[0x3c], cis[0x3e], + cis[0x40], cis[0x42], cis[0x44], cis[0x48]); + printf ("CIS CONF: %02X %02X %02X ...\n", + cis[0x200], cis[0x202], cis[0x204]); + printf ("IDE: %02X %02X %02X %02X %02X %02X %02X %02X\n", + ide[0], ide[1], ide[2], ide[3], + ide[4], ide[5], ide[6], ide[7]); +} +#endif /* DEBUG */ + +#endif /* CONFIG_I82365 */ diff --git a/drivers/pcmcia/mpc8xx_pcmcia.c b/drivers/pcmcia/mpc8xx_pcmcia.c new file mode 100644 index 0000000000..8a34cd3054 --- /dev/null +++ b/drivers/pcmcia/mpc8xx_pcmcia.c @@ -0,0 +1,304 @@ +#include +#if defined(CONFIG_8xx) +#include +#endif +#include + +#undef CONFIG_PCMCIA + +#if defined(CONFIG_CMD_PCMCIA) +#define CONFIG_PCMCIA +#endif + +#if defined(CONFIG_CMD_IDE) && defined(CONFIG_IDE_8xx_PCCARD) +#define CONFIG_PCMCIA +#endif + +#if defined(CONFIG_8xx) && defined(CONFIG_PCMCIA) + +#if defined(CONFIG_IDE_8xx_PCCARD) +extern int check_ide_device (int slot); +#endif + +extern int pcmcia_hardware_enable (int slot); +extern int pcmcia_voltage_set(int slot, int vcc, int vpp); + +#if defined(CONFIG_CMD_PCMCIA) +extern int pcmcia_hardware_disable(int slot); +#endif + +static u_int m8xx_get_graycode(u_int size); +#if 0 /* Disabled */ +static u_int m8xx_get_speed(u_int ns, u_int is_io); +#endif + +/* look up table for pgcrx registers */ +u_int *pcmcia_pgcrx[2] = { + &((immap_t *)CFG_IMMR)->im_pcmcia.pcmc_pgcra, + &((immap_t *)CFG_IMMR)->im_pcmcia.pcmc_pgcrb, +}; + +/* + * Search this table to see if the windowsize is + * supported... + */ + +#define M8XX_SIZES_NO 32 + +static const u_int m8xx_size_to_gray[M8XX_SIZES_NO] = +{ 0x00000001, 0x00000002, 0x00000008, 0x00000004, + 0x00000080, 0x00000040, 0x00000010, 0x00000020, + 0x00008000, 0x00004000, 0x00001000, 0x00002000, + 0x00000100, 0x00000200, 0x00000800, 0x00000400, + + 0x0fffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x01000000, 0x02000000, 0xffffffff, 0x04000000, + 0x00010000, 0x00020000, 0x00080000, 0x00040000, + 0x00800000, 0x00400000, 0x00100000, 0x00200000 }; + + +/* -------------------------------------------------------------------- */ + +#ifdef CONFIG_HMI10 +#define HMI10_FRAM_TIMING ( PCMCIA_SHT(2) \ + | PCMCIA_SST(2) \ + | PCMCIA_SL(4)) +#endif + +#if defined(CONFIG_LWMON) || defined(CONFIG_NSCU) +#define CFG_PCMCIA_TIMING ( PCMCIA_SHT(9) \ + | PCMCIA_SST(3) \ + | PCMCIA_SL(12)) +#else +#define CFG_PCMCIA_TIMING ( PCMCIA_SHT(2) \ + | PCMCIA_SST(4) \ + | PCMCIA_SL(9)) +#endif + +/* -------------------------------------------------------------------- */ + +int pcmcia_on (void) +{ + u_long reg, base; + pcmcia_win_t *win; + u_int slotbit; + u_int rc, slot; + int i; + + debug ("Enable PCMCIA " PCMCIA_SLOT_MSG "\n"); + + /* intialize the fixed memory windows */ + win = (pcmcia_win_t *)(&((immap_t *)CFG_IMMR)->im_pcmcia.pcmc_pbr0); + base = CFG_PCMCIA_MEM_ADDR; + + if((reg = m8xx_get_graycode(CFG_PCMCIA_MEM_SIZE)) == -1) { + printf ("Cannot set window size to 0x%08x\n", + CFG_PCMCIA_MEM_SIZE); + return (1); + } + + slotbit = PCMCIA_SLOT_x; + for (i=0; ibr = base; + +#if (PCMCIA_SOCKETS_NO == 2) + if (i == 4) /* Another slot starting from win 4 */ + slotbit = (slotbit ? PCMCIA_PSLOT_A : PCMCIA_PSLOT_B); +#endif + switch (i) { +#ifdef CONFIG_IDE_8xx_PCCARD + case 4: +#ifdef CONFIG_HMI10 + { /* map FRAM area */ + win->or = ( PCMCIA_BSIZE_256K + | PCMCIA_PPS_8 + | PCMCIA_PRS_ATTR + | slotbit + | PCMCIA_PV + | HMI10_FRAM_TIMING ); + break; + } +#endif + case 0: { /* map attribute memory */ + win->or = ( PCMCIA_BSIZE_64M + | PCMCIA_PPS_8 + | PCMCIA_PRS_ATTR + | slotbit + | PCMCIA_PV + | CFG_PCMCIA_TIMING ); + break; + } + case 5: + case 1: { /* map I/O window for data reg */ + win->or = ( PCMCIA_BSIZE_1K + | PCMCIA_PPS_16 + | PCMCIA_PRS_IO + | slotbit + | PCMCIA_PV + | CFG_PCMCIA_TIMING ); + break; + } + case 6: + case 2: { /* map I/O window for cmd/ctrl reg block */ + win->or = ( PCMCIA_BSIZE_1K + | PCMCIA_PPS_8 + | PCMCIA_PRS_IO + | slotbit + | PCMCIA_PV + | CFG_PCMCIA_TIMING ); + break; + } +#endif /* CONFIG_IDE_8xx_PCCARD */ +#ifdef CONFIG_HMI10 + case 3: { /* map I/O window for 4xUART data/ctrl */ + win->br += 0x40000; + win->or = ( PCMCIA_BSIZE_256K + | PCMCIA_PPS_8 + | PCMCIA_PRS_IO + | slotbit + | PCMCIA_PV + | CFG_PCMCIA_TIMING ); + break; + } +#endif /* CONFIG_HMI10 */ + default: /* set to not valid */ + win->or = 0; + break; + } + + debug ("MemWin %d: PBR 0x%08lX POR %08lX\n", + i, win->br, win->or); + base += CFG_PCMCIA_MEM_SIZE; + ++win; + } + + for (i=0, rc=0, slot=_slot_; iim_pcmcia.pcmc_pscr = PCMCIA_MASK(_slot_); + ((immap_t *)CFG_IMMR)->im_pcmcia.pcmc_per &= ~PCMCIA_MASK(_slot_); + + /* turn off interrupt and disable CxOE */ + PCMCIA_PGCRX(_slot_) = __MY_PCMCIA_GCRX_CXOE; + + /* turn off memory windows */ + win = (pcmcia_win_t *)(&((immap_t *)CFG_IMMR)->im_pcmcia.pcmc_pbr0); + + for (i=0; ior = 0; + ++win; + } + + /* turn off voltage */ + pcmcia_voltage_set(_slot_, 0, 0); + + /* disable external hardware */ + printf ("Shutdown and Poweroff " PCMCIA_SLOT_MSG "\n"); + pcmcia_hardware_disable(_slot_); + return 0; +} +#endif + + +static u_int m8xx_get_graycode(u_int size) +{ + u_int k; + + for (k = 0; k < M8XX_SIZES_NO; k++) { + if(m8xx_size_to_gray[k] == size) + break; + } + + if((k == M8XX_SIZES_NO) || (m8xx_size_to_gray[k] == -1)) + k = -1; + + return k; +} + +#if 0 + +#if defined(CONFIG_RPXCLASSIC) || defined(CONFIG_RPXLITE) + +/* The RPX boards seems to have it's bus monitor timeout set to 6*8 clocks. + * SYPCR is write once only, therefore must the slowest memory be faster + * than the bus monitor or we will get a machine check due to the bus timeout. + */ +#undef PCMCIA_BMT_LIMIT +#define PCMCIA_BMT_LIMIT (6*8) +#endif + +static u_int m8xx_get_speed(u_int ns, u_int is_io) +{ + u_int reg, clocks, psst, psl, psht; + + if(!ns) { + + /* + * We get called with IO maps setup to 0ns + * if not specified by the user. + * They should be 255ns. + */ + + if(is_io) + ns = 255; + else + ns = 100; /* fast memory if 0 */ + } + + /* + * In PSST, PSL, PSHT fields we tell the controller + * timing parameters in CLKOUT clock cycles. + * CLKOUT is the same as GCLK2_50. + */ + + /* how we want to adjust the timing - in percent */ + +#define ADJ 180 /* 80 % longer accesstime - to be sure */ + + clocks = ((M8XX_BUSFREQ / 1000) * ns) / 1000; + clocks = (clocks * ADJ) / (100*1000); + + if(clocks >= PCMCIA_BMT_LIMIT) { + DEBUG(0, "Max access time limit reached\n"); + clocks = PCMCIA_BMT_LIMIT-1; + } + + psst = clocks / 7; /* setup time */ + psht = clocks / 7; /* hold time */ + psl = (clocks * 5) / 7; /* strobe length */ + + psst += clocks - (psst + psht + psl); + + reg = psst << 12; + reg |= psl << 7; + reg |= psht << 16; + + return reg; +} +#endif /* 0 */ + +#endif /* CONFIG_8xx && CONFIG_PCMCIA */ diff --git a/drivers/pcmcia/pxa_pcmcia.c b/drivers/pcmcia/pxa_pcmcia.c new file mode 100644 index 0000000000..6020e46283 --- /dev/null +++ b/drivers/pcmcia/pxa_pcmcia.c @@ -0,0 +1,95 @@ +#include +#include + +#ifdef CONFIG_PXA_PCMCIA + +#include +#include +#include + +static inline void msWait(unsigned msVal) +{ + udelay(msVal*1000); +} + +int pcmcia_on (void) +{ + unsigned int reg_arr[] = { + 0x48000028, CFG_MCMEM0_VAL, + 0x4800002c, CFG_MCMEM1_VAL, + 0x48000030, CFG_MCATT0_VAL, + 0x48000034, CFG_MCATT1_VAL, + 0x48000038, CFG_MCIO0_VAL, + 0x4800003c, CFG_MCIO1_VAL, + + 0, 0 + }; + int i, rc; + +#ifdef CONFIG_EXADRON1 + int cardDetect; + volatile unsigned int *v_pBCRReg = + (volatile unsigned int *) 0x08000000; +#endif + + debug ("%s\n", __FUNCTION__); + + i = 0; + while (reg_arr[i]) + *((volatile unsigned int *) reg_arr[i++]) |= reg_arr[i++]; + udelay (1000); + + debug ("%s: programmed mem controller \n", __FUNCTION__); + +#ifdef CONFIG_EXADRON1 + +/*define useful BCR masks */ +#define BCR_CF_INIT_VAL 0x00007230 +#define BCR_CF_PWRON_BUSOFF_RESETOFF_VAL 0x00007231 +#define BCR_CF_PWRON_BUSOFF_RESETON_VAL 0x00007233 +#define BCR_CF_PWRON_BUSON_RESETON_VAL 0x00007213 +#define BCR_CF_PWRON_BUSON_RESETOFF_VAL 0x00007211 + + /* we see from the GPIO bit if the card is present */ + cardDetect = !(GPLR0 & GPIO_bit (14)); + + if (cardDetect) { + printf ("No PCMCIA card found!\n"); + } + + /* reset the card via the BCR line */ + *v_pBCRReg = (unsigned) BCR_CF_INIT_VAL; + msWait (500); + + *v_pBCRReg = (unsigned) BCR_CF_PWRON_BUSOFF_RESETOFF_VAL; + msWait (500); + + *v_pBCRReg = (unsigned) BCR_CF_PWRON_BUSOFF_RESETON_VAL; + msWait (500); + + *v_pBCRReg = (unsigned) BCR_CF_PWRON_BUSON_RESETON_VAL; + msWait (500); + + *v_pBCRReg = (unsigned) BCR_CF_PWRON_BUSON_RESETOFF_VAL; + msWait (1500); + + /* enable address bus */ + GPCR1 = 0x01; + /* and the first CF slot */ + MECR = 0x00000002; + +#endif /* EXADRON 1 */ + + rc = check_ide_device (0); /* use just slot 0 */ + + return rc; +} + +#if defined(CONFIG_CMD_PCMCIA) +int pcmcia_off (void) +{ + return 0; +} +#endif + +#endif /* CONFIG_PXA_PCMCIA */ diff --git a/drivers/pcmcia/rpx_pcmcia.c b/drivers/pcmcia/rpx_pcmcia.c new file mode 100644 index 0000000000..c7c425b93c --- /dev/null +++ b/drivers/pcmcia/rpx_pcmcia.c @@ -0,0 +1,73 @@ +/* -------------------------------------------------------------------- */ +/* RPX Boards from Embedded Planet */ +/* -------------------------------------------------------------------- */ +#include +#ifdef CONFIG_8xx +#include +#endif +#include + +#undef CONFIG_PCMCIA + +#if defined(CONFIG_CMD_PCMCIA) +#define CONFIG_PCMCIA +#endif + +#if defined(CONFIG_CMD_IDE) && defined(CONFIG_IDE_8xx_PCCARD) +#define CONFIG_PCMCIA +#endif + +#if defined(CONFIG_PCMCIA) \ + && (defined(CONFIG_RPXCLASSIC) || defined(CONFIG_RPXLITE)) + +#define PCMCIA_BOARD_MSG "RPX CLASSIC or RPX LITE" + +int pcmcia_voltage_set(int slot, int vcc, int vpp) +{ + u_long reg = 0; + + switch(vcc) { + case 0: break; + case 33: reg |= BCSR1_PCVCTL4; break; + case 50: reg |= BCSR1_PCVCTL5; break; + default: return 1; + } + + switch(vpp) { + case 0: break; + case 33: + case 50: + if(vcc == vpp) + reg |= BCSR1_PCVCTL6; + else + return 1; + break; + case 120: + reg |= BCSR1_PCVCTL7; + default: return 1; + } + + /* first, turn off all power */ + *((uint *)RPX_CSR_ADDR) &= ~(BCSR1_PCVCTL4 | BCSR1_PCVCTL5 + | BCSR1_PCVCTL6 | BCSR1_PCVCTL7); + + /* enable new powersettings */ + *((uint *)RPX_CSR_ADDR) |= reg; + + return 0; +} + +int pcmcia_hardware_enable (int slot) +{ + return 0; /* No hardware to enable */ +} + +#if defined(CONFIG_CMD_PCMCIA) +static int pcmcia_hardware_disable(int slot) +{ + return 0; /* No hardware to disable */ +} +#endif + + +#endif /* CONFIG_PCMCIA && (CONFIG_RPXCLASSIC || CONFIG_RPXLITE) */ diff --git a/drivers/pcmcia/ti_pci1410a.c b/drivers/pcmcia/ti_pci1410a.c new file mode 100644 index 0000000000..208ca50a74 --- /dev/null +++ b/drivers/pcmcia/ti_pci1410a.c @@ -0,0 +1,665 @@ +/* + * (C) Copyright 2000-2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * (C) Copyright 2002 + * Daniel Engström, Omicron Ceti AB + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that 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 + * + ******************************************************************** + * + * Lots of code copied from: + * + * m8xx_pcmcia.c - Linux PCMCIA socket driver for the mpc8xx series. + * (C) 1999-2000 Magnus Damm + * + * "The ExCA standard specifies that socket controllers should provide + * two IO and five memory windows per socket, which can be independently + * configured and positioned in the host address space and mapped to + * arbitrary segments of card address space. " - David A Hinds. 1999 + * + * This controller does _not_ meet the ExCA standard. + * + * m8xx pcmcia controller brief info: + * + 8 windows (attrib, mem, i/o) + * + up to two slots (SLOT_A and SLOT_B) + * + inputpins, outputpins, event and mask registers. + * - no offset register. sigh. + * + * Because of the lacking offset register we must map the whole card. + * We assign each memory window PCMCIA_MEM_WIN_SIZE address space. + * Make sure there is (PCMCIA_MEM_WIN_SIZE * PCMCIA_MEM_WIN_NO + * * PCMCIA_SOCKETS_NO) bytes at PCMCIA_MEM_WIN_BASE. + * The i/o windows are dynamically allocated at PCMCIA_IO_WIN_BASE. + * They are maximum 64KByte each... + */ + + +#undef DEBUG /**/ + +/* + * PCMCIA support + */ +#include +#include +#include +#include +#include + +#include + +#if defined(CONFIG_CMD_PCMCIA) && defined(CONFIG_IDE_TI_CARDBUS) + +int pcmcia_on(int ide_base_bus); + +static int pcmcia_off(void); +static int hardware_disable(int slot); +static int hardware_enable(int slot); +static int voltage_set(int slot, int vcc, int vpp); +static void print_funcid(int func); +static void print_fixed(volatile uchar *p); +static int identify(volatile uchar *p); +static int check_ide_device(int slot, int ide_base_bus); + + +/* ------------------------------------------------------------------------- */ + + +const char *indent = "\t "; + +/* ------------------------------------------------------------------------- */ + + +int do_pinit(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ +#ifndef CFG_FIRST_PCMCIA_BUS +# define CFG_FIRST_PCMCIA_BUS 0 +#endif + + int rcode = 0; + + if (argc != 2) { + printf ("Usage: pinit {on | off}\n"); + return 1; + } + if (strcmp(argv[1],"on") == 0) { + rcode = pcmcia_on(CFG_FIRST_PCMCIA_BUS); + } else if (strcmp(argv[1],"off") == 0) { + rcode = pcmcia_off(); + } else { + printf ("Usage: pinit {on | off}\n"); + return 1; + } + + return rcode; +} + +/* ------------------------------------------------------------------------- */ + + +static struct pci_device_id supported[] = { + { PCI_VENDOR_ID_TI, 0xac50 }, /* Ti PCI1410A */ + { PCI_VENDOR_ID_TI, 0xac56 }, /* Ti PCI1510 */ + { } +}; + +static pci_dev_t devbusfn; +static u32 socket_base; +static u32 pcmcia_cis_ptr; + +int pcmcia_on(int ide_base_bus) +{ + u16 dev_id; + u32 socket_status; + int slot = 0; + int cis_len; + u16 io_base; + u16 io_len; + + /* + * Find the CardBus PCI device(s). + */ + if ((devbusfn = pci_find_devices(supported, 0)) < 0) { + printf("Ti CardBus: not found\n"); + return 1; + } + + pci_read_config_word(devbusfn, PCI_DEVICE_ID, &dev_id); + + if (dev_id == 0xac56) { + debug("Enable PCMCIA Ti PCI1510\n"); + } else { + debug("Enable PCMCIA Ti PCI1410A\n"); + } + + pcmcia_cis_ptr = CFG_PCMCIA_CIS_WIN; + cis_len = CFG_PCMCIA_CIS_WIN_SIZE; + + io_base = CFG_PCMCIA_IO_WIN; + io_len = CFG_PCMCIA_IO_WIN_SIZE; + + /* + * Setup the PCI device. + */ + pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_0, &socket_base); + socket_base &= ~0xf; + + socket_status = readl(socket_base+8); + if ((socket_status & 6) == 0) { + printf("Card Present: "); + + switch (socket_status & 0x3c00) { + + case 0x400: + printf("5V "); + break; + case 0x800: + printf("3.3V "); + break; + case 0xc00: + printf("3.3/5V "); + break; + default: + printf("unsupported Vcc "); + break; + } + switch (socket_status & 0x30) { + case 0x10: + printf("16bit PC-Card\n"); + break; + case 0x20: + printf("32bit CardBus Card\n"); + break; + default: + printf("8bit PC-Card\n"); + break; + } + } + + + writeb(0x41, socket_base + 0x806); /* Enable I/O window 0 and memory window 0 */ + writeb(0x0e, socket_base + 0x807); /* Reset I/O window options */ + + /* Careful: the linux yenta driver do not seem to reset the offset + * in the i/o windows, so leaving them non-zero is a problem */ + + writeb(io_base & 0xff, socket_base + 0x808); /* I/O window 0 base address */ + writeb(io_base>>8, socket_base + 0x809); + writeb((io_base + io_len - 1) & 0xff, socket_base + 0x80a); /* I/O window 0 end address */ + writeb((io_base + io_len - 1)>>8, socket_base + 0x80b); + writeb(0x00, socket_base + 0x836); /* I/O window 0 offset address 0x000 */ + writeb(0x00, socket_base + 0x837); + + + writeb((pcmcia_cis_ptr&0x000ff000) >> 12, + socket_base + 0x810); /* Memory window 0 start address bits 19-12 */ + writeb((pcmcia_cis_ptr&0x00f00000) >> 20, + socket_base + 0x811); /* Memory window 0 start address bits 23-20 */ + writeb(((pcmcia_cis_ptr+cis_len-1) & 0x000ff000) >> 12, + socket_base + 0x812); /* Memory window 0 end address bits 19-12*/ + writeb(((pcmcia_cis_ptr+cis_len-1) & 0x00f00000) >> 20, + socket_base + 0x813); /* Memory window 0 end address bits 23-20*/ + writeb(0x00, socket_base + 0x814); /* Memory window 0 offset bits 19-12 */ + writeb(0x40, socket_base + 0x815); /* Memory window 0 offset bits 23-20 and + * options (read/write, attribute access) */ + writeb(0x00, socket_base + 0x816); /* ExCA card-detect and general control */ + writeb(0x00, socket_base + 0x81e); /* ExCA global control (interrupt modes) */ + + writeb((pcmcia_cis_ptr & 0xff000000) >> 24, + socket_base + 0x840); /* Memory window address bits 31-24 */ + + + /* turn off voltage */ + if (voltage_set(slot, 0, 0)) { + return 1; + } + + /* Enable external hardware */ + if (hardware_enable(slot)) { + return 1; + } + + if (check_ide_device(slot, ide_base_bus)) { + return 1; + } + + return 0; +} + +/* ------------------------------------------------------------------------- */ + + +static int pcmcia_off (void) +{ + int slot = 0; + + writeb(0x00, socket_base + 0x806); /* disable all I/O and memory windows */ + + writeb(0x00, socket_base + 0x808); /* I/O window 0 base address */ + writeb(0x00, socket_base + 0x809); + writeb(0x00, socket_base + 0x80a); /* I/O window 0 end address */ + writeb(0x00, socket_base + 0x80b); + writeb(0x00, socket_base + 0x836); /* I/O window 0 offset address */ + writeb(0x00, socket_base + 0x837); + + writeb(0x00, socket_base + 0x80c); /* I/O window 1 base address */ + writeb(0x00, socket_base + 0x80d); + writeb(0x00, socket_base + 0x80e); /* I/O window 1 end address */ + writeb(0x00, socket_base + 0x80f); + writeb(0x00, socket_base + 0x838); /* I/O window 1 offset address */ + writeb(0x00, socket_base + 0x839); + + writeb(0x00, socket_base + 0x810); /* Memory window 0 start address */ + writeb(0x00, socket_base + 0x811); + writeb(0x00, socket_base + 0x812); /* Memory window 0 end address */ + writeb(0x00, socket_base + 0x813); + writeb(0x00, socket_base + 0x814); /* Memory window 0 offset */ + writeb(0x00, socket_base + 0x815); + + writeb(0xc0, socket_base + 0x840); /* Memory window 0 page address */ + + + /* turn off voltage */ + voltage_set(slot, 0, 0); + + /* disable external hardware */ + printf ("Shutdown and Poweroff Ti PCI1410A\n"); + hardware_disable(slot); + + return 0; +} + + +/* ------------------------------------------------------------------------- */ + + +#define MAX_TUPEL_SZ 512 +#define MAX_FEATURES 4 +int ide_devices_found; +static int check_ide_device(int slot, int ide_base_bus) +{ + volatile uchar *ident = NULL; + volatile uchar *feature_p[MAX_FEATURES]; + volatile uchar *p, *start; + int n_features = 0; + uchar func_id = ~0; + uchar code, len; + ushort config_base = 0; + int found = 0; + int i; + u32 socket_status; + + debug ("PCMCIA MEM: %08X\n", pcmcia_cis_ptr); + + socket_status = readl(socket_base+8); + + if ((socket_status & 6) != 0 || (socket_status & 0x20) != 0) { + printf("no card or CardBus card\n"); + return 1; + } + + start = p = (volatile uchar *) pcmcia_cis_ptr; + + while ((p - start) < MAX_TUPEL_SZ) { + + code = *p; p += 2; + + if (code == 0xFF) { /* End of chain */ + break; + } + + len = *p; p += 2; +#if defined(DEBUG) && (DEBUG > 1) + { + volatile uchar *q = p; + printf ("\nTuple code %02x length %d\n\tData:", + code, len); + + for (i = 0; i < len; ++i) { + printf (" %02x", *q); + q+= 2; + } + } +#endif /* DEBUG */ + switch (code) { + case CISTPL_VERS_1: + ident = p + 4; + break; + case CISTPL_FUNCID: + /* Fix for broken SanDisk which may have 0x80 bit set */ + func_id = *p & 0x7F; + break; + case CISTPL_FUNCE: + if (n_features < MAX_FEATURES) + feature_p[n_features++] = p; + break; + case CISTPL_CONFIG: + config_base = (*(p+6) << 8) + (*(p+4)); + debug ("\n## Config_base = %04x ###\n", config_base); + default: + break; + } + p += 2 * len; + } + + found = identify(ident); + + if (func_id != ((uchar)~0)) { + print_funcid (func_id); + + if (func_id == CISTPL_FUNCID_FIXED) + found = 1; + else + return 1; /* no disk drive */ + } + + for (i=0; i id_str) { + if (*t == ' ') { + *t = '\0'; + } else { + break; + } + } + puts(id_str); + putc('\n'); + + for (card=known_cards; *card; ++card) { + debug ("## Compare against \"%s\"\n", *card); + if (strcmp(*card, id_str) == 0) { /* found! */ + debug ("## CARD FOUND ##\n"); + return 1; + } + } + + return 0; /* don't know */ +} + +#endif /* CONFIG_IDE_TI_CARDBUS */ diff --git a/drivers/pcmcia/tqm8xx_pcmcia.c b/drivers/pcmcia/tqm8xx_pcmcia.c new file mode 100644 index 0000000000..132c7a5169 --- /dev/null +++ b/drivers/pcmcia/tqm8xx_pcmcia.c @@ -0,0 +1,330 @@ +/* -------------------------------------------------------------------- */ +/* TQM8xxL Boards by TQ Components */ +/* SC8xx Boards by SinoVee Microsystems */ +/* -------------------------------------------------------------------- */ +#include +#ifdef CONFIG_8xx +#include +#endif +#include + +#undef CONFIG_PCMCIA + +#if defined(CONFIG_CMD_PCMCIA) +#define CONFIG_PCMCIA +#endif + +#if defined(CONFIG_CMD_IDE) && defined(CONFIG_IDE_8xx_PCCARD) +#define CONFIG_PCMCIA +#endif + +#if defined(CONFIG_PCMCIA) \ + && (defined(CONFIG_TQM8xxL) || defined(CONFIG_SVM_SC8xx)) + +#if defined(CONFIG_VIRTLAB2) +#define PCMCIA_BOARD_MSG "Virtlab2" +#elif defined(CONFIG_TQM8xxL) +#define PCMCIA_BOARD_MSG "TQM8xxL" +#elif defined(CONFIG_SVM_SC8xx) +#define PCMCIA_BOARD_MSG "SC8xx" +#endif + +#if defined(CONFIG_NSCU) + +#define power_config(slot) do {} while (0) +#define power_off(slot) do {} while (0) +#define power_on_5_0(slot) do {} while (0) +#define power_on_3_3(slot) do {} while (0) + +#elif defined(CONFIG_HMI10) + +static inline void power_config(int slot) +{ + volatile immap_t *immap = (immap_t *)CFG_IMMR; + /* + * Configure Port B pins for + * 5 Volts Enable and 3 Volts enable + */ + immap->im_cpm.cp_pbpar &= ~(0x00000300); +} + +static inline void power_off(int slot) +{ + volatile immap_t *immap = (immap_t *)CFG_IMMR; + /* remove all power */ + immap->im_cpm.cp_pbdat |= 0x00000300; +} + +static inline void power_on_5_0(int slot) +{ + volatile immap_t *immap = (immap_t *)CFG_IMMR; + immap->im_cpm.cp_pbdat &= ~(0x0000100); + immap->im_cpm.cp_pbdir |= 0x00000300; +} + +static inline void power_on_3_3(int slot) +{ + volatile immap_t *immap = (immap_t *)CFG_IMMR; + immap->im_cpm.cp_pbdat &= ~(0x0000200); + immap->im_cpm.cp_pbdir |= 0x00000300; +} + +#elif defined(CONFIG_VIRTLAB2) + +#define power_config(slot) do {} while (0) +static inline void power_off(int slot) +{ + volatile unsigned char *powerctl = + (volatile unsigned char *)PCMCIA_CTRL; + *powerctl = 0; +} + +static inline void power_on_5_0(int slot) +{ + volatile unsigned char *powerctl = + (volatile unsigned char *)PCMCIA_CTRL; + *powerctl = 2; /* Enable 5V Vccout */ +} + +static inline void power_on_3_3(int slot) +{ + volatile unsigned char *powerctl = + (volatile unsigned char *)PCMCIA_CTRL; + *powerctl = 1; /* Enable 3.3V Vccout */ +} + +#else + +static inline void power_config(int slot) +{ + volatile immap_t *immap = (immap_t *)CFG_IMMR; + /* + * Configure Port C pins for + * 5 Volts Enable and 3 Volts enable + */ + immap->im_ioport.iop_pcpar &= ~(0x0002 | 0x0004); + immap->im_ioport.iop_pcso &= ~(0x0002 | 0x0004); +} + +static inline void power_off(int slot) +{ + volatile immap_t *immap = (immap_t *)CFG_IMMR; + immap->im_ioport.iop_pcdat &= ~(0x0002 | 0x0004); +} + +static inline void power_on_5_0(int slot) +{ + volatile immap_t *immap = (immap_t *)CFG_IMMR; + immap->im_ioport.iop_pcdat |= 0x0004; + immap->im_ioport.iop_pcdir |= (0x0002 | 0x0004); +} + +static inline void power_on_3_3(int slot) +{ + volatile immap_t *immap = (immap_t *)CFG_IMMR; + immap->im_ioport.iop_pcdat |= 0x0002; + immap->im_ioport.iop_pcdir |= (0x0002 | 0x0004); +} + +#endif + +#ifdef CONFIG_HMI10 +static inline int check_card_is_absent(int slot) +{ + volatile pcmconf8xx_t *pcmp = + (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia)); + return pcmp->pcmc_pipr & (0x10000000 >> (slot << 4)); +} +#else +static inline int check_card_is_absent(int slot) +{ + volatile pcmconf8xx_t *pcmp = + (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia)); + return pcmp->pcmc_pipr & (0x18000000 >> (slot << 4)); +} +#endif + +#ifdef NSCU_OE_INV +#define NSCU_GCRX_CXOE 0 +#else +#define NSCU_GCRX_CXOE __MY_PCMCIA_GCRX_CXOE +#endif + +int pcmcia_hardware_enable(int slot) +{ + volatile pcmconf8xx_t *pcmp = + (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia)); + volatile sysconf8xx_t *sysp = + (sysconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_siu_conf)); + uint reg, mask; + + debug ("hardware_enable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot); + + udelay(10000); + + /* + * Configure SIUMCR to enable PCMCIA port B + * (VFLS[0:1] are not used for debugging, we connect FRZ# instead) + */ + sysp->sc_siumcr &= ~SIUMCR_DBGC11; /* set DBGC to 00 */ + + /* clear interrupt state, and disable interrupts */ + pcmp->pcmc_pscr = PCMCIA_MASK(slot); + pcmp->pcmc_per &= ~PCMCIA_MASK(slot); + + /* + * Disable interrupts, DMA, and PCMCIA buffers + * (isolate the interface) and assert RESET signal + */ + debug ("Disable PCMCIA buffers and assert RESET\n"); + reg = 0; + reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */ + reg |= NSCU_GCRX_CXOE; + + PCMCIA_PGCRX(slot) = reg; + udelay(500); + + power_config(slot); + power_off(slot); + + /* + * Make sure there is a card in the slot, then configure the interface. + */ + udelay(10000); + debug ("[%d] %s: PIPR(%p)=0x%x\n", __LINE__,__FUNCTION__, + &(pcmp->pcmc_pipr),pcmp->pcmc_pipr); + + if (check_card_is_absent(slot)) { + printf (" No Card found\n"); + return (1); + } + + /* + * Power On. + */ + mask = PCMCIA_VS1(slot) | PCMCIA_VS2(slot); + reg = pcmp->pcmc_pipr; + debug ("PIPR: 0x%x ==> VS1=o%s, VS2=o%s\n", + reg, + (reg&PCMCIA_VS1(slot))?"n":"ff", + (reg&PCMCIA_VS2(slot))?"n":"ff"); + + if ((reg & mask) == mask) { + power_on_5_0(slot); + puts (" 5.0V card found: "); + } else { + power_on_3_3(slot); + puts (" 3.3V card found: "); + } + +#if 0 + /* VCC switch error flag, PCMCIA slot INPACK_ pin */ + cp->cp_pbdir &= ~(0x0020 | 0x0010); + cp->cp_pbpar &= ~(0x0020 | 0x0010); + udelay(500000); +#endif + + udelay(1000); + debug ("Enable PCMCIA buffers and stop RESET\n"); + reg = PCMCIA_PGCRX(slot); + reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */ + reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */ + reg &= ~NSCU_GCRX_CXOE; + + PCMCIA_PGCRX(slot) = reg; + + udelay(250000); /* some cards need >150 ms to come up :-( */ + + debug ("# hardware_enable done\n"); + + return (0); +} + + +#if defined(CONFIG_CMD_PCMCIA) +int pcmcia_hardware_disable(int slot) +{ + u_long reg; + + debug ("hardware_disable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot); + + + /* remove all power */ + power_off(slot); + + debug ("Disable PCMCIA buffers and assert RESET\n"); + reg = 0; + reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */ + reg |= NSCU_GCRX_CXOE; /* active low */ + + PCMCIA_PGCRX(slot) = reg; + + udelay(10000); + + return (0); +} +#endif + +int pcmcia_voltage_set(int slot, int vcc, int vpp) +{ +#ifndef CONFIG_NSCU + u_long reg; +# ifdef DEBUG + volatile pcmconf8xx_t *pcmp = + (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia)); +# endif + + debug ("voltage_set: " PCMCIA_BOARD_MSG + " Slot %c, Vcc=%d.%d, Vpp=%d.%d\n", + 'A'+slot, vcc/10, vcc%10, vpp/10, vcc%10); + + /* + * Disable PCMCIA buffers (isolate the interface) + * and assert RESET signal + */ + debug ("Disable PCMCIA buffers and assert RESET\n"); + reg = PCMCIA_PGCRX(slot); + reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */ + reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */ + reg |= NSCU_GCRX_CXOE; /* active low */ + + PCMCIA_PGCRX(slot) = reg; + udelay(500); + + debug ("PCMCIA power OFF\n"); + power_config(slot); + power_off(slot); + + switch(vcc) { + case 0: break; + case 33: power_on_3_3(slot); break; + case 50: power_on_5_0(slot); break; + default: goto done; + } + + /* Checking supported voltages */ + + debug("PIPR: 0x%x --> %s\n", pcmp->pcmc_pipr, + (pcmp->pcmc_pipr & 0x00008000) ? "only 5 V" : "can do 3.3V"); + + if (vcc) + debug("PCMCIA powered at %sV\n", (vcc == 50) ? "5.0" : "3.3"); + else + debug("PCMCIA powered down\n"); + +done: + debug("Enable PCMCIA buffers and stop RESET\n"); + reg = PCMCIA_PGCRX(slot); + reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */ + reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */ + reg &= ~NSCU_GCRX_CXOE; /* active low */ + + PCMCIA_PGCRX(slot) = reg; + udelay(500); + + debug("voltage_set: " PCMCIA_BOARD_MSG " Slot %c, DONE\n", slot+'A'); +#endif /* CONFIG_NSCU */ + return (0); +} + +#endif /* CONFIG_PCMCIA && (CONFIG_TQM8xxL || CONFIG_SVM_SC8xx) */ diff --git a/drivers/pxa_pcmcia.c b/drivers/pxa_pcmcia.c deleted file mode 100644 index 6020e46283..0000000000 --- a/drivers/pxa_pcmcia.c +++ /dev/null @@ -1,95 +0,0 @@ -#include -#include - -#ifdef CONFIG_PXA_PCMCIA - -#include -#include -#include - -static inline void msWait(unsigned msVal) -{ - udelay(msVal*1000); -} - -int pcmcia_on (void) -{ - unsigned int reg_arr[] = { - 0x48000028, CFG_MCMEM0_VAL, - 0x4800002c, CFG_MCMEM1_VAL, - 0x48000030, CFG_MCATT0_VAL, - 0x48000034, CFG_MCATT1_VAL, - 0x48000038, CFG_MCIO0_VAL, - 0x4800003c, CFG_MCIO1_VAL, - - 0, 0 - }; - int i, rc; - -#ifdef CONFIG_EXADRON1 - int cardDetect; - volatile unsigned int *v_pBCRReg = - (volatile unsigned int *) 0x08000000; -#endif - - debug ("%s\n", __FUNCTION__); - - i = 0; - while (reg_arr[i]) - *((volatile unsigned int *) reg_arr[i++]) |= reg_arr[i++]; - udelay (1000); - - debug ("%s: programmed mem controller \n", __FUNCTION__); - -#ifdef CONFIG_EXADRON1 - -/*define useful BCR masks */ -#define BCR_CF_INIT_VAL 0x00007230 -#define BCR_CF_PWRON_BUSOFF_RESETOFF_VAL 0x00007231 -#define BCR_CF_PWRON_BUSOFF_RESETON_VAL 0x00007233 -#define BCR_CF_PWRON_BUSON_RESETON_VAL 0x00007213 -#define BCR_CF_PWRON_BUSON_RESETOFF_VAL 0x00007211 - - /* we see from the GPIO bit if the card is present */ - cardDetect = !(GPLR0 & GPIO_bit (14)); - - if (cardDetect) { - printf ("No PCMCIA card found!\n"); - } - - /* reset the card via the BCR line */ - *v_pBCRReg = (unsigned) BCR_CF_INIT_VAL; - msWait (500); - - *v_pBCRReg = (unsigned) BCR_CF_PWRON_BUSOFF_RESETOFF_VAL; - msWait (500); - - *v_pBCRReg = (unsigned) BCR_CF_PWRON_BUSOFF_RESETON_VAL; - msWait (500); - - *v_pBCRReg = (unsigned) BCR_CF_PWRON_BUSON_RESETON_VAL; - msWait (500); - - *v_pBCRReg = (unsigned) BCR_CF_PWRON_BUSON_RESETOFF_VAL; - msWait (1500); - - /* enable address bus */ - GPCR1 = 0x01; - /* and the first CF slot */ - MECR = 0x00000002; - -#endif /* EXADRON 1 */ - - rc = check_ide_device (0); /* use just slot 0 */ - - return rc; -} - -#if defined(CONFIG_CMD_PCMCIA) -int pcmcia_off (void) -{ - return 0; -} -#endif - -#endif /* CONFIG_PXA_PCMCIA */ diff --git a/drivers/rpx_pcmcia.c b/drivers/rpx_pcmcia.c deleted file mode 100644 index c7c425b93c..0000000000 --- a/drivers/rpx_pcmcia.c +++ /dev/null @@ -1,73 +0,0 @@ -/* -------------------------------------------------------------------- */ -/* RPX Boards from Embedded Planet */ -/* -------------------------------------------------------------------- */ -#include -#ifdef CONFIG_8xx -#include -#endif -#include - -#undef CONFIG_PCMCIA - -#if defined(CONFIG_CMD_PCMCIA) -#define CONFIG_PCMCIA -#endif - -#if defined(CONFIG_CMD_IDE) && defined(CONFIG_IDE_8xx_PCCARD) -#define CONFIG_PCMCIA -#endif - -#if defined(CONFIG_PCMCIA) \ - && (defined(CONFIG_RPXCLASSIC) || defined(CONFIG_RPXLITE)) - -#define PCMCIA_BOARD_MSG "RPX CLASSIC or RPX LITE" - -int pcmcia_voltage_set(int slot, int vcc, int vpp) -{ - u_long reg = 0; - - switch(vcc) { - case 0: break; - case 33: reg |= BCSR1_PCVCTL4; break; - case 50: reg |= BCSR1_PCVCTL5; break; - default: return 1; - } - - switch(vpp) { - case 0: break; - case 33: - case 50: - if(vcc == vpp) - reg |= BCSR1_PCVCTL6; - else - return 1; - break; - case 120: - reg |= BCSR1_PCVCTL7; - default: return 1; - } - - /* first, turn off all power */ - *((uint *)RPX_CSR_ADDR) &= ~(BCSR1_PCVCTL4 | BCSR1_PCVCTL5 - | BCSR1_PCVCTL6 | BCSR1_PCVCTL7); - - /* enable new powersettings */ - *((uint *)RPX_CSR_ADDR) |= reg; - - return 0; -} - -int pcmcia_hardware_enable (int slot) -{ - return 0; /* No hardware to enable */ -} - -#if defined(CONFIG_CMD_PCMCIA) -static int pcmcia_hardware_disable(int slot) -{ - return 0; /* No hardware to disable */ -} -#endif - - -#endif /* CONFIG_PCMCIA && (CONFIG_RPXCLASSIC || CONFIG_RPXLITE) */ diff --git a/drivers/ti_pci1410a.c b/drivers/ti_pci1410a.c deleted file mode 100644 index 208ca50a74..0000000000 --- a/drivers/ti_pci1410a.c +++ /dev/null @@ -1,665 +0,0 @@ -/* - * (C) Copyright 2000-2002 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * (C) Copyright 2002 - * Daniel Engström, Omicron Ceti AB - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that 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 - * - ******************************************************************** - * - * Lots of code copied from: - * - * m8xx_pcmcia.c - Linux PCMCIA socket driver for the mpc8xx series. - * (C) 1999-2000 Magnus Damm - * - * "The ExCA standard specifies that socket controllers should provide - * two IO and five memory windows per socket, which can be independently - * configured and positioned in the host address space and mapped to - * arbitrary segments of card address space. " - David A Hinds. 1999 - * - * This controller does _not_ meet the ExCA standard. - * - * m8xx pcmcia controller brief info: - * + 8 windows (attrib, mem, i/o) - * + up to two slots (SLOT_A and SLOT_B) - * + inputpins, outputpins, event and mask registers. - * - no offset register. sigh. - * - * Because of the lacking offset register we must map the whole card. - * We assign each memory window PCMCIA_MEM_WIN_SIZE address space. - * Make sure there is (PCMCIA_MEM_WIN_SIZE * PCMCIA_MEM_WIN_NO - * * PCMCIA_SOCKETS_NO) bytes at PCMCIA_MEM_WIN_BASE. - * The i/o windows are dynamically allocated at PCMCIA_IO_WIN_BASE. - * They are maximum 64KByte each... - */ - - -#undef DEBUG /**/ - -/* - * PCMCIA support - */ -#include -#include -#include -#include -#include - -#include - -#if defined(CONFIG_CMD_PCMCIA) && defined(CONFIG_IDE_TI_CARDBUS) - -int pcmcia_on(int ide_base_bus); - -static int pcmcia_off(void); -static int hardware_disable(int slot); -static int hardware_enable(int slot); -static int voltage_set(int slot, int vcc, int vpp); -static void print_funcid(int func); -static void print_fixed(volatile uchar *p); -static int identify(volatile uchar *p); -static int check_ide_device(int slot, int ide_base_bus); - - -/* ------------------------------------------------------------------------- */ - - -const char *indent = "\t "; - -/* ------------------------------------------------------------------------- */ - - -int do_pinit(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) -{ -#ifndef CFG_FIRST_PCMCIA_BUS -# define CFG_FIRST_PCMCIA_BUS 0 -#endif - - int rcode = 0; - - if (argc != 2) { - printf ("Usage: pinit {on | off}\n"); - return 1; - } - if (strcmp(argv[1],"on") == 0) { - rcode = pcmcia_on(CFG_FIRST_PCMCIA_BUS); - } else if (strcmp(argv[1],"off") == 0) { - rcode = pcmcia_off(); - } else { - printf ("Usage: pinit {on | off}\n"); - return 1; - } - - return rcode; -} - -/* ------------------------------------------------------------------------- */ - - -static struct pci_device_id supported[] = { - { PCI_VENDOR_ID_TI, 0xac50 }, /* Ti PCI1410A */ - { PCI_VENDOR_ID_TI, 0xac56 }, /* Ti PCI1510 */ - { } -}; - -static pci_dev_t devbusfn; -static u32 socket_base; -static u32 pcmcia_cis_ptr; - -int pcmcia_on(int ide_base_bus) -{ - u16 dev_id; - u32 socket_status; - int slot = 0; - int cis_len; - u16 io_base; - u16 io_len; - - /* - * Find the CardBus PCI device(s). - */ - if ((devbusfn = pci_find_devices(supported, 0)) < 0) { - printf("Ti CardBus: not found\n"); - return 1; - } - - pci_read_config_word(devbusfn, PCI_DEVICE_ID, &dev_id); - - if (dev_id == 0xac56) { - debug("Enable PCMCIA Ti PCI1510\n"); - } else { - debug("Enable PCMCIA Ti PCI1410A\n"); - } - - pcmcia_cis_ptr = CFG_PCMCIA_CIS_WIN; - cis_len = CFG_PCMCIA_CIS_WIN_SIZE; - - io_base = CFG_PCMCIA_IO_WIN; - io_len = CFG_PCMCIA_IO_WIN_SIZE; - - /* - * Setup the PCI device. - */ - pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_0, &socket_base); - socket_base &= ~0xf; - - socket_status = readl(socket_base+8); - if ((socket_status & 6) == 0) { - printf("Card Present: "); - - switch (socket_status & 0x3c00) { - - case 0x400: - printf("5V "); - break; - case 0x800: - printf("3.3V "); - break; - case 0xc00: - printf("3.3/5V "); - break; - default: - printf("unsupported Vcc "); - break; - } - switch (socket_status & 0x30) { - case 0x10: - printf("16bit PC-Card\n"); - break; - case 0x20: - printf("32bit CardBus Card\n"); - break; - default: - printf("8bit PC-Card\n"); - break; - } - } - - - writeb(0x41, socket_base + 0x806); /* Enable I/O window 0 and memory window 0 */ - writeb(0x0e, socket_base + 0x807); /* Reset I/O window options */ - - /* Careful: the linux yenta driver do not seem to reset the offset - * in the i/o windows, so leaving them non-zero is a problem */ - - writeb(io_base & 0xff, socket_base + 0x808); /* I/O window 0 base address */ - writeb(io_base>>8, socket_base + 0x809); - writeb((io_base + io_len - 1) & 0xff, socket_base + 0x80a); /* I/O window 0 end address */ - writeb((io_base + io_len - 1)>>8, socket_base + 0x80b); - writeb(0x00, socket_base + 0x836); /* I/O window 0 offset address 0x000 */ - writeb(0x00, socket_base + 0x837); - - - writeb((pcmcia_cis_ptr&0x000ff000) >> 12, - socket_base + 0x810); /* Memory window 0 start address bits 19-12 */ - writeb((pcmcia_cis_ptr&0x00f00000) >> 20, - socket_base + 0x811); /* Memory window 0 start address bits 23-20 */ - writeb(((pcmcia_cis_ptr+cis_len-1) & 0x000ff000) >> 12, - socket_base + 0x812); /* Memory window 0 end address bits 19-12*/ - writeb(((pcmcia_cis_ptr+cis_len-1) & 0x00f00000) >> 20, - socket_base + 0x813); /* Memory window 0 end address bits 23-20*/ - writeb(0x00, socket_base + 0x814); /* Memory window 0 offset bits 19-12 */ - writeb(0x40, socket_base + 0x815); /* Memory window 0 offset bits 23-20 and - * options (read/write, attribute access) */ - writeb(0x00, socket_base + 0x816); /* ExCA card-detect and general control */ - writeb(0x00, socket_base + 0x81e); /* ExCA global control (interrupt modes) */ - - writeb((pcmcia_cis_ptr & 0xff000000) >> 24, - socket_base + 0x840); /* Memory window address bits 31-24 */ - - - /* turn off voltage */ - if (voltage_set(slot, 0, 0)) { - return 1; - } - - /* Enable external hardware */ - if (hardware_enable(slot)) { - return 1; - } - - if (check_ide_device(slot, ide_base_bus)) { - return 1; - } - - return 0; -} - -/* ------------------------------------------------------------------------- */ - - -static int pcmcia_off (void) -{ - int slot = 0; - - writeb(0x00, socket_base + 0x806); /* disable all I/O and memory windows */ - - writeb(0x00, socket_base + 0x808); /* I/O window 0 base address */ - writeb(0x00, socket_base + 0x809); - writeb(0x00, socket_base + 0x80a); /* I/O window 0 end address */ - writeb(0x00, socket_base + 0x80b); - writeb(0x00, socket_base + 0x836); /* I/O window 0 offset address */ - writeb(0x00, socket_base + 0x837); - - writeb(0x00, socket_base + 0x80c); /* I/O window 1 base address */ - writeb(0x00, socket_base + 0x80d); - writeb(0x00, socket_base + 0x80e); /* I/O window 1 end address */ - writeb(0x00, socket_base + 0x80f); - writeb(0x00, socket_base + 0x838); /* I/O window 1 offset address */ - writeb(0x00, socket_base + 0x839); - - writeb(0x00, socket_base + 0x810); /* Memory window 0 start address */ - writeb(0x00, socket_base + 0x811); - writeb(0x00, socket_base + 0x812); /* Memory window 0 end address */ - writeb(0x00, socket_base + 0x813); - writeb(0x00, socket_base + 0x814); /* Memory window 0 offset */ - writeb(0x00, socket_base + 0x815); - - writeb(0xc0, socket_base + 0x840); /* Memory window 0 page address */ - - - /* turn off voltage */ - voltage_set(slot, 0, 0); - - /* disable external hardware */ - printf ("Shutdown and Poweroff Ti PCI1410A\n"); - hardware_disable(slot); - - return 0; -} - - -/* ------------------------------------------------------------------------- */ - - -#define MAX_TUPEL_SZ 512 -#define MAX_FEATURES 4 -int ide_devices_found; -static int check_ide_device(int slot, int ide_base_bus) -{ - volatile uchar *ident = NULL; - volatile uchar *feature_p[MAX_FEATURES]; - volatile uchar *p, *start; - int n_features = 0; - uchar func_id = ~0; - uchar code, len; - ushort config_base = 0; - int found = 0; - int i; - u32 socket_status; - - debug ("PCMCIA MEM: %08X\n", pcmcia_cis_ptr); - - socket_status = readl(socket_base+8); - - if ((socket_status & 6) != 0 || (socket_status & 0x20) != 0) { - printf("no card or CardBus card\n"); - return 1; - } - - start = p = (volatile uchar *) pcmcia_cis_ptr; - - while ((p - start) < MAX_TUPEL_SZ) { - - code = *p; p += 2; - - if (code == 0xFF) { /* End of chain */ - break; - } - - len = *p; p += 2; -#if defined(DEBUG) && (DEBUG > 1) - { - volatile uchar *q = p; - printf ("\nTuple code %02x length %d\n\tData:", - code, len); - - for (i = 0; i < len; ++i) { - printf (" %02x", *q); - q+= 2; - } - } -#endif /* DEBUG */ - switch (code) { - case CISTPL_VERS_1: - ident = p + 4; - break; - case CISTPL_FUNCID: - /* Fix for broken SanDisk which may have 0x80 bit set */ - func_id = *p & 0x7F; - break; - case CISTPL_FUNCE: - if (n_features < MAX_FEATURES) - feature_p[n_features++] = p; - break; - case CISTPL_CONFIG: - config_base = (*(p+6) << 8) + (*(p+4)); - debug ("\n## Config_base = %04x ###\n", config_base); - default: - break; - } - p += 2 * len; - } - - found = identify(ident); - - if (func_id != ((uchar)~0)) { - print_funcid (func_id); - - if (func_id == CISTPL_FUNCID_FIXED) - found = 1; - else - return 1; /* no disk drive */ - } - - for (i=0; i id_str) { - if (*t == ' ') { - *t = '\0'; - } else { - break; - } - } - puts(id_str); - putc('\n'); - - for (card=known_cards; *card; ++card) { - debug ("## Compare against \"%s\"\n", *card); - if (strcmp(*card, id_str) == 0) { /* found! */ - debug ("## CARD FOUND ##\n"); - return 1; - } - } - - return 0; /* don't know */ -} - -#endif /* CONFIG_IDE_TI_CARDBUS */ diff --git a/drivers/tqm8xx_pcmcia.c b/drivers/tqm8xx_pcmcia.c deleted file mode 100644 index 132c7a5169..0000000000 --- a/drivers/tqm8xx_pcmcia.c +++ /dev/null @@ -1,330 +0,0 @@ -/* -------------------------------------------------------------------- */ -/* TQM8xxL Boards by TQ Components */ -/* SC8xx Boards by SinoVee Microsystems */ -/* -------------------------------------------------------------------- */ -#include -#ifdef CONFIG_8xx -#include -#endif -#include - -#undef CONFIG_PCMCIA - -#if defined(CONFIG_CMD_PCMCIA) -#define CONFIG_PCMCIA -#endif - -#if defined(CONFIG_CMD_IDE) && defined(CONFIG_IDE_8xx_PCCARD) -#define CONFIG_PCMCIA -#endif - -#if defined(CONFIG_PCMCIA) \ - && (defined(CONFIG_TQM8xxL) || defined(CONFIG_SVM_SC8xx)) - -#if defined(CONFIG_VIRTLAB2) -#define PCMCIA_BOARD_MSG "Virtlab2" -#elif defined(CONFIG_TQM8xxL) -#define PCMCIA_BOARD_MSG "TQM8xxL" -#elif defined(CONFIG_SVM_SC8xx) -#define PCMCIA_BOARD_MSG "SC8xx" -#endif - -#if defined(CONFIG_NSCU) - -#define power_config(slot) do {} while (0) -#define power_off(slot) do {} while (0) -#define power_on_5_0(slot) do {} while (0) -#define power_on_3_3(slot) do {} while (0) - -#elif defined(CONFIG_HMI10) - -static inline void power_config(int slot) -{ - volatile immap_t *immap = (immap_t *)CFG_IMMR; - /* - * Configure Port B pins for - * 5 Volts Enable and 3 Volts enable - */ - immap->im_cpm.cp_pbpar &= ~(0x00000300); -} - -static inline void power_off(int slot) -{ - volatile immap_t *immap = (immap_t *)CFG_IMMR; - /* remove all power */ - immap->im_cpm.cp_pbdat |= 0x00000300; -} - -static inline void power_on_5_0(int slot) -{ - volatile immap_t *immap = (immap_t *)CFG_IMMR; - immap->im_cpm.cp_pbdat &= ~(0x0000100); - immap->im_cpm.cp_pbdir |= 0x00000300; -} - -static inline void power_on_3_3(int slot) -{ - volatile immap_t *immap = (immap_t *)CFG_IMMR; - immap->im_cpm.cp_pbdat &= ~(0x0000200); - immap->im_cpm.cp_pbdir |= 0x00000300; -} - -#elif defined(CONFIG_VIRTLAB2) - -#define power_config(slot) do {} while (0) -static inline void power_off(int slot) -{ - volatile unsigned char *powerctl = - (volatile unsigned char *)PCMCIA_CTRL; - *powerctl = 0; -} - -static inline void power_on_5_0(int slot) -{ - volatile unsigned char *powerctl = - (volatile unsigned char *)PCMCIA_CTRL; - *powerctl = 2; /* Enable 5V Vccout */ -} - -static inline void power_on_3_3(int slot) -{ - volatile unsigned char *powerctl = - (volatile unsigned char *)PCMCIA_CTRL; - *powerctl = 1; /* Enable 3.3V Vccout */ -} - -#else - -static inline void power_config(int slot) -{ - volatile immap_t *immap = (immap_t *)CFG_IMMR; - /* - * Configure Port C pins for - * 5 Volts Enable and 3 Volts enable - */ - immap->im_ioport.iop_pcpar &= ~(0x0002 | 0x0004); - immap->im_ioport.iop_pcso &= ~(0x0002 | 0x0004); -} - -static inline void power_off(int slot) -{ - volatile immap_t *immap = (immap_t *)CFG_IMMR; - immap->im_ioport.iop_pcdat &= ~(0x0002 | 0x0004); -} - -static inline void power_on_5_0(int slot) -{ - volatile immap_t *immap = (immap_t *)CFG_IMMR; - immap->im_ioport.iop_pcdat |= 0x0004; - immap->im_ioport.iop_pcdir |= (0x0002 | 0x0004); -} - -static inline void power_on_3_3(int slot) -{ - volatile immap_t *immap = (immap_t *)CFG_IMMR; - immap->im_ioport.iop_pcdat |= 0x0002; - immap->im_ioport.iop_pcdir |= (0x0002 | 0x0004); -} - -#endif - -#ifdef CONFIG_HMI10 -static inline int check_card_is_absent(int slot) -{ - volatile pcmconf8xx_t *pcmp = - (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia)); - return pcmp->pcmc_pipr & (0x10000000 >> (slot << 4)); -} -#else -static inline int check_card_is_absent(int slot) -{ - volatile pcmconf8xx_t *pcmp = - (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia)); - return pcmp->pcmc_pipr & (0x18000000 >> (slot << 4)); -} -#endif - -#ifdef NSCU_OE_INV -#define NSCU_GCRX_CXOE 0 -#else -#define NSCU_GCRX_CXOE __MY_PCMCIA_GCRX_CXOE -#endif - -int pcmcia_hardware_enable(int slot) -{ - volatile pcmconf8xx_t *pcmp = - (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia)); - volatile sysconf8xx_t *sysp = - (sysconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_siu_conf)); - uint reg, mask; - - debug ("hardware_enable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot); - - udelay(10000); - - /* - * Configure SIUMCR to enable PCMCIA port B - * (VFLS[0:1] are not used for debugging, we connect FRZ# instead) - */ - sysp->sc_siumcr &= ~SIUMCR_DBGC11; /* set DBGC to 00 */ - - /* clear interrupt state, and disable interrupts */ - pcmp->pcmc_pscr = PCMCIA_MASK(slot); - pcmp->pcmc_per &= ~PCMCIA_MASK(slot); - - /* - * Disable interrupts, DMA, and PCMCIA buffers - * (isolate the interface) and assert RESET signal - */ - debug ("Disable PCMCIA buffers and assert RESET\n"); - reg = 0; - reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */ - reg |= NSCU_GCRX_CXOE; - - PCMCIA_PGCRX(slot) = reg; - udelay(500); - - power_config(slot); - power_off(slot); - - /* - * Make sure there is a card in the slot, then configure the interface. - */ - udelay(10000); - debug ("[%d] %s: PIPR(%p)=0x%x\n", __LINE__,__FUNCTION__, - &(pcmp->pcmc_pipr),pcmp->pcmc_pipr); - - if (check_card_is_absent(slot)) { - printf (" No Card found\n"); - return (1); - } - - /* - * Power On. - */ - mask = PCMCIA_VS1(slot) | PCMCIA_VS2(slot); - reg = pcmp->pcmc_pipr; - debug ("PIPR: 0x%x ==> VS1=o%s, VS2=o%s\n", - reg, - (reg&PCMCIA_VS1(slot))?"n":"ff", - (reg&PCMCIA_VS2(slot))?"n":"ff"); - - if ((reg & mask) == mask) { - power_on_5_0(slot); - puts (" 5.0V card found: "); - } else { - power_on_3_3(slot); - puts (" 3.3V card found: "); - } - -#if 0 - /* VCC switch error flag, PCMCIA slot INPACK_ pin */ - cp->cp_pbdir &= ~(0x0020 | 0x0010); - cp->cp_pbpar &= ~(0x0020 | 0x0010); - udelay(500000); -#endif - - udelay(1000); - debug ("Enable PCMCIA buffers and stop RESET\n"); - reg = PCMCIA_PGCRX(slot); - reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */ - reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */ - reg &= ~NSCU_GCRX_CXOE; - - PCMCIA_PGCRX(slot) = reg; - - udelay(250000); /* some cards need >150 ms to come up :-( */ - - debug ("# hardware_enable done\n"); - - return (0); -} - - -#if defined(CONFIG_CMD_PCMCIA) -int pcmcia_hardware_disable(int slot) -{ - u_long reg; - - debug ("hardware_disable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot); - - - /* remove all power */ - power_off(slot); - - debug ("Disable PCMCIA buffers and assert RESET\n"); - reg = 0; - reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */ - reg |= NSCU_GCRX_CXOE; /* active low */ - - PCMCIA_PGCRX(slot) = reg; - - udelay(10000); - - return (0); -} -#endif - -int pcmcia_voltage_set(int slot, int vcc, int vpp) -{ -#ifndef CONFIG_NSCU - u_long reg; -# ifdef DEBUG - volatile pcmconf8xx_t *pcmp = - (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia)); -# endif - - debug ("voltage_set: " PCMCIA_BOARD_MSG - " Slot %c, Vcc=%d.%d, Vpp=%d.%d\n", - 'A'+slot, vcc/10, vcc%10, vpp/10, vcc%10); - - /* - * Disable PCMCIA buffers (isolate the interface) - * and assert RESET signal - */ - debug ("Disable PCMCIA buffers and assert RESET\n"); - reg = PCMCIA_PGCRX(slot); - reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */ - reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */ - reg |= NSCU_GCRX_CXOE; /* active low */ - - PCMCIA_PGCRX(slot) = reg; - udelay(500); - - debug ("PCMCIA power OFF\n"); - power_config(slot); - power_off(slot); - - switch(vcc) { - case 0: break; - case 33: power_on_3_3(slot); break; - case 50: power_on_5_0(slot); break; - default: goto done; - } - - /* Checking supported voltages */ - - debug("PIPR: 0x%x --> %s\n", pcmp->pcmc_pipr, - (pcmp->pcmc_pipr & 0x00008000) ? "only 5 V" : "can do 3.3V"); - - if (vcc) - debug("PCMCIA powered at %sV\n", (vcc == 50) ? "5.0" : "3.3"); - else - debug("PCMCIA powered down\n"); - -done: - debug("Enable PCMCIA buffers and stop RESET\n"); - reg = PCMCIA_PGCRX(slot); - reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */ - reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */ - reg &= ~NSCU_GCRX_CXOE; /* active low */ - - PCMCIA_PGCRX(slot) = reg; - udelay(500); - - debug("voltage_set: " PCMCIA_BOARD_MSG " Slot %c, DONE\n", slot+'A'); -#endif /* CONFIG_NSCU */ - return (0); -} - -#endif /* CONFIG_PCMCIA && (CONFIG_TQM8xxL || CONFIG_SVM_SC8xx) */ -- cgit v1.2.3