xref: /openbsd-src/sys/dev/pci/glxpcib.c (revision 50b7afb2c2c0993b0894d4e34bf857cb13ed9c80)
1 /*      $OpenBSD: glxpcib.c,v 1.11 2013/12/06 21:03:03 deraadt Exp $	*/
2 
3 /*
4  * Copyright (c) 2007 Marc Balmer <mbalmer@openbsd.org>
5  * Copyright (c) 2007 Michael Shalayeff
6  * All rights reserved.
7  *
8  * Permission to use, copy, modify, and distribute this software for any
9  * purpose with or without fee is hereby granted, provided that the above
10  * copyright notice and this permission notice appear in all copies.
11  *
12  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
17  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
18  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19  */
20 
21 /*
22  * AMD CS5536 series LPC bridge also containing timer, watchdog, and GPIO.
23  */
24 
25 #include <sys/param.h>
26 #include <sys/systm.h>
27 #include <sys/proc.h>
28 #include <sys/device.h>
29 #include <sys/gpio.h>
30 #include <sys/timetc.h>
31 #include <sys/rwlock.h>
32 
33 #include <machine/bus.h>
34 #ifdef __i386__
35 #include <machine/cpufunc.h>
36 #endif
37 
38 #include <dev/gpio/gpiovar.h>
39 #include <dev/i2c/i2cvar.h>
40 
41 #include <dev/pci/pcireg.h>
42 #include <dev/pci/pcivar.h>
43 #include <dev/pci/pcidevs.h>
44 
45 #include <dev/pci/glxreg.h>
46 #include <dev/pci/glxvar.h>
47 
48 #include "gpio.h"
49 
50 #define	AMD5536_REV		GLCP_CHIP_REV_ID
51 #define	AMD5536_REV_MASK	0xff
52 #define	AMD5536_TMC		PMC_LTMR
53 
54 #define	MSR_LBAR_ENABLE		0x100000000ULL
55 
56 /* Multi-Functional General Purpose Timer */
57 #define	MSR_LBAR_MFGPT		DIVIL_LBAR_MFGPT
58 #define	MSR_MFGPT_SIZE		0x40
59 #define	MSR_MFGPT_ADDR_MASK	0xffc0
60 #define	AMD5536_MFGPT0_CMP1	0x00000000
61 #define	AMD5536_MFGPT0_CMP2	0x00000002
62 #define	AMD5536_MFGPT0_CNT	0x00000004
63 #define	AMD5536_MFGPT0_SETUP	0x00000006
64 #define	AMD5536_MFGPT_DIV_MASK	0x000f	/* div = 1 << mask */
65 #define	AMD5536_MFGPT_CLKSEL	0x0010
66 #define	AMD5536_MFGPT_REV_EN	0x0020
67 #define	AMD5536_MFGPT_CMP1DIS	0x0000
68 #define	AMD5536_MFGPT_CMP1EQ	0x0040
69 #define	AMD5536_MFGPT_CMP1GE	0x0080
70 #define	AMD5536_MFGPT_CMP1EV	0x00c0
71 #define	AMD5536_MFGPT_CMP2DIS	0x0000
72 #define	AMD5536_MFGPT_CMP2EQ	0x0100
73 #define	AMD5536_MFGPT_CMP2GE	0x0200
74 #define	AMD5536_MFGPT_CMP2EV	0x0300
75 #define	AMD5536_MFGPT_STOP_EN	0x0800
76 #define	AMD5536_MFGPT_SET	0x1000
77 #define	AMD5536_MFGPT_CMP1	0x2000
78 #define	AMD5536_MFGPT_CMP2	0x4000
79 #define	AMD5536_MFGPT_CNT_EN	0x8000
80 #define	AMD5536_MFGPT_IRQ	MFGPT_IRQ
81 #define	AMD5536_MFGPT0_C1_IRQM	0x00000001
82 #define	AMD5536_MFGPT1_C1_IRQM	0x00000002
83 #define	AMD5536_MFGPT2_C1_IRQM	0x00000004
84 #define	AMD5536_MFGPT3_C1_IRQM	0x00000008
85 #define	AMD5536_MFGPT4_C1_IRQM	0x00000010
86 #define	AMD5536_MFGPT5_C1_IRQM	0x00000020
87 #define	AMD5536_MFGPT6_C1_IRQM	0x00000040
88 #define	AMD5536_MFGPT7_C1_IRQM	0x00000080
89 #define	AMD5536_MFGPT0_C2_IRQM	0x00000100
90 #define	AMD5536_MFGPT1_C2_IRQM	0x00000200
91 #define	AMD5536_MFGPT2_C2_IRQM	0x00000400
92 #define	AMD5536_MFGPT3_C2_IRQM	0x00000800
93 #define	AMD5536_MFGPT4_C2_IRQM	0x00001000
94 #define	AMD5536_MFGPT5_C2_IRQM	0x00002000
95 #define	AMD5536_MFGPT6_C2_IRQM	0x00004000
96 #define	AMD5536_MFGPT7_C2_IRQM	0x00008000
97 #define	AMD5536_MFGPT_NR	MFGPT_NR
98 #define	AMD5536_MFGPT0_C1_NMIM	0x00000001
99 #define	AMD5536_MFGPT1_C1_NMIM	0x00000002
100 #define	AMD5536_MFGPT2_C1_NMIM	0x00000004
101 #define	AMD5536_MFGPT3_C1_NMIM	0x00000008
102 #define	AMD5536_MFGPT4_C1_NMIM	0x00000010
103 #define	AMD5536_MFGPT5_C1_NMIM	0x00000020
104 #define	AMD5536_MFGPT6_C1_NMIM	0x00000040
105 #define	AMD5536_MFGPT7_C1_NMIM	0x00000080
106 #define	AMD5536_MFGPT0_C2_NMIM	0x00000100
107 #define	AMD5536_MFGPT1_C2_NMIM	0x00000200
108 #define	AMD5536_MFGPT2_C2_NMIM	0x00000400
109 #define	AMD5536_MFGPT3_C2_NMIM	0x00000800
110 #define	AMD5536_MFGPT4_C2_NMIM	0x00001000
111 #define	AMD5536_MFGPT5_C2_NMIM	0x00002000
112 #define	AMD5536_MFGPT6_C2_NMIM	0x00004000
113 #define	AMD5536_MFGPT7_C2_NMIM	0x00008000
114 #define	AMD5536_NMI_LEG		0x00010000
115 #define	AMD5536_MFGPT0_C2_RSTEN	0x01000000
116 #define	AMD5536_MFGPT1_C2_RSTEN	0x02000000
117 #define	AMD5536_MFGPT2_C2_RSTEN	0x04000000
118 #define	AMD5536_MFGPT3_C2_RSTEN	0x08000000
119 #define	AMD5536_MFGPT4_C2_RSTEN	0x10000000
120 #define	AMD5536_MFGPT5_C2_RSTEN	0x20000000
121 #define	AMD5536_MFGPT_SETUP	MFGPT_SETUP
122 
123 /* GPIO */
124 #define	MSR_LBAR_GPIO		DIVIL_LBAR_GPIO
125 #define	MSR_GPIO_SIZE		0x100
126 #define	MSR_GPIO_ADDR_MASK	0xff00
127 #define	AMD5536_GPIO_NPINS	32
128 #define	AMD5536_GPIOH_OFFSET	0x80	/* high bank register offset */
129 #define	AMD5536_GPIO_OUT_VAL	0x00	/* output value */
130 #define	AMD5536_GPIO_OUT_EN	0x04	/* output enable */
131 #define	AMD5536_GPIO_OD_EN	0x08	/* open-drain enable */
132 #define AMD5536_GPIO_OUT_INVRT_EN 0x0c	/* invert output */
133 #define	AMD5536_GPIO_PU_EN	0x18	/* pull-up enable */
134 #define	AMD5536_GPIO_PD_EN	0x1c	/* pull-down enable */
135 #define	AMD5536_GPIO_IN_EN	0x20	/* input enable */
136 #define AMD5536_GPIO_IN_INVRT_EN 0x24	/* invert input */
137 #define	AMD5536_GPIO_READ_BACK	0x30	/* read back value */
138 
139 /* SMB */
140 #define MSR_LBAR_SMB		DIVIL_LBAR_SMB
141 #define MSR_SMB_SIZE		0x08
142 #define MSR_SMB_ADDR_MASK	0xfff8
143 #define AMD5536_SMB_SDA		0x00 /* serial data */
144 #define AMD5536_SMB_STS		0x01 /* status */
145 #define AMD5536_SMB_STS_SLVSTOP	0x80 /* slave stop */
146 #define AMD5536_SMB_STS_SDAST	0x40 /* smb data status */
147 #define AMD5536_SMB_STS_BER	0x20 /* bus error */
148 #define AMD5536_SMB_STS_NEGACK	0x10 /* negative acknowledge */
149 #define AMD5536_SMB_STS_STASTR	0x08 /* stall after start */
150 #define AMD5536_SMB_STS_MASTER	0x02 /* master */
151 #define AMD5536_SMB_STS_XMIT	0x01 /* transmit or receive */
152 #define AMD5536_SMB_CST		0x02 /* control status */
153 #define AMD5536_SMB_CST_MATCH	0x04 /* address match */
154 #define AMD5536_SMB_CST_BB	0x02 /* bus busy */
155 #define AMD5536_SMB_CST_BUSY	0x01 /* busy */
156 #define AMD5536_SMB_CTL1	0x03 /* control 1 */
157 #define AMD5536_SMB_CTL1_STASTRE 0x80 /* stall after start enable */
158 #define AMD5536_SMB_CTL1_ACK	0x10 /* receive acknowledge */
159 #define AMD5536_SMB_CTL1_INTEN	0x04 /* interrupt enable  */
160 #define AMD5536_SMB_CTL1_STOP	0x02 /* stop */
161 #define AMD5536_SMB_CTL1_START	0x01 /* start */
162 #define AMD5536_SMB_ADDR	0x04 /* serial address */
163 #define AMD5536_SMB_ADDR_SAEN	0x80 /* slave enable */
164 #define AMD5536_SMB_CTL2	0x05 /* control 2 */
165 #define AMD5536_SMB_CTL2_EN	0x01 /* enable clock */
166 #define AMD5536_SMB_CTL2_FREQ	0x78 /* 100 kHz */
167 #define AMD5536_SMB_CTL3	0x06 /* control 3 */
168 
169 /* PMS */
170 #define	MSR_LBAR_PMS		DIVIL_LBAR_PMS
171 #define	MSR_PMS_SIZE		0x80
172 #define	MSR_PMS_ADDR_MASK	0xff80
173 #define	AMD5536_PMS_SSC		0x54
174 #define	AMD5536_PMS_SSC_PI	0x00040000
175 #define	AMD5536_PMS_SSC_CLR_PI	0x00020000
176 #define	AMD5536_PMS_SSC_SET_PI	0x00010000
177 
178 /*
179  * MSR registers we want to preserve accross suspend/resume
180  */
181 const uint32_t glxpcib_msrlist[] = {
182 	GLIU_PAE,
183 	GLCP_GLD_MSR_PM,
184 	DIVIL_BALL_OPTS
185 };
186 
187 struct glxpcib_softc {
188 	struct device		sc_dev;
189 
190 	struct timecounter	sc_timecounter;
191 	bus_space_tag_t		sc_iot;
192 	bus_space_handle_t	sc_ioh;
193 
194 	uint64_t 		sc_msrsave[nitems(glxpcib_msrlist)];
195 
196 #ifndef SMALL_KERNEL
197 #if NGPIO > 0
198 	/* GPIO interface */
199 	bus_space_tag_t		sc_gpio_iot;
200 	bus_space_handle_t	sc_gpio_ioh;
201 	struct gpio_chipset_tag	sc_gpio_gc;
202 	gpio_pin_t		sc_gpio_pins[AMD5536_GPIO_NPINS];
203 #endif
204 	/* I2C interface */
205 	bus_space_tag_t		sc_smb_iot;
206 	bus_space_handle_t	sc_smb_ioh;
207 	struct i2c_controller	sc_smb_ic;
208 	struct rwlock		sc_smb_lck;
209 
210 	/* Watchdog */
211 	int			sc_wdog;
212 	int			sc_wdog_period;
213 #endif
214 };
215 
216 struct cfdriver glxpcib_cd = {
217 	NULL, "glxpcib", DV_DULL
218 };
219 
220 int	glxpcib_match(struct device *, void *, void *);
221 void	glxpcib_attach(struct device *, struct device *, void *);
222 int	glxpcib_activate(struct device *, int);
223 int	glxpcib_search(struct device *, void *, void *);
224 int	glxpcib_print(void *, const char *);
225 
226 struct cfattach glxpcib_ca = {
227 	sizeof(struct glxpcib_softc), glxpcib_match, glxpcib_attach,
228 	NULL, glxpcib_activate
229 };
230 
231 /* from arch/<*>/pci/pcib.c */
232 void	pcibattach(struct device *parent, struct device *self, void *aux);
233 
234 u_int	glxpcib_get_timecount(struct timecounter *tc);
235 
236 #ifndef SMALL_KERNEL
237 int     glxpcib_wdogctl_cb(void *, int);
238 #if NGPIO > 0
239 void	glxpcib_gpio_pin_ctl(void *, int, int);
240 int	glxpcib_gpio_pin_read(void *, int);
241 void	glxpcib_gpio_pin_write(void *, int, int);
242 #endif
243 int	glxpcib_smb_acquire_bus(void *, int);
244 void	glxpcib_smb_release_bus(void *, int);
245 int	glxpcib_smb_send_start(void *, int);
246 int	glxpcib_smb_send_stop(void *, int);
247 void	glxpcib_smb_send_ack(void *, int);
248 int	glxpcib_smb_initiate_xfer(void *, i2c_addr_t, int);
249 int	glxpcib_smb_read_byte(void *, uint8_t *, int);
250 int	glxpcib_smb_write_byte(void *, uint8_t, int);
251 void	glxpcib_smb_reset(struct glxpcib_softc *);
252 int	glxpcib_smb_wait(struct glxpcib_softc *, int, int);
253 #endif
254 
255 const struct pci_matchid glxpcib_devices[] = {
256 	{ PCI_VENDOR_AMD,	PCI_PRODUCT_AMD_CS5536_PCIB }
257 };
258 
259 int
260 glxpcib_match(struct device *parent, void *match, void *aux)
261 {
262 	if (pci_matchbyid((struct pci_attach_args *)aux, glxpcib_devices,
263 	    nitems(glxpcib_devices))) {
264 		/* needs to win over pcib */
265 		return 2;
266 	}
267 
268 	return 0;
269 }
270 
271 void
272 glxpcib_attach(struct device *parent, struct device *self, void *aux)
273 {
274 	struct glxpcib_softc *sc = (struct glxpcib_softc *)self;
275 	struct timecounter *tc = &sc->sc_timecounter;
276 #ifndef SMALL_KERNEL
277 	struct pci_attach_args *pa = (struct pci_attach_args *)aux;
278 	u_int64_t wa;
279 #if NGPIO > 0
280 	u_int64_t ga;
281 	struct gpiobus_attach_args gba;
282 	int i, gpio = 0;
283 #endif
284 	u_int64_t sa;
285 	struct i2cbus_attach_args iba;
286 	int i2c = 0;
287 	bus_space_handle_t tmpioh;
288 #endif
289 	tc->tc_get_timecount = glxpcib_get_timecount;
290 	tc->tc_counter_mask = 0xffffffff;
291 	tc->tc_frequency = 3579545;
292 	tc->tc_name = "CS5536";
293 	tc->tc_quality = 1000;
294 	tc->tc_priv = sc;
295 	tc_init(tc);
296 
297 	printf(": rev %d, 32-bit %lluHz timer",
298 	    (int)rdmsr(AMD5536_REV) & AMD5536_REV_MASK,
299 	    tc->tc_frequency);
300 
301 #ifndef SMALL_KERNEL
302 	/* Attach the watchdog timer */
303 	sc->sc_iot = pa->pa_iot;
304 	wa = rdmsr(MSR_LBAR_MFGPT);
305 	if (wa & MSR_LBAR_ENABLE &&
306 	    !bus_space_map(sc->sc_iot, wa & MSR_MFGPT_ADDR_MASK,
307 	    MSR_MFGPT_SIZE, 0, &sc->sc_ioh)) {
308 		/* count in seconds (as upper level desires) */
309 		bus_space_write_2(sc->sc_iot, sc->sc_ioh, AMD5536_MFGPT0_SETUP,
310 		    AMD5536_MFGPT_CNT_EN | AMD5536_MFGPT_CMP2EV |
311 		    AMD5536_MFGPT_CMP2 | AMD5536_MFGPT_DIV_MASK |
312 		    AMD5536_MFGPT_STOP_EN);
313 		wdog_register(glxpcib_wdogctl_cb, sc);
314 		sc->sc_wdog = 1;
315 		printf(", watchdog");
316 	}
317 
318 #if NGPIO > 0
319 	/* map GPIO I/O space */
320 	sc->sc_gpio_iot = pa->pa_iot;
321 	ga = rdmsr(MSR_LBAR_GPIO);
322 	if (ga & MSR_LBAR_ENABLE &&
323 	    !bus_space_map(sc->sc_gpio_iot, ga & MSR_GPIO_ADDR_MASK,
324 	    MSR_GPIO_SIZE, 0, &sc->sc_gpio_ioh)) {
325 		printf(", gpio");
326 
327 		/* initialize pin array */
328 		for (i = 0; i < AMD5536_GPIO_NPINS; i++) {
329 			sc->sc_gpio_pins[i].pin_num = i;
330 			sc->sc_gpio_pins[i].pin_caps = GPIO_PIN_INPUT |
331 			    GPIO_PIN_OUTPUT | GPIO_PIN_OPENDRAIN |
332 			    GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN |
333 			    GPIO_PIN_INVIN | GPIO_PIN_INVOUT;
334 
335 			/* read initial state */
336 			sc->sc_gpio_pins[i].pin_state =
337 			    glxpcib_gpio_pin_read(sc, i);
338 		}
339 
340 		/* create controller tag */
341 		sc->sc_gpio_gc.gp_cookie = sc;
342 		sc->sc_gpio_gc.gp_pin_read = glxpcib_gpio_pin_read;
343 		sc->sc_gpio_gc.gp_pin_write = glxpcib_gpio_pin_write;
344 		sc->sc_gpio_gc.gp_pin_ctl = glxpcib_gpio_pin_ctl;
345 
346 		gba.gba_name = "gpio";
347 		gba.gba_gc = &sc->sc_gpio_gc;
348 		gba.gba_pins = sc->sc_gpio_pins;
349 		gba.gba_npins = AMD5536_GPIO_NPINS;
350 		gpio = 1;
351 
352 	}
353 #endif /* NGPIO */
354 
355 	/* Map SMB I/O space */
356 	sc->sc_smb_iot = pa->pa_iot;
357 	sa = rdmsr(MSR_LBAR_SMB);
358 	if (sa & MSR_LBAR_ENABLE &&
359 	    !bus_space_map(sc->sc_smb_iot, sa & MSR_SMB_ADDR_MASK,
360 	    MSR_SMB_SIZE, 0, &sc->sc_smb_ioh)) {
361 		printf(", i2c");
362 
363 		/* Enable controller */
364 		bus_space_write_1(sc->sc_smb_iot, sc->sc_smb_ioh,
365 		    AMD5536_SMB_CTL2, AMD5536_SMB_CTL2_EN |
366 		    AMD5536_SMB_CTL2_FREQ);
367 
368 		/* Disable interrupts */
369 		bus_space_write_1(sc->sc_smb_iot, sc->sc_smb_ioh,
370 		    AMD5536_SMB_CTL1, 0);
371 
372 		/* Disable slave address */
373 		bus_space_write_1(sc->sc_smb_iot, sc->sc_smb_ioh,
374 		    AMD5536_SMB_ADDR, 0);
375 
376 		/* Stall the bus after start */
377 		bus_space_write_1(sc->sc_smb_iot, sc->sc_smb_ioh,
378 		    AMD5536_SMB_CTL1, AMD5536_SMB_CTL1_STASTRE);
379 
380 		/* Attach I2C framework */
381 		sc->sc_smb_ic.ic_cookie = sc;
382 		sc->sc_smb_ic.ic_acquire_bus = glxpcib_smb_acquire_bus;
383 		sc->sc_smb_ic.ic_release_bus = glxpcib_smb_release_bus;
384 		sc->sc_smb_ic.ic_send_start = glxpcib_smb_send_start;
385 		sc->sc_smb_ic.ic_send_stop = glxpcib_smb_send_stop;
386 		sc->sc_smb_ic.ic_initiate_xfer = glxpcib_smb_initiate_xfer;
387 		sc->sc_smb_ic.ic_read_byte = glxpcib_smb_read_byte;
388 		sc->sc_smb_ic.ic_write_byte = glxpcib_smb_write_byte;
389 
390 		rw_init(&sc->sc_smb_lck, "iiclk");
391 
392 		bzero(&iba, sizeof(iba));
393 		iba.iba_name = "iic";
394 		iba.iba_tag = &sc->sc_smb_ic;
395 		i2c = 1;
396 	}
397 
398 	/* Map PMS I/O space and enable the ``Power Immediate'' feature */
399 	sa = rdmsr(MSR_LBAR_PMS);
400 	if (sa & MSR_LBAR_ENABLE &&
401 	    !bus_space_map(pa->pa_iot, sa & MSR_PMS_ADDR_MASK,
402 	    MSR_PMS_SIZE, 0, &tmpioh)) {
403 		bus_space_write_4(pa->pa_iot, tmpioh, AMD5536_PMS_SSC,
404 		    AMD5536_PMS_SSC_SET_PI);
405 		bus_space_barrier(pa->pa_iot, tmpioh, AMD5536_PMS_SSC, 4,
406 		    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
407 		bus_space_unmap(pa->pa_iot, tmpioh, MSR_PMS_SIZE);
408 	}
409 #endif /* SMALL_KERNEL */
410 	pcibattach(parent, self, aux);
411 
412 #ifndef SMALL_KERNEL
413 #if NGPIO > 0
414 	if (gpio)
415 		config_found(&sc->sc_dev, &gba, gpiobus_print);
416 #endif
417 	if (i2c)
418 		config_found(&sc->sc_dev, &iba, iicbus_print);
419 #endif
420 
421 	config_search(glxpcib_search, self, pa);
422 }
423 
424 int
425 glxpcib_activate(struct device *self, int act)
426 {
427 #ifndef SMALL_KERNEL
428 	struct glxpcib_softc *sc = (struct glxpcib_softc *)self;
429 	uint i;
430 #endif
431 	int rv = 0;
432 
433 	switch (act) {
434 	case DVACT_SUSPEND:
435 #ifndef SMALL_KERNEL
436 		if (sc->sc_wdog) {
437 			sc->sc_wdog_period = bus_space_read_2(sc->sc_iot,
438 			    sc->sc_ioh, AMD5536_MFGPT0_CMP2);
439 			glxpcib_wdogctl_cb(sc, 0);
440 		}
441 #endif
442 		rv = config_activate_children(self, act);
443 #ifndef SMALL_KERNEL
444 		for (i = 0; i < nitems(glxpcib_msrlist); i++)
445 			sc->sc_msrsave[i] = rdmsr(glxpcib_msrlist[i]);
446 #endif
447 
448 		break;
449 	case DVACT_RESUME:
450 #ifndef SMALL_KERNEL
451 		if (sc->sc_wdog)
452 			glxpcib_wdogctl_cb(sc, sc->sc_wdog_period);
453 		for (i = 0; i < nitems(glxpcib_msrlist); i++)
454 			wrmsr(glxpcib_msrlist[i], sc->sc_msrsave[i]);
455 #endif
456 		rv = config_activate_children(self, act);
457 		break;
458 	default:
459 		rv = config_activate_children(self, act);
460 		break;
461 	}
462 	return (rv);
463 }
464 
465 u_int
466 glxpcib_get_timecount(struct timecounter *tc)
467 {
468         return rdmsr(AMD5536_TMC);
469 }
470 
471 #ifndef SMALL_KERNEL
472 int
473 glxpcib_wdogctl_cb(void *v, int period)
474 {
475 	struct glxpcib_softc *sc = v;
476 
477 	if (period > 0xffff)
478 		period = 0xffff;
479 
480 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, AMD5536_MFGPT0_SETUP,
481 	    AMD5536_MFGPT_CNT_EN | AMD5536_MFGPT_CMP2);
482 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, AMD5536_MFGPT0_CNT, 0);
483 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, AMD5536_MFGPT0_CMP2, period);
484 
485 	if (period)
486 		wrmsr(AMD5536_MFGPT_NR,
487 		    rdmsr(AMD5536_MFGPT_NR) | AMD5536_MFGPT0_C2_RSTEN);
488 	else
489 		wrmsr(AMD5536_MFGPT_NR,
490 		    rdmsr(AMD5536_MFGPT_NR) & ~AMD5536_MFGPT0_C2_RSTEN);
491 
492 	return period;
493 }
494 
495 #if NGPIO > 0
496 int
497 glxpcib_gpio_pin_read(void *arg, int pin)
498 {
499 	struct glxpcib_softc *sc = arg;
500 	u_int32_t data;
501 	int reg, off = 0;
502 
503 	reg = AMD5536_GPIO_IN_EN;
504 	if (pin > 15) {
505 		pin &= 0x0f;
506 		off = AMD5536_GPIOH_OFFSET;
507 	}
508 	reg += off;
509 	data = bus_space_read_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, reg);
510 
511 	if (data & (1 << pin))
512 		reg = AMD5536_GPIO_READ_BACK + off;
513 	else
514 		reg = AMD5536_GPIO_OUT_VAL + off;
515 
516 	data = bus_space_read_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, reg);
517 
518 	return data & 1 << pin ? GPIO_PIN_HIGH : GPIO_PIN_LOW;
519 }
520 
521 void
522 glxpcib_gpio_pin_write(void *arg, int pin, int value)
523 {
524 	struct glxpcib_softc *sc = arg;
525 	u_int32_t data;
526 	int reg;
527 
528 	reg = AMD5536_GPIO_OUT_VAL;
529 	if (pin > 15) {
530 		pin &= 0x0f;
531 		reg += AMD5536_GPIOH_OFFSET;
532 	}
533 	if (value == 1)
534 		data = 1 << pin;
535 	else
536 		data = 1 << (pin + 16);
537 
538 	bus_space_write_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, reg, data);
539 }
540 
541 void
542 glxpcib_gpio_pin_ctl(void *arg, int pin, int flags)
543 {
544 	struct glxpcib_softc *sc = arg;
545 	int n, reg[7], val[7], nreg = 0, off = 0;
546 
547 	if (pin > 15) {
548 		pin &= 0x0f;
549 		off = AMD5536_GPIOH_OFFSET;
550 	}
551 
552 	reg[nreg] = AMD5536_GPIO_IN_EN + off;
553 	if (flags & GPIO_PIN_INPUT)
554 		val[nreg++] = 1 << pin;
555 	else
556 		val[nreg++] = 1 << (pin + 16);
557 
558 	reg[nreg] = AMD5536_GPIO_OUT_EN + off;
559 	if (flags & GPIO_PIN_OUTPUT)
560 		val[nreg++] = 1 << pin;
561 	else
562 		val[nreg++] = 1 << (pin + 16);
563 
564 	reg[nreg] = AMD5536_GPIO_OD_EN + off;
565 	if (flags & GPIO_PIN_OPENDRAIN)
566 		val[nreg++] = 1 << pin;
567 	else
568 		val[nreg++] = 1 << (pin + 16);
569 
570 	reg[nreg] = AMD5536_GPIO_PU_EN + off;
571 	if (flags & GPIO_PIN_PULLUP)
572 		val[nreg++] = 1 << pin;
573 	else
574 		val[nreg++] = 1 << (pin + 16);
575 
576 	reg[nreg] = AMD5536_GPIO_PD_EN + off;
577 	if (flags & GPIO_PIN_PULLDOWN)
578 		val[nreg++] = 1 << pin;
579 	else
580 		val[nreg++] = 1 << (pin + 16);
581 
582 	reg[nreg] = AMD5536_GPIO_IN_INVRT_EN + off;
583 	if (flags & GPIO_PIN_INVIN)
584 		val[nreg++] = 1 << pin;
585 	else
586 		val[nreg++] = 1 << (pin + 16);
587 
588 	reg[nreg] = AMD5536_GPIO_OUT_INVRT_EN + off;
589 	if (flags & GPIO_PIN_INVOUT)
590 		val[nreg++] = 1 << pin;
591 	else
592 		val[nreg++] = 1 << (pin + 16);
593 
594 	/* set flags */
595 	for (n = 0; n < nreg; n++)
596 		bus_space_write_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, reg[n],
597 		    val[n]);
598 }
599 #endif /* GPIO */
600 
601 int
602 glxpcib_smb_acquire_bus(void *arg, int flags)
603 {
604 	struct glxpcib_softc *sc = arg;
605 
606 	if (cold || flags & I2C_F_POLL)
607 		return (0);
608 
609 	return (rw_enter(&sc->sc_smb_lck, RW_WRITE | RW_INTR));
610 }
611 
612 void
613 glxpcib_smb_release_bus(void *arg, int flags)
614 {
615 	struct glxpcib_softc *sc = arg;
616 
617 	if (cold || flags & I2C_F_POLL)
618 		return;
619 
620 	rw_exit(&sc->sc_smb_lck);
621 }
622 
623 int
624 glxpcib_smb_send_start(void *arg, int flags)
625 {
626 	struct glxpcib_softc *sc = arg;
627 	u_int8_t ctl;
628 
629 	ctl = bus_space_read_1(sc->sc_smb_iot, sc->sc_smb_ioh,
630 	    AMD5536_SMB_CTL1);
631 	bus_space_write_1(sc->sc_smb_iot, sc->sc_smb_ioh, AMD5536_SMB_CTL1,
632 	    ctl | AMD5536_SMB_CTL1_START);
633 
634 	return (0);
635 }
636 
637 int
638 glxpcib_smb_send_stop(void *arg, int flags)
639 {
640 	struct glxpcib_softc *sc = arg;
641 	u_int8_t ctl;
642 
643 	ctl = bus_space_read_1(sc->sc_smb_iot, sc->sc_smb_ioh,
644 	    AMD5536_SMB_CTL1);
645 	bus_space_write_1(sc->sc_smb_iot, sc->sc_smb_ioh, AMD5536_SMB_CTL1,
646 	    ctl | AMD5536_SMB_CTL1_STOP);
647 
648 	return (0);
649 }
650 
651 void
652 glxpcib_smb_send_ack(void *arg, int flags)
653 {
654 	struct glxpcib_softc *sc = arg;
655 	u_int8_t ctl;
656 
657 	ctl = bus_space_read_1(sc->sc_smb_iot, sc->sc_smb_ioh,
658 	    AMD5536_SMB_CTL1);
659 	bus_space_write_1(sc->sc_smb_iot, sc->sc_smb_ioh, AMD5536_SMB_CTL1,
660 	    ctl | AMD5536_SMB_CTL1_ACK);
661 }
662 
663 int
664 glxpcib_smb_initiate_xfer(void *arg, i2c_addr_t addr, int flags)
665 {
666 	struct glxpcib_softc *sc = arg;
667 	int error, dir;
668 
669 	/* Issue start condition */
670 	glxpcib_smb_send_start(sc, flags);
671 
672 	/* Wait for bus mastership */
673 	if ((error = glxpcib_smb_wait(sc, AMD5536_SMB_STS_MASTER |
674 	    AMD5536_SMB_STS_SDAST, flags)) != 0)
675 		return (error);
676 
677 	/* Send address byte */
678 	dir = (flags & I2C_F_READ ? 1 : 0);
679 	bus_space_write_1(sc->sc_smb_iot, sc->sc_smb_ioh, AMD5536_SMB_SDA,
680 	    (addr << 1) | dir);
681 
682 	return (0);
683 }
684 
685 int
686 glxpcib_smb_read_byte(void *arg, uint8_t *bytep, int flags)
687 {
688 	struct glxpcib_softc *sc = arg;
689 	int error;
690 
691 	/* Wait for the bus to be ready */
692 	if ((error = glxpcib_smb_wait(sc, AMD5536_SMB_STS_SDAST, flags)))
693 		return (error);
694 
695 	/* Acknowledge the last byte */
696 	if (flags & I2C_F_LAST)
697 		glxpcib_smb_send_ack(sc, 0);
698 
699 	/* Read data byte */
700 	*bytep = bus_space_read_1(sc->sc_smb_iot, sc->sc_smb_ioh,
701 	    AMD5536_SMB_SDA);
702 
703 	return (0);
704 }
705 
706 int
707 glxpcib_print(void *args, const char *parentname)
708 {
709 	struct glxpcib_attach_args *gaa = (struct glxpcib_attach_args *)args;
710 
711 	if (parentname != NULL)
712 		printf("%s at %s", gaa->gaa_name, parentname);
713 
714 	return UNCONF;
715 }
716 
717 int
718 glxpcib_search(struct device *parent, void *gcf, void *args)
719 {
720 	struct glxpcib_softc *sc = (struct glxpcib_softc *)parent;
721 	struct cfdata *cf = (struct cfdata *)gcf;
722 	struct pci_attach_args *pa = (struct pci_attach_args *)args;
723 	struct glxpcib_attach_args gaa;
724 
725 	gaa.gaa_name = cf->cf_driver->cd_name;
726 	gaa.gaa_pa = pa;
727 	gaa.gaa_iot = sc->sc_iot;
728 	gaa.gaa_ioh = sc->sc_ioh;
729 
730 	/*
731 	 * These devices are attached directly, either from
732 	 * glxpcib_attach() or later in time from pcib_callback().
733 	 */
734 	if (strcmp(cf->cf_driver->cd_name, "gpio") == 0 ||
735 	    strcmp(cf->cf_driver->cd_name, "iic") == 0 ||
736 	    strcmp(cf->cf_driver->cd_name, "isa") == 0)
737 		return 0;
738 
739 	if (cf->cf_attach->ca_match(parent, cf, &gaa) == 0)
740 		return 0;
741 
742 	config_attach(parent, cf, &gaa, glxpcib_print);
743 	return 1;
744 }
745 
746 int
747 glxpcib_smb_write_byte(void *arg, uint8_t byte, int flags)
748 {
749 	struct glxpcib_softc *sc = arg;
750 	int error;
751 
752 	/* Wait for the bus to be ready */
753 	if ((error = glxpcib_smb_wait(sc, AMD5536_SMB_STS_SDAST, flags)))
754 		return (error);
755 
756 	/* Send stop after the last byte */
757 	if (flags & I2C_F_STOP)
758 		glxpcib_smb_send_stop(sc, 0);
759 
760 	/* Write data byte */
761 	bus_space_write_1(sc->sc_smb_iot, sc->sc_smb_ioh, AMD5536_SMB_SDA,
762 	    byte);
763 
764 	return (0);
765 }
766 
767 void
768 glxpcib_smb_reset(struct glxpcib_softc *sc)
769 {
770 	u_int8_t st;
771 
772 	/* Clear MASTER, NEGACK and BER */
773 	st = bus_space_read_1(sc->sc_smb_iot, sc->sc_smb_ioh, AMD5536_SMB_STS);
774 	bus_space_write_1(sc->sc_smb_iot, sc->sc_smb_ioh, AMD5536_SMB_STS, st |
775 	    AMD5536_SMB_STS_MASTER | AMD5536_SMB_STS_NEGACK |
776 	    AMD5536_SMB_STS_BER);
777 
778 	/* Disable and re-enable controller */
779 	bus_space_write_1(sc->sc_smb_iot, sc->sc_smb_ioh, AMD5536_SMB_CTL2, 0);
780 	bus_space_write_1(sc->sc_smb_iot, sc->sc_smb_ioh, AMD5536_SMB_CTL2,
781 	    AMD5536_SMB_CTL2_EN | AMD5536_SMB_CTL2_FREQ);
782 
783 	/* Send stop */
784 	glxpcib_smb_send_stop(sc, 0);
785 }
786 
787 int
788 glxpcib_smb_wait(struct glxpcib_softc *sc, int bits, int flags)
789 {
790 	u_int8_t st;
791 	int i;
792 
793 	for (i = 0; i < 100; i++) {
794 		st = bus_space_read_1(sc->sc_smb_iot, sc->sc_smb_ioh,
795 		    AMD5536_SMB_STS);
796 		if (st & AMD5536_SMB_STS_BER) {
797 			printf("%s: bus error, bits=%#x st=%#x\n",
798 			    sc->sc_dev.dv_xname, bits, st);
799 			glxpcib_smb_reset(sc);
800 			return (EIO);
801 		}
802 		if ((bits & AMD5536_SMB_STS_MASTER) == 0 &&
803 		    (st & AMD5536_SMB_STS_NEGACK)) {
804 			glxpcib_smb_reset(sc);
805 			return (EIO);
806 		}
807 		if (st & AMD5536_SMB_STS_STASTR)
808 			bus_space_write_1(sc->sc_smb_iot, sc->sc_smb_ioh,
809 			    AMD5536_SMB_STS, AMD5536_SMB_STS_STASTR);
810 		if ((st & bits) == bits)
811 			break;
812 		delay(2);
813 	}
814 	if ((st & bits) != bits) {
815 		glxpcib_smb_reset(sc);
816 		return (ETIMEDOUT);
817 	}
818 	return (0);
819 }
820 #endif /* SMALL_KERNEL */
821