Hello developers,
in mainline kernel support for trizeps SoM
is now available since several versions now.

now i'd like to commit trizeps pcmcia function 
to kernel mainline. Here is the source code 
for pcmcia on trizeps modules.
 
please feel free to comment and tell me what
do to bring this to mainline kernel.
-- 
Jürgen Schindele
Linux for Trizeps Modules
www.schindele.name
/*
 * linux/drivers/pcmcia/pxa2xx_trizeps4.c
 *
 * TRIZEPS4 PCMCIA specific routines.
 *
 * Author:	Jürgen Schindele
 * Created:	20 02, 2006
 * Copyright:	Jürgen Schindele
 *
 * 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/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>

#include <pcmcia/ss.h>

#include <asm/hardware.h>
#include <asm/irq.h>

#include <asm/arch/pxa-regs.h>
#include <asm/arch/trizeps4.h>

#include "soc_common.h"

extern void board_pcmcia_power(int power);

static struct pcmcia_irqs irqs[] = {
	{ 0, TRIZEPS4_CD_IRQ, "PCMCIA0 CD" }
};

static int trizeps_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
{
    /* we dont have voltage/card/ready detection
     * so we dont need interrupts for it
     * TODO set default state on power
     */
    /*
     * Setup default state of GPIO outputs
     * before we enable them as outputs.
     */
    GPSR(GPIO48_nPOE) =			
	GPIO_bit(GPIO48_nPOE) |
	GPIO_bit(GPIO49_nPWE) |
	GPIO_bit(GPIO50_nPIOR) |
	GPIO_bit(GPIO51_nPIOW) |
	GPIO_bit(GPIO54_nPCE_2);

    GPSR(GPIO102_nPCE_1) = GPIO102_nPCE_1;

    pxa_gpio_mode(GPIO48_nPOE_MD);
    pxa_gpio_mode(GPIO49_nPWE_MD);
    pxa_gpio_mode(GPIO50_nPIOR_MD);
    pxa_gpio_mode(GPIO51_nPIOW_MD);
    pxa_gpio_mode(GPIO102_nPCE_1_MD);
    pxa_gpio_mode(GPIO54_nPCE_2_MD);
    pxa_gpio_mode(GPIO104_pSKTSEL_MD);
    pxa_gpio_mode(GPIO55_nPREG_MD);
    pxa_gpio_mode(GPIO56_nPWAIT_MD);
    pxa_gpio_mode(GPIO57_nIOIS16_MD);
    /* card detect */
    pxa_gpio_mode(GPIO_PCD | GPIO_IN);
    /* card interrupt */
    pxa_gpio_mode(GPIO_PRDY | GPIO_IN);

    switch (skt->nr) {
      case 0:
	skt->irq = TRIZEPS4_READY_NINT;
	break;

      case 1:
      default:
	break;
    }
    /* release the reset of this card */
    /* FIXME Remove Card Reset ?? */
    printk(KERN_DEBUG "%s: sock %d irq %d\n", __FUNCTION__, skt->nr, skt->irq);

    /* supplementory irqs for the socket */
    /* FIXME are interrupts delivered by ConXS Board ?? */
    return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
}

static void trizeps_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
{
    /* nothing to do */
}

static unsigned long trizeps_pcmcia_status[2];

static void trizeps_pcmcia_socket_state(struct soc_pcmcia_socket *skt, struct pcmcia_state *state)
{
    unsigned short status=0, change;
#ifdef CONFIG_MACH_TRIZEPS4_CONXS
    status = ConXS_CFSR; 
    change = (status ^ trizeps_pcmcia_status[skt->nr]) & ConXS_CFSR_BVD_MASK;

    if (change) {
	trizeps_pcmcia_status[skt->nr] = status;
	if (status & ConXS_CFSR_BVD1) {
	    /* enable_irq empty */
	}
	else {
	    /* disable_irq empty */
	}
    }

    switch (skt->nr) {
      case 0:
	/* just fill in fix states */
	state->detect = (GPLR(GPIO_PCD)  & GPIO_bit(GPIO_PCD))  ? 0 : 1;  
	state->ready  = (GPLR(GPIO_PRDY) & GPIO_bit(GPIO_PRDY)) ? 1 : 0; 
	state->bvd1   = (status & ConXS_CFSR_BVD1) ? 1 : 0;
	state->bvd2   = (status & ConXS_CFSR_BVD2) ? 1 : 0;
	state->vs_3v  = (status & ConXS_CFSR_VS1) ? 0 : 1;
	state->vs_Xv  = (status & ConXS_CFSR_VS2) ? 0 : 1;
	state->wrprot = 0;	/* not available */
	break;

      case 1:
	/* on ConXS we only have one slot second is inactive */
	state->detect = 0;
	state->ready  = 0;
	state->bvd1   = 0;
	state->bvd2   = 0;
	state->vs_3v  = 0;
	state->vs_Xv  = 0;
	state->wrprot = 0;
	break;

    }
#endif
}

static int trizeps_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state)
{
    int ret = 0;
    unsigned short power = 0;

    /* we do nothing here just check a bit */
    switch (state->Vcc) {
      case 0:  power &= 0xfc; break;
      case 33: power |= ConXS_BCR_S0_VCC_3V3; break;
      case 50:
	       printk(KERN_ERR "%s(): Vcc 5V not supported in socket\n", __FUNCTION__);
	       break;
      default:
	       printk(KERN_ERR "%s(): bad Vcc %u\n", __FUNCTION__, state->Vcc);
	       ret = -1;
    }

    switch (state->Vpp) {
      case 0:  power &= 0xf3; break;
      case 33: power |= ConXS_BCR_S0_VPP_3V3; break;
      case 120:
	       printk(KERN_ERR "%s(): Vpp 12V not supported in socket\n", __FUNCTION__);
	       break;
      default:
		if(state->Vpp != state->Vcc) {
		    printk(KERN_ERR "%s(): bad Vpp %u\n", __FUNCTION__, state->Vpp);
		    ret = -1;
		}
    }

    switch (skt->nr) {
      case 0:			 /* ony have one socket */
	board_pcmcia_power(power);
	break;

      case 1:			/* do nothing */
      default:
	break;
    }

    return ret;
}

static void trizeps_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
{
    /* default is on */
    board_pcmcia_power(0x9);
}

static void trizeps_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
{
}

static struct pcmcia_low_level trizeps_pcmcia_ops = {
    .owner		= THIS_MODULE,
    .hw_init		= trizeps_pcmcia_hw_init,
    .hw_shutdown	= trizeps_pcmcia_hw_shutdown,
    .socket_state	= trizeps_pcmcia_socket_state,
    .configure_socket	= trizeps_pcmcia_configure_socket,
    .socket_init	= trizeps_pcmcia_socket_init,
    .socket_suspend	= trizeps_pcmcia_socket_suspend,
    .nr			= 2,
    .first		= 0,
};

static struct platform_device *trizeps_pcmcia_device;

static int __init trizeps_pcmcia_init(void)
{
	int ret;

	trizeps_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1);
	if (!trizeps_pcmcia_device)
		return -ENOMEM;

	trizeps_pcmcia_device->dev.platform_data = &trizeps_pcmcia_ops;

	ret = platform_device_add(trizeps_pcmcia_device);

	if (ret)
		platform_device_put(trizeps_pcmcia_device);

	return ret;
}

static void __exit trizeps_pcmcia_exit(void)
{
	platform_device_unregister(trizeps_pcmcia_device);
}

fs_initcall(trizeps_pcmcia_init);
module_exit(trizeps_pcmcia_exit);

MODULE_LICENSE("GPL");
_______________________________________________
Linux PCMCIA reimplementation list
http://lists.infradead.org/mailman/listinfo/linux-pcmcia

Reply via email to