cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

hx4700-pcmcia.c (2985B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 *  Copyright (C) 2012 Paul Parsons <lost.distance@yahoo.com>
      4 */
      5
      6#include <linux/module.h>
      7#include <linux/platform_device.h>
      8#include <linux/err.h>
      9#include <linux/gpio.h>
     10#include <linux/irq.h>
     11
     12#include <asm/mach-types.h>
     13#include "hx4700.h"
     14
     15#include <pcmcia/soc_common.h>
     16
     17static struct gpio gpios[] = {
     18	{ GPIO114_HX4700_CF_RESET,    GPIOF_OUT_INIT_LOW,   "CF reset"        },
     19	{ EGPIO4_CF_3V3_ON,           GPIOF_OUT_INIT_LOW,   "CF 3.3V enable"  },
     20};
     21
     22static int hx4700_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
     23{
     24	int ret;
     25
     26	ret = gpio_request_array(gpios, ARRAY_SIZE(gpios));
     27	if (ret)
     28		goto out;
     29
     30	/*
     31	 * IRQ type must be set before soc_pcmcia_hw_init() calls request_irq().
     32	 * The asic3 default IRQ type is level trigger low level detect, exactly
     33	 * the the signal present on GPIOD4_CF_nCD when a CF card is inserted.
     34	 * If the IRQ type is not changed, the asic3 interrupt handler will loop
     35	 * repeatedly because it is unable to clear the level trigger interrupt.
     36	 */
     37	irq_set_irq_type(gpio_to_irq(GPIOD4_CF_nCD), IRQ_TYPE_EDGE_BOTH);
     38
     39	skt->stat[SOC_STAT_CD].gpio = GPIOD4_CF_nCD;
     40	skt->stat[SOC_STAT_CD].name = "PCMCIA CD";
     41	skt->stat[SOC_STAT_RDY].gpio = GPIO60_HX4700_CF_RNB;
     42	skt->stat[SOC_STAT_RDY].name = "PCMCIA Ready";
     43
     44out:
     45	return ret;
     46}
     47
     48static void hx4700_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
     49{
     50	gpio_free_array(gpios, ARRAY_SIZE(gpios));
     51}
     52
     53static void hx4700_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
     54	struct pcmcia_state *state)
     55{
     56	state->vs_3v = 1;
     57	state->vs_Xv = 0;
     58}
     59
     60static int hx4700_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
     61	const socket_state_t *state)
     62{
     63	switch (state->Vcc) {
     64	case 0:
     65		gpio_set_value(EGPIO4_CF_3V3_ON, 0);
     66		break;
     67	case 33:
     68		gpio_set_value(EGPIO4_CF_3V3_ON, 1);
     69		break;
     70	default:
     71		printk(KERN_ERR "pcmcia: Unsupported Vcc: %d\n", state->Vcc);
     72		return -EINVAL;
     73	}
     74
     75	gpio_set_value(GPIO114_HX4700_CF_RESET, (state->flags & SS_RESET) != 0);
     76
     77	return 0;
     78}
     79
     80static struct pcmcia_low_level hx4700_pcmcia_ops = {
     81	.owner          = THIS_MODULE,
     82	.nr             = 1,
     83	.hw_init        = hx4700_pcmcia_hw_init,
     84	.hw_shutdown    = hx4700_pcmcia_hw_shutdown,
     85	.socket_state   = hx4700_pcmcia_socket_state,
     86	.configure_socket = hx4700_pcmcia_configure_socket,
     87};
     88
     89static struct platform_device *hx4700_pcmcia_device;
     90
     91static int __init hx4700_pcmcia_init(void)
     92{
     93	struct platform_device *pdev;
     94
     95	if (!machine_is_h4700())
     96		return -ENODEV;
     97
     98	pdev = platform_device_register_data(NULL, "pxa2xx-pcmcia", -1,
     99		&hx4700_pcmcia_ops, sizeof(hx4700_pcmcia_ops));
    100	if (IS_ERR(pdev))
    101		return PTR_ERR(pdev);
    102
    103	hx4700_pcmcia_device = pdev;
    104
    105	return 0;
    106}
    107
    108static void __exit hx4700_pcmcia_exit(void)
    109{
    110	platform_device_unregister(hx4700_pcmcia_device);
    111}
    112
    113module_init(hx4700_pcmcia_init);
    114module_exit(hx4700_pcmcia_exit);
    115
    116MODULE_AUTHOR("Paul Parsons <lost.distance@yahoo.com>");
    117MODULE_DESCRIPTION("HP iPAQ hx4700 PCMCIA driver");
    118MODULE_LICENSE("GPL");