blob: b19b8161395b6990b3df4edda87247e27feb03b3 [file] [log] [blame]
Marcelo Roberto Jimenezfa876722010-10-18 22:41:29 +01001/*
2 * drivers/pcmcia/sa1100_nanoengine.c
3 *
4 * PCMCIA implementation routines for BSI nanoEngine.
5 *
6 * In order to have a fully functional pcmcia subsystem in a BSE nanoEngine
7 * board you should carefully read this:
8 * http://cambuca.ldhs.cetuc.puc-rio.br/nanoengine/
9 *
10 * Copyright (C) 2010 Marcelo Roberto Jimenez <mroberto@cpti.cetuc.puc-rio.br>
11 *
12 * Based on original work for kernel 2.4 by
13 * Miguel Freitas <miguel@cpti.cetuc.puc-rio.br>
14 *
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License version 2 as
17 * published by the Free Software Foundation.
18 *
19 */
20#include <linux/device.h>
21#include <linux/errno.h>
22#include <linux/interrupt.h>
23#include <linux/irq.h>
24#include <linux/init.h>
25#include <linux/kernel.h>
26#include <linux/module.h>
27#include <linux/signal.h>
28
29#include <asm/mach-types.h>
30#include <asm/irq.h>
31
32#include <mach/hardware.h>
33#include <mach/nanoengine.h>
34
35#include "sa1100_generic.h"
36
Marcelo Roberto Jimenezfa876722010-10-18 22:41:29 +010037struct nanoengine_pins {
Marcelo Roberto Jimenezfa876722010-10-18 22:41:29 +010038 unsigned output_pins;
39 unsigned clear_outputs;
Russell King7cf779c2012-01-13 23:05:12 +000040 int gpio_cd;
41 int gpio_rdy;
Marcelo Roberto Jimenezfa876722010-10-18 22:41:29 +010042};
43
44static struct nanoengine_pins nano_skts[] = {
45 {
Marcelo Roberto Jimenezfa876722010-10-18 22:41:29 +010046 .output_pins = GPIO_PC_RESET0,
47 .clear_outputs = GPIO_PC_RESET0,
Russell King7cf779c2012-01-13 23:05:12 +000048 .gpio_cd = GPIO_PC_CD0,
49 .gpio_rdy = GPIO_PC_READY0,
Marcelo Roberto Jimenezfa876722010-10-18 22:41:29 +010050 }, {
Marcelo Roberto Jimenezfa876722010-10-18 22:41:29 +010051 .output_pins = GPIO_PC_RESET1,
52 .clear_outputs = GPIO_PC_RESET1,
Russell King7cf779c2012-01-13 23:05:12 +000053 .gpio_cd = GPIO_PC_CD1,
54 .gpio_rdy = GPIO_PC_READY1,
Marcelo Roberto Jimenezfa876722010-10-18 22:41:29 +010055 }
56};
57
58unsigned num_nano_pcmcia_sockets = ARRAY_SIZE(nano_skts);
59
60static int nanoengine_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
61{
62 unsigned i = skt->nr;
63
64 if (i >= num_nano_pcmcia_sockets)
65 return -ENXIO;
66
Marcelo Roberto Jimenezfa876722010-10-18 22:41:29 +010067 GPDR |= nano_skts[i].output_pins;
68 GPCR = nano_skts[i].clear_outputs;
Marcelo Roberto Jimenezfa876722010-10-18 22:41:29 +010069
Russell King7cf779c2012-01-13 23:05:12 +000070 skt->stat[SOC_STAT_CD].gpio = nano_skts[i].gpio_cd;
71 skt->stat[SOC_STAT_CD].name = i ? "PC CD1" : "PC CD0";
72 skt->stat[SOC_STAT_RDY].gpio = nano_skts[i].gpio_rdy;
73 skt->stat[SOC_STAT_RDY].name = i ? "PC RDY1" : "PC RDY0";
Marcelo Roberto Jimenezfa876722010-10-18 22:41:29 +010074
Russell King7cf779c2012-01-13 23:05:12 +000075 return 0;
Marcelo Roberto Jimenezfa876722010-10-18 22:41:29 +010076}
77
78static int nanoengine_pcmcia_configure_socket(
79 struct soc_pcmcia_socket *skt, const socket_state_t *state)
80{
81 unsigned reset;
82 unsigned i = skt->nr;
83
84 if (i >= num_nano_pcmcia_sockets)
85 return -ENXIO;
86
87 switch (i) {
88 case 0:
89 reset = GPIO_PC_RESET0;
90 break;
91 case 1:
92 reset = GPIO_PC_RESET1;
93 break;
94 default:
95 return -ENXIO;
96 }
97
98 if (state->flags & SS_RESET)
99 GPSR = reset;
100 else
101 GPCR = reset;
102
103 return 0;
104}
105
106static void nanoengine_pcmcia_socket_state(
107 struct soc_pcmcia_socket *skt, struct pcmcia_state *state)
108{
Marcelo Roberto Jimenezfa876722010-10-18 22:41:29 +0100109 unsigned i = skt->nr;
110
111 if (i >= num_nano_pcmcia_sockets)
112 return;
113
Marcelo Roberto Jimenezfa876722010-10-18 22:41:29 +0100114 state->bvd1 = 1;
115 state->bvd2 = 1;
116 state->wrprot = 0; /* Not available */
117 state->vs_3v = 1; /* Can only apply 3.3V */
118 state->vs_Xv = 0;
119}
120
Marcelo Roberto Jimenezfa876722010-10-18 22:41:29 +0100121static struct pcmcia_low_level nanoengine_pcmcia_ops = {
122 .owner = THIS_MODULE,
123
124 .hw_init = nanoengine_pcmcia_hw_init,
Marcelo Roberto Jimenezfa876722010-10-18 22:41:29 +0100125
126 .configure_socket = nanoengine_pcmcia_configure_socket,
127 .socket_state = nanoengine_pcmcia_socket_state,
Marcelo Roberto Jimenezfa876722010-10-18 22:41:29 +0100128};
129
130int pcmcia_nanoengine_init(struct device *dev)
131{
132 int ret = -ENODEV;
133
134 if (machine_is_nanoengine())
135 ret = sa11xx_drv_pcmcia_probe(
136 dev, &nanoengine_pcmcia_ops, 0, 2);
137
138 return ret;
139}
140