1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
#include <linux/io.h>
#include <linux/module.h>
#include "l1110.h"
#include "soc_common.h"
enum {
PRS_S1 = BIT(0),
PRS_S2 = BIT(1),
PRS_S3 = BIT(2),
PRS_S4 = BIT(3),
PRS_BVD1 = BIT(4),
PRS_BVD2 = BIT(5),
PRS_VS1 = BIT(6),
PRS_VS2 = BIT(7),
PRS_RDY = BIT(8),
PRS_CD1 = BIT(9),
PRS_CD2 = BIT(10),
PRC_S1 = PRS_S1, /* x1vcc - TPS2205 D2/D7 */
PRC_S2 = PRS_S2, /* x0vcc - TPS2205 D3/D6 */
PRC_S3 = PRS_S3, /* x0vpp - TPS2205 D1/D5 */
PRC_S4 = PRS_S4, /* x1vpp - TPS2205 D0/D4 */
PRC_RST = BIT(4),
PRC_APOE = BIT(5), /* auto power off enable */
PRC_CFE = BIT(6), /* CF enable: A25:11 driven high */
PRC_SOE = BIT(7), /* signal output enable */
PRC_SSP = BIT(8), /* socket select polarity */
};
struct l1110 {
void __iomem *reg;
u16 prc;
};
int l1110_init(struct device *dev, struct l1110 **ptr, resource_size_t base,
unsigned int ssp)
{
struct l1110 *l;
l = devm_kzalloc(dev, sizeof(*l), GFP_KERNEL);
if (!l)
return -ENOMEM;
l->prc = PRC_APOE | (ssp ? PRC_SSP : 0);
l->reg = devm_ioremap(dev, base, 2);
if (!l->reg)
return -ENOMEM;
*ptr = l;
writew_relaxed(l->prc, l->reg);
return 0;
}
EXPORT_SYMBOL_GPL(l1110_init);
void l1110_socket_state(struct l1110 *l, struct pcmcia_state *state)
{
u16 prs = readw_relaxed(l->reg);
state->bvd1 = !!(prs & PRS_BVD1);
state->bvd2 = !!(prs & PRS_BVD2);
state->vs_3v = !(prs & PRS_VS1);
state->vs_Xv = !(prs & PRS_VS2);
}
EXPORT_SYMBOL_GPL(l1110_socket_state);
int l1110_configure_socket(struct l1110 *l, const socket_state_t *state)
{
u16 prc = l->prc;
switch (state->Vcc) {
case 0:
break;
case 33:
prc |= PRC_S1;
break;
case 50:
prc |= PRC_S2;
break;
default:
return -EINVAL;
}
if (state->Vpp) {
if (state->Vpp == 12)
prc |= PRC_S4;
else if (state->Vpp == state->Vcc)
prc |= PRC_S3;
else
return -EINVAL;
}
if (state->flags & SS_RESET)
prc |= PRC_RST;
if (state->flags & SS_OUTPUT_ENA)
prc |= PRC_SOE;
writew_relaxed(prc, l->reg);
return 0;
}
EXPORT_SYMBOL_GPL(l1110_configure_socket);
MODULE_AUTHOR("Russell King <rmk+kernel@armlinux.org.uk>");
MODULE_DESCRIPTION("LinkUp Systems L1110 driver");
MODULE_LICENSE("GPL");
|