1*c7fb772bSthorpej /* $Id: imx23_apbh.c,v 1.3 2021/08/07 16:18:44 thorpej Exp $ */
2eba5cacbSjkunz
3eba5cacbSjkunz /*
4eba5cacbSjkunz * Copyright (c) 2012 The NetBSD Foundation, Inc.
5eba5cacbSjkunz * All rights reserved.
6eba5cacbSjkunz *
7eba5cacbSjkunz * This code is derived from software contributed to The NetBSD Foundation
8eba5cacbSjkunz * by Petri Laakso.
9eba5cacbSjkunz *
10eba5cacbSjkunz * Redistribution and use in source and binary forms, with or without
11eba5cacbSjkunz * modification, are permitted provided that the following conditions
12eba5cacbSjkunz * are met:
13eba5cacbSjkunz * 1. Redistributions of source code must retain the above copyright
14eba5cacbSjkunz * notice, this list of conditions and the following disclaimer.
15eba5cacbSjkunz * 2. Redistributions in binary form must reproduce the above copyright
16eba5cacbSjkunz * notice, this list of conditions and the following disclaimer in the
17eba5cacbSjkunz * documentation and/or other materials provided with the distribution.
18eba5cacbSjkunz *
19eba5cacbSjkunz * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20eba5cacbSjkunz * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21eba5cacbSjkunz * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22eba5cacbSjkunz * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23eba5cacbSjkunz * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24eba5cacbSjkunz * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25eba5cacbSjkunz * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26eba5cacbSjkunz * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27eba5cacbSjkunz * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28eba5cacbSjkunz * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29eba5cacbSjkunz * POSSIBILITY OF SUCH DAMAGE.
30eba5cacbSjkunz */
31eba5cacbSjkunz
32eba5cacbSjkunz #include <sys/param.h>
33eba5cacbSjkunz #include <sys/bus.h>
34eba5cacbSjkunz #include <sys/device.h>
35eba5cacbSjkunz #include <sys/errno.h>
36eba5cacbSjkunz
37eba5cacbSjkunz #include <arm/mainbus/mainbus.h>
38eba5cacbSjkunz
39eba5cacbSjkunz #include <arm/imx/imx23var.h>
40eba5cacbSjkunz
41eba5cacbSjkunz #include "locators.h"
42eba5cacbSjkunz
43eba5cacbSjkunz static int apbh_match(device_t, cfdata_t, void *);
44eba5cacbSjkunz static void apbh_attach(device_t, device_t, void *);
45eba5cacbSjkunz static int apbh_detach(device_t, int);
46eba5cacbSjkunz static int apbh_activate(device_t, enum devact);
47eba5cacbSjkunz
48eba5cacbSjkunz static int apbh_search_cb(device_t, cfdata_t, const int *, void *);
49eba5cacbSjkunz static int apbh_search_crit_cb(device_t, cfdata_t, const int *, void *);
50eba5cacbSjkunz static int apbh_print(void *,const char *);
51eba5cacbSjkunz
52eba5cacbSjkunz struct apbh_softc {
53eba5cacbSjkunz device_t sc_dev;
54eba5cacbSjkunz device_t dmac; /* DMA controller device for this bus. */
55eba5cacbSjkunz };
56eba5cacbSjkunz
57eba5cacbSjkunz CFATTACH_DECL3_NEW(apbh,
58eba5cacbSjkunz sizeof(struct apbh_softc),
59eba5cacbSjkunz apbh_match,
60eba5cacbSjkunz apbh_attach,
61eba5cacbSjkunz apbh_detach,
62eba5cacbSjkunz apbh_activate,
63eba5cacbSjkunz NULL,
64eba5cacbSjkunz NULL,
65eba5cacbSjkunz 0);
66eba5cacbSjkunz
67eba5cacbSjkunz static int
apbh_match(device_t parent,cfdata_t match,void * aux)68eba5cacbSjkunz apbh_match(device_t parent, cfdata_t match, void *aux)
69eba5cacbSjkunz {
70eba5cacbSjkunz struct mainbus_attach_args *mb = aux;
71eba5cacbSjkunz
72eba5cacbSjkunz if ((mb->mb_iobase == APBH_BASE) && (mb->mb_iosize == APBH_SIZE))
73eba5cacbSjkunz return 1;
74eba5cacbSjkunz
75eba5cacbSjkunz return 0;
76eba5cacbSjkunz }
77eba5cacbSjkunz
78eba5cacbSjkunz static void
apbh_attach(device_t parent,device_t self,void * aux)79eba5cacbSjkunz apbh_attach(device_t parent, device_t self, void *aux)
80eba5cacbSjkunz {
81eba5cacbSjkunz struct apb_attach_args aa;
82eba5cacbSjkunz static int apbh_attached = 0;
83eba5cacbSjkunz
84eba5cacbSjkunz if (apbh_attached)
85eba5cacbSjkunz return;
86eba5cacbSjkunz
87eba5cacbSjkunz aa.aa_iot = &imx23_bus_space;
88eba5cacbSjkunz aa.aa_dmat = &imx23_bus_dma_tag;
89eba5cacbSjkunz
90eba5cacbSjkunz aprint_normal("\n");
91eba5cacbSjkunz
922685996bSthorpej config_search(self, &aa,
93*c7fb772bSthorpej CFARGS(.search = apbh_search_crit_cb));
942685996bSthorpej config_search(self, &aa,
95*c7fb772bSthorpej CFARGS(.search = apbh_search_cb));
96eba5cacbSjkunz
97eba5cacbSjkunz apbh_attached = 1;
98eba5cacbSjkunz
99eba5cacbSjkunz return;
100eba5cacbSjkunz }
101eba5cacbSjkunz
102eba5cacbSjkunz static int
apbh_detach(device_t self,int flags)103eba5cacbSjkunz apbh_detach(device_t self, int flags)
104eba5cacbSjkunz {
105eba5cacbSjkunz return 0;
106eba5cacbSjkunz }
107eba5cacbSjkunz
108eba5cacbSjkunz static int
apbh_activate(device_t self,enum devact act)109eba5cacbSjkunz apbh_activate(device_t self, enum devact act)
110eba5cacbSjkunz {
111eba5cacbSjkunz return EOPNOTSUPP;
112eba5cacbSjkunz }
113eba5cacbSjkunz
114eba5cacbSjkunz /*
115eba5cacbSjkunz * config_search_ia() callback function.
116eba5cacbSjkunz */
117eba5cacbSjkunz static int
apbh_search_cb(device_t parent,cfdata_t cf,const int * locs,void * aux)118eba5cacbSjkunz apbh_search_cb(device_t parent, cfdata_t cf, const int *locs, void *aux)
119eba5cacbSjkunz {
120eba5cacbSjkunz struct apb_attach_args *aa = aux;
121eba5cacbSjkunz
122eba5cacbSjkunz aa->aa_name = cf->cf_name;
123eba5cacbSjkunz aa->aa_addr = cf->cf_loc[APBHCF_ADDR];
124eba5cacbSjkunz aa->aa_size = cf->cf_loc[APBHCF_SIZE];
125eba5cacbSjkunz aa->aa_irq = cf->cf_loc[APBHCF_IRQ];
126eba5cacbSjkunz
1272685996bSthorpej if (config_probe(parent, cf, aux))
128*c7fb772bSthorpej config_attach(parent, cf, aux, apbh_print, CFARGS_NONE);
129eba5cacbSjkunz
130eba5cacbSjkunz return 0;
131eba5cacbSjkunz }
132eba5cacbSjkunz
133eba5cacbSjkunz /*
134eba5cacbSjkunz * config_search_ia() callback function which only applies to critical devices.
135eba5cacbSjkunz */
136eba5cacbSjkunz static int
apbh_search_crit_cb(device_t parent,cfdata_t cf,const int * locs,void * aux)137eba5cacbSjkunz apbh_search_crit_cb(device_t parent, cfdata_t cf, const int *locs, void *aux)
138eba5cacbSjkunz {
139eba5cacbSjkunz struct apb_attach_args *aa = aux;
140eba5cacbSjkunz
141eba5cacbSjkunz /* Return if not critical device. */
142eba5cacbSjkunz if ((strcmp(cf->cf_name, "icoll") != 0)
143eba5cacbSjkunz && (strcmp(cf->cf_name, "apbdma") != 0))
144eba5cacbSjkunz return 0;
145eba5cacbSjkunz
146eba5cacbSjkunz aa->aa_name = cf->cf_name;
147eba5cacbSjkunz aa->aa_addr = cf->cf_loc[APBHCF_ADDR];
148eba5cacbSjkunz aa->aa_size = cf->cf_loc[APBHCF_SIZE];
149eba5cacbSjkunz aa->aa_irq = cf->cf_loc[APBHCF_IRQ];
150eba5cacbSjkunz
1512685996bSthorpej if (config_probe(parent, cf, aux))
152*c7fb772bSthorpej config_attach(parent, cf, aux, apbh_print, CFARGS_NONE);
153eba5cacbSjkunz
154eba5cacbSjkunz return 0;
155eba5cacbSjkunz }
156eba5cacbSjkunz
157eba5cacbSjkunz /*
158eba5cacbSjkunz * Called from config_attach()
159eba5cacbSjkunz */
160eba5cacbSjkunz static int
apbh_print(void * aux,const char * name __unused)161eba5cacbSjkunz apbh_print(void *aux, const char *name __unused)
162eba5cacbSjkunz {
163eba5cacbSjkunz struct apb_attach_args *aa = aux;
164eba5cacbSjkunz
165eba5cacbSjkunz if (aa->aa_addr != APBHCF_ADDR_DEFAULT) {
166eba5cacbSjkunz aprint_normal(" addr 0x%lx", aa->aa_addr);
167eba5cacbSjkunz if (aa->aa_size > APBHCF_SIZE_DEFAULT)
168eba5cacbSjkunz aprint_normal("-0x%lx", aa->aa_addr + aa->aa_size-1);
169eba5cacbSjkunz }
170eba5cacbSjkunz
171eba5cacbSjkunz if (aa->aa_irq != APBHCF_IRQ_DEFAULT)
172eba5cacbSjkunz aprint_normal(" irq %d", aa->aa_irq);
173eba5cacbSjkunz
174eba5cacbSjkunz return UNCONF;
175eba5cacbSjkunz }
176