1/*-
2 * Copyright (c) 2006-2008, Juniper Networks, Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
--- 11 unchanged lines hidden (view full) ---
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include <sys/cdefs.h>
30__FBSDID("$FreeBSD: head/sys/powerpc/mpc85xx/lbc.c 184250 2008-10-25 06:03:40Z marcel $");
31
32#include <sys/param.h>
33#include <sys/systm.h>
34#include <sys/ktr.h>
35#include <sys/kernel.h>
36#include <sys/malloc.h>
37#include <sys/module.h>
38#include <sys/bus.h>
39#include <sys/rman.h>
40#include <machine/bus.h>
41#include <machine/ocpbus.h>
42
43#include <vm/vm.h>
44#include <vm/pmap.h>
45
46#include <powerpc/mpc85xx/lbc.h>
47
48struct lbc_softc {
49 device_t sc_dev;
50
51 struct resource *sc_res;
52 bus_space_handle_t sc_bsh;
53 bus_space_tag_t sc_bst;
54 int sc_rid;
55
56 struct rman sc_rman;
57 uintptr_t sc_kva;
58};
59
60struct lbc_devinfo {
61 int lbc_devtype;
62 int lbc_memtype;
63 /* Also the BAR number */
64 int lbc_unit;
65};
66
67static int lbc_probe(device_t);
68static int lbc_attach(device_t);
69static int lbc_shutdown(device_t);
70static int lbc_get_resource(device_t, device_t, int, int, u_long *,
71 u_long *);
72static struct resource *lbc_alloc_resource(device_t, device_t, int, int *,
73 u_long, u_long, u_long, u_int);
74static int lbc_print_child(device_t, device_t);
--- 28 unchanged lines hidden (view full) ---
103static driver_t lbc_driver = {
104 "lbc",
105 lbc_methods,
106 sizeof(struct lbc_softc)
107};
108devclass_t lbc_devclass;
109DRIVER_MODULE(lbc, ocpbus, lbc_driver, lbc_devclass, 0, 0);
110
111static device_t
112lbc_mk_child(device_t dev, int type, int mtype, int unit)
113{
114 struct lbc_devinfo *dinfo;
115 device_t child;
116
117 child = device_add_child(dev, NULL, -1);
118 if (child == NULL) {
119 device_printf(dev, "could not add child device\n");
120 return (NULL);
121 }
122 dinfo = malloc(sizeof(struct lbc_devinfo), M_DEVBUF, M_WAITOK | M_ZERO);
123 dinfo->lbc_devtype = type;
124 dinfo->lbc_memtype = mtype;
125 dinfo->lbc_unit = unit;
126 device_set_ivars(child, dinfo);
127 return (child);
128}
129
130static int
131lbc_probe(device_t dev)
132{
133 device_t parent;
134 uintptr_t devtype;
135 int error;
136
137 parent = device_get_parent(dev);
138 error = BUS_READ_IVAR(parent, dev, OCPBUS_IVAR_DEVTYPE, &devtype);
--- 6 unchanged lines hidden (view full) ---
145 return (BUS_PROBE_DEFAULT);
146}
147
148static int
149lbc_attach(device_t dev)
150{
151 struct lbc_softc *sc;
152 struct rman *rm;
153 u_long start, size;
154 int error;
155
156 sc = device_get_softc(dev);
157 sc->sc_dev = dev;
158
159 sc->sc_rid = 0;
160 sc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rid,
161 RF_ACTIVE);
162 if (sc->sc_res == NULL)
163 return (ENXIO);
164
165 sc->sc_bst = rman_get_bustag(sc->sc_res);
166 sc->sc_bsh = rman_get_bushandle(sc->sc_res);
167
168 error = bus_get_resource(dev, SYS_RES_MEMORY, 1, &start, &size);
169 if (error)
170 goto fail;
171
172 rm = &sc->sc_rman;
173 rm->rm_type = RMAN_ARRAY;
174 rm->rm_descr = "MPC85XX Local Bus Space";
175 rm->rm_start = start;
176 rm->rm_end = start + size - 1;
177 error = rman_init(rm);
178 if (error)
179 goto fail;
180
181 error = rman_manage_region(rm, rm->rm_start, rm->rm_end);
182 if (error) {
183 rman_fini(rm);
184 goto fail;
185 }
186
187 sc->sc_kva = (uintptr_t)pmap_mapdev(start, size);
188
189 lbc_mk_child(dev, LBC_DEVTYPE_CFI, 0, 0);
190
191 return (bus_generic_attach(dev));
192
193 fail:
194 bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_rid, sc->sc_res);
195 return (error);
196}
197
198static int
199lbc_shutdown(device_t dev)
200{
201
202 /* TODO */
203 return(0);
204}
205
206static struct resource *
207lbc_alloc_resource(device_t dev, device_t child, int type, int *rid,
208 u_long start, u_long end, u_long count, u_int flags)
209{
210 struct lbc_softc *sc;
211 struct resource *rv;
212 struct rman *rm;
213 int error;
214
215 sc = device_get_softc(dev);
216
217 if (type != SYS_RES_MEMORY && type != SYS_RES_IRQ)
218 return (NULL);
219
220 /* We only support default allocations. */
221 if (start != 0ul || end != ~0ul)
222 return (NULL);
223
224 if (type == SYS_RES_IRQ)
225 return (bus_alloc_resource(dev, type, rid, start, end, count,
226 flags));
227
228 error = lbc_get_resource(dev, child, type, *rid, &start, &count);
229 if (error)
230 return (NULL);
231
232 rm = &sc->sc_rman;
233 end = start + count - 1;
234 rv = rman_reserve_resource(rm, start, end, count, flags, child);
235 if (rv != NULL) {
236 rman_set_bustag(rv, &bs_be_tag);
237 rman_set_bushandle(rv, sc->sc_kva + rman_get_start(rv) -
238 rm->rm_start);
239 }
240 return (rv);
241}
242
243static int
244lbc_print_child(device_t dev, device_t child)
245{
246 u_long size, start;
--- 27 unchanged lines hidden (view full) ---
274 return (EINVAL);
275
276 dinfo = device_get_ivars(child);
277
278 switch (index) {
279 case LBC_IVAR_DEVTYPE:
280 *result = dinfo->lbc_devtype;
281 return (0);
282 case LBC_IVAR_CLOCK:
283 *result = 1843200;
284 return (0);
285 case LBC_IVAR_REGSHIFT:
286 *result = 0;
287 return (0);
288 default:
289 break;
290 }
291 return (EINVAL);
292}
293
294static int
295lbc_release_resource(device_t dev, device_t child, int type, int rid,
--- 4 unchanged lines hidden (view full) ---
300}
301
302static int
303lbc_get_resource(device_t dev, device_t child, int type, int rid,
304 u_long *startp, u_long *countp)
305{
306 struct lbc_softc *sc;
307 struct lbc_devinfo *dinfo;
308
309 if (type != SYS_RES_MEMORY)
310 return (ENOENT);
311
312 /* Currently all devices have a single RID per type. */
313 if (rid != 0)
314 return (ENOENT);
315
316 sc = device_get_softc(dev);
317 dinfo = device_get_ivars(child);
318
319 switch (dinfo->lbc_devtype) {
320 case LBC_DEVTYPE_CFI:
321 *startp = sc->sc_rman.rm_start;
322 *countp = sc->sc_rman.rm_end - sc->sc_rman.rm_start + 1;
323 break;
324 default:
325 return(EDOOFUS);
326 }
327 return(0);
328}
2 * Copyright (c) 2006-2008, Juniper Networks, Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
--- 11 unchanged lines hidden (view full) ---
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include <sys/cdefs.h>
30__FBSDID("$FreeBSD: head/sys/powerpc/mpc85xx/lbc.c 184250 2008-10-25 06:03:40Z marcel $");
31
32#include <sys/param.h>
33#include <sys/systm.h>
34#include <sys/ktr.h>
35#include <sys/kernel.h>
36#include <sys/malloc.h>
37#include <sys/module.h>
38#include <sys/bus.h>
39#include <sys/rman.h>
40#include <machine/bus.h>
41#include <machine/ocpbus.h>
42
43#include <vm/vm.h>
44#include <vm/pmap.h>
45
46#include <powerpc/mpc85xx/lbc.h>
47
48struct lbc_softc {
49 device_t sc_dev;
50
51 struct resource *sc_res;
52 bus_space_handle_t sc_bsh;
53 bus_space_tag_t sc_bst;
54 int sc_rid;
55
56 struct rman sc_rman;
57 uintptr_t sc_kva;
58};
59
60struct lbc_devinfo {
61 int lbc_devtype;
62 int lbc_memtype;
63 /* Also the BAR number */
64 int lbc_unit;
65};
66
67static int lbc_probe(device_t);
68static int lbc_attach(device_t);
69static int lbc_shutdown(device_t);
70static int lbc_get_resource(device_t, device_t, int, int, u_long *,
71 u_long *);
72static struct resource *lbc_alloc_resource(device_t, device_t, int, int *,
73 u_long, u_long, u_long, u_int);
74static int lbc_print_child(device_t, device_t);
--- 28 unchanged lines hidden (view full) ---
103static driver_t lbc_driver = {
104 "lbc",
105 lbc_methods,
106 sizeof(struct lbc_softc)
107};
108devclass_t lbc_devclass;
109DRIVER_MODULE(lbc, ocpbus, lbc_driver, lbc_devclass, 0, 0);
110
111static device_t
112lbc_mk_child(device_t dev, int type, int mtype, int unit)
113{
114 struct lbc_devinfo *dinfo;
115 device_t child;
116
117 child = device_add_child(dev, NULL, -1);
118 if (child == NULL) {
119 device_printf(dev, "could not add child device\n");
120 return (NULL);
121 }
122 dinfo = malloc(sizeof(struct lbc_devinfo), M_DEVBUF, M_WAITOK | M_ZERO);
123 dinfo->lbc_devtype = type;
124 dinfo->lbc_memtype = mtype;
125 dinfo->lbc_unit = unit;
126 device_set_ivars(child, dinfo);
127 return (child);
128}
129
130static int
131lbc_probe(device_t dev)
132{
133 device_t parent;
134 uintptr_t devtype;
135 int error;
136
137 parent = device_get_parent(dev);
138 error = BUS_READ_IVAR(parent, dev, OCPBUS_IVAR_DEVTYPE, &devtype);
--- 6 unchanged lines hidden (view full) ---
145 return (BUS_PROBE_DEFAULT);
146}
147
148static int
149lbc_attach(device_t dev)
150{
151 struct lbc_softc *sc;
152 struct rman *rm;
153 u_long start, size;
154 int error;
155
156 sc = device_get_softc(dev);
157 sc->sc_dev = dev;
158
159 sc->sc_rid = 0;
160 sc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rid,
161 RF_ACTIVE);
162 if (sc->sc_res == NULL)
163 return (ENXIO);
164
165 sc->sc_bst = rman_get_bustag(sc->sc_res);
166 sc->sc_bsh = rman_get_bushandle(sc->sc_res);
167
168 error = bus_get_resource(dev, SYS_RES_MEMORY, 1, &start, &size);
169 if (error)
170 goto fail;
171
172 rm = &sc->sc_rman;
173 rm->rm_type = RMAN_ARRAY;
174 rm->rm_descr = "MPC85XX Local Bus Space";
175 rm->rm_start = start;
176 rm->rm_end = start + size - 1;
177 error = rman_init(rm);
178 if (error)
179 goto fail;
180
181 error = rman_manage_region(rm, rm->rm_start, rm->rm_end);
182 if (error) {
183 rman_fini(rm);
184 goto fail;
185 }
186
187 sc->sc_kva = (uintptr_t)pmap_mapdev(start, size);
188
189 lbc_mk_child(dev, LBC_DEVTYPE_CFI, 0, 0);
190
191 return (bus_generic_attach(dev));
192
193 fail:
194 bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_rid, sc->sc_res);
195 return (error);
196}
197
198static int
199lbc_shutdown(device_t dev)
200{
201
202 /* TODO */
203 return(0);
204}
205
206static struct resource *
207lbc_alloc_resource(device_t dev, device_t child, int type, int *rid,
208 u_long start, u_long end, u_long count, u_int flags)
209{
210 struct lbc_softc *sc;
211 struct resource *rv;
212 struct rman *rm;
213 int error;
214
215 sc = device_get_softc(dev);
216
217 if (type != SYS_RES_MEMORY && type != SYS_RES_IRQ)
218 return (NULL);
219
220 /* We only support default allocations. */
221 if (start != 0ul || end != ~0ul)
222 return (NULL);
223
224 if (type == SYS_RES_IRQ)
225 return (bus_alloc_resource(dev, type, rid, start, end, count,
226 flags));
227
228 error = lbc_get_resource(dev, child, type, *rid, &start, &count);
229 if (error)
230 return (NULL);
231
232 rm = &sc->sc_rman;
233 end = start + count - 1;
234 rv = rman_reserve_resource(rm, start, end, count, flags, child);
235 if (rv != NULL) {
236 rman_set_bustag(rv, &bs_be_tag);
237 rman_set_bushandle(rv, sc->sc_kva + rman_get_start(rv) -
238 rm->rm_start);
239 }
240 return (rv);
241}
242
243static int
244lbc_print_child(device_t dev, device_t child)
245{
246 u_long size, start;
--- 27 unchanged lines hidden (view full) ---
274 return (EINVAL);
275
276 dinfo = device_get_ivars(child);
277
278 switch (index) {
279 case LBC_IVAR_DEVTYPE:
280 *result = dinfo->lbc_devtype;
281 return (0);
282 case LBC_IVAR_CLOCK:
283 *result = 1843200;
284 return (0);
285 case LBC_IVAR_REGSHIFT:
286 *result = 0;
287 return (0);
288 default:
289 break;
290 }
291 return (EINVAL);
292}
293
294static int
295lbc_release_resource(device_t dev, device_t child, int type, int rid,
--- 4 unchanged lines hidden (view full) ---
300}
301
302static int
303lbc_get_resource(device_t dev, device_t child, int type, int rid,
304 u_long *startp, u_long *countp)
305{
306 struct lbc_softc *sc;
307 struct lbc_devinfo *dinfo;
308
309 if (type != SYS_RES_MEMORY)
310 return (ENOENT);
311
312 /* Currently all devices have a single RID per type. */
313 if (rid != 0)
314 return (ENOENT);
315
316 sc = device_get_softc(dev);
317 dinfo = device_get_ivars(child);
318
319 switch (dinfo->lbc_devtype) {
320 case LBC_DEVTYPE_CFI:
321 *startp = sc->sc_rman.rm_start;
322 *countp = sc->sc_rman.rm_end - sc->sc_rman.rm_start + 1;
323 break;
324 default:
325 return(EDOOFUS);
326 }
327 return(0);
328}