1/*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2015-2016 Landon Fuller <landonf@FreeBSD.org>
5 * Copyright (c) 2017 The FreeBSD Foundation
6 * All rights reserved.
7 *
8 * Portions of this software were developed by Landon Fuller
9 * under sponsorship from the FreeBSD Foundation.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer,
16 *    without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
19 *    redistribution must be conditioned upon including a substantially
20 *    similar Disclaimer requirement for further binary redistribution.
21 *
22 * NO WARRANTY
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
26 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
27 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
28 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
31 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
33 * THE POSSIBILITY OF SUCH DAMAGES.
34 */
35
36#include <sys/cdefs.h>
37__FBSDID("$FreeBSD$");
38
39/*
40 * Broadcom Home Networking Division (HND) Bus Driver.
41 *
42 * The Broadcom HND family of devices consists of both SoCs and host-connected
43 * networking chipsets containing a common family of Broadcom IP cores,
44 * including an integrated MIPS and/or ARM cores.
45 *
46 * HND devices expose a nearly identical interface whether accessible over a
47 * native SoC interconnect, or when connected via a host interface such as
48 * PCIe. As a result, the majority of hardware support code should be re-usable
49 * across host drivers for HND networking chipsets, as well as FreeBSD support
50 * for Broadcom MIPS/ARM HND SoCs.
51 *
52 * Earlier HND models used the siba(4) on-chip interconnect, while later models
53 * use bcma(4); the programming model is almost entirely independent
54 * of the actual underlying interconect.
55 */
56
57#include <sys/param.h>
58#include <sys/kernel.h>
59#include <sys/bus.h>
60#include <sys/module.h>
61#include <sys/systm.h>
62
63#include <machine/bus.h>
64#include <sys/rman.h>
65#include <machine/resource.h>
66
67#include <dev/bhnd/cores/pmu/bhnd_pmu.h>
68
69#include "bhnd_chipc_if.h"
70#include "bhnd_nvram_if.h"
71
72#include "bhnd.h"
73#include "bhndreg.h"
74#include "bhndvar.h"
75
76#include "bhnd_private.h"
77
78MALLOC_DEFINE(M_BHND, "bhnd", "bhnd bus data structures");
79
80/**
81 * bhnd_generic_probe_nomatch() reporting configuration.
82 */
83static const struct bhnd_nomatch {
84	uint16_t	vendor;		/**< core designer */
85	uint16_t	device;		/**< core id */
86	bool		if_verbose;	/**< print when bootverbose is set. */
87} bhnd_nomatch_table[] = {
88	{ BHND_MFGID_ARM,	BHND_COREID_OOB_ROUTER,		true	},
89	{ BHND_MFGID_ARM,	BHND_COREID_EROM,		true	},
90	{ BHND_MFGID_ARM,	BHND_COREID_PL301,		true	},
91	{ BHND_MFGID_ARM,	BHND_COREID_APB_BRIDGE,		true	},
92	{ BHND_MFGID_ARM,	BHND_COREID_AXI_UNMAPPED,	false	},
93	{ BHND_MFGID_INVALID,	BHND_COREID_INVALID,		false	}
94};
95
96static int			 bhnd_delete_children(struct bhnd_softc *sc);
97
98/**
99 * Default bhnd(4) bus driver implementation of DEVICE_ATTACH().
100 *
101 * This implementation calls device_probe_and_attach() for each of the device's
102 * children, in bhnd probe order.
103 */
104int
105bhnd_generic_attach(device_t dev)
106{
107	struct bhnd_softc	*sc;
108	int			 error;
109
110	if (device_is_attached(dev))
111		return (EBUSY);
112
113	sc = device_get_softc(dev);
114	sc->dev = dev;
115
116	/* Probe and attach all children */
117	if ((error = bhnd_bus_probe_children(dev))) {
118		bhnd_delete_children(sc);
119		return (error);
120	}
121
122	return (0);
123}
124
125/**
126 * Detach and delete all children, in reverse of their attach order.
127 */
128static int
129bhnd_delete_children(struct bhnd_softc *sc)
130{
131	device_t		*devs;
132	int			 ndevs;
133	int			 error;
134
135	/* Fetch children in detach order */
136	error = bhnd_bus_get_children(sc->dev, &devs, &ndevs,
137	    BHND_DEVICE_ORDER_DETACH);
138	if (error)
139		return (error);
140
141	/* Perform detach */
142	for (int i = 0; i < ndevs; i++) {
143		device_t child = devs[i];
144
145		/* Terminate on first error */
146		if ((error = device_delete_child(sc->dev, child)))
147			goto cleanup;
148	}
149
150cleanup:
151	bhnd_bus_free_children(devs);
152	return (error);
153}
154
155/**
156 * Default bhnd(4) bus driver implementation of DEVICE_DETACH().
157 *
158 * This implementation calls device_detach() for each of the device's
159 * children, in reverse bhnd probe order, terminating if any call to
160 * device_detach() fails.
161 */
162int
163bhnd_generic_detach(device_t dev)
164{
165	struct bhnd_softc	*sc;
166	int			 error;
167
168	if (!device_is_attached(dev))
169		return (EBUSY);
170
171	sc = device_get_softc(dev);
172
173	if ((error = bhnd_delete_children(sc)))
174		return (error);
175
176	return (0);
177}
178
179/**
180 * Default bhnd(4) bus driver implementation of DEVICE_SHUTDOWN().
181 *
182 * This implementation calls device_shutdown() for each of the device's
183 * children, in reverse bhnd probe order, terminating if any call to
184 * device_shutdown() fails.
185 */
186int
187bhnd_generic_shutdown(device_t dev)
188{
189	device_t	*devs;
190	int		 ndevs;
191	int		 error;
192
193	if (!device_is_attached(dev))
194		return (EBUSY);
195
196	/* Fetch children in detach order */
197	error = bhnd_bus_get_children(dev, &devs, &ndevs,
198	    BHND_DEVICE_ORDER_DETACH);
199	if (error)
200		return (error);
201
202	/* Perform shutdown */
203	for (int i = 0; i < ndevs; i++) {
204		device_t child = devs[i];
205
206		/* Terminate on first error */
207		if ((error = device_shutdown(child)))
208			goto cleanup;
209	}
210
211cleanup:
212	bhnd_bus_free_children(devs);
213	return (error);
214}
215
216/**
217 * Default bhnd(4) bus driver implementation of DEVICE_RESUME().
218 *
219 * This implementation calls BUS_RESUME_CHILD() for each of the device's
220 * children in bhnd probe order, terminating if any call to BUS_RESUME_CHILD()
221 * fails.
222 */
223int
224bhnd_generic_resume(device_t dev)
225{
226	device_t	*devs;
227	int		 ndevs;
228	int		 error;
229
230	if (!device_is_attached(dev))
231		return (EBUSY);
232
233	/* Fetch children in attach order */
234	error = bhnd_bus_get_children(dev, &devs, &ndevs,
235	    BHND_DEVICE_ORDER_ATTACH);
236	if (error)
237		return (error);
238
239	/* Perform resume */
240	for (int i = 0; i < ndevs; i++) {
241		device_t child = devs[i];
242
243		/* Terminate on first error */
244		if ((error = BUS_RESUME_CHILD(device_get_parent(child), child)))
245			goto cleanup;
246	}
247
248cleanup:
249	bhnd_bus_free_children(devs);
250	return (error);
251}
252
253/**
254 * Default bhnd(4) bus driver implementation of DEVICE_SUSPEND().
255 *
256 * This implementation calls BUS_SUSPEND_CHILD() for each of the device's
257 * children in reverse bhnd probe order. If any call to BUS_SUSPEND_CHILD()
258 * fails, the suspend operation is terminated and any devices that were
259 * suspended are resumed immediately by calling their BUS_RESUME_CHILD()
260 * methods.
261 */
262int
263bhnd_generic_suspend(device_t dev)
264{
265	device_t	*devs;
266	int		 ndevs;
267	int		 error;
268
269	if (!device_is_attached(dev))
270		return (EBUSY);
271
272	/* Fetch children in detach order */
273	error = bhnd_bus_get_children(dev, &devs, &ndevs,
274	    BHND_DEVICE_ORDER_DETACH);
275	if (error)
276		return (error);
277
278	/* Perform suspend */
279	for (int i = 0; i < ndevs; i++) {
280		device_t child = devs[i];
281		error = BUS_SUSPEND_CHILD(device_get_parent(child), child);
282
283		/* On error, resume suspended devices and then terminate */
284		if (error) {
285			for (int j = 0; j < i; j++) {
286				BUS_RESUME_CHILD(device_get_parent(devs[j]),
287				    devs[j]);
288			}
289
290			goto cleanup;
291		}
292	}
293
294cleanup:
295	bhnd_bus_free_children(devs);
296	return (error);
297}
298
299/**
300 * Default bhnd(4) bus driver implementation of BHND_BUS_GET_PROBE_ORDER().
301 *
302 * This implementation determines probe ordering based on the device's class
303 * and other properties, including whether the device is serving as a host
304 * bridge.
305 */
306int
307bhnd_generic_get_probe_order(device_t dev, device_t child)
308{
309	switch (bhnd_get_class(child)) {
310	case BHND_DEVCLASS_CC:
311		/* Must be early enough to provide NVRAM access to the
312		 * host bridge */
313		return (BHND_PROBE_ROOT + BHND_PROBE_ORDER_FIRST);
314
315	case BHND_DEVCLASS_CC_B:
316		/* fall through */
317	case BHND_DEVCLASS_PMU:
318		return (BHND_PROBE_BUS + BHND_PROBE_ORDER_EARLY);
319
320	case BHND_DEVCLASS_SOC_ROUTER:
321		return (BHND_PROBE_BUS + BHND_PROBE_ORDER_LATE);
322
323	case BHND_DEVCLASS_SOC_BRIDGE:
324		return (BHND_PROBE_BUS + BHND_PROBE_ORDER_LAST);
325
326	case BHND_DEVCLASS_CPU:
327		return (BHND_PROBE_CPU + BHND_PROBE_ORDER_FIRST);
328
329	case BHND_DEVCLASS_RAM:
330		/* fall through */
331	case BHND_DEVCLASS_MEMC:
332		return (BHND_PROBE_CPU + BHND_PROBE_ORDER_EARLY);
333
334	case BHND_DEVCLASS_NVRAM:
335		return (BHND_PROBE_RESOURCE + BHND_PROBE_ORDER_EARLY);
336
337	case BHND_DEVCLASS_PCI:
338	case BHND_DEVCLASS_PCIE:
339	case BHND_DEVCLASS_PCCARD:
340	case BHND_DEVCLASS_ENET:
341	case BHND_DEVCLASS_ENET_MAC:
342	case BHND_DEVCLASS_ENET_PHY:
343	case BHND_DEVCLASS_WLAN:
344	case BHND_DEVCLASS_WLAN_MAC:
345	case BHND_DEVCLASS_WLAN_PHY:
346	case BHND_DEVCLASS_EROM:
347	case BHND_DEVCLASS_OTHER:
348	case BHND_DEVCLASS_INVALID:
349		if (bhnd_bus_find_hostb_device(dev) == child)
350			return (BHND_PROBE_ROOT + BHND_PROBE_ORDER_EARLY);
351
352		return (BHND_PROBE_DEFAULT);
353	default:
354		return (BHND_PROBE_DEFAULT);
355	}
356}
357
358/**
359 * Default bhnd(4) bus driver implementation of BHND_BUS_ALLOC_PMU().
360 */
361int
362bhnd_generic_alloc_pmu(device_t dev, device_t child)
363{
364	struct bhnd_softc		*sc;
365	struct bhnd_resource		*r;
366	struct bhnd_core_clkctl		*clkctl;
367	struct resource_list		*rl;
368	struct resource_list_entry	*rle;
369	device_t			 pmu_dev;
370	bhnd_addr_t			 r_addr;
371	bhnd_size_t			 r_size;
372	bus_size_t			 pmu_regs;
373	u_int				 max_latency;
374	int				 error;
375
376	GIANT_REQUIRED;	/* for newbus */
377
378	if (device_get_parent(child) != dev)
379		return (EINVAL);
380
381	sc = device_get_softc(dev);
382	clkctl = bhnd_get_pmu_info(child);
383	pmu_regs = BHND_CLK_CTL_ST;
384
385	/* already allocated? */
386	if (clkctl != NULL) {
387		panic("duplicate PMU allocation for %s",
388		    device_get_nameunit(child));
389	}
390
391	/* Determine address+size of the core's PMU register block */
392	error = bhnd_get_region_addr(child, BHND_PORT_DEVICE, 0, 0, &r_addr,
393	    &r_size);
394	if (error) {
395		device_printf(sc->dev, "error fetching register block info for "
396		    "%s: %d\n", device_get_nameunit(child), error);
397		return (error);
398	}
399
400	if (r_size < (pmu_regs + sizeof(uint32_t))) {
401		device_printf(sc->dev, "pmu offset %#jx would overrun %s "
402		    "register block\n", (uintmax_t)pmu_regs,
403		    device_get_nameunit(child));
404		return (ENODEV);
405	}
406
407	/* Locate actual resource containing the core's register block */
408	if ((rl = BUS_GET_RESOURCE_LIST(dev, child)) == NULL) {
409		device_printf(dev, "NULL resource list returned for %s\n",
410		    device_get_nameunit(child));
411		return (ENXIO);
412	}
413
414	if ((rle = resource_list_find(rl, SYS_RES_MEMORY, 0)) == NULL) {
415		device_printf(dev, "cannot locate core register resource "
416		    "for %s\n", device_get_nameunit(child));
417		return (ENXIO);
418	}
419
420	if (rle->res == NULL) {
421		device_printf(dev, "core register resource unallocated for "
422		    "%s\n", device_get_nameunit(child));
423		return (ENXIO);
424	}
425
426	if (r_addr+pmu_regs < rman_get_start(rle->res) ||
427	    r_addr+pmu_regs >= rman_get_end(rle->res))
428	{
429		device_printf(dev, "core register resource does not map PMU "
430		    "registers at %#jx\n for %s\n", r_addr+pmu_regs,
431		    device_get_nameunit(child));
432		return (ENXIO);
433	}
434
435	/* Adjust PMU register offset relative to the actual start address
436	 * of the core's register block allocation.
437	 *
438	 * XXX: The saved offset will be invalid if bus_adjust_resource is
439	 * used to modify the resource's start address.
440	 */
441	if (rman_get_start(rle->res) > r_addr)
442		pmu_regs -= rman_get_start(rle->res) - r_addr;
443	else
444		pmu_regs -= r_addr - rman_get_start(rle->res);
445
446	/* Retain a PMU reference for the clkctl instance state */
447	pmu_dev = bhnd_retain_provider(child, BHND_SERVICE_PMU);
448	if (pmu_dev == NULL) {
449		device_printf(sc->dev, "PMU not found\n");
450		return (ENXIO);
451	}
452
453	/* Fetch the maximum transition latency from our PMU */
454	max_latency = bhnd_pmu_get_max_transition_latency(pmu_dev);
455
456	/* Allocate a new bhnd_resource wrapping the standard resource we
457	 * fetched from the resource list; we'll free this in
458	 * bhnd_generic_release_pmu() */
459	r = malloc(sizeof(struct bhnd_resource), M_BHND, M_NOWAIT);
460	if (r == NULL) {
461		bhnd_release_provider(child, pmu_dev, BHND_SERVICE_PMU);
462		return (ENOMEM);
463	}
464
465	r->res = rle->res;
466	r->direct = ((rman_get_flags(rle->res) & RF_ACTIVE) != 0);
467
468	/* Allocate the clkctl instance */
469	clkctl = bhnd_alloc_core_clkctl(child, pmu_dev, r, pmu_regs,
470	    max_latency);
471	if (clkctl == NULL) {
472		free(r, M_BHND);
473		bhnd_release_provider(child, pmu_dev, BHND_SERVICE_PMU);
474		return (ENOMEM);
475	}
476
477	bhnd_set_pmu_info(child, clkctl);
478	return (0);
479}
480
481/**
482 * Default bhnd(4) bus driver implementation of BHND_BUS_RELEASE_PMU().
483 */
484int
485bhnd_generic_release_pmu(device_t dev, device_t child)
486{
487	struct bhnd_softc	*sc;
488	struct bhnd_core_clkctl	*clkctl;
489	struct bhnd_resource	*r;
490	device_t		 pmu_dev;
491
492	GIANT_REQUIRED;	/* for newbus */
493
494	sc = device_get_softc(dev);
495
496	if (device_get_parent(child) != dev)
497		return (EINVAL);
498
499	clkctl = bhnd_get_pmu_info(child);
500	if (clkctl == NULL)
501		panic("pmu over-release for %s", device_get_nameunit(child));
502
503	/* Clear all FORCE, AREQ, and ERSRC flags, unless we're already in
504	 * RESET. Suspending a core clears clkctl automatically (and attempting
505	 * to access the PMU registers in a suspended core will trigger a
506	 * system livelock). */
507	if (!bhnd_is_hw_suspended(clkctl->cc_dev)) {
508		BHND_CLKCTL_LOCK(clkctl);
509
510		/* Clear all FORCE, AREQ, and ERSRC flags */
511		BHND_CLKCTL_SET_4(clkctl, 0x0, BHND_CCS_FORCE_MASK |
512		    BHND_CCS_AREQ_MASK | BHND_CCS_ERSRC_REQ_MASK);
513
514		BHND_CLKCTL_UNLOCK(clkctl);
515	}
516
517	/* Clear child's PMU info reference */
518	bhnd_set_pmu_info(child, NULL);
519
520	/* Before freeing the clkctl instance, save a pointer to resources we
521	 * need to clean up manually */
522	r = clkctl->cc_res;
523	pmu_dev = clkctl->cc_pmu_dev;
524
525	/* Free the clkctl instance */
526	bhnd_free_core_clkctl(clkctl);
527
528	/* Free the child's bhnd resource wrapper */
529	free(r, M_BHND);
530
531	/* Release the child's PMU provider reference */
532	bhnd_release_provider(child, pmu_dev, BHND_SERVICE_PMU);
533
534	return (0);
535}
536
537/**
538 * Default bhnd(4) bus driver implementation of BHND_BUS_GET_CLOCK_LATENCY().
539 */
540int
541bhnd_generic_get_clock_latency(device_t dev, device_t child, bhnd_clock clock,
542    u_int *latency)
543{
544	struct bhnd_core_clkctl *clkctl;
545
546	if (device_get_parent(child) != dev)
547		return (EINVAL);
548
549	if ((clkctl = bhnd_get_pmu_info(child)) == NULL)
550		panic("no active PMU allocation");
551
552	return (bhnd_pmu_get_clock_latency(clkctl->cc_pmu_dev, clock, latency));
553}
554
555/**
556 * Default bhnd(4) bus driver implementation of BHND_BUS_GET_CLOCK_FREQ().
557 */
558int
559bhnd_generic_get_clock_freq(device_t dev, device_t child, bhnd_clock clock,
560    u_int *freq)
561{
562	struct bhnd_core_clkctl *clkctl;
563
564	if (device_get_parent(child) != dev)
565		return (EINVAL);
566
567	if ((clkctl = bhnd_get_pmu_info(child)) == NULL)
568		panic("no active PMU allocation");
569
570	return (bhnd_pmu_get_clock_freq(clkctl->cc_pmu_dev, clock, freq));
571}
572
573/**
574 * Default bhnd(4) bus driver implementation of BHND_BUS_REQUEST_CLOCK().
575 */
576int
577bhnd_generic_request_clock(device_t dev, device_t child, bhnd_clock clock)
578{
579	struct bhnd_softc	*sc;
580	struct bhnd_core_clkctl	*clkctl;
581	uint32_t		 avail;
582	uint32_t		 req;
583	int			 error;
584
585	sc = device_get_softc(dev);
586
587	if (device_get_parent(child) != dev)
588		return (EINVAL);
589
590	if ((clkctl = bhnd_get_pmu_info(child)) == NULL)
591		panic("no active PMU allocation");
592
593	BHND_ASSERT_CLKCTL_AVAIL(clkctl);
594
595	avail = 0x0;
596	req = 0x0;
597
598	switch (clock) {
599	case BHND_CLOCK_DYN:
600		break;
601	case BHND_CLOCK_ILP:
602		req |= BHND_CCS_FORCEILP;
603		break;
604	case BHND_CLOCK_ALP:
605		req |= BHND_CCS_FORCEALP;
606		avail |= BHND_CCS_ALPAVAIL;
607		break;
608	case BHND_CLOCK_HT:
609		req |= BHND_CCS_FORCEHT;
610		avail |= BHND_CCS_HTAVAIL;
611		break;
612	default:
613		device_printf(dev, "%s requested unknown clock: %#x\n",
614		    device_get_nameunit(clkctl->cc_dev), clock);
615		return (ENODEV);
616	}
617
618	BHND_CLKCTL_LOCK(clkctl);
619
620	/* Issue request */
621	BHND_CLKCTL_SET_4(clkctl, req, BHND_CCS_FORCE_MASK);
622
623	/* Wait for clock availability */
624	error = bhnd_core_clkctl_wait(clkctl, avail, avail);
625
626	BHND_CLKCTL_UNLOCK(clkctl);
627
628	return (error);
629}
630
631/**
632 * Default bhnd(4) bus driver implementation of BHND_BUS_ENABLE_CLOCKS().
633 */
634int
635bhnd_generic_enable_clocks(device_t dev, device_t child, uint32_t clocks)
636{
637	struct bhnd_softc	*sc;
638	struct bhnd_core_clkctl	*clkctl;
639	uint32_t		 avail;
640	uint32_t		 req;
641	int			 error;
642
643	sc = device_get_softc(dev);
644
645	if (device_get_parent(child) != dev)
646		return (EINVAL);
647
648	if ((clkctl = bhnd_get_pmu_info(child)) == NULL)
649		panic("no active PMU allocation");
650
651	BHND_ASSERT_CLKCTL_AVAIL(clkctl);
652
653	sc = device_get_softc(dev);
654
655	avail = 0x0;
656	req = 0x0;
657
658	/* Build clock request flags */
659	if (clocks & BHND_CLOCK_DYN)		/* nothing to enable */
660		clocks &= ~BHND_CLOCK_DYN;
661
662	if (clocks & BHND_CLOCK_ILP)		/* nothing to enable */
663		clocks &= ~BHND_CLOCK_ILP;
664
665	if (clocks & BHND_CLOCK_ALP) {
666		req |= BHND_CCS_ALPAREQ;
667		avail |= BHND_CCS_ALPAVAIL;
668		clocks &= ~BHND_CLOCK_ALP;
669	}
670
671	if (clocks & BHND_CLOCK_HT) {
672		req |= BHND_CCS_HTAREQ;
673		avail |= BHND_CCS_HTAVAIL;
674		clocks &= ~BHND_CLOCK_HT;
675	}
676
677	/* Check for unknown clock values */
678	if (clocks != 0x0) {
679		device_printf(dev, "%s requested unknown clocks: %#x\n",
680		    device_get_nameunit(clkctl->cc_dev), clocks);
681		return (ENODEV);
682	}
683
684	BHND_CLKCTL_LOCK(clkctl);
685
686	/* Issue request */
687	BHND_CLKCTL_SET_4(clkctl, req, BHND_CCS_AREQ_MASK);
688
689	/* Wait for clock availability */
690	error = bhnd_core_clkctl_wait(clkctl, avail, avail);
691
692	BHND_CLKCTL_UNLOCK(clkctl);
693
694	return (error);
695}
696
697/**
698 * Default bhnd(4) bus driver implementation of BHND_BUS_REQUEST_EXT_RSRC().
699 */
700int
701bhnd_generic_request_ext_rsrc(device_t dev, device_t child, u_int rsrc)
702{
703	struct bhnd_softc	*sc;
704	struct bhnd_core_clkctl	*clkctl;
705	uint32_t		 req;
706	uint32_t		 avail;
707	int			 error;
708
709	sc = device_get_softc(dev);
710
711	if (device_get_parent(child) != dev)
712		return (EINVAL);
713
714	if ((clkctl = bhnd_get_pmu_info(child)) == NULL)
715		panic("no active PMU allocation");
716
717	BHND_ASSERT_CLKCTL_AVAIL(clkctl);
718
719	sc = device_get_softc(dev);
720
721	if (rsrc > BHND_CCS_ERSRC_MAX)
722		return (EINVAL);
723
724	req = BHND_CCS_SET_BITS((1<<rsrc), BHND_CCS_ERSRC_REQ);
725	avail = BHND_CCS_SET_BITS((1<<rsrc), BHND_CCS_ERSRC_STS);
726
727	BHND_CLKCTL_LOCK(clkctl);
728
729	/* Write request */
730	BHND_CLKCTL_SET_4(clkctl, req, req);
731
732	/* Wait for resource availability */
733	error = bhnd_core_clkctl_wait(clkctl, avail, avail);
734
735	BHND_CLKCTL_UNLOCK(clkctl);
736
737	return (error);
738}
739
740/**
741 * Default bhnd(4) bus driver implementation of BHND_BUS_RELEASE_EXT_RSRC().
742 */
743int
744bhnd_generic_release_ext_rsrc(device_t dev, device_t child, u_int rsrc)
745{
746	struct bhnd_softc	*sc;
747	struct bhnd_core_clkctl	*clkctl;
748	uint32_t		 mask;
749
750	sc = device_get_softc(dev);
751
752	if (device_get_parent(child) != dev)
753		return (EINVAL);
754
755	if ((clkctl = bhnd_get_pmu_info(child)) == NULL)
756		panic("no active PMU allocation");
757
758	BHND_ASSERT_CLKCTL_AVAIL(clkctl);
759
760	sc = device_get_softc(dev);
761
762	if (rsrc > BHND_CCS_ERSRC_MAX)
763		return (EINVAL);
764
765	mask = BHND_CCS_SET_BITS((1<<rsrc), BHND_CCS_ERSRC_REQ);
766
767	/* Clear request */
768	BHND_CLKCTL_LOCK(clkctl);
769	BHND_CLKCTL_SET_4(clkctl, 0x0, mask);
770	BHND_CLKCTL_UNLOCK(clkctl);
771
772	return (0);
773}
774
775/**
776 * Default bhnd(4) bus driver implementation of BHND_BUS_IS_REGION_VALID().
777 *
778 * This implementation assumes that port and region numbers are 0-indexed and
779 * are allocated non-sparsely, using BHND_BUS_GET_PORT_COUNT() and
780 * BHND_BUS_GET_REGION_COUNT() to determine if @p port and @p region fall
781 * within the defined range.
782 */
783static bool
784bhnd_generic_is_region_valid(device_t dev, device_t child,
785    bhnd_port_type type, u_int port, u_int region)
786{
787	if (port >= bhnd_get_port_count(child, type))
788		return (false);
789
790	if (region >= bhnd_get_region_count(child, type, port))
791		return (false);
792
793	return (true);
794}
795
796/**
797 * Default bhnd(4) bus driver implementation of BHND_BUS_GET_NVRAM_VAR().
798 *
799 * This implementation searches @p dev for a registered NVRAM child device.
800 *
801 * If no NVRAM device is registered with @p dev, the request is delegated to
802 * the BHND_BUS_GET_NVRAM_VAR() method on the parent of @p dev.
803 */
804int
805bhnd_generic_get_nvram_var(device_t dev, device_t child, const char *name,
806    void *buf, size_t *size, bhnd_nvram_type type)
807{
808	struct bhnd_softc	*sc;
809	device_t		 nvram, parent;
810	int			 error;
811
812	sc = device_get_softc(dev);
813
814	/* If a NVRAM device is available, consult it first */
815	nvram = bhnd_retain_provider(child, BHND_SERVICE_NVRAM);
816	if (nvram != NULL) {
817		error = BHND_NVRAM_GETVAR(nvram, name, buf, size, type);
818		bhnd_release_provider(child, nvram, BHND_SERVICE_NVRAM);
819		return (error);
820	}
821
822	/* Otherwise, try to delegate to parent */
823	if ((parent = device_get_parent(dev)) == NULL)
824		return (ENODEV);
825
826	return (BHND_BUS_GET_NVRAM_VAR(device_get_parent(dev), child,
827	    name, buf, size, type));
828}
829
830/**
831 * Default bhnd(4) bus driver implementation of BUS_PRINT_CHILD().
832 *
833 * This implementation requests the device's struct resource_list via
834 * BUS_GET_RESOURCE_LIST.
835 */
836int
837bhnd_generic_print_child(device_t dev, device_t child)
838{
839	struct resource_list	*rl;
840	int			retval = 0;
841
842	retval += bus_print_child_header(dev, child);
843
844	rl = BUS_GET_RESOURCE_LIST(dev, child);
845
846	if (rl != NULL) {
847		retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY,
848		    "%#jx");
849
850		retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ,
851		    "%#jd");
852	}
853
854	retval += printf(" at core %u", bhnd_get_core_index(child));
855
856	retval += bus_print_child_domain(dev, child);
857	retval += bus_print_child_footer(dev, child);
858
859	return (retval);
860}
861
862/**
863 * Default bhnd(4) bus driver implementation of BUS_PROBE_NOMATCH().
864 *
865 * This implementation requests the device's struct resource_list via
866 * BUS_GET_RESOURCE_LIST.
867 */
868void
869bhnd_generic_probe_nomatch(device_t dev, device_t child)
870{
871	struct resource_list		*rl;
872	const struct bhnd_nomatch	*nm;
873	bool				 report;
874
875	/* Fetch reporting configuration for this device */
876	report = true;
877	for (nm = bhnd_nomatch_table; nm->device != BHND_COREID_INVALID; nm++) {
878		if (nm->vendor != bhnd_get_vendor(child))
879			continue;
880
881		if (nm->device != bhnd_get_device(child))
882			continue;
883
884		report = false;
885		if (bootverbose && nm->if_verbose)
886			report = true;
887		break;
888	}
889
890	if (!report)
891		return;
892
893	/* Print the non-matched device info */
894	device_printf(dev, "<%s %s, rev %hhu>", bhnd_get_vendor_name(child),
895		bhnd_get_device_name(child), bhnd_get_hwrev(child));
896
897	rl = BUS_GET_RESOURCE_LIST(dev, child);
898	if (rl != NULL) {
899		resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#jx");
900		resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%#jd");
901	}
902
903	printf(" at core %u (no driver attached)\n",
904	    bhnd_get_core_index(child));
905}
906
907/**
908 * Default implementation of BUS_CHILD_PNPINFO_STR().
909 */
910static int
911bhnd_child_pnpinfo_str(device_t dev, device_t child, char *buf,
912    size_t buflen)
913{
914	if (device_get_parent(child) != dev) {
915		return (BUS_CHILD_PNPINFO_STR(device_get_parent(dev), child,
916		    buf, buflen));
917	}
918
919	snprintf(buf, buflen, "vendor=0x%hx device=0x%hx rev=0x%hhx",
920	    bhnd_get_vendor(child), bhnd_get_device(child),
921	    bhnd_get_hwrev(child));
922
923	return (0);
924}
925
926/**
927 * Default implementation of BUS_CHILD_LOCATION_STR().
928 */
929static int
930bhnd_child_location_str(device_t dev, device_t child, char *buf,
931    size_t buflen)
932{
933	bhnd_addr_t	addr;
934	bhnd_size_t	size;
935
936	if (device_get_parent(child) != dev) {
937		return (BUS_CHILD_LOCATION_STR(device_get_parent(dev), child,
938		    buf, buflen));
939	}
940
941	if (bhnd_get_region_addr(child, BHND_PORT_DEVICE, 0, 0, &addr, &size)) {
942		/* No device default port/region */
943		if (buflen > 0)
944			*buf = '\0';
945		return (0);
946	}
947
948	snprintf(buf, buflen, "port0.0=0x%llx", (unsigned long long) addr);
949	return (0);
950}
951
952/**
953 * Default bhnd(4) bus driver implementation of BUS_CHILD_DELETED().
954 *
955 * This implementation manages internal bhnd(4) state, and must be called
956 * by subclassing drivers.
957 */
958void
959bhnd_generic_child_deleted(device_t dev, device_t child)
960{
961	struct bhnd_softc	*sc;
962
963	sc = device_get_softc(dev);
964
965	/* Free device info */
966	if (bhnd_get_pmu_info(child) != NULL) {
967		/* Releasing PMU requests automatically would be nice,
968		 * but we can't reference per-core PMU register
969		 * resource after driver detach */
970		panic("%s leaked device pmu state\n",
971		    device_get_nameunit(child));
972	}
973}
974
975/**
976 * Helper function for implementing BUS_SUSPEND_CHILD().
977 *
978 * TODO: Power management
979 *
980 * If @p child is not a direct child of @p dev, suspension is delegated to
981 * the @p dev parent.
982 */
983int
984bhnd_generic_suspend_child(device_t dev, device_t child)
985{
986	if (device_get_parent(child) != dev)
987		BUS_SUSPEND_CHILD(device_get_parent(dev), child);
988
989	return bus_generic_suspend_child(dev, child);
990}
991
992/**
993 * Helper function for implementing BUS_RESUME_CHILD().
994 *
995 * TODO: Power management
996 *
997 * If @p child is not a direct child of @p dev, suspension is delegated to
998 * the @p dev parent.
999 */
1000int
1001bhnd_generic_resume_child(device_t dev, device_t child)
1002{
1003	if (device_get_parent(child) != dev)
1004		BUS_RESUME_CHILD(device_get_parent(dev), child);
1005
1006	return bus_generic_resume_child(dev, child);
1007}
1008
1009/**
1010 * Default bhnd(4) bus driver implementation of BUS_SETUP_INTR().
1011 *
1012 * This implementation of BUS_SETUP_INTR() will delegate interrupt setup
1013 * to the parent of @p dev, if any.
1014 */
1015int
1016bhnd_generic_setup_intr(device_t dev, device_t child, struct resource *irq,
1017    int flags, driver_filter_t *filter, driver_intr_t *intr, void *arg,
1018    void **cookiep)
1019{
1020	return (bus_generic_setup_intr(dev, child, irq, flags, filter, intr,
1021	    arg, cookiep));
1022}
1023
1024/*
1025 * Delegate all indirect I/O to the parent device. When inherited by
1026 * non-bridged bus implementations, resources will never be marked as
1027 * indirect, and these methods will never be called.
1028 */
1029#define	BHND_IO_READ(_type, _name, _method)				\
1030static _type								\
1031bhnd_read_ ## _name (device_t dev, device_t child,			\
1032    struct bhnd_resource *r, bus_size_t offset)				\
1033{									\
1034	return (BHND_BUS_READ_ ## _method(				\
1035		    device_get_parent(dev), child, r, offset));		\
1036}
1037
1038#define	BHND_IO_WRITE(_type, _name, _method)				\
1039static void								\
1040bhnd_write_ ## _name (device_t dev, device_t child,			\
1041    struct bhnd_resource *r, bus_size_t offset, _type value)		\
1042{									\
1043	return (BHND_BUS_WRITE_ ## _method(				\
1044		    device_get_parent(dev), child, r, offset,		\
1045		    value));	\
1046}
1047
1048#define	BHND_IO_MISC(_type, _op, _method)				\
1049static void								\
1050bhnd_ ## _op (device_t dev, device_t child,				\
1051    struct bhnd_resource *r, bus_size_t offset, _type datap,		\
1052    bus_size_t count)							\
1053{									\
1054	BHND_BUS_ ## _method(device_get_parent(dev), child, r,		\
1055	    offset, datap, count);					\
1056}
1057
1058#define	BHND_IO_METHODS(_type, _size)					\
1059	BHND_IO_READ(_type, _size, _size)				\
1060	BHND_IO_WRITE(_type, _size, _size)				\
1061									\
1062	BHND_IO_READ(_type, stream_ ## _size, STREAM_ ## _size)		\
1063	BHND_IO_WRITE(_type, stream_ ## _size, STREAM_ ## _size)	\
1064									\
1065	BHND_IO_MISC(_type*, read_multi_ ## _size,			\
1066	    READ_MULTI_ ## _size)					\
1067	BHND_IO_MISC(_type*, write_multi_ ## _size,			\
1068	    WRITE_MULTI_ ## _size)					\
1069									\
1070	BHND_IO_MISC(_type*, read_multi_stream_ ## _size,		\
1071	   READ_MULTI_STREAM_ ## _size)					\
1072	BHND_IO_MISC(_type*, write_multi_stream_ ## _size,		\
1073	   WRITE_MULTI_STREAM_ ## _size)				\
1074									\
1075	BHND_IO_MISC(_type, set_multi_ ## _size, SET_MULTI_ ## _size)	\
1076	BHND_IO_MISC(_type, set_region_ ## _size, SET_REGION_ ## _size)	\
1077									\
1078	BHND_IO_MISC(_type*, read_region_ ## _size,			\
1079	    READ_REGION_ ## _size)					\
1080	BHND_IO_MISC(_type*, write_region_ ## _size,			\
1081	    WRITE_REGION_ ## _size)					\
1082									\
1083	BHND_IO_MISC(_type*, read_region_stream_ ## _size,		\
1084	    READ_REGION_STREAM_ ## _size)				\
1085	BHND_IO_MISC(_type*, write_region_stream_ ## _size,		\
1086	    WRITE_REGION_STREAM_ ## _size)				\
1087
1088BHND_IO_METHODS(uint8_t, 1);
1089BHND_IO_METHODS(uint16_t, 2);
1090BHND_IO_METHODS(uint32_t, 4);
1091
1092static void
1093bhnd_barrier(device_t dev, device_t child, struct bhnd_resource *r,
1094    bus_size_t offset, bus_size_t length, int flags)
1095{
1096	BHND_BUS_BARRIER(device_get_parent(dev), child, r, offset, length,
1097	    flags);
1098}
1099
1100static device_method_t bhnd_methods[] = {
1101	/* Device interface */ \
1102	DEVMETHOD(device_attach,		bhnd_generic_attach),
1103	DEVMETHOD(device_detach,		bhnd_generic_detach),
1104	DEVMETHOD(device_shutdown,		bhnd_generic_shutdown),
1105	DEVMETHOD(device_suspend,		bhnd_generic_suspend),
1106	DEVMETHOD(device_resume,		bhnd_generic_resume),
1107
1108	/* Bus interface */
1109	DEVMETHOD(bus_child_deleted,		bhnd_generic_child_deleted),
1110	DEVMETHOD(bus_probe_nomatch,		bhnd_generic_probe_nomatch),
1111	DEVMETHOD(bus_print_child,		bhnd_generic_print_child),
1112	DEVMETHOD(bus_child_pnpinfo_str,	bhnd_child_pnpinfo_str),
1113	DEVMETHOD(bus_child_location_str,	bhnd_child_location_str),
1114
1115	DEVMETHOD(bus_suspend_child,		bhnd_generic_suspend_child),
1116	DEVMETHOD(bus_resume_child,		bhnd_generic_resume_child),
1117
1118	DEVMETHOD(bus_set_resource,		bus_generic_rl_set_resource),
1119	DEVMETHOD(bus_get_resource,		bus_generic_rl_get_resource),
1120	DEVMETHOD(bus_delete_resource,		bus_generic_rl_delete_resource),
1121	DEVMETHOD(bus_alloc_resource,		bus_generic_rl_alloc_resource),
1122	DEVMETHOD(bus_adjust_resource,		bus_generic_adjust_resource),
1123	DEVMETHOD(bus_release_resource,		bus_generic_rl_release_resource),
1124	DEVMETHOD(bus_activate_resource,	bus_generic_activate_resource),
1125	DEVMETHOD(bus_deactivate_resource,	bus_generic_deactivate_resource),
1126
1127	DEVMETHOD(bus_setup_intr,		bhnd_generic_setup_intr),
1128	DEVMETHOD(bus_teardown_intr,		bus_generic_teardown_intr),
1129	DEVMETHOD(bus_config_intr,		bus_generic_config_intr),
1130	DEVMETHOD(bus_bind_intr,		bus_generic_bind_intr),
1131	DEVMETHOD(bus_describe_intr,		bus_generic_describe_intr),
1132
1133	DEVMETHOD(bus_get_dma_tag,		bus_generic_get_dma_tag),
1134
1135	/* BHND interface */
1136	DEVMETHOD(bhnd_bus_get_chipid,		bhnd_bus_generic_get_chipid),
1137	DEVMETHOD(bhnd_bus_is_hw_disabled,	bhnd_bus_generic_is_hw_disabled),
1138
1139	DEVMETHOD(bhnd_bus_get_probe_order,	bhnd_generic_get_probe_order),
1140
1141	DEVMETHOD(bhnd_bus_alloc_pmu,		bhnd_generic_alloc_pmu),
1142	DEVMETHOD(bhnd_bus_release_pmu,		bhnd_generic_release_pmu),
1143	DEVMETHOD(bhnd_bus_request_clock,	bhnd_generic_request_clock),
1144	DEVMETHOD(bhnd_bus_enable_clocks,	bhnd_generic_enable_clocks),
1145	DEVMETHOD(bhnd_bus_request_ext_rsrc,	bhnd_generic_request_ext_rsrc),
1146	DEVMETHOD(bhnd_bus_release_ext_rsrc,	bhnd_generic_release_ext_rsrc),
1147	DEVMETHOD(bhnd_bus_get_clock_latency,	bhnd_generic_get_clock_latency),
1148	DEVMETHOD(bhnd_bus_get_clock_freq,	bhnd_generic_get_clock_freq),
1149
1150	DEVMETHOD(bhnd_bus_is_region_valid,	bhnd_generic_is_region_valid),
1151	DEVMETHOD(bhnd_bus_get_nvram_var,	bhnd_generic_get_nvram_var),
1152
1153	/* BHND interface (bus I/O) */
1154	DEVMETHOD(bhnd_bus_read_1,		bhnd_read_1),
1155	DEVMETHOD(bhnd_bus_read_2,		bhnd_read_2),
1156	DEVMETHOD(bhnd_bus_read_4,		bhnd_read_4),
1157	DEVMETHOD(bhnd_bus_write_1,		bhnd_write_1),
1158	DEVMETHOD(bhnd_bus_write_2,		bhnd_write_2),
1159	DEVMETHOD(bhnd_bus_write_4,		bhnd_write_4),
1160
1161	DEVMETHOD(bhnd_bus_read_stream_1,	bhnd_read_stream_1),
1162	DEVMETHOD(bhnd_bus_read_stream_2,	bhnd_read_stream_2),
1163	DEVMETHOD(bhnd_bus_read_stream_4,	bhnd_read_stream_4),
1164	DEVMETHOD(bhnd_bus_write_stream_1,	bhnd_write_stream_1),
1165	DEVMETHOD(bhnd_bus_write_stream_2,	bhnd_write_stream_2),
1166	DEVMETHOD(bhnd_bus_write_stream_4,	bhnd_write_stream_4),
1167
1168	DEVMETHOD(bhnd_bus_read_multi_1,	bhnd_read_multi_1),
1169	DEVMETHOD(bhnd_bus_read_multi_2,	bhnd_read_multi_2),
1170	DEVMETHOD(bhnd_bus_read_multi_4,	bhnd_read_multi_4),
1171	DEVMETHOD(bhnd_bus_write_multi_1,	bhnd_write_multi_1),
1172	DEVMETHOD(bhnd_bus_write_multi_2,	bhnd_write_multi_2),
1173	DEVMETHOD(bhnd_bus_write_multi_4,	bhnd_write_multi_4),
1174
1175	DEVMETHOD(bhnd_bus_read_multi_stream_1,	bhnd_read_multi_stream_1),
1176	DEVMETHOD(bhnd_bus_read_multi_stream_2,	bhnd_read_multi_stream_2),
1177	DEVMETHOD(bhnd_bus_read_multi_stream_4,	bhnd_read_multi_stream_4),
1178	DEVMETHOD(bhnd_bus_write_multi_stream_1,bhnd_write_multi_stream_1),
1179	DEVMETHOD(bhnd_bus_write_multi_stream_2,bhnd_write_multi_stream_2),
1180	DEVMETHOD(bhnd_bus_write_multi_stream_4,bhnd_write_multi_stream_4),
1181
1182	DEVMETHOD(bhnd_bus_set_multi_1,		bhnd_set_multi_1),
1183	DEVMETHOD(bhnd_bus_set_multi_2,		bhnd_set_multi_2),
1184	DEVMETHOD(bhnd_bus_set_multi_4,		bhnd_set_multi_4),
1185
1186	DEVMETHOD(bhnd_bus_set_region_1,	bhnd_set_region_1),
1187	DEVMETHOD(bhnd_bus_set_region_2,	bhnd_set_region_2),
1188	DEVMETHOD(bhnd_bus_set_region_4,	bhnd_set_region_4),
1189
1190	DEVMETHOD(bhnd_bus_read_region_1,	bhnd_read_region_1),
1191	DEVMETHOD(bhnd_bus_read_region_2,	bhnd_read_region_2),
1192	DEVMETHOD(bhnd_bus_read_region_4,	bhnd_read_region_4),
1193	DEVMETHOD(bhnd_bus_write_region_1,	bhnd_write_region_1),
1194	DEVMETHOD(bhnd_bus_write_region_2,	bhnd_write_region_2),
1195	DEVMETHOD(bhnd_bus_write_region_4,	bhnd_write_region_4),
1196
1197	DEVMETHOD(bhnd_bus_read_region_stream_1,bhnd_read_region_stream_1),
1198	DEVMETHOD(bhnd_bus_read_region_stream_2,bhnd_read_region_stream_2),
1199	DEVMETHOD(bhnd_bus_read_region_stream_4,bhnd_read_region_stream_4),
1200	DEVMETHOD(bhnd_bus_write_region_stream_1, bhnd_write_region_stream_1),
1201	DEVMETHOD(bhnd_bus_write_region_stream_2, bhnd_write_region_stream_2),
1202	DEVMETHOD(bhnd_bus_write_region_stream_4, bhnd_write_region_stream_4),
1203
1204	DEVMETHOD(bhnd_bus_barrier,			bhnd_barrier),
1205
1206	DEVMETHOD_END
1207};
1208
1209devclass_t bhnd_devclass;	/**< bhnd bus. */
1210devclass_t bhnd_hostb_devclass;	/**< bhnd bus host bridge. */
1211devclass_t bhnd_nvram_devclass;	/**< bhnd NVRAM device */
1212
1213DEFINE_CLASS_0(bhnd, bhnd_driver, bhnd_methods, sizeof(struct bhnd_softc));
1214MODULE_VERSION(bhnd, 1);
1215