Commit 4c4f9ecf authored by Russell King's avatar Russell King

Merge flint.arm.linux.org.uk:/usr/src/linux-bk-2.5/linux-2.5

into flint.arm.linux.org.uk:/usr/src/linux-bk-2.5/linux-2.5-rmk
parents c39e9205 3a630cb6
......@@ -682,7 +682,6 @@ comment 'Kernel hacking'
bool 'Compile kernel without frame pointer' CONFIG_NO_FRAME_POINTER
bool 'Verbose user fault messages' CONFIG_DEBUG_USER
bool 'Include debugging information in kernel binary' CONFIG_DEBUG_INFO
dep_bool 'Disable pgtable cache' CONFIG_NO_PGT_CACHE $CONFIG_CPU_26
bool 'Kernel debugging' CONFIG_DEBUG_KERNEL
dep_bool ' Debug memory allocations' CONFIG_DEBUG_SLAB $CONFIG_DEBUG_KERNEL
......
......@@ -167,10 +167,6 @@ EXPORT_SYMBOL(__virt_to_bus);
#endif
#ifndef __bus_to_virt__is_a_macro
EXPORT_SYMBOL(__bus_to_virt);
#endif
#ifndef CONFIG_NO_PGT_CACHE
EXPORT_SYMBOL(quicklists);
#endif
/* string / mem functions */
......
......@@ -95,9 +95,6 @@ void cpu_idle(void)
idle();
leds_event(led_idle_end);
schedule();
#ifndef CONFIG_NO_PGT_CACHE
check_pgt_cache();
#endif
}
}
......
......@@ -78,15 +78,16 @@ pgd_t *get_pgd_slow(struct mm_struct *mm)
if (!new_pmd)
goto no_pmd;
new_pte = pte_alloc(mm, new_pmd, 0);
new_pte = pte_alloc_map(mm, new_pmd, 0);
if (!new_pte)
goto no_pte;
init_pgd = pgd_offset_k(0);
init_pmd = pmd_offset(init_pgd, 0);
init_pte = pte_offset(init_pmd, 0);
init_pte = pte_offset_map_nested(init_pmd, 0);
set_pte(new_pte, *init_pte);
pte_unmap_nested(init_pte);
pte_unmap(new_pte);
/*
* most of the page table entries are zeroed
......
......@@ -32,67 +32,62 @@
* Handlers for GraphicsClient's external IRQ logic
*/
static void ADS_IRQ_demux( int irq, void *dev_id, struct pt_regs *regs )
static void
gc_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
{
int i;
unsigned int mask;
while ((mask = ADS_INT_ST1 | (ADS_INT_ST2 << 8))) {
/* clear the parent IRQ */
GEDR = GPIO_GPIO0;
while( (irq = ADS_INT_ST1 | (ADS_INT_ST2 << 8)) ){
for( i = 0; i < 16; i++ )
if( irq & (1<<i) )
do_IRQ( ADS_EXT_IRQ(i), regs );
irq = ADS_EXT_IRQ(0);
desc = irq_desc + irq;
do {
if (mask & 1)
desc->handle(irq, desc, regs);
mask >>= 1;
irq++;
desc++;
} while (mask);
}
}
static struct irqaction ADS_ext_irq = {
name: "ADS_ext_IRQ",
handler: ADS_IRQ_demux,
flags: SA_INTERRUPT
};
static void ADS_mask_and_ack_irq0(unsigned int irq)
static void gc_mask_irq1(unsigned int irq)
{
int mask = (1 << (irq - ADS_EXT_IRQ(0)));
ADS_INT_EN1 &= ~mask;
ADS_INT_ST1 = mask;
}
static void ADS_mask_irq0(unsigned int irq)
{
ADS_INT_ST1 = (1 << (irq - ADS_EXT_IRQ(0)));
}
static void ADS_unmask_irq0(unsigned int irq)
static void gc_unmask_irq1(unsigned int irq)
{
ADS_INT_EN1 |= (1 << (irq - ADS_EXT_IRQ(0)));
}
static struct irqchip ADS0_chip = {
ack: ADS_mask_and_ack_irq0,
mask: ADS_mask_irq0,
unmask: ADS_unmask_irq0,
static struct irqchip gc_irq1_chip = {
ack: gc_mask_irq1,
mask: gc_mask_irq1,
unmask: gc_unmask_irq1,
};
static void ADS_mask_and_ack_irq1(unsigned int irq)
static void gc_mask_irq2(unsigned int irq)
{
int mask = (1 << (irq - ADS_EXT_IRQ(8)));
ADS_INT_EN2 &= ~mask;
ADS_INT_ST2 = mask;
}
static void ADS_mask_irq1(unsigned int irq)
{
ADS_INT_ST2 = (1 << (irq - ADS_EXT_IRQ(8)));
}
static void ADS_unmask_irq1(unsigned int irq)
static void gc_unmask_irq2(unsigned int irq)
{
ADS_INT_EN2 |= (1 << (irq - ADS_EXT_IRQ(8)));
}
static struct irqchip ADS1_chip = {
ack: ADS_mask_and_ack_irq1,
mask: ADS_mask_irq1,
unmask: ADS_unmask_irq1,
static struct irqchip gc_irq2_chip = {
ack: gc_mask_irq2,
mask: gc_mask_irq2,
unmask: gc_unmask_irq2,
};
static void __init graphicsclient_init_irq(void)
......@@ -105,22 +100,23 @@ static void __init graphicsclient_init_irq(void)
/* disable all IRQs */
ADS_INT_EN1 = 0;
ADS_INT_EN2 = 0;
/* clear all IRQs */
ADS_INT_ST1 = 0xff;
ADS_INT_ST2 = 0xff;
for (irq = ADS_EXT_IRQ(0); irq <= ADS_EXT_IRQ(7); irq++) {
set_irq_chip(irq, &ADS0_chip);
set_irq_chip(irq, &gc_irq1_chip);
set_irq_handler(irq, do_level_IRQ);
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
}
for (irq = ADS_EXT_IRQ(8); irq <= ADS_EXT_IRQ(15); irq++) {
set_irq_chip(irq, &ADS1_chip);
set_irq_chip(irq, &gc_irq2_chip);
set_irq_handler(irq, do_level_IRQ);
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
}
set_GPIO_IRQ_edge(GPIO_GPIO0, GPIO_FALLING_EDGE);
setup_arm_irq( IRQ_GPIO0, &ADS_ext_irq );
set_irq_type(IRQ_GPIO0, IRQT_FALLING);
set_irq_chained_handler(IRQ_GPIO0, gc_irq_handler);
}
......@@ -148,111 +144,6 @@ static struct map_desc graphicsclient_io_desc[] __initdata = {
LAST_DESC
};
static struct gc_uart_ctrl_data_t gc_uart_ctrl_data[] = {
{ GPIO_GC_UART0_CTS, 0, NULL,NULL },
{ GPIO_GC_UART1_CTS, 0, NULL,NULL },
{ GPIO_GC_UART2_CTS, 0, NULL,NULL }
};
#error Old code. Someone needs to decide what to do with this
#if 0
static void
graphicsclient_cts_intr(int irq, void *dev_id, struct pt_regs *regs)
{
struct gc_uart_ctrl_data_t * uart_data = (struct gc_uart_ctrl_data_t *)dev_id;
int cts = !(GPLR & uart_data->cts_gpio);
/* NOTE: I supose that we will no get any interrupt
if the GPIO is not changed, so maybe
the cts_prev_state can be removed ... */
if (cts != uart_data->cts_prev_state) {
uart_data->cts_prev_state = cts;
uart_handle_cts_change(uart_data->info, cts);
}
}
static int
graphicsclient_register_cts_intr(int gpio, int irq,
struct gc_uart_ctrl_data_t *uart_data)
{
int ret = 0;
set_GPIO_IRQ_edge(gpio, GPIO_BOTH_EDGES);
ret = request_irq(irq, graphicsclient_cts_intr,
0, "GC RS232 CTS", uart_data);
if (ret) {
printk(KERN_ERR "uart_open: failed to register CTS irq (%d)\n",
ret);
free_irq(irq, uart_data);
}
return ret;
}
static int
graphicsclient_uart_open(struct uart_port *port, struct uart_info *info)
{
int ret = 0;
if (port->mapbase == _Ser1UTCR0) {
Ser1SDCR0 |= SDCR0_UART;
/* Set RTS Output */
GPSR = GPIO_GC_UART0_RTS;
gc_uart_ctrl_data[0].cts_prev_state = 0;
gc_uart_ctrl_data[0].info = info;
gc_uart_ctrl_data[0].port = port;
/* register uart0 CTS irq */
ret = graphicsclient_register_cts_intr(GPIO_GC_UART0_CTS,
IRQ_GC_UART0_CTS,
&gc_uart_ctrl_data[0]);
} else if (port->mapbase == _Ser2UTCR0) {
Ser2UTCR4 = Ser2HSCR0 = 0;
/* Set RTS Output */
GPSR = GPIO_GC_UART1_RTS;
gc_uart_ctrl_data[1].cts_prev_state = 0;
gc_uart_ctrl_data[1].info = info;
gc_uart_ctrl_data[1].port = port;
/* register uart1 CTS irq */
ret = graphicsclient_register_cts_intr(GPIO_GC_UART1_CTS,
IRQ_GC_UART1_CTS,
&gc_uart_ctrl_data[1]);
} else if (port->mapbase == _Ser3UTCR0) {
/* Set RTS Output */
GPSR = GPIO_GC_UART2_RTS;
gc_uart_ctrl_data[2].cts_prev_state = 0;
gc_uart_ctrl_data[2].info = info;
gc_uart_ctrl_data[2].port = port;
/* register uart2 CTS irq */
ret = graphicsclient_register_cts_intr(GPIO_GC_UART2_CTS,
IRQ_GC_UART2_CTS,
&gc_uart_ctrl_data[2]);
}
return ret;
}
static int
graphicsclient_uart_close(struct uart_port *port, struct uart_info *info)
{
if (port->mapbase == _Ser1UTCR0) {
free_irq(IRQ_GC_UART0_CTS, &gc_uart_ctrl_data[0]);
} else if (port->mapbase == _Ser2UTCR0) {
free_irq(IRQ_GC_UART1_CTS, &gc_uart_ctrl_data[1]);
} else if (port->mapbase == _Ser3UTCR0) {
free_irq(IRQ_GC_UART2_CTS, &gc_uart_ctrl_data[2]);
}
return 0;
}
#endif
static u_int graphicsclient_get_mctrl(struct uart_port *port)
{
u_int result = TIOCM_CD | TIOCM_DSR;
......
......@@ -93,68 +93,62 @@ __initcall(graphicsmaster_init);
* Handlers for GraphicsMaster's external IRQ logic
*/
static void ADS_IRQ_demux( int irq, void *dev_id, struct pt_regs *regs )
static void
gm_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
{
int i;
while( (irq = ADS_INT_ST1 | (ADS_INT_ST2 << 8)) ){
for( i = 0; i < 16; i++ )
if( irq & (1<<i) ) {
do_IRQ( ADS_EXT_IRQ(i), regs );
}
unsigned int mask;
while ((mask = ADS_INT_ST1 | (ADS_INT_ST2 << 8))) {
/* clear the parent IRQ */
GEDR = GPIO_GPIO0;
irq = ADS_EXT_IRQ(0);
desc = irq_desc + irq;
do {
if (mask & 1)
desc->handle(irq, desc, regs);
mask >>= 1;
irq++;
desc++;
} while (mask);
}
}
static struct irqaction ADS_ext_irq = {
name: "ADS_ext_IRQ",
handler: ADS_IRQ_demux,
flags: SA_INTERRUPT
};
static void ADS_mask_and_ack_irq0(unsigned int irq)
static void gm_mask_irq1(unsigned int irq)
{
int mask = (1 << (irq - ADS_EXT_IRQ(0)));
ADS_INT_EN1 &= ~mask;
ADS_INT_ST1 = mask;
}
static void ADS_mask_irq0(unsigned int irq)
{
ADS_INT_ST1 = (1 << (irq - ADS_EXT_IRQ(0)));
}
static void ADS_unmask_irq0(unsigned int irq)
static void gm_unmask_irq1(unsigned int irq)
{
ADS_INT_EN1 |= (1 << (irq - ADS_EXT_IRQ(0)));
}
static struct irqchip ADS0_chip = {
ack: ADS_mask_and_ack_irq0,
mask: ADS_mask_irq0,
unmask: ADS_unmask_irq0,
static struct irqchip gm_irq1_chip = {
ack: gm_mask_irq1,
mask: gm_mask_irq1,
unmask: gm_unmask_irq1,
};
static void ADS_mask_and_ack_irq1(unsigned int irq)
static void gm_mask_irq2(unsigned int irq)
{
int mask = (1 << (irq - ADS_EXT_IRQ(8)));
ADS_INT_EN2 &= ~mask;
ADS_INT_ST2 = mask;
}
static void ADS_mask_irq1(unsigned int irq)
{
ADS_INT_ST2 = (1 << (irq - ADS_EXT_IRQ(8)));
}
static void ADS_unmask_irq1(unsigned int irq)
static void gm_unmask_irq2(unsigned int irq)
{
ADS_INT_EN2 |= (1 << (irq - ADS_EXT_IRQ(8)));
}
static struct irqchip ADS1_chip = {
ack: ADS_mask_irq1,
mask: ADS_mask_irq1,
unmask: ADS_mask_irq1,
static struct irqchip gm_irq2_chip = {
ack: gm_mask_irq2,
mask: gm_mask_irq2,
unmask: gm_unmask_irq2,
};
static void __init graphicsmaster_init_irq(void)
......@@ -167,22 +161,23 @@ static void __init graphicsmaster_init_irq(void)
/* disable all IRQs */
ADS_INT_EN1 = 0;
ADS_INT_EN2 = 0;
/* clear all IRQs */
ADS_INT_ST1 = 0xff;
ADS_INT_ST2 = 0xff;
for (irq = ADS_EXT_IRQ(0); irq <= ADS_EXT_IRQ(7); irq++) {
set_irq_chip(irq, &ADS0_chip);
set_irq_chip(irq, &gm_irq1_chip);
set_irq_handler(irq, do_level_IRQ);
set_irq_flags(irq, IRQF_PROBE | IRQF_VALID);
}
for (irq = ADS_EXT_IRQ(8); irq <= ADS_EXT_IRQ(15); irq++) {
set_irq_chip(irq, &ADS1_chip);
set_irq_chip(irq, &gm_irq2_chip);
set_irq_handler(irq, do_level_IRQ);
set_irq_flags(irq, IRQF_PROBE | IRQF_VALID);
}
set_GPIO_IRQ_edge(GPIO_GPIO0, GPIO_FALLING_EDGE);
setup_arm_irq( IRQ_GPIO0, &ADS_ext_irq );
set_irq_type(IRQ_GPIO0, IRQT_FALLING);
set_irq_chained_handler(IRQ_GPIO0, gm_irq_handler);
}
......
......@@ -58,6 +58,7 @@
#include "generic.h"
#include "sa1111.h"
#include <asm/hardware/sa1111.h>
#define DEBUG 1
......@@ -74,19 +75,17 @@
/* init funcs */
static void __init fixup_system3(struct machine_desc *desc,
struct param_struct *params, char **cmdline, struct meminfo *mi);
static void __init get_system3_scr(void);
static int __init system3_init(void);
static void __init system3_init_irq(void);
static void __init system3_map_io(void);
static void system3_IRQ_demux( int irq, void *dev_id, struct pt_regs *regs );
static int system3_get_mctrl(struct uart_port *port);
static u_int system3_get_mctrl(struct uart_port *port);
static void system3_set_mctrl(struct uart_port *port, u_int mctrl);
static void system3_uart_pm(struct uart_port *port, u_int state, u_int oldstate);
static int sdram_notifier(struct notifier_block *nb, unsigned long event, void *data);
static int system3_lcd_power(int on);
static int system3_backlight_power(int on);
static void system3_lcd_power(int on);
static void system3_backlight_power(int on);
extern void convert_to_tag_list(struct param_struct *params, int mem_init);
......@@ -102,8 +101,8 @@ extern void convert_to_tag_list(struct param_struct *params, int mem_init);
static struct map_desc system3_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
{ 0xe8000000, 0x00000000, 0x01000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 0 */
{ 0xf3000000, 0x10000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* System Registers */
{ 0xf4000000, 0x40000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* SA-1111 */
{ 0xf3000000, PT_CPLD_BASE, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* System Registers */
{ 0xf4000000, PT_SA1111_BASE, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* SA-1111 */
LAST_DESC
};
......@@ -113,12 +112,6 @@ static struct sa1100_port_fns system3_port_fns __initdata = {
pm: system3_uart_pm,
};
static struct irqaction system3_irq = {
name: "PT Digital Board SA1111 IRQ",
handler: system3_IRQ_demux,
flags: SA_INTERRUPT
};
static struct notifier_block system3_clkchg_block = {
notifier_call: sdram_notifier,
};
......@@ -145,56 +138,82 @@ static void __init system3_map_io(void)
/*********************************************************************
* Install IRQ handler
*/
static void system3_IRQ_demux( int irq, void *dev_id, struct pt_regs *regs )
static void
system3_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
{
u_char irr;
for(;;){
//irr = PTCPLD_REG_IRQSR & (PT_IRQ_LAN | PT_IRQ_USAR | PT_IRQ_SA1111);
irr = PT_IRQSR & (PT_IRQ_LAN | PT_IRQ_SA1111);
//DPRINTK( "irq=%d, desc=%p, regs=%p\n", irq, desc, regs );
irr ^= (PT_IRQ_LAN);
if (!irr) break;
while (1) {
struct irqdesc *d;
if( irr & PT_IRQ_LAN )
do_IRQ(IRQ_SYSTEM3_SMC9196, regs);
/*
* Acknowledge the parent IRQ.
*/
desc->chip->ack(irq);
#if 0
/* Highspeed Serial Bus not yet used */
if( irr & PT_IRQ_USAR )
do_IRQ(PT_USAR_IRQ, regs);
#endif
/*
* Read the interrupt reason register. Let's have all
* active IRQ bits high. Note: there is a typo in the
* Neponset user's guide for the SA1111 IRR level.
*/
//irr = PT_IRQSR & (PT_IRR_LAN | PT_IRR_SA1111);
irr = PT_IRQSR & (PT_IRR_SA1111);
if( irr & PT_IRQ_SA1111 )
sa1111_IRQ_demux(irq, dev_id, regs);
}
}
/* SMC IRQ is low-active, so "switch" bit over */
//irr ^= (PT_IRR_LAN);
//DPRINTK( "irr=0x%02x\n", irr );
static void __init system3_init_irq(void)
{
int irq;
DPRINTK( "%s\n", "START" );
if ((irr & (PT_IRR_LAN | PT_IRR_SA1111)) == 0)
break;
/* SA1111 IRQ not routed to a GPIO. */
sa1111_init_irq(-1);
/*
* Since there is no individual mask, we have to
* mask the parent IRQ. This is safe, since we'll
* recheck the register for any pending IRQs.
*/
if (irr & (PT_IRR_LAN)) {
desc->chip->mask(irq);
/* setup extra IRQs */
irq = IRQ_SYSTEM3_SMC9196;
irq_desc[irq].valid = 1;
irq_desc[irq].probe_ok = 1;
if (irr & PT_IRR_LAN) {
//DPRINTK( "SMC9196, irq=%d\n", IRQ_SYSTEM3_SMC9196 );
d = irq_desc + IRQ_SYSTEM3_SMC9196;
d->handle(IRQ_SYSTEM3_SMC9196, d, regs);
}
#if 0
/* Highspeed Serial Bus not yet used */
irq = PT_USAR_IRQ;
irq_desc[irq].valid = 1;
irq_desc[irq].probe_ok = 1;
#if 0 /* no SSP yet on system 4 */
if (irr & IRR_USAR) {
d = irq_desc + IRQ_NEPONSET_USAR;
d->handle(IRQ_NEPONSET_USAR, d, regs);
}
#endif
/* IRQ by CPLD */
set_GPIO_IRQ_edge( GPIO_GPIO(25), GPIO_RISING_EDGE );
setup_arm_irq( IRQ_GPIO25, &system3_irq );
desc->chip->unmask(irq);
}
if (irr & PT_IRR_SA1111) {
//DPRINTK( "SA1111, irq=%d\n", IRQ_SYSTEM3_SA1111 );
d = irq_desc + IRQ_SYSTEM3_SA1111;
d->handle(IRQ_SYSTEM3_SA1111, d, regs);
}
}
}
static void __init system3_init_irq(void)
{
/*
* Install handler for GPIO25.
*/
set_irq_type(IRQ_GPIO25, IRQT_RISING);
set_irq_chained_handler(IRQ_GPIO25, system3_irq_handler);
/*
* install eth irq
*/
set_irq_handler(IRQ_SYSTEM3_SMC9196, do_simple_IRQ);
set_irq_flags(IRQ_SYSTEM3_SMC9196, IRQF_VALID | IRQF_PROBE);
}
/**********************************************************************
......@@ -270,7 +289,7 @@ static void system3_set_mctrl(struct uart_port *port, u_int mctrl)
}
}
static int system3_get_mctrl(struct uart_port *port)
static u_int system3_get_mctrl(struct uart_port *port)
{
u_int ret = 0;
u_int irqsr = PT_IRQSR;
......@@ -358,12 +377,8 @@ static void system3_lcd_brightness(unsigned char value)
static void system3_lcd_power(int on)
{
#error why is backlight stuff here???
if (on) {
system3_lcd_on();
system3_lcd_backlight_on();
system3_lcd_contrast(0x95);
system3_lcd_brightness(240);
} else {
system3_lcd_off();
}
......@@ -407,10 +422,12 @@ static int __init system3_init(void)
*/
sa1110_mb_disable();
system3_init_irq();
/*
* Probe for a SA1111.
*/
ret = sa1111_probe(0x40000000);
ret = sa1111_probe(PT_SA1111_BASE);
if (ret < 0) {
printk( KERN_WARNING"PT Digital Board: no SA1111 found!\n" );
goto DONE;
......@@ -443,7 +460,11 @@ static int __init system3_init(void)
*/
sa1110_mb_enable();
system3_init_irq();
/*
* Initialise SA1111 IRQs
*/
sa1111_init_irq(IRQ_SYSTEM3_SA1111);
#if defined( CONFIG_CPU_FREQ )
ret = cpufreq_register_notifier(&system3_clkchg_block);
......@@ -453,6 +474,7 @@ static int __init system3_init(void)
}
#endif
ret = 0;
DONE:
DPRINTK( "ret=%d\n", ret );
......
......@@ -151,7 +151,7 @@ static void adjust_pte(struct vm_area_struct *vma, unsigned long address)
if (pmd_bad(*pmd))
goto bad_pmd;
pte = pte_offset(pmd, address);
pte = pte_offset_map(pmd, address);
entry = *pte;
/*
......@@ -164,6 +164,7 @@ static void adjust_pte(struct vm_area_struct *vma, unsigned long address)
set_pte(pte, entry);
flush_tlb_page(vma, address);
}
pte_unmap(pte);
return;
bad_pgd:
......
......@@ -83,10 +83,14 @@ void show_pte(struct mm_struct *mm, unsigned long addr)
break;
}
pte = pte_offset(pmd, addr);
#ifndef CONFIG_HIGHMEM
/* We must not map this if we have highmem enabled */
pte = pte_offset_map(pmd, addr);
printk(", *pte = %08lx", pte_val(*pte));
#ifdef CONFIG_CPU_32
printk(", *ppte = %08lx", pte_val(pte[-PTRS_PER_PTE]));
#endif
pte_unmap(pte);
#endif
} while(0);
......
......@@ -64,38 +64,6 @@ static struct meminfo meminfo __initdata = { 0, };
*/
struct page *empty_zero_page;
#ifndef CONFIG_NO_PGT_CACHE
struct pgtable_cache_struct quicklists;
int do_check_pgt_cache(int low, int high)
{
int freed = 0;
if(pgtable_cache_size > high) {
do {
if(pgd_quicklist) {
free_pgd_slow(get_pgd_fast());
freed++;
}
if(pmd_quicklist) {
pmd_free_slow(pmd_alloc_one_fast(NULL, 0));
freed++;
}
if(pte_quicklist) {
pte_free_slow(pte_alloc_one_fast(NULL, 0));
freed++;
}
} while(pgtable_cache_size > low);
}
return freed;
}
#else
int do_check_pgt_cache(int low, int high)
{
return 0;
}
#endif
/* This is currently broken
* PG_skip is used on sparc/sparc64 architectures to "skip" certain
* parts of the address space.
......@@ -145,9 +113,6 @@ void show_mem(void)
printk("%d slab pages\n", slab);
printk("%d pages shared\n", shared);
printk("%d pages swap cached\n", cached);
#ifndef CONFIG_NO_PGT_CACHE
printk("%ld page tables cached\n", pgtable_cache_size);
#endif
show_buffers();
}
......
......@@ -58,7 +58,7 @@ static int __init minicache_init(void)
pmd = pmd_alloc(&init_mm, pgd, minicache_address);
if (!pmd)
BUG();
minicache_pte = pte_alloc(&init_mm, pmd, minicache_address);
minicache_pte = pte_alloc_kernel(&init_mm, pmd, minicache_address);
if (!minicache_pte)
BUG();
......
......@@ -98,11 +98,15 @@ pgd_t *get_pgd_slow(struct mm_struct *mm)
if (!new_pmd)
goto no_pmd;
new_pte = pte_alloc(mm, new_pmd, 0);
new_pte = pte_alloc_map(mm, new_pmd, 0);
if (!new_pte)
goto no_pte;
init_pmd = pmd_offset(init_pgd, 0);
init_pte = pte_offset_map_nested(init_pmd, 0);
set_pte(new_pte, *init_pte);
pte_unmap_nested(init_pte);
pte_unmap(new_pte);
spin_unlock(&mm->page_table_lock);
}
......@@ -138,7 +142,7 @@ pgd_t *get_pgd_slow(struct mm_struct *mm)
void free_pgd_slow(pgd_t *pgd)
{
pmd_t *pmd;
pte_t *pte;
struct page *pte;
if (!pgd)
return;
......@@ -153,7 +157,7 @@ void free_pgd_slow(pgd_t *pgd)
goto free;
}
pte = pte_offset(pmd, 0);
pte = pmd_page(*pmd);
pmd_clear(pmd);
pte_free(pte);
pmd_free(pmd);
......@@ -198,7 +202,7 @@ alloc_init_page(unsigned long virt, unsigned long phys, int domain, int prot)
set_pmd(pmdp, __mk_pmd(ptep, PMD_TYPE_TABLE | PMD_DOMAIN(domain)));
}
ptep = pte_offset(pmdp, virt);
ptep = pte_offset_kernel(pmdp, virt);
set_pte(ptep, mk_pte_phys(phys, __pgprot(prot)));
}
......@@ -225,6 +229,20 @@ static void __init create_mapping(struct map_desc *md)
int prot_sect, prot_pte;
long off;
if (md->prot_read && md->prot_write &&
!md->cacheable && !md->bufferable) {
printk(KERN_WARNING "Security risk: creating user "
"accessible mapping for 0x%08lx at 0x%08lx\n",
md->physical, md->virtual);
}
if (md->virtual != vectors_base() && md->virtual < PAGE_OFFSET) {
printk(KERN_WARNING "MM: not creating mapping for "
"0x%08lx at 0x%08lx in user region\n",
md->physical, md->virtual);
return;
}
prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
(md->prot_read ? L_PTE_USER : 0) |
(md->prot_write ? L_PTE_WRITE : 0) |
......
......@@ -663,8 +663,8 @@ cpu_manu_name:
cpu_80200_name:
.asciz "XScale-80200"
cpu_cotulla_name:
.asciz "XScale-Cotulla"
cpu_pxa250_name:
.asciz "XScale-PXA250"
.align
......@@ -734,11 +734,11 @@ cpu_80200_info:
.long cpu_80200_name
.size cpu_80200_info, . - cpu_80200_info
.type cpu_cotulla_info, #object
cpu_cotulla_info:
.type cpu_pxa250_info, #object
cpu_pxa250_info:
.long cpu_manu_name
.long cpu_cotulla_name
.size cpu_cotulla_info, . - cpu_cotulla_info
.long cpu_pxa250_name
.size cpu_pxa250_info, . - cpu_pxa250_info
.type cpu_arch_name, #object
cpu_arch_name:
......@@ -767,8 +767,8 @@ __80200_proc_info:
.long v4wbi_tlb_fns
.size __80200_proc_info, . - __80200_proc_info
.type __cotulla_proc_info,#object
__cotulla_proc_info:
.type __pxa250_proc_info,#object
__pxa250_proc_info:
.long 0x69052100
.long 0xfffffff0
.long 0x00000c0e
......@@ -776,8 +776,9 @@ __cotulla_proc_info:
.long cpu_arch_name
.long cpu_elf_name
.long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
.long cpu_cotulla_info
.long cpu_pxa250_info
.long xscale_processor_functions
.long v4wbi_tlb_fns
.size __cotulla_proc_info, . - __cotulla_proc_info
.size __pxa250_proc_info, . - __pxa250_proc_info
......@@ -24,5 +24,6 @@ if [ "$CONFIG_PCMCIA" != "n" ]; then
dep_tristate ' HD64465 host bridge support' CONFIG_HD64465_PCMCIA $CONFIG_PCMCIA
fi
fi
dep_tristate ' SA1100 support' CONFIG_PCMCIA_SA1100 $CONFIG_ARCH_SA1100 $CONFIG_PCMCIA
endmenu
......@@ -62,22 +62,24 @@ endif
obj-$(CONFIG_PCMCIA_SA1100) += sa1100_cs.o
sa1100_cs-objs-y := sa1100_generic.o
sa1100_cs-objs-$(CONFIG_SA1100_ADSBITSY) += sa1100_adsbitsy.o sa1111_generic.o
sa1100_cs-objs-$(CONFIG_SA1100_ASSABET) += sa1100_assabet.o
sa1100_cs-objs-$(CONFIG_ASSABET_NEPONSET) += sa1100_neponset.o
sa1100_cs-objs-$(CONFIG_SA1100_H3600) += sa1100_h3600.o
sa1100_cs-objs-$(CONFIG_ASSABET_NEPONSET) += sa1100_neponset.o sa1111_generic.o
sa1100_cs-objs-$(CONFIG_SA1100_BADGE4) += sa1100_badge4.o sa1111_generic.o
sa1100_cs-objs-$(CONFIG_SA1100_CERF) += sa1100_cerf.o
sa1100_cs-objs-$(CONFIG_SA1100_FLEXANET) += sa1100_flexanet.o
sa1100_cs-objs-$(CONFIG_SA1100_FREEBIRD) += sa1100_freebird.o
sa1100_cs-objs-$(CONFIG_SA1100_GRAPHICSMASTER) += sa1100_graphicsmaster.o sa1111_generic.o
sa1100_cs-objs-$(CONFIG_SA1100_GRAPHICSCLIENT) += sa1100_graphicsclient.o
sa1100_cs-objs-$(CONFIG_SA1100_XP860) += sa1100_xp860.o
sa1100_cs-objs-$(CONFIG_SA1100_H3600) += sa1100_h3600.o
sa1100_cs-objs-$(CONFIG_SA1100_JORNADA720) += sa1100_jornada720.o sa1111_generic.o
sa1100_cs-objs-$(CONFIG_SA1100_PANGOLIN) += sa1100_pangolin.o
sa1100_cs-objs-$(CONFIG_SA1100_YOPY) += sa1100_yopy.o
sa1100_cs-objs-$(CONFIG_SA1100_FREEBIRD) += sa1100_freebird.o
sa1100_cs-objs-$(CONFIG_SA1100_PFS168) += sa1100_pfs168.o
sa1100_cs-objs-$(CONFIG_SA1100_JORNADA720) += sa1100_jornada720.o
sa1100_cs-objs-$(CONFIG_SA1100_FLEXANET) += sa1100_flexanet.o
sa1100_cs-objs-$(CONFIG_SA1100_PFS168) += sa1100_pfs168.o sa1111_generic.o
sa1100_cs-objs-$(CONFIG_SA1100_SHANNON) += sa1100_shannon.o
sa1100_cs-objs-$(CONFIG_SA1100_SIMPAD) += sa1100_simpad.o
sa1100_cs-objs-$(CONFIG_SA1100_GRAPHICSMASTER) += sa1100_graphicsmaster.o
sa1100_cs-objs-$(CONFIG_SA1100_ADSBITSY) += sa1100_adsbitsy.o
sa1100_cs-objs-$(CONFIG_SA1100_STORK) += sa1100_stork.o
sa1100_cs-objs-$(CONFIG_SA1100_XP860) += sa1100_xp860.o sa1111_generic.o
sa1100_cs-objs-$(CONFIG_SA1100_YOPY) += sa1100_yopy.o
include $(TOPDIR)/Rules.make
......@@ -85,7 +87,7 @@ pcmcia_core.o: $(pcmcia_core-objs)
$(LD) $(LD_RFLAG) -r -o $@ $(pcmcia_core-objs)
sa1100_cs.o: $(sa1100_cs-objs-y)
$(LD) -r -o $@ $(sa1100_cs-objs-y)
$(LD) -r -o $@ $(sort $(sa1100_cs-objs-y))
yenta_socket.o: $(yenta_socket-objs)
$(LD) $(LD_RFLAG) -r -o $@ $(yenta_socket-objs)
......@@ -38,9 +38,7 @@
#include <pcmcia/bulkmem.h>
#include <pcmcia/cistpl.h>
#include "cs_internal.h"
#include <asm/arch/pcmcia.h>
#include "sa1100_generic.h"
/* MECR: Expansion Memory Configuration Register
* (SA-1100 Developers Manual, p.10-13; SA-1110 Developers Manual, p.10-24)
......@@ -157,15 +155,24 @@ static inline unsigned int sa1100_pcmcia_cmd_time(unsigned int cpu_clock_khz,
* use when responding to a Card Services query of some kind.
*/
struct sa1100_pcmcia_socket {
/*
* Core PCMCIA state
*/
socket_state_t cs_state;
struct pcmcia_state k_state;
unsigned int irq;
void (*handler)(void *, unsigned int);
void *handler_info;
pccard_io_map io_map[MAX_IO_WIN];
pccard_mem_map mem_map[MAX_WIN];
ioaddr_t virt_io, phys_attr, phys_mem;
void (*handler)(void *, unsigned int);
void *handler_info;
struct pcmcia_state k_state;
ioaddr_t phys_attr, phys_mem;
void *virt_io;
unsigned short speed_io, speed_attr, speed_mem;
/*
* Info from low level handler
*/
unsigned int irq;
};
......@@ -180,23 +187,57 @@ struct sa1100_pcmcia_socket {
/*
* Declaration for all implementation specific low_level operations.
* Declaration for all machine specific init/exit functions.
*/
extern struct pcmcia_low_level assabet_pcmcia_ops;
extern struct pcmcia_low_level neponset_pcmcia_ops;
extern struct pcmcia_low_level h3600_pcmcia_ops;
extern struct pcmcia_low_level cerf_pcmcia_ops;
extern struct pcmcia_low_level gcplus_pcmcia_ops;
extern struct pcmcia_low_level xp860_pcmcia_ops;
extern struct pcmcia_low_level yopy_pcmcia_ops;
extern struct pcmcia_low_level pangolin_pcmcia_ops;
extern struct pcmcia_low_level freebird_pcmcia_ops;
extern struct pcmcia_low_level pfs168_pcmcia_ops;
extern struct pcmcia_low_level jornada720_pcmcia_ops;
extern struct pcmcia_low_level flexanet_pcmcia_ops;
extern struct pcmcia_low_level simpad_pcmcia_ops;
extern struct pcmcia_low_level graphicsmaster_pcmcia_ops;
extern struct pcmcia_low_level adsbitsy_pcmcia_ops;
extern struct pcmcia_low_level stork_pcmcia_ops;
extern int pcmcia_adsbitsy_init(void);
extern void pcmcia_adsbitsy_exit(void);
extern int pcmcia_assabet_init(void);
extern void pcmcia_assabet_exit(void);
extern int pcmcia_badge4_init(void);
extern void pcmcia_badge4_exit(void);
extern int pcmcia_cerf_init(void);
extern void pcmcia_cerf_exit(void);
extern int pcmcia_flexanet_init(void);
extern void pcmcia_flexanet_exit(void);
extern int pcmcia_freebird_init(void);
extern void pcmcia_freebird_exit(void);
extern int pcmcia_gcplus_init(void);
extern void pcmcia_gcplus_exit(void);
extern int pcmcia_graphicsmaster_init(void);
extern void pcmcia_graphicsmaster_exit(void);
extern int pcmcia_jornada720_init(void);
extern void pcmcia_jornada720_exit(void);
extern int pcmcia_neponset_init(void);
extern void pcmcia_neponset_exit(void);
extern int pcmcia_pangolin_init(void);
extern void pcmcia_pangolin_exit(void);
extern int pcmcia_pfs168_init(void);
extern void pcmcia_pfs168_exit(void);
extern int pcmcia_shannon_init(void);
extern void pcmcia_shannon_exit(void);
extern int pcmcia_simpad_init(void);
extern void pcmcia_simpad_exit(void);
extern int pcmcia_stork_init(void);
extern void pcmcia_stork_exit(void);
extern int pcmcia_xp860_init(void);
extern void pcmcia_xp860_exit(void);
extern int pcmcia_yopy_init(void);
extern void pcmcia_yopy_exit(void);
#endif /* !defined(_PCMCIA_SA1100_H) */
......@@ -11,206 +11,97 @@
*/
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <asm/delay.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/arch/pcmcia.h>
#include "sa1100_generic.h"
#include "sa1111_generic.h"
static int adsbitsy_pcmcia_init(struct pcmcia_init *init)
{
int return_val=0;
/* Set GPIO_A<3:0> to be outputs for PCMCIA/CF power controller: */
PA_DDR &= ~(GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3);
/* Disable Power 3.3V/5V for PCMCIA/CF */
PA_DWR |= GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3;
INTPOL1 |= (1 << (S0_READY_NINT - SA1111_IRQ(32))) |
(1 << (S1_READY_NINT - SA1111_IRQ(32))) |
(1 << (S0_CD_VALID - SA1111_IRQ(32))) |
(1 << (S1_CD_VALID - SA1111_IRQ(32))) |
(1 << (S0_BVD1_STSCHG - SA1111_IRQ(32))) |
(1 << (S1_BVD1_STSCHG - SA1111_IRQ(32)));
return_val+=request_irq(S0_CD_VALID, init->handler, SA_INTERRUPT,
"GC Master PCMCIA (0) CD", NULL);
return_val+=request_irq(S1_CD_VALID, init->handler, SA_INTERRUPT,
"GC Master CF (1) CD", NULL);
return_val+=request_irq(S0_BVD1_STSCHG, init->handler, SA_INTERRUPT,
"GC Master PCMCIA (0) BVD1", NULL);
return_val+=request_irq(S1_BVD1_STSCHG, init->handler, SA_INTERRUPT,
"GC Master CF (1) BVD1", NULL);
/* Why? */
MECR = 0x09430943;
return (return_val<0) ? -1 : 2;
}
static int adsbitsy_pcmcia_shutdown(void)
{
free_irq(S0_CD_VALID, NULL);
free_irq(S1_CD_VALID, NULL);
free_irq(S0_BVD1_STSCHG, NULL);
free_irq(S1_BVD1_STSCHG, NULL);
INTPOL1 &= ~((1 << (S0_CD_VALID - SA1111_IRQ(32))) |
(1 << (S1_CD_VALID - SA1111_IRQ(32))) |
(1 << (S0_BVD1_STSCHG - SA1111_IRQ(32))) |
(1 << (S1_BVD1_STSCHG - SA1111_IRQ(32))));
return 0;
return sa1111_pcmcia_init(init);
}
static int adsbitsy_pcmcia_socket_state(struct pcmcia_state_array *state_array)
static int
adsbitsy_pcmcia_configure_socket(const struct pcmcia_configure *conf)
{
unsigned long status;
int return_val=1;
if(state_array->size<2) return -1;
memset(state_array->state, 0,
(state_array->size)*sizeof(struct pcmcia_state));
status=PCSR;
state_array->state[0].detect=((status & PCSR_S0_DETECT)==0)?1:0;
state_array->state[0].ready=((status & PCSR_S0_READY)==0)?0:1;
state_array->state[0].bvd1=((status & PCSR_S0_BVD1)==0)?0:1;
state_array->state[0].bvd2=((status & PCSR_S0_BVD2)==0)?0:1;
state_array->state[0].wrprot=((status & PCSR_S0_WP)==0)?0:1;
state_array->state[0].vs_3v=((status & PCSR_S0_VS1)==0)?1:0;
unsigned int pa_dwr_mask, pa_dwr_set;
int ret;
state_array->state[0].vs_Xv=((status & PCSR_S0_VS2)==0)?1:0;
state_array->state[1].detect=((status & PCSR_S1_DETECT)==0)?1:0;
state_array->state[1].ready=((status & PCSR_S1_READY)==0)?0:1;
state_array->state[1].bvd1=((status & PCSR_S1_BVD1)==0)?0:1;
state_array->state[1].bvd2=((status & PCSR_S1_BVD2)==0)?0:1;
state_array->state[1].wrprot=((status & PCSR_S1_WP)==0)?0:1;
state_array->state[1].vs_3v=((status & PCSR_S1_VS1)==0)?1:0;
state_array->state[1].vs_Xv=((status & PCSR_S1_VS2)==0)?1:0;
return return_val;
}
static int adsbitsy_pcmcia_get_irq_info(struct pcmcia_irq_info *info)
{
switch(info->sock){
switch (conf->sock) {
case 0:
info->irq=S0_READY_NINT;
break;
case 1:
info->irq=S1_READY_NINT;
break;
pa_dwr_mask = GPIO_GPIO0 | GPIO_GPIO1;
switch (conf->vcc) {
default:
return -1;
case 0: pa_dwr_set = GPIO_GPIO0 | GPIO_GPIO1; break;
case 33: pa_dwr_set = GPIO_GPIO1; break;
case 50: pa_dwr_set = GPIO_GPIO0; break;
}
return 0;
}
static int adsbitsy_pcmcia_configure_socket(const struct pcmcia_configure *configure)
{
unsigned long pccr=PCCR, gpio=PA_DWR;
switch(configure->sock){
case 0:
switch(configure->vcc){
case 0:
pccr = (pccr & ~PCCR_S0_FLT);
gpio |= GPIO_GPIO0 | GPIO_GPIO1;
break;
case 33:
pccr = (pccr & ~PCCR_S0_PSE) | PCCR_S0_FLT | PCCR_S0_PWAITEN;
gpio &= ~(GPIO_GPIO0 | GPIO_GPIO1);
gpio &= ~GPIO_GPIO0;
break;
case 50:
pccr = (pccr | PCCR_S0_PSE | PCCR_S0_FLT | PCCR_S0_PWAITEN);
gpio &= ~(GPIO_GPIO0 | GPIO_GPIO1);
gpio |= GPIO_GPIO0;
break;
case 1:
pa_dwr_mask = GPIO_GPIO2 | GPIO_GPIO3;
switch (conf->vcc) {
default:
printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
configure->vcc);
return -1;
case 0: pa_dwr_set = 0; break;
case 33: pa_dwr_set = GPIO_GPIO2; break;
case 50: pa_dwr_set = GPIO_GPIO3; break;
}
pccr=(configure->reset)?(pccr | PCCR_S0_RST):(pccr & ~PCCR_S0_RST);
break;
case 1:
switch(configure->vcc){
case 0:
pccr = (pccr & ~PCCR_S1_FLT);
gpio &= ~(GPIO_GPIO2 | GPIO_GPIO3);
break;
case 33:
pccr = (pccr & ~PCCR_S1_PSE) | PCCR_S1_FLT | PCCR_S1_PWAITEN;
gpio &= ~(GPIO_GPIO2 | GPIO_GPIO3);
gpio |= GPIO_GPIO2;
break;
case 50:
pccr = (pccr | PCCR_S1_PSE | PCCR_S1_FLT | PCCR_S1_PWAITEN);
gpio &= ~(GPIO_GPIO2 | GPIO_GPIO3);
gpio |= GPIO_GPIO3;
break;
default:
printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
configure->vcc);
return -1;
}
if(configure->vpp!=configure->vcc && configure->vpp!=0){
printk(KERN_ERR "%s(): CF slot cannot support Vpp %u\n", __FUNCTION__,
configure->vpp);
if (conf->vpp != conf->vcc && conf->vpp != 0) {
printk(KERN_ERR "%s(): CF slot cannot support VPP %u\n",
__FUNCTION__, conf->vpp);
return -1;
}
pccr=(configure->reset)?(pccr | PCCR_S1_RST):(pccr & ~PCCR_S1_RST);
break;
ret = sa1111_pcmcia_configure_socket(conf);
if (ret == 0) {
unsigned long flags;
default:
return -1;
local_irq_save(flags);
PA_DWR = (PA_DWR & ~pa_dwr_mask) | pa_dwr_set;
local_irq_restore(flags);
}
PCCR = pccr;
PA_DWR = gpio;
return 0;
return ret;
}
struct pcmcia_low_level adsbitsy_pcmcia_ops = {
adsbitsy_pcmcia_init,
adsbitsy_pcmcia_shutdown,
adsbitsy_pcmcia_socket_state,
adsbitsy_pcmcia_get_irq_info,
adsbitsy_pcmcia_configure_socket
static struct pcmcia_low_level adsbitsy_pcmcia_ops = {
init: adsbitsy_pcmcia_init,
shutdown: sa1111_pcmcia_shutdown,
socket_state: sa1111_pcmcia_socket_state,
get_irq_info: sa1111_pcmcia_get_irq_info,
configure_socket: adsbitsy_pcmcia_configure_socket,
socket_init: sa1111_pcmcia_socket_init,
socket_suspend: sa1111_pcmcia_socket_suspend,
};
int __init pcmcia_adsbitsy_init(void)
{
int ret = -ENODEV;
if (machine_is_adsbitsy())
ret = sa1100_register_pcmcia(&adsbitsy_pcmcia_ops);
return ret;
}
void __exit pcmcia_adsbitsy_exit(void)
{
sa1100_unregister_pcmcia(&adsbitsy_pcmcia_ops);
}
......@@ -4,113 +4,114 @@
* PCMCIA implementation routines for Assabet
*
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/arch/pcmcia.h>
#include <asm/arch/assabet.h>
static int assabet_pcmcia_init(struct pcmcia_init *init){
int irq, res;
#include "sa1100_generic.h"
/* Enable CF bus: */
ASSABET_BCR_clear(ASSABET_BCR_CF_BUS_OFF);
static struct irqs {
int irq;
const char *str;
} irqs[] = {
{ ASSABET_IRQ_GPIO_CF_CD, "CF_CD" },
{ ASSABET_IRQ_GPIO_CF_BVD2, "CF_BVD2" },
{ ASSABET_IRQ_GPIO_CF_BVD1, "CF_BVD1" },
};
/* All those are inputs */
GPDR &= ~(ASSABET_GPIO_CF_CD | ASSABET_GPIO_CF_BVD2 | ASSABET_GPIO_CF_BVD1 | ASSABET_GPIO_CF_IRQ);
static int assabet_pcmcia_init(struct pcmcia_init *init)
{
int i, res;
/* Set transition detect */
set_GPIO_IRQ_edge( ASSABET_GPIO_CF_CD|ASSABET_GPIO_CF_BVD2|ASSABET_GPIO_CF_BVD1, GPIO_BOTH_EDGES );
set_GPIO_IRQ_edge( ASSABET_GPIO_CF_IRQ, GPIO_FALLING_EDGE );
set_irq_type(ASSABET_IRQ_GPIO_CF_IRQ, IRQT_FALLING);
/* Register interrupts */
irq = ASSABET_IRQ_GPIO_CF_CD;
res = request_irq( irq, init->handler, SA_INTERRUPT, "CF_CD", NULL );
if( res < 0 ) goto irq_err;
irq = ASSABET_IRQ_GPIO_CF_BVD2;
res = request_irq( irq, init->handler, SA_INTERRUPT, "CF_BVD2", NULL );
if( res < 0 ) goto irq_err;
irq = ASSABET_IRQ_GPIO_CF_BVD1;
res = request_irq( irq, init->handler, SA_INTERRUPT, "CF_BVD1", NULL );
if( res < 0 ) goto irq_err;
for (i = 0; i < ARRAY_SIZE(irqs); i++) {
set_irq_type(irqs[i].irq, IRQT_NOEDGE);
res = request_irq(irqs[i].irq, init->handler, SA_INTERRUPT,
irqs[i].str, NULL);
if (res)
goto irq_err;
}
/* There's only one slot, but it's "Slot 1": */
return 2;
irq_err:
printk( KERN_ERR "%s: Request for IRQ %u failed\n", __FUNCTION__, irq );
return -1;
irq_err:
printk(KERN_ERR "%s: request for IRQ%d failed (%d)\n",
__FUNCTION__, irqs[i].irq, res);
while (i--)
free_irq(irqs[i].irq, NULL);
return res;
}
/*
* Release all resources.
*/
static int assabet_pcmcia_shutdown(void)
{
/* disable IRQs */
free_irq( ASSABET_IRQ_GPIO_CF_CD, NULL );
free_irq( ASSABET_IRQ_GPIO_CF_BVD2, NULL );
free_irq( ASSABET_IRQ_GPIO_CF_BVD1, NULL );
int i;
/* Disable CF bus: */
ASSABET_BCR_set(ASSABET_BCR_CF_BUS_OFF);
for (i = 0; i < ARRAY_SIZE(irqs); i++)
free_irq(irqs[i].irq, NULL);
return 0;
}
static int assabet_pcmcia_socket_state(struct pcmcia_state_array
*state_array){
static int
assabet_pcmcia_socket_state(struct pcmcia_state_array *state_array)
{
unsigned long levels;
if(state_array->size<2) return -1;
memset(state_array->state, 0,
(state_array->size)*sizeof(struct pcmcia_state));
levels=GPLR;
state_array->state[1].detect=((levels & ASSABET_GPIO_CF_CD)==0)?1:0;
state_array->state[1].ready=(levels & ASSABET_GPIO_CF_IRQ)?1:0;
state_array->state[1].bvd1=(levels & ASSABET_GPIO_CF_BVD1)?1:0;
state_array->state[1].bvd2=(levels & ASSABET_GPIO_CF_BVD2)?1:0;
state_array->state[1].wrprot=0; /* Not available on Assabet. */
if (state_array->size < 2)
return -1;
state_array->state[1].vs_3v=1; /* Can only apply 3.3V on Assabet. */
levels = GPLR;
state_array->state[1].vs_Xv=0;
state_array->state[1].detect = (levels & ASSABET_GPIO_CF_CD) ? 0 : 1;
state_array->state[1].ready = (levels & ASSABET_GPIO_CF_IRQ) ? 1 : 0;
state_array->state[1].bvd1 = (levels & ASSABET_GPIO_CF_BVD1) ? 1 : 0;
state_array->state[1].bvd2 = (levels & ASSABET_GPIO_CF_BVD2) ? 1 : 0;
state_array->state[1].wrprot = 0; /* Not available on Assabet. */
state_array->state[1].vs_3v = 1; /* Can only apply 3.3V on Assabet. */
state_array->state[1].vs_Xv = 0;
return 1;
}
static int assabet_pcmcia_get_irq_info(struct pcmcia_irq_info *info){
if(info->sock>1) return -1;
static int assabet_pcmcia_get_irq_info(struct pcmcia_irq_info *info)
{
if (info->sock > 1)
return -1;
if(info->sock==1)
info->irq=ASSABET_IRQ_GPIO_CF_IRQ;
if (info->sock == 1)
info->irq = ASSABET_IRQ_GPIO_CF_IRQ;
return 0;
}
static int assabet_pcmcia_configure_socket(const struct pcmcia_configure
*configure)
static int
assabet_pcmcia_configure_socket(const struct pcmcia_configure *configure)
{
unsigned long value, flags;
if(configure->sock>1) return -1;
if(configure->sock==0) return 0;
unsigned int mask;
save_flags_cli(flags);
if (configure->sock > 1)
return -1;
value = BCR_value;
if (configure->sock == 0)
return 0;
switch(configure->vcc){
switch (configure->vcc) {
case 0:
value &= ~ASSABET_BCR_CF_PWR;
mask = 0;
break;
case 50:
......@@ -118,32 +119,106 @@ static int assabet_pcmcia_configure_socket(const struct pcmcia_configure
__FUNCTION__);
case 33: /* Can only apply 3.3V to the CF slot. */
value |= ASSABET_BCR_CF_PWR;
mask = ASSABET_BCR_CF_PWR;
break;
default:
printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
configure->vcc);
restore_flags(flags);
return -1;
}
value = (configure->reset) ? (value | ASSABET_BCR_CF_RST) : (value & ~ASSABET_BCR_CF_RST);
/* Silently ignore Vpp, output enable, speaker enable. */
ASSABET_BCR = BCR_value = value;
if (configure->reset)
mask |= ASSABET_BCR_CF_RST;
restore_flags(flags);
ASSABET_BCR_frob(ASSABET_BCR_CF_RST | ASSABET_BCR_CF_PWR, mask);
/*
* Handle suspend mode properly. This prevents a
* flood of IRQs from the CF device.
*/
if (configure->irq)
enable_irq(ASSABET_IRQ_GPIO_CF_IRQ);
else
disable_irq(ASSABET_IRQ_GPIO_CF_IRQ);
return 0;
}
struct pcmcia_low_level assabet_pcmcia_ops = {
assabet_pcmcia_init,
assabet_pcmcia_shutdown,
assabet_pcmcia_socket_state,
assabet_pcmcia_get_irq_info,
assabet_pcmcia_configure_socket
/*
* Enable card status IRQs on (re-)initialisation. This can
* be called at initialisation, power management event, or
* pcmcia event.
*/
static int assabet_pcmcia_socket_init(int sock)
{
int i;
if (sock == 1) {
/*
* Enable CF bus
*/
ASSABET_BCR_clear(ASSABET_BCR_CF_BUS_OFF);
for (i = 0; i < ARRAY_SIZE(irqs); i++)
set_irq_type(irqs[i].irq, IRQT_BOTHEDGE);
}
return 0;
}
/*
* Disable card status IRQs on suspend.
*/
static int assabet_pcmcia_socket_suspend(int sock)
{
int i;
if (sock == 1) {
for (i = 0; i < ARRAY_SIZE(irqs); i++)
set_irq_type(irqs[i].irq, IRQT_NOEDGE);
/*
* Tristate the CF bus signals. Also assert CF
* reset as per user guide page 4-11.
*/
ASSABET_BCR_set(ASSABET_BCR_CF_BUS_OFF | ASSABET_BCR_CF_RST);
}
return 0;
}
static struct pcmcia_low_level assabet_pcmcia_ops = {
init: assabet_pcmcia_init,
shutdown: assabet_pcmcia_shutdown,
socket_state: assabet_pcmcia_socket_state,
get_irq_info: assabet_pcmcia_get_irq_info,
configure_socket: assabet_pcmcia_configure_socket,
socket_init: assabet_pcmcia_socket_init,
socket_suspend: assabet_pcmcia_socket_suspend,
};
int __init pcmcia_assabet_init(void)
{
int ret = -ENODEV;
if (machine_is_assabet()) {
if (!machine_has_neponset())
ret = sa1100_register_pcmcia(&assabet_pcmcia_ops);
#ifndef CONFIG_ASSABET_NEPONSET
else
printk(KERN_ERR "Card Services disabled: missing "
"Neponset support\n");
#endif
}
return ret;
}
void __exit pcmcia_assabet_exit(void)
{
sa1100_unregister_pcmcia(&assabet_pcmcia_ops);
}
/*
* linux/drivers/pcmcia/sa1100_badge4.c
*
* BadgePAD 4 PCMCIA specific routines
*
* Christopher Hoover <ch@hpl.hp.com>
*
* Copyright (C) 2002 Hewlett-Packard Company
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <asm/hardware.h>
#include <asm/arch/badge4.h>
#include <asm/hardware/sa1111.h>
#include "sa1100_generic.h"
#include "sa1111_generic.h"
/*
* BadgePAD 4 Details
*
* PCM Vcc:
*
* PCM Vcc on BadgePAD 4 can be jumpered for 3.3V (short pins 1 and 3
* on JP6) or 5V (short pins 3 and 5 on JP6). N.B., 5V supply rail
* is enabled by the SA-1110's BADGE4_GPIO_PCMEN5V (GPIO 24).
*
* PCM Vpp:
*
* PCM Vpp on BadgePAD 4 can be jumpered for 12V (short pins 2 and 4
* on JP6) or tied to PCM Vcc (short pins 4 and 6 on JP6). N.B., 12V
* operation requires that the power supply actually supply 12V.
*
* CF Vcc:
*
* CF Vcc on BadgePAD 4 can be jumpered either for 3.3V (short pins 1
* and 2 on JP10) or 5V (short pins 2 and 3 on JP10). The note above
* about the 5V supply rail applies.
*
* There's no way programmatically to determine how a given board is
* jumpered. This code assumes a default jumpering: 5V PCM Vcc (pins
* 3 and 5 shorted) and PCM Vpp = PCM Vcc (pins 4 and 6 shorted) and
* no jumpering for CF Vcc. If this isn't correct, Override these
* defaults with a pcmv setup argument: pcmv=<pcm vcc>,<pcm vpp>,<cf
* vcc>. E.g. pcmv=33,120,50 indicates 3.3V PCM Vcc, 12.0V PCM Vpp,
* and 5.0V CF Vcc.
*
*/
static int badge4_pcmvcc = 50;
static int badge4_pcmvpp = 50;
static int badge4_cfvcc = 0;
static int badge4_pcmcia_init(struct pcmcia_init *init)
{
printk(KERN_INFO __FUNCTION__
": badge4_pcmvcc=%d, badge4_pcmvpp=%d, badge4_cfvcc=%d\n",
badge4_pcmvcc, badge4_pcmvpp, badge4_cfvcc);
return sa1111_pcmcia_init(init);
}
static int badge4_pcmcia_shutdown(void)
{
int rc = sa1111_pcmcia_shutdown();
/* be sure to disable 5V use */
badge4_set_5V(BADGE4_5V_PCMCIA_SOCK0, 0);
badge4_set_5V(BADGE4_5V_PCMCIA_SOCK1, 0);
return rc;
}
static void complain_about_jumpering(const char *whom,
const char *supply,
int given, int wanted)
{
printk(KERN_ERR
"%s: %s %d.%dV wanted but board is jumpered for %s %d.%dV operation"
"; re-jumper the board and/or use pcmv=xx,xx,xx\n",
whom, supply,
wanted / 10, wanted % 10,
supply,
given / 10, given % 10);
}
static unsigned badge4_need_5V_bitmap = 0;
static int
badge4_pcmcia_configure_socket(const struct pcmcia_configure *conf)
{
int ret;
switch (conf->sock) {
case 0:
if ((conf->vcc != 0) &&
(conf->vcc != badge4_pcmvcc)) {
complain_about_jumpering(__FUNCTION__, "pcmvcc",
badge4_pcmvcc, conf->vcc);
return -1;
}
if ((conf->vpp != 0) &&
(conf->vpp != badge4_pcmvpp)) {
complain_about_jumpering(__FUNCTION__, "pcmvpp",
badge4_pcmvpp, conf->vpp);
return -1;
}
break;
case 1:
if ((conf->vcc != 0) &&
(conf->vcc != badge4_cfvcc)) {
complain_about_jumpering(__FUNCTION__, "cfvcc",
badge4_cfvcc, conf->vcc);
return -1;
}
break;
default:
return -1;
}
ret = sa1111_pcmcia_configure_socket(conf);
if (ret == 0) {
unsigned long flags;
int need5V;
local_irq_save(flags);
need5V = ((conf->vcc == 50) || (conf->vpp == 50));
badge4_set_5V(BADGE4_5V_PCMCIA_SOCK(conf->sock), need5V);
local_irq_restore(flags);
}
return 0;
}
static struct pcmcia_low_level badge4_pcmcia_ops = {
init: badge4_pcmcia_init,
shutdown: badge4_pcmcia_shutdown,
socket_state: sa1111_pcmcia_socket_state,
get_irq_info: sa1111_pcmcia_get_irq_info,
configure_socket: badge4_pcmcia_configure_socket,
socket_init: sa1111_pcmcia_socket_init,
socket_suspend: sa1111_pcmcia_socket_suspend,
};
int __init pcmcia_badge4_init(void)
{
int ret = -ENODEV;
if (machine_is_badge4())
ret = sa1100_register_pcmcia(&badge4_pcmcia_ops);
return ret;
}
void __exit pcmcia_badge4_exit(void)
{
sa1100_unregister_pcmcia(&badge4_pcmcia_ops);
}
static int __init pcmv_setup(char *s)
{
int v[4];
s = get_options(s, ARRAY_SIZE(v), v);
if (v[0] >= 1) badge4_pcmvcc = v[1];
if (v[0] >= 2) badge4_pcmvpp = v[2];
if (v[0] >= 3) badge4_cfvcc = v[3];
return 1;
}
__setup("pcmv=", pcmv_setup);
......@@ -5,45 +5,62 @@
* Based off the Assabet.
*
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/arch/pcmcia.h>
#include "sa1100_generic.h"
#ifdef CONFIG_SA1100_CERF_CPLD
#define CERF_SOCKET 0
#else
#define CERF_SOCKET 1
#endif
static int cerf_pcmcia_init(struct pcmcia_init *init){
int irq, res;
static struct irqs {
int irq;
const char *str;
} irqs[] = {
{ IRQ_GPIO_CF_CD, "CF_CD" },
{ IRQ_GPIO_CF_BVD2, "CF_BVD2" },
{ IRQ_GPIO_CF_BVD1, "CF_BVD1" }
};
GPDR &= ~(GPIO_CF_CD | GPIO_CF_BVD2 | GPIO_CF_BVD1 | GPIO_CF_IRQ);
GPDR |= (GPIO_CF_RESET);
static int cerf_pcmcia_init(struct pcmcia_init *init)
{
int i, res;
set_GPIO_IRQ_edge( GPIO_CF_CD|GPIO_CF_BVD2|GPIO_CF_BVD1, GPIO_BOTH_EDGES );
set_GPIO_IRQ_edge( GPIO_CF_IRQ, GPIO_FALLING_EDGE );
set_irq_type(IRQ_GPIO_CF_IRQ, IRQT_FALLING);
irq = IRQ_GPIO_CF_CD;
res = request_irq( irq, init->handler, SA_INTERRUPT, "CF_CD", NULL );
if( res < 0 ) goto irq_err;
irq = IRQ_GPIO_CF_BVD2;
res = request_irq( irq, init->handler, SA_INTERRUPT, "CF_BVD2", NULL );
if( res < 0 ) goto irq_err;
irq = IRQ_GPIO_CF_BVD1;
res = request_irq( irq, init->handler, SA_INTERRUPT, "CF_BVD1", NULL );
if( res < 0 ) goto irq_err;
for (i = 0; i < ARRAY_SIZE(irqs); i++) {
set_irq_type(irqs[i].irq, IRQT_NOEDGE);
res = request_irq(irqs[i].irq, init->handler, SA_INTERRUPT,
irqs[i].str, NULL);
if (res)
goto irq_err;
}
return 2;
irq_err:
printk( KERN_ERR "%s: Request for IRQ %lu failed\n", __FUNCTION__, irq );
return -1;
irq_err:
printk(KERN_ERR "%s: request for IRQ%d failed (%d)\n",
__FUNCTION__, irqs[i].irq, res);
while (i--)
free_irq(irqs[i].irq, NULL);
return res;
}
static int cerf_pcmcia_shutdown(void)
{
free_irq( IRQ_GPIO_CF_CD, NULL );
free_irq( IRQ_GPIO_CF_BVD2, NULL );
free_irq( IRQ_GPIO_CF_BVD1, NULL );
int i;
for (i = 0; i < ARRAY_SIZE(irqs); i++)
free_irq(irqs[i].irq, NULL);
return 0;
}
......@@ -51,31 +68,18 @@ static int cerf_pcmcia_shutdown(void)
static int cerf_pcmcia_socket_state(struct pcmcia_state_array
*state_array){
unsigned long levels;
#ifdef CONFIG_SA1100_CERF_CPLD
int i = 0;
#else
int i = 1;
#endif
int i = CERF_SOCKET;
if(state_array->size<2) return -1;
memset(state_array->state, 0,
(state_array->size)*sizeof(struct pcmcia_state));
levels=GPLR;
state_array->state[i].detect=((levels & GPIO_CF_CD)==0)?1:0;
state_array->state[i].ready=(levels & GPIO_CF_IRQ)?1:0;
state_array->state[i].bvd1=(levels & GPIO_CF_BVD1)?1:0;
state_array->state[i].bvd2=(levels & GPIO_CF_BVD2)?1:0;
state_array->state[i].wrprot=0;
state_array->state[i].vs_3v=1;
state_array->state[i].vs_Xv=0;
return 1;
......@@ -85,11 +89,7 @@ static int cerf_pcmcia_get_irq_info(struct pcmcia_irq_info *info){
if(info->sock>1) return -1;
#ifdef CONFIG_SA1100_CERF_CPLD
if(info->sock==0)
#else
if(info->sock==1)
#endif
if (info->sock == CERF_SOCKET)
info->irq=IRQ_GPIO_CF_IRQ;
return 0;
......@@ -98,20 +98,12 @@ static int cerf_pcmcia_get_irq_info(struct pcmcia_irq_info *info){
static int cerf_pcmcia_configure_socket(const struct pcmcia_configure
*configure)
{
unsigned long flags;
if(configure->sock>1)
return -1;
#ifdef CONFIG_SA1100_CERF_CPLD
if(configure->sock==1)
#else
if(configure->sock==0)
#endif
if (configure->sock != CERF_SOCKET)
return 0;
save_flags_cli(flags);
switch(configure->vcc){
case 0:
break;
......@@ -119,43 +111,76 @@ static int cerf_pcmcia_configure_socket(const struct pcmcia_configure
case 50:
case 33:
#ifdef CONFIG_SA1100_CERF_CPLD
GPDR |= GPIO_PWR_SHUTDOWN;
GPCR |= GPIO_PWR_SHUTDOWN;
GPCR = GPIO_PWR_SHUTDOWN;
#endif
break;
default:
printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
configure->vcc);
restore_flags(flags);
return -1;
}
if(configure->reset)
{
#ifdef CONFIG_SA1100_CERF_CPLD
GPDR |= GPIO_CF_RESET;
GPSR |= GPIO_CF_RESET;
GPSR = GPIO_CF_RESET;
#endif
}
else
{
#ifdef CONFIG_SA1100_CERF_CPLD
GPDR |= GPIO_CF_RESET;
GPCR |= GPIO_CF_RESET;
GPCR = GPIO_CF_RESET;
#endif
}
restore_flags(flags);
return 0;
}
static int cerf_pcmcia_socket_init(int sock)
{
int i;
if (sock == CERF_SOCKET)
for (i = 0; i < ARRAY_SIZE(irqs); i++)
set_irq_type(irqs[i].irq, IRQT_BOTHEDGE);
return 0;
}
struct pcmcia_low_level cerf_pcmcia_ops = {
cerf_pcmcia_init,
cerf_pcmcia_shutdown,
cerf_pcmcia_socket_state,
cerf_pcmcia_get_irq_info,
cerf_pcmcia_configure_socket
static int cerf_pcmcia_socket_suspend(int sock)
{
int i;
if (sock == CERF_SOCKET)
for (i = 0; i < ARRAY_SIZE(irqs); i++)
set_irq_type(irqs[i].irq, IRQT_NOEDGE);
return 0;
}
static struct pcmcia_low_level cerf_pcmcia_ops = {
init: cerf_pcmcia_init,
shutdown: cerf_pcmcia_shutdown,
socket_state: cerf_pcmcia_socket_state,
get_irq_info: cerf_pcmcia_get_irq_info,
configure_socket: cerf_pcmcia_configure_socket,
socket_init: cerf_pcmcia_socket_init,
socket_suspend: cerf_pcmcia_socket_suspend,
};
int __init pcmcia_cerf_init(void)
{
int ret = -ENODEV;
if (machine_is_cerf())
ret = sa1100_register_pcmcia(&cerf_pcmcia_ops);
return ret;
}
void __exit pcmcia_cerf_exit(void)
{
sa1100_unregister_pcmcia(&cerf_pcmcia_ops);
}
......@@ -4,16 +4,25 @@
* PCMCIA implementation routines for Flexanet.
* by Jordi Colomer, 09/05/2001
*
* Yet to be defined.
*/
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/arch/pcmcia.h>
#include "sa1100_generic.h"
static struct {
int irq;
const char *name;
} irqs[] = {
{ IRQ_GPIO_CF1_CD, "CF1_CD" },
{ IRQ_GPIO_CF1_BVD1, "CF1_BVD1" },
{ IRQ_GPIO_CF2_CD, "CF2_CD" },
{ IRQ_GPIO_CF2_BVD1, "CF2_BVD1" }
};
/*
* Socket initialization.
......@@ -22,9 +31,37 @@
* Must return the number of slots.
*
*/
static int flexanet_pcmcia_init(struct pcmcia_init *init){
return 0;
static int flexanet_pcmcia_init(struct pcmcia_init *init)
{
int i, res;
/* Configure the GPIOs as inputs (BVD2 is not implemented) */
GPDR &= ~(GPIO_CF1_NCD | GPIO_CF1_BVD1 | GPIO_CF1_IRQ |
GPIO_CF2_NCD | GPIO_CF2_BVD1 | GPIO_CF2_IRQ );
/* Set IRQ edge */
set_irq_type(IRQ_GPIO_CF1_IRQ, IRQT_FALLING);
set_irq_type(IRQ_GPIO_CF2_IRQ, IRQT_FALLING);
/* Register the socket interrupts (not the card interrupts) */
for (i = 0; i < ARRAY_SIZE(irqs); i++) {
set_irq_type(irqs[i].irq, IRQT_NOEDGE);
res = request_irq(irqs[i].irq, init->handler, SA_INTERRUPT,
irqs[i].name, NULL);
if (res < 0)
break;
}
/* If we failed, then free all interrupts requested thus far. */
if (res < 0) {
printk(KERN_ERR "%s: request for IRQ%d failed: %d\n",
__FUNCTION__, irqs[i].irq, res);
while (i--)
free_irq(irqs[i].irq, NULL);
return res;
}
return 2;
}
......@@ -34,6 +71,12 @@ static int flexanet_pcmcia_init(struct pcmcia_init *init){
*/
static int flexanet_pcmcia_shutdown(void)
{
int i;
/* disable IRQs */
for (i = 0; i < ARRAY_SIZE(irqs); i++)
free_irq(irqs[i].irq, NULL);
return 0;
}
......@@ -46,7 +89,33 @@ static int flexanet_pcmcia_shutdown(void)
*/
static int flexanet_pcmcia_socket_state(struct pcmcia_state_array
*state_array){
unsigned long levels;
if (state_array->size < 2)
return -1;
/* Sense the GPIOs, asynchronously */
levels = GPLR;
/* Socket 0 */
state_array->state[0].detect = ((levels & GPIO_CF1_NCD)==0)?1:0;
state_array->state[0].ready = (levels & GPIO_CF1_IRQ)?1:0;
state_array->state[0].bvd1 = (levels & GPIO_CF1_BVD1)?1:0;
state_array->state[0].bvd2 = 1;
state_array->state[0].wrprot = 0;
state_array->state[0].vs_3v = 1;
state_array->state[0].vs_Xv = 0;
/* Socket 1 */
state_array->state[1].detect = ((levels & GPIO_CF2_NCD)==0)?1:0;
state_array->state[1].ready = (levels & GPIO_CF2_IRQ)?1:0;
state_array->state[1].bvd1 = (levels & GPIO_CF2_BVD1)?1:0;
state_array->state[1].bvd2 = 1;
state_array->state[1].wrprot = 0;
state_array->state[1].vs_3v = 1;
state_array->state[1].vs_Xv = 0;
return 1;
}
......@@ -56,7 +125,16 @@ static int flexanet_pcmcia_socket_state(struct pcmcia_state_array
*/
static int flexanet_pcmcia_get_irq_info(struct pcmcia_irq_info *info){
/* check the socket index */
if (info->sock > 1)
return -1;
if (info->sock == 0)
info->irq = IRQ_GPIO_CF1_IRQ;
else if (info->sock == 1)
info->irq = IRQ_GPIO_CF2_IRQ;
return 0;
}
......@@ -66,19 +144,105 @@ static int flexanet_pcmcia_get_irq_info(struct pcmcia_irq_info *info){
static int flexanet_pcmcia_configure_socket(const struct pcmcia_configure
*configure)
{
unsigned long value, flags, mask;
if (configure->sock > 1)
return -1;
/* Ignore the VCC level since it is 3.3V and always on */
switch (configure->vcc)
{
case 0:
printk(KERN_WARNING "%s(): CS asked to power off.\n", __FUNCTION__);
break;
case 50:
printk(KERN_WARNING "%s(): CS asked for 5V, applying 3.3V...\n",
__FUNCTION__);
case 33:
break;
default:
printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
configure->vcc);
return -1;
}
/* Reset the slot(s) using the controls in the BCR */
mask = 0;
switch (configure->sock)
{
case 0 : mask = FHH_BCR_CF1_RST; break;
case 1 : mask = FHH_BCR_CF2_RST; break;
}
local_irq_save(flags);
value = flexanet_BCR;
value = (configure->reset) ? (value | mask) : (value & ~mask);
FHH_BCR = flexanet_BCR = value;
local_irq_restore(flags);
return 0;
}
static int flexanet_pcmcia_socket_init(int sock)
{
if (sock == 0) {
set_irq_type(IRQ_GPIO_CF1_CD, IRQT_BOTHEDGE);
set_irq_type(IRQ_GPIO_CF1_BVD1, IRQT_BOTHEDGE);
} else if (sock == 1) {
set_irq_type(IRQ_GPIO_CF2_CD, IRQT_BOTHEDGE);
set_irq_type(IRQ_GPIO_CF2_BVD1, IRQT_BOTHEDGE);
}
return 0;
}
static int flexanet_pcmcia_socket_suspend(int sock)
{
if (sock == 0) {
set_irq_type(IRQ_GPIO_CF1_CD, IRQT_NOEDGE);
set_irq_type(IRQ_GPIO_CF1_BVD1, IRQT_NOEDGE);
} else if (sock == 1) {
set_irq_type(IRQ_GPIO_CF2_CD, IRQT_NOEDGE);
set_irq_type(IRQ_GPIO_CF2_BVD1, IRQT_NOEDGE);
}
return 0;
}
/*
* The set of socket operations
*
*/
struct pcmcia_low_level flexanet_pcmcia_ops = {
flexanet_pcmcia_init,
flexanet_pcmcia_shutdown,
flexanet_pcmcia_socket_state,
flexanet_pcmcia_get_irq_info,
flexanet_pcmcia_configure_socket
static struct pcmcia_low_level flexanet_pcmcia_ops = {
init: flexanet_pcmcia_init,
shutdown: flexanet_pcmcia_shutdown,
socket_state: flexanet_pcmcia_socket_state,
get_irq_info: flexanet_pcmcia_get_irq_info,
configure_socket: flexanet_pcmcia_configure_socket,
socket_init: flexanet_pcmcia_socket_init,
socket_suspend: flexanet_pcmcia_socket_suspend,
};
int __init pcmcia_flexanet_init(void)
{
int ret = -ENODEV;
if (machine_is_flexanet())
ret = sa1100_register_pcmcia(&flexanet_pcmcia_ops);
return ret;
}
void __exit pcmcia_flexanet_exit(void)
{
sa1100_unregister_pcmcia(&flexanet_pcmcia_ops);
}
......@@ -6,14 +6,22 @@
*/
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/arch/pcmcia.h>
#include "sa1100_generic.h"
static struct irqs {
int irq;
const char *str;
} irqs[] = {
{ IRQ_GPIO_FREEBIRD_CF_CD, "CF_CD" },
{ IRQ_GPIO_FREEBIRD_CF_BVD, "CF_BVD1" },
};
static int freebird_pcmcia_init(struct pcmcia_init *init){
int irq, res;
int i, res;
/* Enable Linkup CF card */
LINKUP_PRC = 0xc0;
......@@ -26,37 +34,38 @@ static int freebird_pcmcia_init(struct pcmcia_init *init){
mdelay(100);
LINKUP_PRC = 0xc0;
/* All those are inputs */
////GPDR &= ~(GPIO_CF_CD | GPIO_CF_BVD2 | GPIO_CF_BVD1 | GPIO_CF_IRQ);
GPDR &= ~(GPIO_FREEBIRD_CF_CD | GPIO_FREEBIRD_CF_IRQ | GPIO_FREEBIRD_CF_BVD);
/* Set transition detect */
//set_GPIO_IRQ_edge( GPIO_CF_CD|GPIO_CF_BVD2|GPIO_CF_BVD1, GPIO_BOTH_EDGES );
//set_GPIO_IRQ_edge( GPIO_CF_IRQ, GPIO_FALLING_EDGE );
set_GPIO_IRQ_edge(GPIO_FREEBIRD_CF_CD|GPIO_FREEBIRD_CF_BVD,GPIO_BOTH_EDGES);
set_GPIO_IRQ_edge(GPIO_FREEBIRD_CF_IRQ, GPIO_FALLING_EDGE);
set_irq_type(IRQ_GPIO_FREEBIRD_CF_IRQ, IRQT_FALLING);
/* Register interrupts */
irq = IRQ_GPIO_FREEBIRD_CF_CD;
res = request_irq( irq, init->handler, SA_INTERRUPT, "CF_CD", NULL );
if( res < 0 ) goto irq_err;
irq = IRQ_GPIO_FREEBIRD_CF_BVD;
res = request_irq( irq, init->handler, SA_INTERRUPT, "CF_BVD1", NULL );
if( res < 0 ) goto irq_err;
for (i = 0; i < ARRAY_SIZE(irqs); i++) {
set_irq_type(irqs[i].irq, IRQT_NOEDGE);
res = request_irq(irqs[i].irq, init->handler, SA_INTERRUPT,
irqs[i].str, NULL);
if (res)
goto irq_err;
}
/* There's only one slot, but it's "Slot 1": */
return 2;
irq_err:
printk( KERN_ERR "%s: Request for IRQ %lu failed\n", __FUNCTION__, irq );
return -1;
printk(KERN_ERR "%s: request for IRQ%d failed (%d)\n",
__FUNCTION__, irqs[i].irq, res);
while (i--)
free_irq(irqs[i].irq, NULL);
return res;
}
static int freebird_pcmcia_shutdown(void)
{
int i;
/* disable IRQs */
free_irq( IRQ_GPIO_FREEBIRD_CF_CD, NULL );
free_irq( IRQ_GPIO_FREEBIRD_CF_BVD, NULL );
for (i = 0; i < ARRAY_SIZE(irqs); i++)
free_irq(irqs[i].irq, NULL);
/* Disable CF card */
LINKUP_PRC = 0x40; /* SSP=1 SOE=0 */
......@@ -75,7 +84,7 @@ static int freebird_pcmcia_socket_state(struct pcmcia_state_array
(state_array->size)*sizeof(struct pcmcia_state));
levels = LINKUP_PRS;
//printk("LINKUP_PRS=%x \n",levels);
//printk("LINKUP_PRS=%x\n",levels);
state_array->state[0].detect=
((levels & (LINKUP_CD1 | LINKUP_CD2))==0)?1:0;
......@@ -114,7 +123,7 @@ static int freebird_pcmcia_configure_socket(const struct pcmcia_configure
if(configure->sock==1) return 0;
save_flags_cli(flags);
local_irq_save(flags);
value = 0xc0; /* SSP=1 SOE=1 CFE=1 */
......@@ -134,7 +143,7 @@ static int freebird_pcmcia_configure_socket(const struct pcmcia_configure
default:
printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
configure->vcc);
restore_flags(flags);
local_irq_restore(flags);
return -1;
}
......@@ -145,16 +154,51 @@ static int freebird_pcmcia_configure_socket(const struct pcmcia_configure
LINKUP_PRC = value;
//printk("LINKUP_PRC=%x\n",value);
restore_flags(flags);
local_irq_restore(flags);
return 0;
}
static int freebird_pcmcia_socket_init(int sock)
{
if (sock == 1) {
set_irq_type(IRQ_GPIO_FREEBIRD_CF_CD, IRQT_BOTHEDGE);
set_irq_type(IRQ_GPIO_FREEBIRD_CF_BVD, IRQT_BOTHEDGE);
}
return 0;
}
static int freebird_pcmcia_socket_suspend(int sock)
{
if (sock == 1) {
set_irq_type(IRQ_GPIO_FREEBIRD_CF_CD, IRQT_NOEDGE);
set_irq_type(IRQ_GPIO_FREEBIRD_CF_BVD, IRQT_NOEDGE);
}
return 0;
}
struct pcmcia_low_level freebird_pcmcia_ops = {
freebird_pcmcia_init,
freebird_pcmcia_shutdown,
freebird_pcmcia_socket_state,
freebird_pcmcia_get_irq_info,
freebird_pcmcia_configure_socket
static struct pcmcia_low_level freebird_pcmcia_ops = {
init: freebird_pcmcia_init,
shutdown: freebird_pcmcia_shutdown,
socket_state: freebird_pcmcia_socket_state,
get_irq_info: freebird_pcmcia_get_irq_info,
configure_socket: freebird_pcmcia_configure_socket,
socket_init: freebird_pcmcia_socket_init,
socket_suspend: freebird_pcmcia_socket_suspend,
};
int __init pcmcia_freebird_init(void)
{
int ret = -ENODEV;
if (machine_is_freebird())
ret = sa1100_register_pcmcia(&freebird_pcmcia_ops);
return ret;
}
void __exit pcmcia_freebird_exit(void)
{
sa1100_unregister_pcmcia(&freebird_pcmcia_ops);
}
This diff is collapsed.
/*
* linux/include/asm/arch/pcmcia.h
*
* Copyright (C) 2000 John G Dorsey <john+@cs.cmu.edu>
*
* This file contains definitions for the low-level SA-1100 kernel PCMCIA
* interface. Please see linux/Documentation/arm/SA1100/PCMCIA for details.
*/
#ifndef _ASM_ARCH_PCMCIA
#define _ASM_ARCH_PCMCIA
/* Ideally, we'd support up to MAX_SOCK sockets, but the SA-1100 only
* has support for two. This shows up in lots of hardwired ways, such
* as the fact that MECR only has enough bits to configure two sockets.
* Since it's so entrenched in the hardware, limiting the software
* in this way doesn't seem too terrible.
*/
#define SA1100_PCMCIA_MAX_SOCK (2)
struct pcmcia_init {
void (*handler)(int irq, void *dev, struct pt_regs *regs);
};
struct pcmcia_state {
unsigned detect: 1,
ready: 1,
bvd1: 1,
bvd2: 1,
wrprot: 1,
vs_3v: 1,
vs_Xv: 1;
};
struct pcmcia_state_array {
unsigned int size;
struct pcmcia_state *state;
};
struct pcmcia_configure {
unsigned sock: 8,
vcc: 8,
vpp: 8,
output: 1,
speaker: 1,
reset: 1,
irq: 1;
};
struct pcmcia_irq_info {
unsigned int sock;
unsigned int irq;
};
struct pcmcia_low_level {
int (*init)(struct pcmcia_init *);
int (*shutdown)(void);
int (*socket_state)(struct pcmcia_state_array *);
int (*get_irq_info)(struct pcmcia_irq_info *);
int (*configure_socket)(const struct pcmcia_configure *);
/*
* Enable card status IRQs on (re-)initialisation. This can
* be called at initialisation, power management event, or
* pcmcia event.
*/
int (*socket_init)(int sock);
/*
* Disable card status IRQs and PCMCIA bus on suspend.
*/
int (*socket_suspend)(int sock);
};
extern int sa1100_register_pcmcia(struct pcmcia_low_level *);
extern void sa1100_unregister_pcmcia(struct pcmcia_low_level *);
#endif
......@@ -14,10 +14,13 @@
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/arch/pcmcia.h>
#include "sa1100_generic.h"
#error This is broken!
#define S0_CD_IRQ 60 // Socket 0 Card Detect IRQ
#define S0_STS_IRQ 55 // Socket 0 PCMCIA IRQ
......@@ -47,8 +50,9 @@ static int gcplus_pcmcia_init(struct pcmcia_init *init)
irq = S0_CD_IRQ;
res = request_irq(irq, init->handler, SA_INTERRUPT, "PCMCIA 0 CD", NULL);
if (res < 0) {
printk(KERN_ERR "%s: Request for IRQ %lu failed\n", __FUNCTION__, irq);
return -1;
printk(KERN_ERR "%s: request for IRQ%d failed (%d)\n",
__FUNCTION__, irq, res);
return res;
}
return 1; // 1 PCMCIA Slot
......@@ -106,7 +110,7 @@ static int gcplus_pcmcia_configure_socket(const struct pcmcia_configure
if(configure->sock>1) return -1;
save_flags_cli(flags);
local_irq_save(flags);
switch (configure->vcc) {
case 0:
......@@ -126,7 +130,7 @@ static int gcplus_pcmcia_configure_socket(const struct pcmcia_configure
default:
printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
configure->vcc);
restore_flags(flags);
local_irq_restore(flags);
return -1;
}
......@@ -139,16 +143,44 @@ static int gcplus_pcmcia_configure_socket(const struct pcmcia_configure
*PCMCIA_Power |= ADS_CS_PR_A_RESET;
mdelay(30);
restore_flags(flags);
local_irq_restore(flags);
return 0;
}
static int gcplus_pcmcia_socket_init(int sock)
{
return 0;
}
static int gcplus_pcmcia_socket_suspend(int sock)
{
return 0;
}
struct pcmcia_low_level gcplus_pcmcia_ops = {
gcplus_pcmcia_init,
gcplus_pcmcia_shutdown,
gcplus_pcmcia_socket_state,
gcplus_pcmcia_get_irq_info,
gcplus_pcmcia_configure_socket
static struct pcmcia_low_level gcplus_pcmcia_ops = {
init: gcplus_pcmcia_init,
shutdown: gcplus_pcmcia_shutdown,
socket_state: gcplus_pcmcia_socket_state,
get_irq_info: gcplus_pcmcia_get_irq_info,
configure_socket: gcplus_pcmcia_configure_socket,
socket_init: gcplus_pcmcia_socket_init,
socket_suspend: gcplus_pcmcia_socket_suspend,
};
int __init pcmcia_gcplus_init(void)
{
int ret = -ENODEV;
if (machine_is_gcplus())
ret = sa1100_register_pcmcia(&gcplus_pcmcia_ops);
return ret;
}
void __exit pcmcia_gcplus_exit(void)
{
sa1100_unregister_pcmcia(&gcplus_pcmcia_ops);
}
......@@ -10,11 +10,12 @@
*/
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <asm/delay.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/arch/pcmcia.h>
#include "sa1100_generic.h"
#include "sa1111_generic.h"
static int graphicsmaster_pcmcia_init(struct pcmcia_init *init)
{
......@@ -26,190 +27,82 @@ static int graphicsmaster_pcmcia_init(struct pcmcia_init *init)
/* Disable Power 3.3V/5V for PCMCIA/CF */
PA_DWR |= GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3;
INTPOL1 |= (1 << (S0_READY_NINT - SA1111_IRQ(32))) |
(1 << (S1_READY_NINT - SA1111_IRQ(32))) |
(1 << (S0_CD_VALID - SA1111_IRQ(32))) |
(1 << (S1_CD_VALID - SA1111_IRQ(32))) |
(1 << (S0_BVD1_STSCHG - SA1111_IRQ(32))) |
(1 << (S1_BVD1_STSCHG - SA1111_IRQ(32)));
return_val+=request_irq(S0_CD_VALID, init->handler, SA_INTERRUPT,
"GC Master PCMCIA (0) CD", NULL);
return_val+=request_irq(S1_CD_VALID, init->handler, SA_INTERRUPT,
"GC Master CF (1) CD", NULL);
return_val+=request_irq(S0_BVD1_STSCHG, init->handler, SA_INTERRUPT,
"GC Master PCMCIA (0) BVD1", NULL);
return_val+=request_irq(S1_BVD1_STSCHG, init->handler, SA_INTERRUPT,
"GC Master CF (1) BVD1", NULL);
/* why? */
MECR = 0x09430943;
return (return_val<0) ? -1 : 2;
}
static int graphicsmaster_pcmcia_shutdown(void)
{
free_irq(S0_CD_VALID, NULL);
free_irq(S1_CD_VALID, NULL);
free_irq(S0_BVD1_STSCHG, NULL);
free_irq(S1_BVD1_STSCHG, NULL);
INTPOL1 &= ~((1 << (S0_CD_VALID - SA1111_IRQ(32))) |
(1 << (S1_CD_VALID - SA1111_IRQ(32))) |
(1 << (S0_BVD1_STSCHG - SA1111_IRQ(32))) |
(1 << (S1_BVD1_STSCHG - SA1111_IRQ(32))));
return 0;
}
static int graphicsmaster_pcmcia_socket_state(struct pcmcia_state_array *state_array)
{
unsigned long status;
int return_val=1;
if(state_array->size<2) return -1;
memset(state_array->state, 0,
(state_array->size)*sizeof(struct pcmcia_state));
status=PCSR;
state_array->state[0].detect=((status & PCSR_S0_DETECT)==0)?1:0;
state_array->state[0].ready=((status & PCSR_S0_READY)==0)?0:1;
state_array->state[0].bvd1=((status & PCSR_S0_BVD1)==0)?0:1;
state_array->state[0].bvd2=((status & PCSR_S0_BVD2)==0)?0:1;
state_array->state[0].wrprot=((status & PCSR_S0_WP)==0)?0:1;
state_array->state[0].vs_3v=((status & PCSR_S0_VS1)==0)?1:0;
state_array->state[0].vs_Xv=((status & PCSR_S0_VS2)==0)?1:0;
state_array->state[1].detect=((status & PCSR_S1_DETECT)==0)?1:0;
state_array->state[1].ready=((status & PCSR_S1_READY)==0)?0:1;
state_array->state[1].bvd1=((status & PCSR_S1_BVD1)==0)?0:1;
state_array->state[1].bvd2=((status & PCSR_S1_BVD2)==0)?0:1;
state_array->state[1].wrprot=((status & PCSR_S1_WP)==0)?0:1;
state_array->state[1].vs_3v=((status & PCSR_S1_VS1)==0)?1:0;
state_array->state[1].vs_Xv=((status & PCSR_S1_VS2)==0)?1:0;
return return_val;
return sa1111_pcmcia_init(init);
}
static int graphicsmaster_pcmcia_get_irq_info(struct pcmcia_irq_info *info)
static int
graphicsmaster_pcmcia_configure_socket(const struct pcmcia_configure *conf)
{
unsigned int pa_dwr_mask, pa_dwr_set;
int ret;
switch(info->sock){
switch (conf->sock) {
case 0:
info->irq=S0_READY_NINT;
break;
case 1:
info->irq=S1_READY_NINT;
break;
pa_dwr_mask = GPIO_GPIO0 | GPIO_GPIO1;
switch (conf->vcc) {
default:
return -1;
case 0: pa_dwr_set = GPIO_GPIO0 | GPIO_GPIO1; break;
case 33: pa_dwr_set = GPIO_GPIO1; break;
case 50: pa_dwr_set = GPIO_GPIO0; break;
}
return 0;
}
static int graphicsmaster_pcmcia_configure_socket(const struct pcmcia_configure *configure)
{
unsigned long pccr=PCCR, gpio=PA_DWR;
switch(configure->sock){
case 0:
switch(configure->vcc){
case 0:
pccr = (pccr & ~PCCR_S0_FLT);
gpio |= GPIO_GPIO0 | GPIO_GPIO1;
break;
case 33:
pccr = (pccr & ~PCCR_S0_PSE) | PCCR_S0_FLT | PCCR_S0_PWAITEN;
gpio &= ~(GPIO_GPIO0 | GPIO_GPIO1);
gpio &= ~GPIO_GPIO0;
break;
case 50:
pccr = (pccr | PCCR_S0_PSE | PCCR_S0_FLT | PCCR_S0_PWAITEN);
gpio &= ~(GPIO_GPIO0 | GPIO_GPIO1);
gpio |= GPIO_GPIO0;
break;
default:
printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
configure->vcc);
return -1;
}
pccr=(configure->reset)?(pccr | PCCR_S0_RST):(pccr & ~PCCR_S0_RST);
break;
case 1:
switch(configure->vcc){
case 0:
pccr = (pccr & ~PCCR_S1_FLT);
gpio |= GPIO_GPIO2 | GPIO_GPIO3;
break;
case 33:
pccr = (pccr & ~PCCR_S1_PSE) | PCCR_S1_FLT | PCCR_S1_PWAITEN;
gpio &= ~(GPIO_GPIO2 | GPIO_GPIO3);
gpio &= ~GPIO_GPIO2;
break;
case 50:
pccr = (pccr | PCCR_S1_PSE | PCCR_S1_FLT | PCCR_S1_PWAITEN);
gpio &= ~(GPIO_GPIO2 | GPIO_GPIO3);
gpio |= GPIO_GPIO2;
break;
pa_dwr_mask = GPIO_GPIO2 | GPIO_GPIO3;
switch (conf->vcc) {
default:
printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
configure->vcc);
return -1;
case 0: pa_dwr_set = GPIO_GPIO2 | GPIO_GPIO3; break;
case 33: pa_dwr_set = GPIO_GPIO3; break;
case 50: pa_dwr_set = GPIO_GPIO2; break;
}
}
if(configure->vpp!=configure->vcc && configure->vpp!=0){
if (conf->vpp != conf->vcc && conf->vpp != 0) {
printk(KERN_ERR "%s(): CF slot cannot support Vpp %u\n", __FUNCTION__,
configure->vpp);
conf->vpp);
return -1;
}
pccr=(configure->reset)?(pccr | PCCR_S1_RST):(pccr & ~PCCR_S1_RST);
ret = sa1111_pcmcia_configure_socket(conf);
if (ret == 0) {
unsigned long flags;
break;
default:
return -1;
local_irq_save(flags);
PA_DWR = (PA_DWR & ~pa_dwr_mask) | pa_dwr_set;
local_irq_restore(flags);
}
PCCR = pccr;
PA_DWR = gpio;
return 0;
return ret;
}
struct pcmcia_low_level graphicsmaster_pcmcia_ops = {
graphicsmaster_pcmcia_init,
graphicsmaster_pcmcia_shutdown,
graphicsmaster_pcmcia_socket_state,
graphicsmaster_pcmcia_get_irq_info,
graphicsmaster_pcmcia_configure_socket
static struct pcmcia_low_level graphicsmaster_pcmcia_ops = {
init: graphicsmaster_pcmcia_init,
shutdown: sa1111_pcmcia_shutdown,
socket_state: sa1111_pcmcia_socket_state,
get_irq_info: sa1111_pcmcia_get_irq_info,
configure_socket: graphicsmaster_pcmcia_configure_socket,
socket_init: sa1111_pcmcia_socket_init,
socket_suspend: sa1111_pcmcia_socket_suspend,
};
int __init pcmcia_graphicsmaster_init(void)
{
int ret = -ENODEV;
if (machine_is_graphicsmaster())
ret = sa1100_register_pcmcia(&graphicsmaster_pcmcia_ops);
return ret;
}
void __exit pcmcia_graphicsmaster_exit(void)
{
sa1100_unregister_pcmcia(&graphicsmaster_pcmcia_ops);
}
......@@ -6,92 +6,106 @@
*/
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/arch/pcmcia.h>
static int h3600_pcmcia_init(struct pcmcia_init *init){
int irq, res;
#include "sa1100_generic.h"
static struct irqs {
int irq;
const char *str;
} irqs[] = {
{ IRQ_GPIO_H3600_PCMCIA_CD0, "PCMCIA CD0" },
{ IRQ_GPIO_H3600_PCMCIA_CD1, "PCMCIA CD1" }
};
/* Enable CF bus: */
set_h3600_egpio(EGPIO_H3600_OPT_NVRAM_ON);
clr_h3600_egpio(EGPIO_H3600_OPT_RESET);
static int h3600_pcmcia_init(struct pcmcia_init *init)
{
int i, res;
/* All those are inputs */
GPDR &= ~(GPIO_H3600_PCMCIA_CD0 | GPIO_H3600_PCMCIA_CD1 | GPIO_H3600_PCMCIA_IRQ0| GPIO_H3600_PCMCIA_IRQ1);
/*
* Set transition detect
*/
set_irq_type(IRQ_GPIO_H3600_PCMCIA_IRQ0, IRQT_FALLING);
set_irq_type(IRQ_GPIO_H3600_PCMCIA_IRQ1, IRQT_FALLING);
/* Set transition detect */
set_GPIO_IRQ_edge( GPIO_H3600_PCMCIA_CD0 | GPIO_H3600_PCMCIA_CD1, GPIO_BOTH_EDGES );
set_GPIO_IRQ_edge( GPIO_H3600_PCMCIA_IRQ0| GPIO_H3600_PCMCIA_IRQ1, GPIO_FALLING_EDGE );
/*
* Register interrupts
*/
for (i = res = 0; i < ARRAY_SIZE(irqs); i++) {
res = request_irq(irqs[i].irq, init->handler, SA_INTERRUPT,
irqs[i].str, NULL);
if (res)
break;
}
/* Register interrupts */
irq = IRQ_GPIO_H3600_PCMCIA_CD0;
res = request_irq( irq, init->handler, SA_INTERRUPT, "PCMCIA_CD0", NULL );
if( res < 0 ) goto irq_err;
irq = IRQ_GPIO_H3600_PCMCIA_CD1;
res = request_irq( irq, init->handler, SA_INTERRUPT, "PCMCIA_CD1", NULL );
if( res < 0 ) goto irq_err;
if (res) {
printk(KERN_ERR "%s: request for IRQ%d failed (%d)\n",
__FUNCTION__, irqs[i].irq, res);
return 2;
while (i--)
free_irq(irqs[i].irq, NULL);
}
irq_err:
printk( KERN_ERR __FUNCTION__ ": Request for IRQ %u failed\n", irq );
return -1;
return res ? res : 2;
}
static int h3600_pcmcia_shutdown(void)
{
/* disable IRQs */
free_irq( IRQ_GPIO_H3600_PCMCIA_CD0, NULL );
free_irq( IRQ_GPIO_H3600_PCMCIA_CD1, NULL );
int i;
/*
* disable IRQs
*/
for (i = 0; i < ARRAY_SIZE(irqs); i++)
free_irq(irqs[i].irq, NULL);
/* Disable CF bus: */
clr_h3600_egpio(EGPIO_H3600_OPT_NVRAM_ON|EGPIO_H3600_OPT_ON);
set_h3600_egpio(EGPIO_H3600_OPT_RESET);
clr_h3600_egpio(IPAQ_EGPIO_OPT_NVRAM_ON);
clr_h3600_egpio(IPAQ_EGPIO_OPT_ON);
set_h3600_egpio(IPAQ_EGPIO_OPT_RESET);
return 0;
}
static int h3600_pcmcia_socket_state(struct pcmcia_state_array
*state_array){
static int
h3600_pcmcia_socket_state(struct pcmcia_state_array *state)
{
unsigned long levels;
if(state_array->size<2) return -1;
memset(state_array->state, 0,
(state_array->size)*sizeof(struct pcmcia_state));
if (state->size < 2)
return -1;
levels=GPLR;
levels = GPLR;
state_array->state[0].detect=((levels & GPIO_H3600_PCMCIA_CD0)==0)?1:0;
state_array->state[0].ready=(levels & GPIO_H3600_PCMCIA_IRQ0)?1:0;
state_array->state[0].bvd1= 0;
state_array->state[0].bvd2= 0;
state_array->state[0].wrprot=0; /* Not available on H3600. */
state_array->state[0].vs_3v=0;
state_array->state[0].vs_Xv=0;
state->state[0].detect = levels & GPIO_H3600_PCMCIA_CD0 ? 0 : 1;
state->state[0].ready = levels & GPIO_H3600_PCMCIA_IRQ0 ? 1 : 0;
state->state[0].bvd1 = 0;
state->state[0].bvd2 = 0;
state->state[0].wrprot = 0; /* Not available on H3600. */
state->state[0].vs_3v = 0;
state->state[0].vs_Xv = 0;
state_array->state[1].detect=((levels & GPIO_H3600_PCMCIA_CD1)==0)?1:0;
state_array->state[1].ready=(levels & GPIO_H3600_PCMCIA_IRQ1)?1:0;
state_array->state[1].bvd1=0;
state_array->state[1].bvd2=0;
state_array->state[1].wrprot=0; /* Not available on H3600. */
state_array->state[1].vs_3v=0;
state_array->state[1].vs_Xv=0;
state->state[1].detect = levels & GPIO_H3600_PCMCIA_CD1 ? 0 : 1;
state->state[1].ready = levels & GPIO_H3600_PCMCIA_IRQ1 ? 1 : 0;
state->state[1].bvd1 = 0;
state->state[1].bvd2 = 0;
state->state[1].wrprot = 0; /* Not available on H3600. */
state->state[1].vs_3v = 0;
state->state[1].vs_Xv = 0;
return 1;
}
static int h3600_pcmcia_get_irq_info(struct pcmcia_irq_info *info){
static int h3600_pcmcia_get_irq_info(struct pcmcia_irq_info *info)
{
switch (info->sock) {
case 0:
info->irq=IRQ_GPIO_H3600_PCMCIA_IRQ0;
info->irq = IRQ_GPIO_H3600_PCMCIA_IRQ0;
break;
case 1:
info->irq=IRQ_GPIO_H3600_PCMCIA_IRQ1;
info->irq = IRQ_GPIO_H3600_PCMCIA_IRQ1;
break;
default:
return -1;
......@@ -99,49 +113,85 @@ static int h3600_pcmcia_get_irq_info(struct pcmcia_irq_info *info){
return 0;
}
static int h3600_pcmcia_configure_socket(const struct pcmcia_configure
*configure)
static int
h3600_pcmcia_configure_socket(const struct pcmcia_configure *conf)
{
unsigned long flags;
if (conf->sock > 1)
return -1;
if (conf->vcc != 0 && conf->vcc != 33 && conf->vcc != 50) {
printk(KERN_ERR "h3600_pcmcia: unrecognized Vcc %u.%uV\n",
conf->vcc / 10, conf->vcc % 10);
return -1;
}
if (conf->reset)
set_h3600_egpio(IPAQ_EGPIO_CARD_RESET);
else
clr_h3600_egpio(IPAQ_EGPIO_CARD_RESET);
if(configure->sock>1) return -1;
/* Silently ignore Vpp, output enable, speaker enable. */
return 0;
}
static int h3600_pcmcia_socket_init(int sock)
{
/* Enable CF bus: */
set_h3600_egpio(IPAQ_EGPIO_OPT_NVRAM_ON);
set_h3600_egpio(IPAQ_EGPIO_OPT_ON);
clr_h3600_egpio(IPAQ_EGPIO_OPT_RESET);
save_flags_cli(flags);
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(10*HZ / 1000);
switch (configure->vcc) {
switch (sock) {
case 0:
clr_h3600_egpio(EGPIO_H3600_OPT_ON);
set_irq_type(IRQ_GPIO_H3600_PCMCIA_CD0, IRQT_BOTHEDGE);
break;
case 33:
case 50:
set_h3600_egpio(EGPIO_H3600_OPT_ON);
case 1:
set_irq_type(IRQ_GPIO_H3600_PCMCIA_CD1, IRQT_BOTHEDGE);
break;
default:
printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
configure->vcc);
restore_flags(flags);
return -1;
}
if (configure->reset)
set_h3600_egpio(EGPIO_H3600_CARD_RESET);
else
clr_h3600_egpio(EGPIO_H3600_CARD_RESET);
return 0;
}
/* Silently ignore Vpp, output enable, speaker enable. */
static int h3600_pcmcia_socket_suspend(int sock)
{
switch (sock) {
case 0:
set_irq_type(IRQ_GPIO_H3600_PCMCIA_CD0, IRQT_NOEDGE);
break;
case 1:
set_irq_type(IRQ_GPIO_H3600_PCMCIA_CD1, IRQT_NOEDGE);
break;
}
restore_flags(flags);
/*
* FIXME: This doesn't fit well. We don't have the mechanism in
* the generic PCMCIA layer to deal with the idea of two sockets
* on one bus. We rely on the cs.c behaviour shutting down
* socket 0 then socket 1.
*/
if (sock == 1) {
clr_h3600_egpio(IPAQ_EGPIO_OPT_ON);
clr_h3600_egpio(IPAQ_EGPIO_OPT_NVRAM_ON);
/* hmm, does this suck power? */
set_h3600_egpio(IPAQ_EGPIO_OPT_RESET);
}
return 0;
}
struct pcmcia_low_level h3600_pcmcia_ops = {
h3600_pcmcia_init,
h3600_pcmcia_shutdown,
h3600_pcmcia_socket_state,
h3600_pcmcia_get_irq_info,
h3600_pcmcia_configure_socket
init: h3600_pcmcia_init,
shutdown: h3600_pcmcia_shutdown,
socket_state: h3600_pcmcia_socket_state,
get_irq_info: h3600_pcmcia_get_irq_info,
configure_socket: h3600_pcmcia_configure_socket,
socket_init: h3600_pcmcia_socket_init,
socket_suspend: h3600_pcmcia_socket_suspend,
};
This diff is collapsed.
This diff is collapsed.
......@@ -4,48 +4,45 @@
* PCMCIA implementation routines for Pangolin
*
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/arch/pcmcia.h>
#include "sa1100_generic.h"
static int pangolin_pcmcia_init(struct pcmcia_init *init){
int irq, res;
int res;
/* set GPIO_PCMCIA_CD & GPIO_PCMCIA_IRQ as inputs */
GPDR &= ~(GPIO_PCMCIA_CD|GPIO_PCMCIA_IRQ);
#ifndef CONFIG_SA1100_PANGOLIN_PCMCIA_IDE
/* set GPIO pins GPIO_PCMCIA_BUS_ON & GPIO_PCMCIA_RESET as output */
GPDR |= (GPIO_PCMCIA_BUS_ON|GPIO_PCMCIA_RESET);
/* Enable PCMCIA bus: */
GPCR = GPIO_PCMCIA_BUS_ON;
#else
/* set GPIO pin GPIO_PCMCIA_RESET as output */
GPDR |= GPIO_PCMCIA_RESET;
#endif
/* Set transition detect */
set_GPIO_IRQ_edge( GPIO_PCMCIA_CD, GPIO_BOTH_EDGES );
set_GPIO_IRQ_edge( GPIO_PCMCIA_IRQ, GPIO_FALLING_EDGE );
set_irq_type(IRQ_PCMCIA_CD, IRQT_NOEDGE);
set_irq_type(IRQ_PCMCIA_IRQ, IRQT_FALLING);
/* Register interrupts */
irq = IRQ_PCMCIA_CD;
res = request_irq( irq, init->handler, SA_INTERRUPT, "PCMCIA_CD", NULL );
if( res < 0 ) goto irq_err;
res = request_irq(IRQ_PCMCIA_CD, init->handler, SA_INTERRUPT,
"PCMCIA_CD", NULL);
if (res >= 0)
/* There's only one slot, but it's "Slot 1": */
return 2;
irq_err:
printk( KERN_ERR "%s: Request for IRQ %lu failed\n", __FUNCTION__, irq );
return -1;
printk(KERN_ERR "%s: request for IRQ%d failed (%d)\n",
__FUNCTION__, IRQ_PCMCIA_CD, res);
return res;
}
static int pangolin_pcmcia_shutdown(void)
{
/* disable IRQs */
free_irq( IRQ_PCMCIA_CD, NULL );
free_irq(IRQ_PCMCIA_CD, NULL);
#ifndef CONFIG_SA1100_PANGOLIN_PCMCIA_IDE
/* Disable PCMCIA bus: */
GPSR = GPIO_PCMCIA_BUS_ON;
......@@ -105,7 +102,7 @@ static int pangolin_pcmcia_configure_socket(const struct pcmcia_configure
#ifndef CONFIG_SA1100_PANGOLIN_PCMCIA_IDE
if(configure->sock==0) return 0;
#endif
save_flags_cli(flags);
local_irq_save(flags);
/* Murphy: BUS_ON different from POWER ? */
......@@ -129,7 +126,7 @@ static int pangolin_pcmcia_configure_socket(const struct pcmcia_configure
default:
printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
configure->vcc);
restore_flags(flags);
local_irq_restore(flags);
return -1;
}
#ifdef CONFIG_SA1100_PANGOLIN_PCMCIA_IDE
......@@ -143,15 +140,47 @@ static int pangolin_pcmcia_configure_socket(const struct pcmcia_configure
}
#endif
/* Silently ignore Vpp, output enable, speaker enable. */
restore_flags(flags);
local_irq_restore(flags);
return 0;
}
static int pangolin_pcmcia_socket_init(int sock)
{
if (sock == 1)
set_irq_type(IRQ_PCmCIA_CD, IRQT_BOTHEDGE);
return 0;
}
static int pangolin_pcmcia_socket_suspend(int sock)
{
if (sock == 1)
set_irq_type(IRQ_PCmCIA_CD, IRQT_NOEDGE);
return 0;
}
struct pcmcia_low_level pangolin_pcmcia_ops = {
pangolin_pcmcia_init,
pangolin_pcmcia_shutdown,
pangolin_pcmcia_socket_state,
pangolin_pcmcia_get_irq_info,
pangolin_pcmcia_configure_socket
static struct pcmcia_low_level pangolin_pcmcia_ops = {
init: pangolin_pcmcia_init,
shutdown: pangolin_pcmcia_shutdown,
socket_state: pangolin_pcmcia_socket_state,
get_irq_info: pangolin_pcmcia_get_irq_info,
configure_socket: pangolin_pcmcia_configure_socket,
socket_init: pangolin_pcmcia_socket_init,
socket_suspend, pangolin_pcmcia_socket_suspend,
};
int __init pcmcia_pangolin_init(void)
{
int ret = -ENODEV;
if (machine_is_pangolin())
ret = sa1100_register_pcmcia(&pangolin_pcmcia_ops);
return ret;
}
void __exit pcmcia_pangolin_exit(void)
{
sa1100_unregister_pcmcia(&pangolin_pcmcia_ops);
}
This diff is collapsed.
This diff is collapsed.
......@@ -6,10 +6,11 @@
*/
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/arch/pcmcia.h>
#include "sa1100_generic.h"
extern long get_cs3_shadow(void);
extern void set_cs3_bit(int value);
......@@ -19,9 +20,6 @@ extern void clear_cs3_bit(int value);
static int simpad_pcmcia_init(struct pcmcia_init *init){
int irq, res;
/* set GPIO_CF_CD & GPIO_CF_IRQ as inputs */
GPDR &= ~(GPIO_CF_CD|GPIO_CF_IRQ);
set_cs3_bit(PCMCIA_RESET);
clear_cs3_bit(PCMCIA_BUFF_DIS);
clear_cs3_bit(PCMCIA_RESET);
......@@ -29,8 +27,8 @@ static int simpad_pcmcia_init(struct pcmcia_init *init){
clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1);
/* Set transition detect */
set_GPIO_IRQ_edge( GPIO_CF_CD, GPIO_BOTH_EDGES );
set_GPIO_IRQ_edge( GPIO_CF_IRQ, GPIO_FALLING_EDGE );
set_irq_type( IRQ_GPIO_CF_CD, IRQT_NOEDGE );
set_irq_type( IRQ_GPIO_CF_IRQ, IRQT_FALLING );
/* Register interrupts */
irq = IRQ_GPIO_CF_CD;
......@@ -41,8 +39,9 @@ static int simpad_pcmcia_init(struct pcmcia_init *init){
return 2;
irq_err:
printk( KERN_ERR "%s: Request for IRQ %lu failed\n", __FUNCTION__, irq );
return -1;
printk( KERN_ERR "%s: request for IRQ%d failed (%d)\n",
__FUNCTION__, irq, res);
return res;
}
static int simpad_pcmcia_shutdown(void)
......@@ -112,7 +111,7 @@ static int simpad_pcmcia_configure_socket(const struct pcmcia_configure
if(configure->sock==0) return 0;
save_flags_cli(flags);
local_irq_save(flags);
/* Murphy: see table of MIC2562a-1 */
......@@ -135,22 +134,51 @@ static int simpad_pcmcia_configure_socket(const struct pcmcia_configure
printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
configure->vcc);
clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1);
restore_flags(flags);
local_irq_restore(flags);
return -1;
}
/* Silently ignore Vpp, output enable, speaker enable. */
restore_flags(flags);
local_irq_restore(flags);
return 0;
}
static int simpad_pcmcia_socket_init(int sock)
{
set_irq_type(IRQ_GPIO_CF_CD, IRQT_BOTHEDGE);
return 0;
}
static int simpad_pcmcia_socket_suspend(int sock)
{
set_irq_type(IRQ_GPIO_CF_CD, IRQT_NOEDGE);
return 0;
}
struct pcmcia_low_level simpad_pcmcia_ops = {
simpad_pcmcia_init,
simpad_pcmcia_shutdown,
simpad_pcmcia_socket_state,
simpad_pcmcia_get_irq_info,
simpad_pcmcia_configure_socket
static struct pcmcia_low_level simpad_pcmcia_ops = {
init: simpad_pcmcia_init,
shutdown: simpad_pcmcia_shutdown,
socket_state: simpad_pcmcia_socket_state,
get_irq_info: simpad_pcmcia_get_irq_info,
configure_socket: simpad_pcmcia_configure_socket,
socket_init: simpad_pcmcia_socket_init,
socket_suspend: simpad_pcmcia_socket_suspend,
};
int __init pcmcia_simpad_init(void)
{
int ret = -ENODEV;
if (machine_is_simpad())
ret = sa1100_register_pcmcia(&simpad_pcmcia_ops);
return ret;
}
void __exit pcmcia_simpad_exit(void)
{
sa1100_unregister_pcmcia(&simpad_pcmcia_ops);
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment