[PATCH 1/1] [PCMCIA]: add support the CF PCMCIA driver for Blackfin - Kernel

This is a discussion on [PATCH 1/1] [PCMCIA]: add support the CF PCMCIA driver for Blackfin - Kernel ; From: Michael Hennerich Signed-off-by: Michael Hennerich Signed-off-by: Bryan Wu --- drivers/pcmcia/Kconfig | 7 + drivers/pcmcia/Makefile | 1 + drivers/pcmcia/bfin_cf_pcmcia.c | 324 +++++++++++++++++++++++++++++++++++++++ include/pcmcia/cs_types.h | 2 +- 4 files changed, 333 insertions(+), 1 deletions(-) create mode 100644 drivers/pcmcia/bfin_cf_pcmcia.c diff --git a/drivers/pcmcia/Kconfig ...

+ Reply to Thread
Results 1 to 3 of 3

Thread: [PATCH 1/1] [PCMCIA]: add support the CF PCMCIA driver for Blackfin

  1. [PATCH 1/1] [PCMCIA]: add support the CF PCMCIA driver for Blackfin

    From: Michael Hennerich

    Signed-off-by: Michael Hennerich
    Signed-off-by: Bryan Wu
    ---
    drivers/pcmcia/Kconfig | 7 +
    drivers/pcmcia/Makefile | 1 +
    drivers/pcmcia/bfin_cf_pcmcia.c | 324 +++++++++++++++++++++++++++++++++++++++
    include/pcmcia/cs_types.h | 2 +-
    4 files changed, 333 insertions(+), 1 deletions(-)
    create mode 100644 drivers/pcmcia/bfin_cf_pcmcia.c

    diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
    index 1b0eb5a..e45402a 100644
    --- a/drivers/pcmcia/Kconfig
    +++ b/drivers/pcmcia/Kconfig
    @@ -263,6 +263,13 @@ config OMAP_CF
    Say Y here to support the CompactFlash controller on OMAP.
    Note that this doesn't support "True IDE" mode.

    +config BFIN_CFPCMCIA
    + tristate "Blackfin CompactFlash PCMCIA Driver"
    + depends on PCMCIA && BLACKFIN
    + help
    + Say Y here to support the CompactFlash PCMCIA driver for Blackfin.
    +
    +
    config AT91_CF
    tristate "AT91 CompactFlash Controller"
    depends on PCMCIA && ARCH_AT91RM9200
    diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile
    index 6f6478b..85c6cc9 100644
    --- a/drivers/pcmcia/Makefile
    +++ b/drivers/pcmcia/Makefile
    @@ -36,6 +36,7 @@ obj-$(CONFIG_PCMCIA_AU1X00) += au1x00_ss.o
    obj-$(CONFIG_PCMCIA_VRC4171) += vrc4171_card.o
    obj-$(CONFIG_PCMCIA_VRC4173) += vrc4173_cardu.o
    obj-$(CONFIG_OMAP_CF) += omap_cf.o
    +obj-$(CONFIG_BFIN_CFPCMCIA) += bfin_cf_pcmcia.o
    obj-$(CONFIG_AT91_CF) += at91_cf.o
    obj-$(CONFIG_ELECTRA_CF) += electra_cf.o

    diff --git a/drivers/pcmcia/bfin_cf_pcmcia.c b/drivers/pcmcia/bfin_cf_pcmcia.c
    new file mode 100644
    index 0000000..7964675
    --- /dev/null
    +++ b/drivers/pcmcia/bfin_cf_pcmcia.c
    @@ -0,0 +1,324 @@
    +/*
    + * file: drivers/pcmcia/bfin_cf.c
    + * author: Michael Hennerich (hennerich@blackfin.uclinux.org)
    + *
    + * based on: drivers/pcmcia/omap_cf.c
    + * omap_cf.c -- OMAP 16xx CompactFlash controller driver
    + *
    + * Copyright (c) 2005 David Brownell
    + * Copyright (c) 2006 Michael Hennerich Analog Devices Inc.
    + *
    + * bugs: enter bugs at http://blackfin.uclinux.org/
    + *
    + * this program is free software; you can redistribute it and/or modify
    + * it under the terms of the gnu general public license as published by
    + * the free software foundation; either version 2, or (at your option)
    + * any later version.
    + *
    + * this program is distributed in the hope that it will be useful,
    + * but without any warranty; without even the implied warranty of
    + * merchantability or fitness for a particular purpose. see the
    + * gnu general public license for more details.
    + *
    + * you should have received a copy of the gnu general public license
    + * along with this program; see the file copying.
    + * if not, write to the free software foundation,
    + * 59 temple place - suite 330, boston, ma 02111-1307, usa.
    + */
    +
    +#include
    +#include
    +#include
    +#include
    +#include
    +#include
    +#include
    +#include
    +#include
    +
    +#include
    +#include
    +#include
    +#include
    +
    +#define SZ_1K 0x00000400
    +#define SZ_8K 0x00002000
    +#define SZ_2K (2 * SZ_1K)
    +
    +#define POLL_INTERVAL (2 * HZ)
    +
    +#define CF_ATASEL_ENA 0x20311802 /* Inverts RESET */
    +#define CF_ATASEL_DIS 0x20311800
    +
    +#define bfin_cf_present(pfx) (gpio_get_value(pfx))
    +
    +/*--------------------------------------------------------------------------*/
    +
    +static const char driver_name[] = "bfin_cf_pcmcia";
    +
    +struct bfin_cf_socket {
    + struct pcmcia_socket socket;
    +
    + struct timer_list timer;
    + unsigned present:1;
    + unsigned active:1;
    +
    + struct platform_device *pdev;
    + unsigned long phys_cf_io;
    + unsigned long phys_cf_attr;
    + u_int irq;
    + u_short cd_pfx;
    +};
    +
    +/*--------------------------------------------------------------------------*/
    +static int bfin_cf_reset(void)
    +{
    + outw(0, CF_ATASEL_ENA);
    + mdelay(200);
    + outw(0, CF_ATASEL_DIS);
    +
    + return 0;
    +
    +}
    +
    +static int bfin_cf_ss_init(struct pcmcia_socket *s)
    +{
    + return 0;
    +}
    +
    +/* the timer is primarily to kick this socket's pccardd */
    +static void bfin_cf_timer(unsigned long _cf)
    +{
    + struct bfin_cf_socket *cf = (void *) _cf;
    + unsigned short present = bfin_cf_present(cf->cd_pfx);
    +
    + if (present != cf->present) {
    + cf->present = present;
    + pr_debug("%s: card %s\n", driver_name,
    + present ? "present" : "gone");
    + pcmcia_parse_events(&cf->socket, SS_DETECT);
    + }
    +
    + if (cf->active)
    + mod_timer(&cf->timer, jiffies + POLL_INTERVAL);
    +}
    +
    +static int bfin_cf_get_status(struct pcmcia_socket *s, u_int *sp)
    +{
    + struct bfin_cf_socket *cf;
    +
    + if (!sp)
    + return -EINVAL;
    +
    + cf = container_of(s, struct bfin_cf_socket, socket);
    +
    + if (bfin_cf_present(cf->cd_pfx)) {
    + *sp = SS_READY | SS_DETECT | SS_POWERON | SS_3VCARD;
    + s->irq.AssignedIRQ = 0;
    + s->pci_irq = cf->irq;
    +
    + } else
    + *sp = 0;
    + return 0;
    +}
    +
    +static int
    +bfin_cf_set_socket(struct pcmcia_socket *sock, struct socket_state_t *s)
    +{
    +
    + struct bfin_cf_socket *cf;
    + cf = container_of(sock, struct bfin_cf_socket, socket);
    +
    + switch (s->Vcc) {
    + case 0:
    + case 33:
    + break;
    + case 50:
    + break;
    + default:
    + return -EINVAL;
    + }
    +
    + if (s->flags & SS_RESET){
    + disable_irq(cf->irq);
    + bfin_cf_reset();
    + enable_irq(cf->irq);
    + }
    +
    + pr_debug("%s: Vcc %d, io_irq %d, flags %04x csc %04x\n",
    + driver_name, s->Vcc, s->io_irq, s->flags, s->csc_mask);
    +
    + return 0;
    +}
    +
    +static int bfin_cf_ss_suspend(struct pcmcia_socket *s)
    +{
    + pr_debug("%s: %s\n", driver_name, __FUNCTION__);
    + return bfin_cf_set_socket(s, &dead_socket);
    +}
    +
    +/* regions are 2K each: mem, attrib, io (and reserved-for-ide) */
    +
    +static int bfin_cf_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io)
    +{ struct bfin_cf_socket *cf;
    +
    + cf = container_of(s, struct bfin_cf_socket, socket);
    + io->flags &= MAP_ACTIVE|MAP_ATTRIB|MAP_16BIT;
    + io->start = cf->phys_cf_io;
    + io->stop = io->start + SZ_2K - 1;
    + return 0;
    +}
    +
    +static int
    +bfin_cf_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *map)
    +{
    + struct bfin_cf_socket *cf;
    +
    + if (map->card_start)
    + return -EINVAL;
    + cf = container_of(s, struct bfin_cf_socket, socket);
    + map->static_start = cf->phys_cf_io;
    + map->flags &= MAP_ACTIVE|MAP_ATTRIB|MAP_16BIT;
    + if (map->flags & MAP_ATTRIB)
    + map->static_start = cf->phys_cf_attr;
    +
    + return 0;
    +}
    +
    +static struct pccard_operations bfin_cf_ops = {
    + .init = bfin_cf_ss_init,
    + .suspend = bfin_cf_ss_suspend,
    + .get_status = bfin_cf_get_status,
    + .set_socket = bfin_cf_set_socket,
    + .set_io_map = bfin_cf_set_io_map,
    + .set_mem_map = bfin_cf_set_mem_map,
    +};
    +
    +/*--------------------------------------------------------------------------*/
    +
    +static int __init bfin_cf_probe(struct device *dev)
    +{
    + struct bfin_cf_socket *cf;
    + struct platform_device *pdev = to_platform_device(dev);
    + struct resource *io_mem,*attr_mem;
    + int irq;
    + unsigned short cd_pfx;
    + int status = 0;
    +
    + printk(KERN_INFO "Blackfin CompactFlash/PCMCIA Socket Driver\n");
    +
    + irq = platform_get_irq(pdev, 0);
    + if (!irq)
    + return -EINVAL;
    +
    + cd_pfx = platform_get_irq(pdev, 1); /*Card Detect GPIO PIN*/
    + if (cd_pfx > MAX_BLACKFIN_GPIOS)
    + return -EINVAL;
    +
    + if (gpio_request(cd_pfx, "pcmcia: CD")) {
    + printk(KERN_ERR "BF5xx flash: Failed ro request Card Detect GPIO_%d\n", cd_pfx);
    + return -EBUSY;
    + }
    + gpio_direction_input(cd_pfx);
    +
    + cf = kcalloc(1, sizeof *cf, GFP_KERNEL);
    + if (!cf)
    + return -ENOMEM;
    +
    + cf->cd_pfx = cd_pfx;
    +
    + init_timer(&cf->timer);
    + cf->timer.function = bfin_cf_timer;
    + cf->timer.data = (unsigned long) cf;
    +
    + cf->pdev = pdev;
    + dev_set_drvdata(dev, cf);
    +
    + cf->irq = irq;
    + cf->socket.pci_irq = irq;
    +
    + set_irq_type(irq, IRQF_TRIGGER_LOW);
    +
    + io_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    + attr_mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
    +
    + if (!io_mem || !attr_mem)
    + goto fail0;
    +
    + cf->phys_cf_io = io_mem->start;
    + cf->phys_cf_attr = attr_mem->start;
    +
    + /* pcmcia layer only remaps "real" memory */
    + cf->socket.io_offset = (unsigned long)
    + ioremap(cf->phys_cf_io, SZ_2K);
    +
    + if (!cf->socket.io_offset)
    + goto fail0;
    +
    + pr_info("%s: on irq %d\n", driver_name, irq);
    +
    + pr_debug("%s: %s\n", driver_name, bfin_cf_present(cf->cd_pfx) ? "present" : "(not present)");
    +
    + cf->socket.owner = THIS_MODULE;
    + cf->socket.dev.parent = dev;
    + cf->socket.ops = &bfin_cf_ops;
    + cf->socket.resource_ops = &pccard_static_ops;
    + cf->socket.features = SS_CAP_PCCARD | SS_CAP_STATIC_MAP
    + | SS_CAP_MEM_ALIGN;
    + cf->socket.map_size = SZ_2K;
    +
    + status = pcmcia_register_socket(&cf->socket);
    + if (status < 0)
    + goto fail2;
    +
    + cf->active = 1;
    + mod_timer(&cf->timer, jiffies + POLL_INTERVAL);
    + return 0;
    +
    +fail2:
    + iounmap((void __iomem *) cf->socket.io_offset);
    + release_mem_region(cf->phys_cf_io, SZ_8K);
    +
    +fail0:
    + kfree(cf);
    + return status;
    +}
    +
    +static int __devexit bfin_cf_remove(struct device *dev)
    +{
    + struct bfin_cf_socket *cf = dev_get_drvdata(dev);
    +
    + gpio_free(cf->cd_pfx);
    + cf->active = 0;
    + pcmcia_unregister_socket(&cf->socket);
    + del_timer_sync(&cf->timer);
    + iounmap((void __iomem *) cf->socket.io_offset);
    + release_mem_region(cf->phys_cf_io, SZ_8K);
    + kfree(cf);
    + return 0;
    +}
    +
    +static struct device_driver bfin_cf_driver = {
    + .name = (char *) driver_name,
    + .bus = &platform_bus_type,
    + .probe = bfin_cf_probe,
    + .remove = __devexit_p(bfin_cf_remove),
    + .suspend = pcmcia_socket_dev_suspend,
    + .resume = pcmcia_socket_dev_resume,
    +};
    +
    +static int __init bfin_cf_init(void)
    +{
    + return driver_register(&bfin_cf_driver);
    +}
    +
    +static void __exit bfin_cf_exit(void)
    +{
    + driver_unregister(&bfin_cf_driver);
    +}
    +
    +module_init(bfin_cf_init);
    +module_exit(bfin_cf_exit);
    +
    +MODULE_DESCRIPTION("BFIN CF/PCMCIA Driver");
    +MODULE_LICENSE("GPL");
    diff --git a/include/pcmcia/cs_types.h b/include/pcmcia/cs_types.h
    index 9a6bcc4..c3257c1 100644
    --- a/include/pcmcia/cs_types.h
    +++ b/include/pcmcia/cs_types.h
    @@ -21,7 +21,7 @@
    #include
    #endif

    -#if defined(__arm__) || defined(__mips__) || defined(__avr32__)
    +#if defined(__arm__) || defined(__mips__) || defined(__avr32__) || defined(bfin)
    /* This (ioaddr_t) is exposed to userspace & hence cannot be changed. */
    typedef u_int ioaddr_t;
    #else
    --
    1.5.5

    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  2. Re: [PATCH 1/1] [PCMCIA]: add support the CF PCMCIA driver for Blackfin

    On Mon, May 12, 2008 at 06:46:40PM +0800, Bryan Wu wrote:
    > +static struct device_driver bfin_cf_driver = {
    > + .name = (char *) driver_name,
    > + .bus = &platform_bus_type,
    > + .probe = bfin_cf_probe,
    > + .remove = __devexit_p(bfin_cf_remove),
    > + .suspend = pcmcia_socket_dev_suspend,
    > + .resume = pcmcia_socket_dev_resume,
    > +};


    NAK. All platform device drivers must be of type 'struct platform_driver'.

    --
    Russell King
    Linux kernel 2.6 ARM Linux - http://www.arm.linux.org.uk/
    maintainer of:
    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  3. RE: [PATCH 1/1] [PCMCIA]: add support the CF PCMCIA driver for Blackfin

    >-----Original Message-----
    >From: Russell King [mailto:rmk@arm.linux.org.uk] On Behalf Of Russell

    King
    >Sent: Montag, 12. Mai 2008 13:37
    >To: Bryan Wu
    >Cc: linux-pcmcia@lists.infradead.org; linux-kernel@vger.kernel.org;

    Michael
    >Hennerich
    >Subject: Re: [PATCH 1/1] [PCMCIA]: add support the CF PCMCIA driver for
    >Blackfin
    >
    >On Mon, May 12, 2008 at 06:46:40PM +0800, Bryan Wu wrote:
    >> +static struct device_driver bfin_cf_driver = {
    >> + .name = (char *) driver_name,
    >> + .bus = &platform_bus_type,
    >> + .probe = bfin_cf_probe,
    >> + .remove = __devexit_p(bfin_cf_remove),
    >> + .suspend = pcmcia_socket_dev_suspend,
    >> + .resume = pcmcia_socket_dev_resume,
    >> +};

    >
    >NAK. All platform device drivers must be of type 'struct

    platform_driver'.

    Haven't looked at the code since a great while...

    ACK - were going to update.

    Best regards,
    Michael


    >
    >--
    >Russell King
    > Linux kernel 2.6 ARM Linux - http://www.arm.linux.org.uk/
    > maintainer of:

    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

+ Reply to Thread