Initial version of Cardbus support with the TI1225 Cardbus controler.
This commit is contained in:
parent
e44aaf4c37
commit
d65c8c116c
5 changed files with 778 additions and 0 deletions
|
@ -32,6 +32,7 @@ all install depend clean:
|
|||
cd ./sb16 && $(MAKE) $@
|
||||
cd ./lance && $(MAKE) $@
|
||||
cd ./pci && $(MAKE) $@
|
||||
cd ./ti1225 && $(MAKE) $@
|
||||
|
||||
image:
|
||||
cd ./libdriver && $(MAKE) build
|
||||
|
|
40
drivers/ti1225/Makefile
Normal file
40
drivers/ti1225/Makefile
Normal file
|
@ -0,0 +1,40 @@
|
|||
# Makefile for the Texas Instruments PCI1225 PC Card controller driver (ti1225)
|
||||
DRIVER = ti1225
|
||||
|
||||
# directories
|
||||
u = /usr
|
||||
i = $u/include
|
||||
s = $i/sys
|
||||
m = $i/minix
|
||||
b = $i/ibm
|
||||
d = ..
|
||||
|
||||
# programs, flags, etc.
|
||||
CC = exec cc
|
||||
CFLAGS = -I$i
|
||||
LDFLAGS = -i
|
||||
LIBS = -lsys -lsysutil -ltimers
|
||||
|
||||
OBJ = ti1225.o
|
||||
|
||||
# build local binary
|
||||
all build: $(DRIVER)
|
||||
$(DRIVER): $(OBJ)
|
||||
$(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBS)
|
||||
install -S 4096 $(DRIVER)
|
||||
|
||||
# install with other drivers
|
||||
install: /usr/sbin/$(DRIVER)
|
||||
/usr/sbin/$(DRIVER): $(DRIVER)
|
||||
install -o root -cs $? $@
|
||||
|
||||
# clean up local files
|
||||
clean:
|
||||
rm -f *.o *.bak $(DRIVER)
|
||||
|
||||
depend:
|
||||
/usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" *.c > .depend
|
||||
|
||||
# Include generated dependencies.
|
||||
include .depend
|
||||
|
167
drivers/ti1225/i82365.h
Normal file
167
drivers/ti1225/i82365.h
Normal file
|
@ -0,0 +1,167 @@
|
|||
/*
|
||||
i82365.h
|
||||
|
||||
Created: May 1995 by Philip Homburg <philip@cs.vu.nl>
|
||||
*/
|
||||
|
||||
#ifndef I82365_H
|
||||
#define I82365_H
|
||||
|
||||
/* The default I/O ports used by a i82365 are the following: */
|
||||
#define I365_INDEX 0x3E0
|
||||
#define I365_DATA 0x3E1
|
||||
|
||||
/* The index register is used to select one of the following registers: */
|
||||
#define I365_REVISION 0x00 /* IDREG */
|
||||
#define I365R_ID_MASK 0xC0
|
||||
#define I365R_ID_IO 0x00
|
||||
#define I365R_ID_MEM 0x40
|
||||
#define I365R_ID_MEM_IO 0x80
|
||||
#define I365R_RES_MASK 0x30
|
||||
#define I365R_REV_MASK 0x0F
|
||||
|
||||
#define I365_IF_STAT 0x01 /* ISTAT */
|
||||
#define I365IS_GPI 0x80
|
||||
#define CL6722IS_VPPVALID 0x80
|
||||
#define I365IS_POWER 0x40
|
||||
#define I365IS_READY 0x20
|
||||
#define I365IS_WRTPROT 0x10
|
||||
#define I365IS_CARD_MASK 0x0C
|
||||
#define I365IS_CARD_ABSENT 0x00
|
||||
#define I365IS_CARD_PART_0 0x04
|
||||
#define I365IS_CARD_PART_1 0x08
|
||||
#define I365IS_CARD_PRESENT 0x0C
|
||||
#define I365IS_BAT_MASK 0x03
|
||||
#define I365IS_BAT_LOST_0 0x00
|
||||
#define I365IS_BAT_LOW 0x01
|
||||
#define I365IS_BAT_LOST_1 0x02
|
||||
#define I365IS_BAT_OKAY 0x03
|
||||
|
||||
#define I365_PWR_CTL 0x02 /* PCTRL */
|
||||
#define I365PC_CARD_EN 0x80
|
||||
#define I365PC_NORESET 0x40
|
||||
#define CL6722PC_COMPAT_0 0x40
|
||||
#define I365PC_AUTO_PWR 0x20
|
||||
#define I365PC_Vcc_MASK 0x18
|
||||
#define I365PC_Vcc_NC 0x00
|
||||
#define I365PC_Vcc_Reserved 0x08
|
||||
#define I365PC_Vcc_5 0x10
|
||||
#define I365PC_Vcc_33 0x18
|
||||
#define CL6722PC_Vcc_PWR 0x10
|
||||
#define CL6722PC_COMPAT_1 0x08
|
||||
#define I365PC_Vpp_MASK 0x03
|
||||
#define I365PC_Vpp_NC 0x00
|
||||
#define CL6722PC_Vpp_ZERO_0 0x00
|
||||
#define I365PC_Vpp_5 0x01
|
||||
#define CL6722PC_Vpp_Vcc 0x01
|
||||
#define I365PC_Vpp_12 0x02
|
||||
#define I365PC_Vpp_Reserved 0x03
|
||||
#define CL6722PC_Vpp_ZERO_1 0x03
|
||||
|
||||
#define I365_INT_GEN_CTL 0x03
|
||||
#define I365IGC_RING_IND 0x80
|
||||
#define I365IGC_RESET 0x40
|
||||
#define I365IGC_CARD_IS_IO 0x20
|
||||
#define I365IGC_EN_MNG_INT 0x10
|
||||
#define I365IGC_IRQ_MASK 0x0F
|
||||
|
||||
#define I365_CRD_STAT_CHG 0x04 /* CSTCH */
|
||||
#define I365CSC_GPI 0x10
|
||||
#define I365CSC_CARD_DETECT 0x08
|
||||
#define I365CSC_READY 0x04
|
||||
#define I365CSC_BAT_WARN 0x02
|
||||
#define I365CSC_BAT_DEAD 0x01
|
||||
|
||||
#define I365_MNG_INT_CONF 0x05
|
||||
#define I365MIC_IRQ_MASK 0xF0
|
||||
#define I365MIC_CARD_DETECT 0x08
|
||||
#define I365MIC_READY 0x04
|
||||
#define I365MIC_BAT_WARN 0x02
|
||||
#define I365MIC_BAT_DEAD 0x01
|
||||
|
||||
#define I365_MAP_ENABLE 0x06 /* ADWEN */
|
||||
#define I365ME_IO_MAP_0 0x40
|
||||
#define I365ME_MEM_MAP_0 0x01
|
||||
|
||||
#define I365_IO_WND_CTL 0x07
|
||||
#define I365IWC_AUTO_1 0x80
|
||||
#define CL6722IWC_TIMING_1 0x80
|
||||
#define I365IWC_0WS_1 0x40
|
||||
#define I365IWC_AUTO_SIZE_1 0x20
|
||||
#define I365IWC_IO_SIZE_1 0x10
|
||||
#define I365IWC_WAIT_0 0x08
|
||||
#define I365IWC_0WS_0 0x04
|
||||
#define CL6722IWC_TIMING_0 0x08
|
||||
#define I365IWC_AUTO_SIZE_0 0x02
|
||||
#define I365IWC_IO_SIZE_0 0x01
|
||||
|
||||
#define I365_IO_0_START_LOW 0x08
|
||||
#define I365_IO_0_START_HIGH 0x09
|
||||
#define I365_IO_0_END_LOW 0x0A
|
||||
#define I365_IO_0_END_HIGH 0x0B
|
||||
#define I365_IO_1_START_LOW 0x0C
|
||||
#define I365_IO_1_START_HIGH 0x0D
|
||||
#define I365_IO_1_END_LOW 0x0E
|
||||
#define I365_IO_1_END_HIGH 0x0F
|
||||
|
||||
#define I365_MEM_0_START_LOW 0x10
|
||||
#define I365_MEM_0_START_HIGH 0x11
|
||||
#define I365_MEM_0_END_LOW 0x12
|
||||
#define I365_MEM_0_END_HIGH 0x13
|
||||
#define I365_MEM_0_OFF_LOW 0x14
|
||||
#define I365_MEM_0_OFF_HIGH 0x15
|
||||
|
||||
#define CL6722_MISC_CTL_1 0x16
|
||||
#define CL6722_FIFO_CTL 0x17
|
||||
|
||||
#define I365_MEM_1_START_LOW 0x18
|
||||
#define I365_MEM_1_START_HIGH 0x19
|
||||
#define I365_MEM_1_END_LOW 0x1A
|
||||
#define I365_MEM_1_END_HIGH 0x1B
|
||||
#define I365_MEM_1_OFF_LOW 0x1C
|
||||
#define I365_MEM_1_OFF_HIGH 0x1D
|
||||
|
||||
#define CL6722_MISC_CTL_2 0x1E
|
||||
#define CL6722_CHIP_INFO 0x1F
|
||||
#define CL6722CI_ID_MASK 0xC0
|
||||
|
||||
#define I365_MEM_2_START_LOW 0x20
|
||||
#define I365_MEM_2_START_HIGH 0x21
|
||||
#define I365_MEM_2_END_LOW 0x22
|
||||
#define I365_MEM_2_END_HIGH 0x23
|
||||
#define I365_MEM_2_OFF_LOW 0x24
|
||||
#define I365_MEM_2_OFF_HIGH 0x25
|
||||
|
||||
#define CL6722_ATA_CONTROL 0x26 /* CPAGE */
|
||||
#define I365_RESERVED 0x27
|
||||
|
||||
#define I365_MEM_3_START_LOW 0x28
|
||||
#define I365_MEM_3_START_HIGH 0x29
|
||||
#define I365_MEM_3_END_LOW 0x2A
|
||||
#define I365_MEM_3_END_HIGH 0x2B
|
||||
#define I365_MEM_3_OFF_LOW 0x2C
|
||||
#define I365_MEM_3_OFF_HIGH 0x2D
|
||||
|
||||
#define CL6722_EXT_INDEX 0x2E /* CSCTRL */
|
||||
#define CL6722_EXT_DATA 0x2F
|
||||
|
||||
#define I365_MEM_4_START_LOW 0x30
|
||||
#define I365_MEM_4_START_HIGH 0x31
|
||||
#define I365_MEM_4_END_LOW 0x32
|
||||
#define I365_MEM_4_END_HIGH 0x33
|
||||
#define I365_MEM_4_OFF_LOW 0x34
|
||||
#define I365_MEM_4_OFF_HIGH 0x35
|
||||
|
||||
#define CL6722_IO_0_OFF_LOW 0x36
|
||||
#define CL6722_IO_0_OFF_HIGH 0x37
|
||||
#define CL6722_IO_1_OFF_LOW 0x38
|
||||
#define CL6722_IO_1_OFF_HIGH 0x39
|
||||
|
||||
#define I365_SETUP_TIM_0 0x3A
|
||||
#define I365_CMD_TIM_0 0x3B
|
||||
#define I365_RECOV_TIM_0 0x3C
|
||||
#define I365_SETUP_TIM_1 0x3D
|
||||
#define I365_CMD_TIM_1 0x3E
|
||||
#define I365_RECOV_TIM_1 0x3F
|
||||
|
||||
#endif /* I82365_H */
|
499
drivers/ti1225/ti1225.c
Normal file
499
drivers/ti1225/ti1225.c
Normal file
|
@ -0,0 +1,499 @@
|
|||
/*
|
||||
ti1225.c
|
||||
|
||||
Created: Dec 2005 by Philip Homburg
|
||||
*/
|
||||
|
||||
#include "../drivers.h"
|
||||
#include <ibm/pci.h>
|
||||
#include <sys/vm.h>
|
||||
|
||||
#include "ti1225.h"
|
||||
#include "i82365.h"
|
||||
|
||||
/* The use of interrupts is not yet ready for prime time */
|
||||
#define USE_INTS 0
|
||||
|
||||
#define MICROS_TO_TICKS(m) (((m)*HZ/1000000)+1)
|
||||
|
||||
#define NR_PORTS 2
|
||||
|
||||
PRIVATE struct port
|
||||
{
|
||||
unsigned p_flags;
|
||||
int p_devind;
|
||||
u8_t p_cb_busnr;
|
||||
u16_t p_exca_port;
|
||||
#if USE_INTS
|
||||
int p_irq;
|
||||
int p_hook;
|
||||
#endif
|
||||
char *base_ptr;
|
||||
volatile struct csr *csr_ptr;
|
||||
|
||||
char buffer[2*PAGE_SIZE];
|
||||
} ports[NR_PORTS];
|
||||
|
||||
#define PF_PRESENT 1
|
||||
|
||||
struct pcitab
|
||||
{
|
||||
u16_t vid;
|
||||
u16_t did;
|
||||
int checkclass;
|
||||
};
|
||||
|
||||
PRIVATE struct pcitab pcitab_ti[]=
|
||||
{
|
||||
{ 0x104C, 0xAC1C, 0 }, /* TI PCI1225 */
|
||||
|
||||
{ 0x0000, 0x0000, 0 }
|
||||
};
|
||||
PRIVATE char *progname;
|
||||
PRIVATE int debug;
|
||||
|
||||
FORWARD _PROTOTYPE( void init, (void) );
|
||||
FORWARD _PROTOTYPE( void hw_init, (struct port *pp) );
|
||||
FORWARD _PROTOTYPE( void map_regs, (struct port *pp, u32_t base) );
|
||||
FORWARD _PROTOTYPE( void do_int, (struct port *pp) );
|
||||
FORWARD _PROTOTYPE( u8_t read_exca, (struct port *pp, int socket, int reg) );
|
||||
FORWARD _PROTOTYPE( void do_outb, (port_t port, u8_t value) );
|
||||
FORWARD _PROTOTYPE( u8_t do_inb, (port_t port) );
|
||||
FORWARD _PROTOTYPE( void micro_delay, (unsigned long usecs) );
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int c, r;
|
||||
message m;
|
||||
|
||||
(progname=strrchr(argv[0],'/')) ? progname++ : (progname=argv[0]);
|
||||
|
||||
debug= 0;
|
||||
while (c= getopt(argc, argv, "d?"), c != -1)
|
||||
{
|
||||
switch(c)
|
||||
{
|
||||
case '?': panic("ti1225", "Usage: ti1225 [-d]", NO_NUM);
|
||||
case 'd': debug++; break;
|
||||
default: panic("ti1225", "getopt failed", NO_NUM);
|
||||
}
|
||||
}
|
||||
|
||||
init();
|
||||
|
||||
for (;;)
|
||||
{
|
||||
r= receive(ANY, &m);
|
||||
if (r != OK)
|
||||
panic("ti1225", "receive failed", r);
|
||||
printf("ti1225: got message %u from %d\n",
|
||||
m.m_type, m.m_source);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
PRIVATE void init()
|
||||
{
|
||||
int i, r, first, devind, port;
|
||||
u16_t vid, did;
|
||||
|
||||
pci_init1(progname);
|
||||
|
||||
first= 1;
|
||||
port= 0;
|
||||
for (;;)
|
||||
{
|
||||
if (first)
|
||||
{
|
||||
first= 0;
|
||||
r= pci_first_dev(&devind, &vid, &did);
|
||||
}
|
||||
else
|
||||
r= pci_next_dev(&devind, &vid, &did);
|
||||
if (r != 1)
|
||||
break;
|
||||
|
||||
for (i= 0; pcitab_ti[i].vid != 0; i++)
|
||||
{
|
||||
if (pcitab_ti[i].vid != vid)
|
||||
continue;
|
||||
if (pcitab_ti[i].did != did)
|
||||
continue;
|
||||
if (pcitab_ti[i].checkclass)
|
||||
{
|
||||
panic("ti1225",
|
||||
"fxp_probe: class check not implemented",
|
||||
NO_NUM);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (pcitab_ti[i].vid == 0)
|
||||
continue;
|
||||
|
||||
pci_reserve(devind);
|
||||
|
||||
if (debug)
|
||||
printf("ti1225: found device %04x/%04x\n", vid, did);
|
||||
ports[port].p_devind= devind;
|
||||
ports[port].p_flags |= PF_PRESENT;
|
||||
port++;
|
||||
if (port >= NR_PORTS)
|
||||
break;
|
||||
}
|
||||
|
||||
for (i= 0; i<NR_PORTS; i++)
|
||||
{
|
||||
if (!(ports[i].p_flags & PF_PRESENT))
|
||||
continue;
|
||||
hw_init(&ports[i]);
|
||||
}
|
||||
}
|
||||
|
||||
PRIVATE void hw_init(pp)
|
||||
struct port *pp;
|
||||
{
|
||||
int i, r, devind, irq, socket;
|
||||
u8_t v8;
|
||||
u16_t v16;
|
||||
u32_t v32;
|
||||
|
||||
devind= pp->p_devind;
|
||||
if (debug)
|
||||
printf("hw_init: devind = %d\n", devind);
|
||||
|
||||
if (debug)
|
||||
{
|
||||
v16= pci_attr_r16(devind, PCI_CR);
|
||||
printf("ti1225: command register 0x%x\n", v16);
|
||||
}
|
||||
|
||||
v32= pci_attr_r32(devind, TI_CB_BASEADDR);
|
||||
if (debug)
|
||||
printf("ti1225: Cardbus/ExCA base address 0x%x\n", v32);
|
||||
map_regs(pp, v32);
|
||||
pp->csr_ptr= (struct csr *)pp->base_ptr;
|
||||
|
||||
if (debug)
|
||||
{
|
||||
v8= pci_attr_r8(devind, TI_PCI_BUS_NR);
|
||||
printf("ti1225: PCI bus number %d\n", v8);
|
||||
}
|
||||
v8= pci_attr_r8(devind, TI_CB_BUS_NR);
|
||||
pp->p_cb_busnr= v8;
|
||||
if (debug)
|
||||
{
|
||||
printf("ti1225: CardBus bus number %d\n", v8);
|
||||
v8= pci_attr_r8(devind, TI_SO_BUS_NR);
|
||||
printf("ti1225: Subordinate bus number %d\n", v8);
|
||||
}
|
||||
|
||||
#if USE_INTS
|
||||
irq= pci_attr_r8(devind, PCI_ILR);
|
||||
pp->p_irq= irq;
|
||||
printf("ti1225 using IRQ %d\n", irq);
|
||||
#endif
|
||||
|
||||
v32= pci_attr_r32(devind, TI_LEGACY_BA);
|
||||
v32 &= ~1;
|
||||
if (debug)
|
||||
{
|
||||
printf("ti1225: PC Card 16-bit legacy-mode base address 0x%x\n",
|
||||
v32);
|
||||
}
|
||||
|
||||
if (v32 == 0)
|
||||
panic("ti1225", "bad lagacy-mode base address 0x%x\n", v32);
|
||||
pp->p_exca_port= v32;
|
||||
|
||||
if (debug)
|
||||
{
|
||||
v32= pci_attr_r32(devind, TI_MF_ROUTE);
|
||||
printf("ti1225: Multifunction routing 0x%08x\n", v32);
|
||||
}
|
||||
|
||||
#if USE_INTS
|
||||
pp->p_hook = pp->p_irq;
|
||||
r= sys_irqsetpolicy(pp->p_irq, 0, &pp->p_hook);
|
||||
if (r != OK)
|
||||
panic("ti1225","sys_irqsetpolicy failed", r);
|
||||
#endif
|
||||
|
||||
/* Clear CBB_BC_INTEXCA */
|
||||
v16= pci_attr_r16(devind, CBB_BRIDGECTRL);
|
||||
if (debug)
|
||||
printf("ti1225: Bridge control 0x%04x\n", v16);
|
||||
v16 &= ~CBB_BC_INTEXCA;
|
||||
pci_attr_w16(devind, CBB_BRIDGECTRL, v16);
|
||||
|
||||
if (debug)
|
||||
{
|
||||
v32= pci_attr_r32(devind, TI_SYSCTRL);
|
||||
printf("ti1225: System Control Register 0x%08x\n", v32);
|
||||
|
||||
v8= pci_attr_r8(devind, TI_CARD_CTRL);
|
||||
printf("ti1225: Card Control 0x%02x\n", v8);
|
||||
|
||||
v8= pci_attr_r8(devind, TI_DEV_CTRL);
|
||||
printf("ti1225: Device Control 0x%02x\n", v8);
|
||||
}
|
||||
|
||||
/* Enable socket interrupts */
|
||||
pp->csr_ptr->csr_mask |= CM_PWRMASK | CM_CDMASK | CM_CSTSMASK;
|
||||
|
||||
do_int(pp);
|
||||
|
||||
#if USE_INTS
|
||||
r= sys_irqenable(&pp->p_hook);
|
||||
if (r != OK)
|
||||
panic("ti1225","unable enable interrupts", r);
|
||||
#endif
|
||||
}
|
||||
|
||||
PRIVATE void map_regs(pp, base)
|
||||
struct port *pp;
|
||||
u32_t base;
|
||||
{
|
||||
int r;
|
||||
vir_bytes buf_base;
|
||||
|
||||
buf_base= (vir_bytes)pp->buffer;
|
||||
if (buf_base % PAGE_SIZE)
|
||||
buf_base += PAGE_SIZE-(buf_base % PAGE_SIZE);
|
||||
pp->base_ptr= (char *)buf_base;
|
||||
if (debug)
|
||||
{
|
||||
printf("ti1225: map_regs: using %p for %p\n",
|
||||
pp->base_ptr, pp->buffer);
|
||||
}
|
||||
|
||||
/* Clear low order bits in base */
|
||||
base &= ~(u32_t)0xF;
|
||||
|
||||
r= sys_vm_map(SELF, 1 /* map */, (vir_bytes)pp->base_ptr,
|
||||
PAGE_SIZE, (phys_bytes)base);
|
||||
if (r != OK)
|
||||
panic("ti1225", "map_regs: sys_vm_map failed", r);
|
||||
}
|
||||
|
||||
PRIVATE void do_int(pp)
|
||||
struct port *pp;
|
||||
{
|
||||
int i, r, devind, vcc_5v, vcc_3v, vcc_Xv, vcc_Yv,
|
||||
socket_5v, socket_3v, socket_Xv, socket_Yv;
|
||||
clock_t t0, t1;
|
||||
u32_t csr_event, csr_present, csr_control;
|
||||
u8_t v8;
|
||||
u16_t v16;
|
||||
|
||||
devind= pp->p_devind;
|
||||
v8= pci_attr_r8(devind, TI_CARD_CTRL);
|
||||
if (v8 & TI_CCR_IFG)
|
||||
{
|
||||
printf("ti1225: got functional interrupt\n", v8);
|
||||
pci_attr_w8(devind, TI_CARD_CTRL, v8);
|
||||
}
|
||||
|
||||
if (debug)
|
||||
{
|
||||
printf("Socket event: 0x%x\n", pp->csr_ptr->csr_event);
|
||||
printf("Socket mask: 0x%x\n", pp->csr_ptr->csr_mask);
|
||||
}
|
||||
|
||||
csr_present= pp->csr_ptr->csr_present;
|
||||
csr_control= pp->csr_ptr->csr_control;
|
||||
|
||||
if ((csr_present & (CP_CDETECT1|CP_CDETECT2)) != 0)
|
||||
{
|
||||
if (debug)
|
||||
printf("do_int: no card present\n");
|
||||
return;
|
||||
}
|
||||
if (csr_present & CP_BADVCCREQ)
|
||||
{
|
||||
printf("do_int: Bad Vcc request\n");
|
||||
/* return; */
|
||||
}
|
||||
if (csr_present & CP_DATALOST)
|
||||
{
|
||||
/* Do we care? */
|
||||
if (debug)
|
||||
printf("do_int: Data lost\n");
|
||||
/* return; */
|
||||
}
|
||||
if (csr_present & CP_NOTACARD)
|
||||
{
|
||||
printf("do_int: Not a card\n");
|
||||
return;
|
||||
}
|
||||
if (debug)
|
||||
{
|
||||
if (csr_present & CP_CBCARD)
|
||||
printf("do_int: Cardbus card detected\n");
|
||||
if (csr_present & CP_16BITCARD)
|
||||
printf("do_int: 16-bit card detected\n");
|
||||
}
|
||||
if (csr_present & CP_PWRCYCLE)
|
||||
{
|
||||
if (debug)
|
||||
printf("do_int: powered up\n");
|
||||
return;
|
||||
}
|
||||
vcc_5v= !!(csr_present & CP_5VCARD);
|
||||
vcc_3v= !!(csr_present & CP_3VCARD);
|
||||
vcc_Xv= !!(csr_present & CP_XVCARD);
|
||||
vcc_Yv= !!(csr_present & CP_YVCARD);
|
||||
if (debug)
|
||||
{
|
||||
printf("do_int: card supports:%s%s%s%s\n",
|
||||
vcc_5v ? " 5V" : "", vcc_3v ? " 3V" : "",
|
||||
vcc_Xv ? " X.X V" : "", vcc_Yv ? " Y.Y V" : "");
|
||||
}
|
||||
socket_5v= !!(csr_present & CP_5VSOCKET);
|
||||
socket_3v= !!(csr_present & CP_3VSOCKET);
|
||||
socket_Xv= !!(csr_present & CP_XVSOCKET);
|
||||
socket_Yv= !!(csr_present & CP_YVSOCKET);
|
||||
if (debug)
|
||||
{
|
||||
printf("do_int: socket supports:%s%s%s%s\n",
|
||||
socket_5v ? " 5V" : "", socket_3v ? " 3V" : "",
|
||||
socket_Xv ? " X.X V" : "", socket_Yv ? " Y.Y V" : "");
|
||||
}
|
||||
if (vcc_5v && socket_5v)
|
||||
{
|
||||
csr_control= (csr_control & ~CC_VCCCTRL) | CC_VCC_5V;
|
||||
pp->csr_ptr->csr_control= csr_control;
|
||||
if (debug)
|
||||
printf("do_int: applying 5V\n");
|
||||
}
|
||||
else if (vcc_3v && socket_3v)
|
||||
{
|
||||
csr_control= (csr_control & ~CC_VCCCTRL) | CC_VCC_3V;
|
||||
pp->csr_ptr->csr_control= csr_control;
|
||||
if (debug)
|
||||
printf("do_int: applying 3V\n");
|
||||
}
|
||||
else if (vcc_Xv && socket_Xv)
|
||||
{
|
||||
csr_control= (csr_control & ~CC_VCCCTRL) | CC_VCC_XV;
|
||||
pp->csr_ptr->csr_control= csr_control;
|
||||
printf("do_int: applying X.X V\n");
|
||||
}
|
||||
else if (vcc_Yv && socket_Yv)
|
||||
{
|
||||
csr_control= (csr_control & ~CC_VCCCTRL) | CC_VCC_YV;
|
||||
pp->csr_ptr->csr_control= csr_control;
|
||||
printf("do_int: applying Y.Y V\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("do_int: socket and card are not compatible\n");
|
||||
return;
|
||||
}
|
||||
|
||||
csr_event= pp->csr_ptr->csr_event;
|
||||
if (csr_event)
|
||||
{
|
||||
if (debug)
|
||||
printf("clearing socket event\n");
|
||||
pp->csr_ptr->csr_event= csr_event;
|
||||
if (debug)
|
||||
{
|
||||
printf("Socket event (cleared): 0x%x\n",
|
||||
pp->csr_ptr->csr_event);
|
||||
}
|
||||
}
|
||||
|
||||
devind= pp->p_devind;
|
||||
v8= pci_attr_r8(devind, TI_CARD_CTRL);
|
||||
if (v8 & TI_CCR_IFG)
|
||||
{
|
||||
printf("ti1225: got functional interrupt\n", v8);
|
||||
pci_attr_w8(devind, TI_CARD_CTRL, v8);
|
||||
}
|
||||
|
||||
if (debug)
|
||||
{
|
||||
v8= pci_attr_r8(devind, TI_CARD_CTRL);
|
||||
printf("TI_CARD_CTRL: 0x%02x\n", v8);
|
||||
}
|
||||
|
||||
getuptime(&t0);
|
||||
do {
|
||||
csr_present= pp->csr_ptr->csr_present;
|
||||
if (csr_present & CP_PWRCYCLE)
|
||||
break;
|
||||
} while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(100000));
|
||||
|
||||
if (!(csr_present & CP_PWRCYCLE))
|
||||
{
|
||||
printf("do_int: not powered up?\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Reset device */
|
||||
v16= pci_attr_r16(devind, CBB_BRIDGECTRL);
|
||||
v16 |= CBB_BC_CRST;
|
||||
pci_attr_w16(devind, CBB_BRIDGECTRL, v16);
|
||||
|
||||
/* Wait one microsecond. Is this correct? What are the specs? */
|
||||
micro_delay(1);
|
||||
|
||||
/* Clear CBB_BC_CRST */
|
||||
v16= pci_attr_r16(devind, CBB_BRIDGECTRL);
|
||||
v16 &= ~CBB_BC_CRST;
|
||||
pci_attr_w16(devind, CBB_BRIDGECTRL, v16);
|
||||
|
||||
/* Wait one microsecond after clearing the reset line. Is this
|
||||
* correct? What are the specs?
|
||||
*/
|
||||
micro_delay(1);
|
||||
|
||||
pci_rescan_bus(pp->p_cb_busnr);
|
||||
|
||||
#if USE_INTS
|
||||
r= sys_irqenable(&pp->p_hook);
|
||||
if (r != OK)
|
||||
panic("ti1225","unable enable interrupts", r);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
PRIVATE u8_t read_exca(pp, socket, reg)
|
||||
struct port *pp;
|
||||
int socket;
|
||||
int reg;
|
||||
{
|
||||
u16_t port;
|
||||
|
||||
port= pp->p_exca_port;
|
||||
if (port == 0)
|
||||
panic("ti1225", "read_exca: bad port", NO_NUM);
|
||||
do_outb(port, socket * 0x40 + reg);
|
||||
return do_inb(port+1);
|
||||
}
|
||||
|
||||
PRIVATE u8_t do_inb(port_t port)
|
||||
{
|
||||
int r;
|
||||
u32_t value;
|
||||
|
||||
r= sys_inb(port, &value);
|
||||
if (r != OK)
|
||||
panic("ti1225","sys_inb failed", r);
|
||||
return value;
|
||||
}
|
||||
|
||||
PRIVATE void do_outb(port_t port, u8_t value)
|
||||
{
|
||||
int r;
|
||||
|
||||
r= sys_outb(port, value);
|
||||
if (r != OK)
|
||||
panic("ti1225","sys_outb failed", r);
|
||||
}
|
||||
|
||||
PRIVATE void micro_delay(unsigned long usecs)
|
||||
{
|
||||
tickdelay(MICROS_TO_TICKS(usecs));
|
||||
}
|
||||
|
71
drivers/ti1225/ti1225.h
Normal file
71
drivers/ti1225/ti1225.h
Normal file
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
ti1225.h
|
||||
|
||||
Created: Dec 2005 by Philip Homburg
|
||||
*/
|
||||
|
||||
/* PCI attribute space registers */
|
||||
#define TI_CB_BASEADDR 0x10
|
||||
#define TI_PCI_BUS_NR 0x18
|
||||
#define TI_CB_BUS_NR 0x19
|
||||
#define TI_SO_BUS_NR 0x1A
|
||||
#define TI_LEGACY_BA 0x44
|
||||
#define TI_SYSCTRL 0x80
|
||||
#define TI_MF_ROUTE 0x8C
|
||||
#define TI_CARD_CTRL 0x91
|
||||
#define TI_CCR_IFG 0x01
|
||||
#define TI_DEV_CTRL 0x92
|
||||
|
||||
/* CardBus Socket Registers */
|
||||
struct csr
|
||||
{
|
||||
/*00*/ u32_t csr_event;
|
||||
/*04*/ u32_t csr_mask;
|
||||
/*08*/ u32_t csr_present;
|
||||
/*0C*/ u32_t csr_force_event;
|
||||
/*10*/ u32_t csr_control;
|
||||
/*14*/ u32_t csr_res0;
|
||||
/*18*/ u32_t csr_res1;
|
||||
/*1C*/ u32_t csr_res2;
|
||||
/*20*/ u32_t csr_power;
|
||||
};
|
||||
|
||||
/* csr_mask */
|
||||
#define CM_PWRMASK 0x00000008
|
||||
#define CM_CDMASK 0x00000006
|
||||
#define CM_CSTSMASK 0x00000001
|
||||
|
||||
/* csr_present */
|
||||
#define CP_YVSOCKET 0x80000000
|
||||
#define CP_XVSOCKET 0x40000000
|
||||
#define CP_3VSOCKET 0x20000000
|
||||
#define CP_5VSOCKET 0x10000000
|
||||
#define CP_YVCARD 0x00002000
|
||||
#define CP_XVCARD 0x00001000
|
||||
#define CP_3VCARD 0x00000800
|
||||
#define CP_5VCARD 0x00000400
|
||||
#define CP_BADVCCREQ 0x00000200
|
||||
#define CP_DATALOST 0x00000100
|
||||
#define CP_NOTACARD 0x00000080
|
||||
#define CP_IREQCINT 0x00000040
|
||||
#define CP_CBCARD 0x00000020
|
||||
#define CP_16BITCARD 0x00000010
|
||||
#define CP_PWRCYCLE 0x00000008
|
||||
#define CP_CDETECT2 0x00000004
|
||||
#define CP_CDETECT1 0x00000002
|
||||
#define CP_CARDSTS 0x00000001
|
||||
|
||||
/* csr_control */
|
||||
#define CC_VCCCTRL 0x00000070
|
||||
#define CC_VCC_OFF 0x00000000
|
||||
#define CC_VCC_5V 0x00000020
|
||||
#define CC_VCC_3V 0x00000030
|
||||
#define CC_VCC_XV 0x00000040
|
||||
#define CC_VCC_YV 0x00000050
|
||||
#define CC_VPPCTRL 0x00000007
|
||||
#define CC_VPP_OFF 0x00000000
|
||||
#define CC_VPP_12V 0x00000001
|
||||
#define CC_VPP_5V 0x00000002
|
||||
#define CC_VPP_3V 0x00000003
|
||||
#define CC_VPP_XV 0x00000004
|
||||
#define CC_VPP_YV 0x00000005
|
Loading…
Reference in a new issue