2 * Copyright (c) 2003 Markus Friedl <markus@openbsd.org>
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 * Copyright (c) 2009 The DragonFly Project. All rights reserved.
19 * This code is derived from software contributed to The DragonFly Project
20 * by Alex Hornung <ahornung@gmail.com>
22 * Redistribution and use in source and binary forms, with or without
23 * modification, are permitted provided that the following conditions
26 * 1. Redistributions of source code must retain the above copyright
27 * notice, this list of conditions and the following disclaimer.
28 * 2. Redistributions in binary form must reproduce the above copyright
29 * notice, this list of conditions and the following disclaimer in
30 * the documentation and/or other materials provided with the
32 * 3. Neither the name of The DragonFly Project nor the names of its
33 * contributors may be used to endorse or promote products derived
34 * from this software without specific, prior written permission.
36 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
37 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
38 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
39 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
40 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
41 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
42 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
44 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51 #include <sys/param.h>
52 #include <sys/systm.h>
53 #include <sys/systimer.h>
55 #include <sys/kernel.h>
56 #include <sys/module.h>
58 #include <bus/pci/pcireg.h>
59 #include <bus/pci/pcivar.h>
60 #include <bus/pci/pcidevs.h>
61 #include <bus/pci/pcib_private.h>
62 #include <machine/pc/bios.h>
65 * Geode SC1100 Information Appliance On a Chip
66 * http://www.national.com/ds.cgi/SC/SC1100.pdf
69 /* Configuration Space Register Map */
71 #define SC1100_F5_SCRATCHPAD 0x64
73 #define GCB_WDTO 0x0000 /* WATCHDOG Timeout */
74 #define GCB_WDCNFG 0x0002 /* WATCHDOG Configuration */
75 #define GCB_WDSTS 0x0004 /* WATCHDOG Status */
76 #define GCB_TSC 0x0008 /* Cyclecounter at 27MHz */
77 #define GCB_TSCNFG 0x000c /* config for the above */
78 #define GCB_IID 0x003c /* IA On a Chip ID */
79 #define GCB_REV 0x003d /* Revision */
80 #define GCB_CBA 0x003e /* Configuration Base Address */
84 #define WD32KPD_ENABLE 0x0000
85 #define WD32KPD_DISABLE 0x0100
86 #define WDTYPE1_RESET 0x0030
87 #define WDTYPE2_RESET 0x00c0
88 #define WDPRES_DIV_512 0x0009
89 #define WDPRES_DIV_8192 0x000d
90 #define WDCNFG_MASK 0x00ff
91 #define WDOVF_CLEAR 0x0001
94 #define TSC_ENABLE 0x0200
95 #define GEODE_TIMER_FREQ 27000000
98 bus_space_tag_t sc_iot;
99 bus_space_handle_t sc_ioh;
102 static struct geode_softc geode_sc;
103 static sysclock_t geode_get_timecount(void);
106 geode_cputimer_construct(struct cputimer *timer, sysclock_t oldclock)
109 timer->base = oldclock - geode_get_timecount();
112 static struct cputimer geode_timer = {
113 SLIST_ENTRY_INITIALIZER,
118 cputimer_default_fromhz,
119 cputimer_default_fromus,
120 geode_cputimer_construct,
121 cputimer_default_destruct,
127 geode_get_timecount(void)
130 return (geode_timer.base +
131 bus_space_read_4(geode_sc.sc_iot, geode_sc.sc_ioh, GCB_TSC));
135 geode_watchdog(void *unused, int period)
140 bus_space_write_2(geode_sc.sc_iot, geode_sc.sc_ioh, GCB_WDTO, period * 64);
145 static struct watchdog geode_wdog = {
146 .name = "Geode SC1100",
147 .wdog_fn = geode_watchdog,
149 .period_max = 0x03ff,
153 geode_probe(device_t self)
155 if (pci_get_vendor(self) == PCI_VENDOR_NS &&
156 (pci_get_device(self) == PCI_PRODUCT_NS_SC1100_XBUS ||
157 pci_get_device(self) == PCI_PRODUCT_NS_SCx200_XBUS)) {
158 /* device_set_desc(self, ...) */
165 geode_attach(device_t self)
169 u_int8_t sts, rev, iid;
172 * The address of the CBA is written to this register
173 * by the bios, see p161 in data sheet.
175 reg = pci_read_config(self, SC1100_F5_SCRATCHPAD, 4);
179 /* bus_space_map(sc->sc_iot, reg, 64, 0, &sc->sc_ioh)) */
180 geode_sc.sc_iot = I386_BUS_SPACE_IO;
181 geode_sc.sc_ioh = reg;
183 cba = bus_space_read_2(geode_sc.sc_iot, geode_sc.sc_ioh, GCB_CBA);
185 kprintf("Geode LX: cba mismatch: cba 0x%x != reg 0x%x\n", cba, reg);
189 /* outl(cba + 0x0d, 2); ??? */
190 sts = bus_space_read_1(geode_sc.sc_iot, geode_sc.sc_ioh, GCB_WDSTS);
191 cnfg = bus_space_read_2(geode_sc.sc_iot, geode_sc.sc_ioh, GCB_WDCNFG);
192 iid = bus_space_read_1(geode_sc.sc_iot, geode_sc.sc_ioh, GCB_IID);
193 rev = bus_space_read_1(geode_sc.sc_iot, geode_sc.sc_ioh, GCB_REV);
194 #define WDSTSBITS "\20\x04WDRST\x03WDSMI\x02WDINT\x01WDOVF"
195 kprintf("Geode LX: iid %d revision %d wdstatus %b\n", iid, rev, sts, WDSTSBITS);
198 bus_space_write_4(geode_sc.sc_iot, geode_sc.sc_iot, GCB_TSCNFG, TSC_ENABLE);
199 cputimer_register(&geode_timer);
200 cputimer_select(&geode_timer, 0);
202 /* enable watchdog and configure */
203 bus_space_write_2(geode_sc.sc_iot, geode_sc.sc_ioh, GCB_WDTO, 0);
205 bus_space_write_1(geode_sc.sc_iot, geode_sc.sc_ioh, GCB_WDSTS, sts);
206 cnfg &= ~WDCNFG_MASK;
207 cnfg |= WDTYPE1_RESET | WDPRES_DIV_512;
208 bus_space_write_2(geode_sc.sc_iot, geode_sc.sc_ioh, GCB_WDCNFG, cnfg);
209 wdog_register(&geode_wdog);
214 static device_method_t geode_methods[] = {
215 /* Device interface */
216 DEVMETHOD(device_probe, geode_probe),
217 DEVMETHOD(device_attach, geode_attach),
218 DEVMETHOD(device_suspend, bus_generic_suspend),
219 DEVMETHOD(device_resume, bus_generic_resume),
220 DEVMETHOD(device_shutdown, bus_generic_shutdown),
224 static driver_t geode_driver = {
230 static devclass_t geode_devclass;
232 DRIVER_MODULE(geode, pci, geode_driver, geode_devclass, NULL, NULL);