linux/drivers/pcmcia/pxa2xx_stargate2.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * linux/drivers/pcmcia/pxa2xx_stargate2.c
   4 *
   5 * Stargate 2 PCMCIA specific routines.
   6 *
   7 * Created:     December 6, 2005
   8 * Author:      Ed C. Epp
   9 * Copyright:   Intel Corp 2005
  10 *              Jonathan Cameron <jic23@cam.ac.uk> 2009
  11 */
  12
  13#include <linux/module.h>
  14#include <linux/init.h>
  15#include <linux/kernel.h>
  16#include <linux/interrupt.h>
  17#include <linux/delay.h>
  18#include <linux/platform_device.h>
  19#include <linux/gpio.h>
  20
  21#include <pcmcia/ss.h>
  22
  23#include <asm/irq.h>
  24#include <asm/mach-types.h>
  25
  26#include "soc_common.h"
  27
  28#define SG2_S0_POWER_CTL        108
  29#define SG2_S0_GPIO_RESET       82
  30#define SG2_S0_GPIO_DETECT      53
  31#define SG2_S0_GPIO_READY       81
  32
  33static struct gpio sg2_pcmcia_gpios[] = {
  34        { SG2_S0_GPIO_RESET, GPIOF_OUT_INIT_HIGH, "PCMCIA Reset" },
  35        { SG2_S0_POWER_CTL, GPIOF_OUT_INIT_HIGH, "PCMCIA Power Ctrl" },
  36};
  37
  38static int sg2_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
  39{
  40        skt->stat[SOC_STAT_CD].gpio = SG2_S0_GPIO_DETECT;
  41        skt->stat[SOC_STAT_CD].name = "PCMCIA0 CD";
  42        skt->stat[SOC_STAT_RDY].gpio = SG2_S0_GPIO_READY;
  43        skt->stat[SOC_STAT_RDY].name = "PCMCIA0 RDY";
  44        return 0;
  45}
  46
  47static void sg2_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
  48                                    struct pcmcia_state *state)
  49{
  50        state->bvd1   = 0; /* not available - battery detect on card */
  51        state->bvd2   = 0; /* not available */
  52        state->vs_3v  = 1; /* not available - voltage detect for card */
  53        state->vs_Xv  = 0; /* not available */
  54}
  55
  56static int sg2_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
  57                                       const socket_state_t *state)
  58{
  59        /* Enable card power */
  60        switch (state->Vcc) {
  61        case 0:
  62                /* sets power ctl register high */
  63                gpio_set_value(SG2_S0_POWER_CTL, 1);
  64                break;
  65        case 33:
  66        case 50:
  67                /* sets power control register low (clear) */
  68                gpio_set_value(SG2_S0_POWER_CTL, 0);
  69                msleep(100);
  70                break;
  71        default:
  72                pr_err("%s(): bad Vcc %u\n",
  73                       __func__, state->Vcc);
  74                return -1;
  75        }
  76
  77        /* reset */
  78        gpio_set_value(SG2_S0_GPIO_RESET, !!(state->flags & SS_RESET));
  79
  80        return 0;
  81}
  82
  83static struct pcmcia_low_level sg2_pcmcia_ops __initdata = {
  84        .owner                  = THIS_MODULE,
  85        .hw_init                = sg2_pcmcia_hw_init,
  86        .socket_state           = sg2_pcmcia_socket_state,
  87        .configure_socket       = sg2_pcmcia_configure_socket,
  88        .nr                     = 1,
  89};
  90
  91static struct platform_device *sg2_pcmcia_device;
  92
  93static int __init sg2_pcmcia_init(void)
  94{
  95        int ret;
  96
  97        if (!machine_is_stargate2())
  98                return -ENODEV;
  99
 100        sg2_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1);
 101        if (!sg2_pcmcia_device)
 102                return -ENOMEM;
 103
 104        ret = gpio_request_array(sg2_pcmcia_gpios, ARRAY_SIZE(sg2_pcmcia_gpios));
 105        if (ret)
 106                goto error_put_platform_device;
 107
 108        ret = platform_device_add_data(sg2_pcmcia_device,
 109                                       &sg2_pcmcia_ops,
 110                                       sizeof(sg2_pcmcia_ops));
 111        if (ret)
 112                goto error_free_gpios;
 113
 114        ret = platform_device_add(sg2_pcmcia_device);
 115        if (ret)
 116                goto error_free_gpios;
 117
 118        return 0;
 119error_free_gpios:
 120        gpio_free_array(sg2_pcmcia_gpios, ARRAY_SIZE(sg2_pcmcia_gpios));
 121error_put_platform_device:
 122        platform_device_put(sg2_pcmcia_device);
 123
 124        return ret;
 125}
 126
 127static void __exit sg2_pcmcia_exit(void)
 128{
 129        platform_device_unregister(sg2_pcmcia_device);
 130        gpio_free_array(sg2_pcmcia_gpios, ARRAY_SIZE(sg2_pcmcia_gpios));
 131}
 132
 133fs_initcall(sg2_pcmcia_init);
 134module_exit(sg2_pcmcia_exit);
 135
 136MODULE_LICENSE("GPL");
 137MODULE_ALIAS("platform:pxa2xx-pcmcia");
 138