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
52 #include <sys/param.h>
53 #include <sys/systm.h>
54 #include <sys/systimer.h>
56 #include <sys/kernel.h>
57 #include <sys/module.h>
59 #include <bus/pci/pcireg.h>
60 #include <bus/pci/pcivar.h>
61 #include <bus/pci/pcidevs.h>
62 #include <bus/pci/pcib_private.h>
63 #include <machine/pc/bios.h>
66 * Geode SC1100 Information Appliance On a Chip
67 * http://www.national.com/ds.cgi/SC/SC1100.pdf
70 /* Configuration Space Register Map */
72 #define SC1100_F5_SCRATCHPAD 0x64
74 #define GCB_WDTO 0x0000 /* WATCHDOG Timeout */
75 #define GCB_WDCNFG 0x0002 /* WATCHDOG Configuration */
76 #define GCB_WDSTS 0x0004 /* WATCHDOG Status */
77 #define GCB_TSC 0x0008 /* Cyclecounter at 27MHz */
78 #define GCB_TSCNFG 0x000c /* config for the above */
79 #define GCB_IID 0x003c /* IA On a Chip ID */
80 #define GCB_REV 0x003d /* Revision */
81 #define GCB_CBA 0x003e /* Configuration Base Address */
85 #define WD32KPD_ENABLE 0x0000
86 #define WD32KPD_DISABLE 0x0100
87 #define WDTYPE1_RESET 0x0030
88 #define WDTYPE2_RESET 0x00c0
89 #define WDPRES_DIV_512 0x0009
90 #define WDPRES_DIV_8192 0x000d
91 #define WDCNFG_MASK 0x00ff
92 #define WDOVF_CLEAR 0x0001
95 #define TSC_ENABLE 0x0200
96 #define GEODE_TIMER_FREQ 27000000
99 bus_space_tag_t sc_iot;
100 bus_space_handle_t sc_ioh;
103 static struct geode_softc geode_sc;
104 static sysclock_t geode_get_timecount(void);
107 geode_cputimer_construct(struct cputimer *timer, sysclock_t oldclock)
110 timer->base = oldclock - geode_get_timecount();
113 static struct cputimer geode_timer = {
114 SLIST_ENTRY_INITIALIZER,
119 cputimer_default_fromhz,
120 cputimer_default_fromus,
121 geode_cputimer_construct,
122 cputimer_default_destruct,
128 geode_get_timecount(void)
131 return (geode_timer.base +
132 bus_space_read_4(geode_sc.sc_iot, geode_sc.sc_ioh, GCB_TSC));
136 #ifdef WATCHDOG_ENABLE
138 geode_watchdog(void *unused, int period)
147 bus_space_write_2(geode_sc.sc_iot, geode_sc.sc_ioh, GCB_WDTO, period * 64);
152 static struct watchdog geode_wdog = {
153 .name = "Geode SC1100",
154 .wdog_fn = geode_watchdog,
156 .period_max = 0x03ff,
158 #endif /* WATCHDOG_ENABLE */
161 geode_probe(device_t self)
163 if (pci_get_vendor(self) == PCI_VENDOR_NS &&
164 (pci_get_device(self) == PCI_PRODUCT_NS_SC1100_XBUS ||
165 pci_get_device(self) == PCI_PRODUCT_NS_SCx200_XBUS)) {
166 /* device_set_desc(self, ...) */
173 geode_attach(device_t self)
177 u_int8_t sts, rev, iid;
180 * The address of the CBA is written to this register
181 * by the bios, see p161 in data sheet.
183 reg = pci_read_config(self, SC1100_F5_SCRATCHPAD, 4);
187 /* bus_space_map(sc->sc_iot, reg, 64, 0, &sc->sc_ioh)) */
188 geode_sc.sc_iot = I386_BUS_SPACE_IO;
189 geode_sc.sc_ioh = reg;
191 cba = bus_space_read_2(geode_sc.sc_iot, geode_sc.sc_ioh, GCB_CBA);
193 kprintf("Geode LX: cba mismatch: cba 0x%x != reg 0x%x\n", cba, reg);
197 /* outl(cba + 0x0d, 2); ??? */
198 sts = bus_space_read_1(geode_sc.sc_iot, geode_sc.sc_ioh, GCB_WDSTS);
199 cnfg = bus_space_read_2(geode_sc.sc_iot, geode_sc.sc_ioh, GCB_WDCNFG);
200 iid = bus_space_read_1(geode_sc.sc_iot, geode_sc.sc_ioh, GCB_IID);
201 rev = bus_space_read_1(geode_sc.sc_iot, geode_sc.sc_ioh, GCB_REV);
202 #define WDSTSBITS "\20\x04WDRST\x03WDSMI\x02WDINT\x01WDOVF"
203 kprintf("Geode LX: iid %d revision %d wdstatus %b\n", iid, rev, sts, WDSTSBITS);
206 bus_space_write_4(geode_sc.sc_iot, geode_sc.sc_iot, GCB_TSCNFG, TSC_ENABLE);
207 cputimer_register(&geode_timer);
208 cputimer_select(&geode_timer, 0);
210 #ifdef WATCHDOG_ENABLE
211 /* enable watchdog and configure */
212 bus_space_write_2(geode_sc.sc_iot, geode_sc.sc_ioh, GCB_WDTO, 0);
214 bus_space_write_1(geode_sc.sc_iot, geode_sc.sc_ioh, GCB_WDSTS, sts);
215 cnfg &= ~WDCNFG_MASK;
216 cnfg |= WDTYPE1_RESET | WDPRES_DIV_512;
217 bus_space_write_2(geode_sc.sc_iot, geode_sc.sc_ioh, GCB_WDCNFG, cnfg);
218 wdog_register(&geode_wdog);
219 #endif /* WATCHDOG_ENABLE */
224 static device_method_t geode_methods[] = {
225 /* Device interface */
226 DEVMETHOD(device_probe, geode_probe),
227 DEVMETHOD(device_attach, geode_attach),
228 DEVMETHOD(device_suspend, bus_generic_suspend),
229 DEVMETHOD(device_resume, bus_generic_resume),
230 DEVMETHOD(device_shutdown, bus_generic_shutdown),
234 static driver_t geode_driver = {
240 static devclass_t geode_devclass;
242 DRIVER_MODULE(geode, pci, geode_driver, geode_devclass, 0, 0);