Commit fd014d52 authored by Guennadi Liakhovetski's avatar Guennadi Liakhovetski Committed by Russell King

[PATCH] 1096/3: trizeps PCMCIA support

(a minor fix to the previous version - 1096/2)
The enclosed patch includes trizeps-specific PCMCIA code. All
modifications are enclosed in
#ifdef CONFIG_SA1100_TRIZEPS
#endif
blocks or are linked as
+sa1100_cs-objs-        += sa1100_trizeps.o
so, other platforms remain unaffected. The patch is built against
2.5.6-rmk1.
parent 8a34869c
......@@ -71,6 +71,7 @@ sa1100_cs-objs-$(CONFIG_SA1100_PT_SYSTEM3) += sa1100_system3.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_STORK) += sa1100_stork.o
sa1100_cs-objs-$(CONFIG_SA1100_TRIZEPS) += sa1100_trizeps.o
sa1100_cs-objs-$(CONFIG_SA1100_XP860) += sa1100_xp860.o sa1111_generic.o
sa1100_cs-objs-$(CONFIG_SA1100_YOPY) += sa1100_yopy.o
......
......@@ -237,6 +237,9 @@ extern void pcmcia_stork_exit(void);
extern int pcmcia_system3_init(void);
extern void pcmcia_system3_exit(void);
extern int pcmcia_trizeps_init(void);
extern void pcmcia_trizeps_exit(void);
extern int pcmcia_xp860_init(void);
extern void pcmcia_xp860_exit(void);
......
......@@ -1180,6 +1180,9 @@ static int __init sa1100_pcmcia_init(void)
#ifdef CONFIG_SA1100_STORK
pcmcia_stork_init();
#endif
#ifdef CONFIG_SA1100_TRIZEPS
pcmcia_trizeps_init();
#endif
#ifdef CONFIG_SA1100_XP860
pcmcia_xp860_init();
#endif
......
/*
* drivers/pcmcia/sa1100_trizeps.c
*
* PCMCIA implementation routines for Trizeps
*
* Authors:
* Andreas Hofer <ho@dsa-ac.de>,
* Peter Lueg <pl@dsa-ac.de>,
* Guennadi Liakhovetski <gl@dsa-ac.de>
*
*/
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <asm/hardware.h> // included trizeps.h
#include <asm/system.h>
#include <asm/irq.h>
#include "sa1100_generic.h"
#define NUMBER_OF_TRIZEPS_PCMCIA_SLOTS 1
/**
*
*
******************************************************/
static int trizeps_pcmcia_init(struct pcmcia_init *init)
{
int res;
/* Enable CF bus: */
TRIZEPS_BCR_clear(TRIZEPS_BCR1, TRIZEPS_nPCM_ENA_REG);
/* All those are inputs */
GPDR &= ~((GPIO_GPIO(TRIZEPS_GPIO_PCMCIA_CD0))
| (GPIO_GPIO(TRIZEPS_GPIO_PCMCIA_IRQ0)));
/* Set transition detect */
// set_irq_type(SA1100_GPIO_TO_IRQ(GPIO_TRIZEPS_PCMCIA_CD0), IRQT_BOTHEDGE);
set_irq_type(TRIZEPS_IRQ_PCMCIA_IRQ0, IRQT_FALLING);
/* Register SOCKET interrupts */
/* WHY? */
set_irq_type(TRIZEPS_IRQ_PCMCIA_CD0, IRQT_NOEDGE);
res = request_irq( TRIZEPS_IRQ_PCMCIA_CD0, init->handler, SA_INTERRUPT, "PCMCIA_CD0", NULL );
if( res < 0 ) goto irq_err;
//MECR = 0x00060006; // Initialised on trizeps init
// return=sa1100_pcmcia_socket_count (sa1100_generic.c)
// -> number of PCMCIA Slots
// Slot 0 -> Trizeps PCMCIA
// Slot 1 -> Trizeps ISA-Bus
return NUMBER_OF_TRIZEPS_PCMCIA_SLOTS;
irq_err:
printk( KERN_ERR __FUNCTION__ ": PCMCIA Request for IRQ %u failed\n", TRIZEPS_IRQ_PCMCIA_CD0 );
return -1;
}
/**
*
*
******************************************************/
static int trizeps_pcmcia_shutdown(void)
{
printk(">>>>>PCMCIA TRIZEPS shutdown\n");
/* disable IRQs */
free_irq(TRIZEPS_IRQ_PCMCIA_CD0, NULL );
/* Disable CF bus: */
TRIZEPS_BCR_set(TRIZEPS_BCR1, TRIZEPS_nPCM_ENA_REG);
return 0;
}
/**
*
******************************************************/
static int trizeps_pcmcia_socket_state(struct pcmcia_state_array
*state_array){
unsigned long levels;
if (state_array->size < NUMBER_OF_TRIZEPS_PCMCIA_SLOTS) return -1;
memset(state_array->state, 0,
(state_array->size)*sizeof(struct pcmcia_state));
levels = GPLR;
state_array->state[0].detect = ((levels & GPIO_GPIO(TRIZEPS_GPIO_PCMCIA_CD0)) == 0) ? 1 : 0;
state_array->state[0].ready = ((levels & GPIO_GPIO(TRIZEPS_GPIO_PCMCIA_IRQ0)) != 0) ? 1 : 0;
state_array->state[0].bvd1 = ((TRIZEPS_BCR1 & TRIZEPS_PCM_BVD1) !=0 ) ? 1 : 0;
state_array->state[0].bvd2 = ((TRIZEPS_BCR1 & TRIZEPS_PCM_BVD2) != 0) ? 1 : 0;
state_array->state[0].wrprot = 0; // not write protected
state_array->state[0].vs_3v = ((TRIZEPS_BCR1 & TRIZEPS_nPCM_VS1) == 0) ? 1 : 0; //VS1=0 -> vs_3v=1
state_array->state[0].vs_Xv = ((TRIZEPS_BCR1 & TRIZEPS_nPCM_VS2) == 0) ? 1 : 0; //VS2=0 -> vs_Xv=1
return 1; // success
}
/**
*
*
******************************************************/
static int trizeps_pcmcia_get_irq_info(struct pcmcia_irq_info *info){
switch (info->sock) {
case 0:
info->irq=TRIZEPS_IRQ_PCMCIA_IRQ0;
break;
case 1:
// MFTB2 use only one Slot
default:
return -1;
}
return 0;
}
/**
*
*
******************************************************/
static int trizeps_pcmcia_configure_socket(const struct pcmcia_configure *configure)
{
unsigned long flags;
if(configure->sock>1) return -1;
local_irq_save(flags);
switch (configure->vcc) {
case 0:
printk(">>> PCMCIA Power off\n");
TRIZEPS_BCR_clear(TRIZEPS_BCR1, TRIZEPS_PCM_V3_EN_REG);
TRIZEPS_BCR_clear(TRIZEPS_BCR1, TRIZEPS_PCM_V5_EN_REG);
break;
case 33:
// 3.3V Power on
TRIZEPS_BCR_clear(TRIZEPS_BCR1, TRIZEPS_PCM_V3_EN_REG);
TRIZEPS_BCR_set(TRIZEPS_BCR1, TRIZEPS_PCM_V5_EN_REG);
break;
case 50:
// 5.0V Power on
TRIZEPS_BCR_set(TRIZEPS_BCR1, TRIZEPS_PCM_V3_EN_REG);
TRIZEPS_BCR_clear(TRIZEPS_BCR1, TRIZEPS_PCM_V5_EN_REG);
break;
default:
printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
configure->vcc);
local_irq_restore(flags);
return -1;
}
if (configure->reset)
TRIZEPS_BCR_set(TRIZEPS_BCR1, TRIZEPS_nPCM_RESET_DISABLE); // Reset
else
TRIZEPS_BCR_clear(TRIZEPS_BCR1, TRIZEPS_nPCM_RESET_DISABLE); // no Reset
/*
printk(" vcc=%u vpp=%u -->reset=%i\n",
configure->vcc,
configure->vpp,
((BCR_read(1) & nPCM_RESET_DISABLE)? 1:0));
*/
local_irq_restore(flags);
if (configure->irq) {
enable_irq(TRIZEPS_IRQ_PCMCIA_CD0);
enable_irq(TRIZEPS_IRQ_PCMCIA_IRQ0);
} else {
disable_irq(TRIZEPS_IRQ_PCMCIA_IRQ0);
disable_irq(TRIZEPS_IRQ_PCMCIA_CD0);
}
return 0;
}
static int trizeps_pcmcia_socket_init(int sock)
{
return 0;
}
static int trizeps_pcmcia_socket_suspend(int sock)
{
return 0;
}
/**
* low-level PCMCIA interface
*
******************************************************/
struct pcmcia_low_level trizeps_pcmcia_ops = {
init: trizeps_pcmcia_init,
shutdown: trizeps_pcmcia_shutdown,
socket_state: trizeps_pcmcia_socket_state,
get_irq_info: trizeps_pcmcia_get_irq_info,
configure_socket: trizeps_pcmcia_configure_socket,
socket_init: trizeps_pcmcia_socket_init,
socket_suspend: trizeps_pcmcia_socket_suspend,
};
int __init pcmcia_trizeps_init(void)
{
if (machine_is_trizeps()) {
return sa1100_register_pcmcia(&trizeps_pcmcia_ops);
}
return -ENODEV;
}
void __exit pcmcia_trizeps_exit(void)
{
sa1100_unregister_pcmcia(&trizeps_pcmcia_ops);
}
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