Remove inclusion of <sys/cdefs.h> from kernel .c files.
[dragonfly.git] / sys / platform / pc32 / i386 / geode.c
1 /*
2  * Copyright (c) 2003 Markus Friedl <markus@openbsd.org>
3  *
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.
7  *
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.
15  *
16  *
17  * Copyright (c) 2009 The DragonFly Project.  All rights reserved.
18  *
19  * This code is derived from software contributed to The DragonFly Project
20  * by Alex Hornung <ahornung@gmail.com>
21  *
22  * Redistribution and use in source and binary forms, with or without
23  * modification, are permitted provided that the following conditions
24  * are met:
25  *
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
31  *    distribution.
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.
35  *
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
47  * SUCH DAMAGE.
48  *
49  */
50 #include "opt_cpu.h"
51
52 #include <sys/param.h>
53 #include <sys/systm.h>
54 #include <sys/systimer.h>
55 #include <sys/bus.h>
56 #include <sys/kernel.h>
57 #include <sys/module.h>
58 #include <sys/wdog.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>
64
65 /*
66  * Geode SC1100 Information Appliance On a Chip
67  * http://www.national.com/ds.cgi/SC/SC1100.pdf
68  */
69
70 /* Configuration Space Register Map */
71
72 #define SC1100_F5_SCRATCHPAD    0x64
73
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 */
82
83 /* Watchdog */
84
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
93
94 /* cyclecounter */
95 #define TSC_ENABLE      0x0200
96 #define GEODE_TIMER_FREQ        27000000
97
98 struct geode_softc {
99         bus_space_tag_t         sc_iot;
100         bus_space_handle_t      sc_ioh;
101 };
102
103 static struct geode_softc geode_sc;
104 static sysclock_t geode_get_timecount(void);
105
106 static void
107 geode_cputimer_construct(struct cputimer *timer, sysclock_t oldclock)
108 {
109         timer->base = 0;
110         timer->base = oldclock - geode_get_timecount();
111 }
112
113 static struct cputimer geode_timer = {
114         SLIST_ENTRY_INITIALIZER,
115         "Geode",
116         CPUTIMER_PRI_GEODE,
117         CPUTIMER_GEODE,
118         geode_get_timecount,
119         cputimer_default_fromhz,
120         cputimer_default_fromus,
121         geode_cputimer_construct,
122         cputimer_default_destruct,
123         GEODE_TIMER_FREQ,
124         0, 0, 0
125 };
126
127 static sysclock_t
128 geode_get_timecount(void)
129 {
130
131         return (geode_timer.base +
132                 bus_space_read_4(geode_sc.sc_iot, geode_sc.sc_ioh, GCB_TSC));
133 }
134
135
136 #ifdef WATCHDOG_ENABLE
137 static int
138 geode_watchdog(void *unused, int period)
139 {
140         uint32_t data;
141         uint16_t port;
142         int     reg;
143
144         if (period > 0x03ff)
145                 period = 0x03ff;
146
147         bus_space_write_2(geode_sc.sc_iot, geode_sc.sc_ioh, GCB_WDTO, period * 64);
148
149         return period;
150 }
151
152 static struct watchdog  geode_wdog = {
153         .name           =       "Geode SC1100",
154         .wdog_fn        =       geode_watchdog,
155         .arg            =       NULL,
156         .period_max     =       0x03ff,
157 };
158 #endif /* WATCHDOG_ENABLE */
159
160 static int
161 geode_probe(device_t self)
162 {
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, ...) */
167                 return 0;
168         }
169
170         return ENXIO;
171 }
172 static int
173 geode_attach(device_t self)
174 {
175         u_int32_t       reg;
176         u_int16_t       cnfg, cba;
177         u_int8_t        sts, rev, iid;
178
179         /*
180          * The address of the CBA is written to this register
181          * by the bios, see p161 in data sheet.
182          */
183         reg = pci_read_config(self, SC1100_F5_SCRATCHPAD, 4);
184         if (reg == 0)
185                 return ENODEV;
186
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;
190
191         cba = bus_space_read_2(geode_sc.sc_iot, geode_sc.sc_ioh, GCB_CBA);
192         if (cba != reg) {
193                 kprintf("Geode LX: cba mismatch: cba 0x%x != reg 0x%x\n", cba, reg);
194                 return ENODEV;
195         }
196
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);
204
205         /* enable timer */
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);
209
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);
213         sts |= WDOVF_CLEAR;
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 */
220
221         return 0;
222 }
223
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),
231         {0, 0}
232 };
233
234 static driver_t geode_driver = {
235         "geode",
236         geode_methods,
237         0,
238 };
239
240 static devclass_t geode_devclass;
241
242 DRIVER_MODULE(geode, pci, geode_driver, geode_devclass, 0, 0);