2 * Copyright 2012 Red Hat Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
27 struct nv50_gpio_priv
{
28 struct nouveau_gpio base
;
32 nv50_gpio_reset(struct nouveau_gpio
*gpio
, u8 match
)
34 struct nouveau_bios
*bios
= nouveau_bios(gpio
);
35 struct nv50_gpio_priv
*priv
= (void *)gpio
;
40 while ((entry
= dcb_gpio_entry(bios
, 0, ++ent
, &ver
, &len
))) {
41 static const u32 regs
[] = { 0xe100, 0xe28c };
42 u32 data
= nv_ro32(bios
, entry
);
43 u8 line
= (data
& 0x0000001f);
44 u8 func
= (data
& 0x0000ff00) >> 8;
45 u8 defs
= !!(data
& 0x01000000);
46 u8 unk0
= !!(data
& 0x02000000);
47 u8 unk1
= !!(data
& 0x04000000);
48 u32 val
= (unk1
<< 16) | unk0
;
49 u32 reg
= regs
[line
>> 4]; line
&= 0x0f;
51 if ( func
== DCB_GPIO_UNUSED
||
52 (match
!= DCB_GPIO_UNUSED
&& match
!= func
))
55 gpio
->set(gpio
, 0, func
, line
, defs
);
57 nv_mask(priv
, reg
, 0x00010001 << line
, val
<< line
);
62 nv50_gpio_location(int line
, u32
*reg
, u32
*shift
)
64 const u32 nv50_gpio_reg
[4] = { 0xe104, 0xe108, 0xe280, 0xe284 };
69 *reg
= nv50_gpio_reg
[line
>> 3];
70 *shift
= (line
& 7) << 2;
75 nv50_gpio_drive(struct nouveau_gpio
*gpio
, int line
, int dir
, int out
)
79 if (nv50_gpio_location(line
, ®
, &shift
))
82 nv_mask(gpio
, reg
, 7 << shift
, (((dir
^ 1) << 1) | out
) << shift
);
87 nv50_gpio_sense(struct nouveau_gpio
*gpio
, int line
)
91 if (nv50_gpio_location(line
, ®
, &shift
))
94 return !!(nv_rd32(gpio
, reg
) & (4 << shift
));
98 nv50_gpio_intr(struct nouveau_subdev
*subdev
)
100 struct nv50_gpio_priv
*priv
= (void *)subdev
;
101 u32 intr0
, intr1
= 0;
105 intr0
= nv_rd32(priv
, 0xe054) & nv_rd32(priv
, 0xe050);
106 if (nv_device(priv
)->chipset
> 0x92)
107 intr1
= nv_rd32(priv
, 0xe074) & nv_rd32(priv
, 0xe070);
109 hi
= (intr0
& 0x0000ffff) | (intr1
<< 16);
110 lo
= (intr0
>> 16) | (intr1
& 0xffff0000);
112 for (i
= 0; (hi
| lo
) && i
< 32; i
++) {
113 if ((hi
| lo
) & (1 << i
))
114 nouveau_event_trigger(priv
->base
.events
, i
);
117 nv_wr32(priv
, 0xe054, intr0
);
118 if (nv_device(priv
)->chipset
> 0x92)
119 nv_wr32(priv
, 0xe074, intr1
);
123 nv50_gpio_intr_enable(struct nouveau_event
*event
, int line
)
125 const u32 addr
= line
< 16 ? 0xe050 : 0xe070;
126 const u32 mask
= 0x00010001 << (line
& 0xf);
127 nv_wr32(event
->priv
, addr
+ 0x04, mask
);
128 nv_mask(event
->priv
, addr
+ 0x00, mask
, mask
);
132 nv50_gpio_intr_disable(struct nouveau_event
*event
, int line
)
134 const u32 addr
= line
< 16 ? 0xe050 : 0xe070;
135 const u32 mask
= 0x00010001 << (line
& 0xf);
136 nv_wr32(event
->priv
, addr
+ 0x04, mask
);
137 nv_mask(event
->priv
, addr
+ 0x00, mask
, 0x00000000);
141 nv50_gpio_ctor(struct nouveau_object
*parent
, struct nouveau_object
*engine
,
142 struct nouveau_oclass
*oclass
, void *data
, u32 size
,
143 struct nouveau_object
**pobject
)
145 struct nv50_gpio_priv
*priv
;
148 ret
= nouveau_gpio_create(parent
, engine
, oclass
,
149 nv_device(parent
)->chipset
> 0x92 ? 32 : 16,
151 *pobject
= nv_object(priv
);
155 priv
->base
.reset
= nv50_gpio_reset
;
156 priv
->base
.drive
= nv50_gpio_drive
;
157 priv
->base
.sense
= nv50_gpio_sense
;
158 priv
->base
.events
->priv
= priv
;
159 priv
->base
.events
->enable
= nv50_gpio_intr_enable
;
160 priv
->base
.events
->disable
= nv50_gpio_intr_disable
;
161 nv_subdev(priv
)->intr
= nv50_gpio_intr
;
166 nv50_gpio_dtor(struct nouveau_object
*object
)
168 struct nv50_gpio_priv
*priv
= (void *)object
;
169 nouveau_gpio_destroy(&priv
->base
);
173 nv50_gpio_init(struct nouveau_object
*object
)
175 struct nv50_gpio_priv
*priv
= (void *)object
;
178 ret
= nouveau_gpio_init(&priv
->base
);
182 /* disable, and ack any pending gpio interrupts */
183 nv_wr32(priv
, 0xe050, 0x00000000);
184 nv_wr32(priv
, 0xe054, 0xffffffff);
185 if (nv_device(priv
)->chipset
> 0x92) {
186 nv_wr32(priv
, 0xe070, 0x00000000);
187 nv_wr32(priv
, 0xe074, 0xffffffff);
194 nv50_gpio_fini(struct nouveau_object
*object
, bool suspend
)
196 struct nv50_gpio_priv
*priv
= (void *)object
;
197 nv_wr32(priv
, 0xe050, 0x00000000);
198 if (nv_device(priv
)->chipset
> 0x92)
199 nv_wr32(priv
, 0xe070, 0x00000000);
200 return nouveau_gpio_fini(&priv
->base
, suspend
);
203 struct nouveau_oclass
205 .handle
= NV_SUBDEV(GPIO
, 0x50),
206 .ofuncs
= &(struct nouveau_ofuncs
) {
207 .ctor
= nv50_gpio_ctor
,
208 .dtor
= nv50_gpio_dtor
,
209 .init
= nv50_gpio_init
,
210 .fini
= nv50_gpio_fini
,
This page took 0.037708 seconds and 5 git commands to generate.