Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.8.
  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 <mach/hx4700.h>
 14
 15#include "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");