cregit-Linux how code gets into the kernel

Release 4.14 drivers/pcmcia/bfin_cf_pcmcia.c

Directory: drivers/pcmcia
/*
 * file: drivers/pcmcia/bfin_cf.c
 *
 * based on: drivers/pcmcia/omap_cf.c
 * omap_cf.c -- OMAP 16xx CompactFlash controller driver
 *
 * Copyright (c) 2005 David Brownell
 * Copyright (c) 2006-2008 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 <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/platform_device.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/io.h>
#include <linux/gpio.h>

#include <pcmcia/ss.h>
#include <pcmcia/cisreg.h>


#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; }

Contributors

PersonTokensPropCommitsCommitProp
Michael Hennerich30100.00%1100.00%
Total30100.00%1100.00%


static int bfin_cf_ss_init(struct pcmcia_socket *s) { return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Michael Hennerich14100.00%1100.00%
Total14100.00%1100.00%

/* 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; dev_dbg(&cf->pdev->dev, ": card %s\n", present ? "present" : "gone"); pcmcia_parse_events(&cf->socket, SS_DETECT); } if (cf->active) mod_timer(&cf->timer, jiffies + POLL_INTERVAL); }

Contributors

PersonTokensPropCommitsCommitProp
Michael Hennerich94100.00%1100.00%
Total94100.00%1100.00%


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->pcmcia_irq = 0; s->pci_irq = cf->irq; } else *sp = 0; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Michael Hennerich8598.84%150.00%
Dominik Brodowski11.16%150.00%
Total86100.00%2100.00%


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); } dev_dbg(&cf->pdev->dev, ": Vcc %d, io_irq %d, flags %04x csc %04x\n", s->Vcc, s->io_irq, s->flags, s->csc_mask); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Michael Hennerich115100.00%1100.00%
Total115100.00%1100.00%


static int bfin_cf_ss_suspend(struct pcmcia_socket *s) { return bfin_cf_set_socket(s, &dead_socket); }

Contributors

PersonTokensPropCommitsCommitProp
Michael Hennerich20100.00%1100.00%
Total20100.00%1100.00%

/* 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; }

Contributors

PersonTokensPropCommitsCommitProp
Michael Hennerich66100.00%1100.00%
Total66100.00%1100.00%


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; }

Contributors

PersonTokensPropCommitsCommitProp
Michael Hennerich80100.00%1100.00%
Total80100.00%1100.00%

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 bfin_cf_probe(struct platform_device *pdev) { struct bfin_cf_socket *cf; struct resource *io_mem, *attr_mem; int irq; unsigned short cd_pfx; int status = 0; dev_info(&pdev->dev, "Blackfin CompactFlash/PCMCIA Socket Driver\n"); irq = platform_get_irq(pdev, 0); if (irq <= 0) return -EINVAL; cd_pfx = platform_get_irq(pdev, 1); /*Card Detect GPIO PIN */ if (gpio_request(cd_pfx, "pcmcia: CD")) { dev_err(&pdev->dev, "Failed ro request Card Detect GPIO_%d\n", cd_pfx); return -EBUSY; } gpio_direction_input(cd_pfx); cf = kzalloc(sizeof *cf, GFP_KERNEL); if (!cf) { gpio_free(cd_pfx); return -ENOMEM; } cf->cd_pfx = cd_pfx; setup_timer(&cf->timer, bfin_cf_timer, (unsigned long)cf); cf->pdev = pdev; platform_set_drvdata(pdev, cf); cf->irq = irq; cf->socket.pci_irq = 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; dev_err(&pdev->dev, ": on irq %d\n", irq); dev_dbg(&pdev->dev, ": %s\n", bfin_cf_present(cf->cd_pfx) ? "present" : "(not present)"); cf->socket.owner = THIS_MODULE; cf->socket.dev.parent = &pdev->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: gpio_free(cf->cd_pfx); kfree(cf); platform_set_drvdata(pdev, NULL); return status; }

Contributors

PersonTokensPropCommitsCommitProp
Michael Hennerich44999.34%133.33%
Uwe Kleine-König20.44%133.33%
Thomas Gleixner10.22%133.33%
Total452100.00%3100.00%


static int bfin_cf_remove(struct platform_device *pdev) { struct bfin_cf_socket *cf = platform_get_drvdata(pdev); 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); platform_set_drvdata(pdev, NULL); kfree(cf); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Michael Hennerich88100.00%1100.00%
Total88100.00%1100.00%

static struct platform_driver bfin_cf_driver = { .driver = { .name = driver_name, }, .probe = bfin_cf_probe, .remove = bfin_cf_remove, }; module_platform_driver(bfin_cf_driver); MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); MODULE_DESCRIPTION("BFIN CF/PCMCIA Driver"); MODULE_LICENSE("GPL");

Overall Contributors

PersonTokensPropCommitsCommitProp
Michael Hennerich124698.97%112.50%
Tejun Heo30.24%112.50%
Björn Helgaas30.24%112.50%
Uwe Kleine-König20.16%112.50%
Axel Lin20.16%112.50%
Thomas Gleixner10.08%112.50%
Mike Frysinger10.08%112.50%
Dominik Brodowski10.08%112.50%
Total1259100.00%8100.00%
Directory: drivers/pcmcia
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.