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#include <subdev/gpio.h>
28
29struct nv10_gpio_priv {
30 struct nouveau_gpio base;
31};
32
33static int
34nv10_gpio_sense(struct nouveau_gpio *gpio, int line)
35{
36 if (line < 2) {
37 line = line * 16;
38 line = nv_rd32(gpio, 0x600818) >> line;
39 return !!(line & 0x0100);
40 } else
41 if (line < 10) {
42 line = (line - 2) * 4;
43 line = nv_rd32(gpio, 0x60081c) >> line;
44 return !!(line & 0x04);
45 } else
46 if (line < 14) {
47 line = (line - 10) * 4;
48 line = nv_rd32(gpio, 0x600850) >> line;
49 return !!(line & 0x04);
50 }
51
52 return -EINVAL;
53}
54
55static int
56nv10_gpio_drive(struct nouveau_gpio *gpio, int line, int dir, int out)
57{
58 u32 reg, mask, data;
59
60 if (line < 2) {
61 line = line * 16;
62 reg = 0x600818;
63 mask = 0x00000011;
64 data = (dir << 4) | out;
65 } else
66 if (line < 10) {
67 line = (line - 2) * 4;
68 reg = 0x60081c;
69 mask = 0x00000003;
70 data = (dir << 1) | out;
71 } else
72 if (line < 14) {
73 line = (line - 10) * 4;
74 reg = 0x600850;
75 mask = 0x00000003;
76 data = (dir << 1) | out;
77 } else {
78 return -EINVAL;
79 }
80
81 nv_mask(gpio, reg, mask << line, data << line);
82 return 0;
83}
84
85static void
86nv10_gpio_irq_enable(struct nouveau_gpio *gpio, int line, bool on)
87{
88 u32 mask = 0x00010001 << line;
89
90 nv_wr32(gpio, 0x001104, mask);
91 nv_mask(gpio, 0x001144, mask, on ? mask : 0);
92}
93
94static void
95nv10_gpio_intr(struct nouveau_subdev *subdev)
96{
97 struct nv10_gpio_priv *priv = (void *)subdev;
98 u32 intr = nv_rd32(priv, 0x001104);
99 u32 hi = (intr & 0x0000ffff) >> 0;
100 u32 lo = (intr & 0xffff0000) >> 16;
101
102 priv->base.isr_run(&priv->base, 0, hi | lo);
103
104 nv_wr32(priv, 0x001104, intr);
105}
106
107static int
108nv10_gpio_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
109 struct nouveau_oclass *oclass, void *data, u32 size,
110 struct nouveau_object **pobject)
111{
112 struct nv10_gpio_priv *priv;
113 int ret;
114
115 ret = nouveau_gpio_create(parent, engine, oclass, &priv);
116 *pobject = nv_object(priv);
117 if (ret)
118 return ret;
119
120 priv->base.drive = nv10_gpio_drive;
121 priv->base.sense = nv10_gpio_sense;
122 priv->base.irq_enable = nv10_gpio_irq_enable;
123 nv_subdev(priv)->intr = nv10_gpio_intr;
124 return 0;
125}
126
127static void
128nv10_gpio_dtor(struct nouveau_object *object)
129{
130 struct nv10_gpio_priv *priv = (void *)object;
131 nouveau_gpio_destroy(&priv->base);
132}
133
134static int
135nv10_gpio_init(struct nouveau_object *object)
136{
137 struct nv10_gpio_priv *priv = (void *)object;
138 int ret;
139
140 ret = nouveau_gpio_init(&priv->base);
141 if (ret)
142 return ret;
143
144 nv_wr32(priv, 0x001140, 0x00000000);
145 nv_wr32(priv, 0x001100, 0xffffffff);
146 nv_wr32(priv, 0x001144, 0x00000000);
147 nv_wr32(priv, 0x001104, 0xffffffff);
148 return 0;
149}
150
151static int
152nv10_gpio_fini(struct nouveau_object *object, bool suspend)
153{
154 struct nv10_gpio_priv *priv = (void *)object;
155 nv_wr32(priv, 0x001140, 0x00000000);
156 nv_wr32(priv, 0x001144, 0x00000000);
157 return nouveau_gpio_fini(&priv->base, suspend);
158}
159
160struct nouveau_oclass
161nv10_gpio_oclass = {
162 .handle = NV_SUBDEV(GPIO, 0x10),
163 .ofuncs = &(struct nouveau_ofuncs) {
164 .ctor = nv10_gpio_ctor,
165 .dtor = nv10_gpio_dtor,
166 .init = nv10_gpio_init,
167 .fini = nv10_gpio_fini,
168 },
169};
170