1*c7fb772bSthorpej /* $NetBSD: sbobio.c,v 1.25 2021/08/07 16:18:59 thorpej Exp $ */
21b5ddfe4Ssimonb
31b5ddfe4Ssimonb /*
41b5ddfe4Ssimonb * Copyright 2000, 2001
51b5ddfe4Ssimonb * Broadcom Corporation. All rights reserved.
61b5ddfe4Ssimonb *
71b5ddfe4Ssimonb * This software is furnished under license and may be used and copied only
81b5ddfe4Ssimonb * in accordance with the following terms and conditions. Subject to these
91b5ddfe4Ssimonb * conditions, you may download, copy, install, use, modify and distribute
101b5ddfe4Ssimonb * modified or unmodified copies of this software in source and/or binary
111b5ddfe4Ssimonb * form. No title or ownership is transferred hereby.
121b5ddfe4Ssimonb *
131b5ddfe4Ssimonb * 1) Any source code used, modified or distributed must reproduce and
141b5ddfe4Ssimonb * retain this copyright notice and list of conditions as they appear in
151b5ddfe4Ssimonb * the source file.
161b5ddfe4Ssimonb *
171b5ddfe4Ssimonb * 2) No right is granted to use any trade name, trademark, or logo of
188a6b8c3bScgd * Broadcom Corporation. The "Broadcom Corporation" name may not be
198a6b8c3bScgd * used to endorse or promote products derived from this software
208a6b8c3bScgd * without the prior written permission of Broadcom Corporation.
211b5ddfe4Ssimonb *
221b5ddfe4Ssimonb * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR IMPLIED
231b5ddfe4Ssimonb * WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED WARRANTIES OF
241b5ddfe4Ssimonb * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
251b5ddfe4Ssimonb * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM BE LIABLE
261b5ddfe4Ssimonb * FOR ANY DAMAGES WHATSOEVER, AND IN PARTICULAR, BROADCOM SHALL NOT BE
271b5ddfe4Ssimonb * LIABLE FOR DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
281b5ddfe4Ssimonb * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
291b5ddfe4Ssimonb * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
301b5ddfe4Ssimonb * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
311b5ddfe4Ssimonb * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
321b5ddfe4Ssimonb * OR OTHERWISE), EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
331b5ddfe4Ssimonb */
341b5ddfe4Ssimonb
354b2744bfSlukem #include <sys/cdefs.h>
36*c7fb772bSthorpej __KERNEL_RCSID(0, "$NetBSD: sbobio.c,v 1.25 2021/08/07 16:18:59 thorpej Exp $");
374b2744bfSlukem
381b5ddfe4Ssimonb #include <sys/param.h>
391b5ddfe4Ssimonb #include <sys/device.h>
401b5ddfe4Ssimonb #include <sys/systm.h>
411b5ddfe4Ssimonb
42d1cae3a2Smatt #include <mips/locore.h>
43d1cae3a2Smatt
4400bf4c87Ssimonb #include <mips/sibyte/include/sb1250_int.h>
454cb13fbeSsimonb #include <mips/sibyte/include/sb1250_regs.h>
4648164df6Scgd #include <mips/sibyte/include/sb1250_scd.h>
471b5ddfe4Ssimonb #include <mips/sibyte/include/zbbusvar.h>
481b5ddfe4Ssimonb #include <mips/sibyte/dev/sbobiovar.h>
491b5ddfe4Ssimonb
501b5ddfe4Ssimonb #include "locators.h"
511b5ddfe4Ssimonb
52916ee5b6Smatt static int sbobio_match(device_t, cfdata_t, void *);
53916ee5b6Smatt static void sbobio_attach(device_t, device_t, void *);
541b5ddfe4Ssimonb
55916ee5b6Smatt CFATTACH_DECL_NEW(sbobio, 0,
5689bf5a8fSthorpej sbobio_match, sbobio_attach, NULL, NULL);
571b5ddfe4Ssimonb
581b5ddfe4Ssimonb static int sbobio_print(void *, const char *);
591b5ddfe4Ssimonb static const char *sbobio_device_type_name(enum sbobio_device_type type);
601b5ddfe4Ssimonb
6100bf4c87Ssimonb /*
6200bf4c87Ssimonb * XXXsimonb:
6300bf4c87Ssimonb * DUART register addresses seem to offset by 0x100 for some
6400bf4c87Ssimonb * reason I can't fathom so we just can't use A_DUART for the
6500bf4c87Ssimonb * address of the DUART. Eg,
6600bf4c87Ssimonb * A_DUART_CHANREG(0, 0) = 0x0010060000
6700bf4c87Ssimonb * and R_DUART_MODE_REG_1 = 0x100 (first reg in the duart)
6800bf4c87Ssimonb * but the 1125/1250 manual says the DUART starts at
6900bf4c87Ssimonb * 0x0010060100.
7000bf4c87Ssimonb * We define our own R_DUART_REGBASE to R_DUART_MODE_REG_1
7100bf4c87Ssimonb * so that we can use a symbolic name to refer to the start
7200bf4c87Ssimonb * of the duart register space.
7300bf4c87Ssimonb */
7400bf4c87Ssimonb
7548164df6Scgd static const struct sbobio_attach_locs sb1250_rev1_sbobio_devs[] = {
7600bf4c87Ssimonb { A_SMB_0,
7700bf4c87Ssimonb { K_INT_SMB_0, -1 },
7800bf4c87Ssimonb SBOBIO_DEVTYPE_SMBUS },
7900bf4c87Ssimonb { A_SMB_1,
8000bf4c87Ssimonb { K_INT_SMB_1, -1 },
8100bf4c87Ssimonb SBOBIO_DEVTYPE_SMBUS },
8200bf4c87Ssimonb { A_DUART_CHANREG(0, R_DUART_REGBASE),
8300bf4c87Ssimonb { K_INT_UART_0, K_INT_UART_1 },
8400bf4c87Ssimonb SBOBIO_DEVTYPE_DUART },
8500bf4c87Ssimonb { A_SER_BASE_0,
8600bf4c87Ssimonb { K_INT_SER_0, -1 },
8700bf4c87Ssimonb SBOBIO_DEVTYPE_SYNCSERIAL },
8800bf4c87Ssimonb { A_SER_BASE_1,
8900bf4c87Ssimonb { K_INT_SER_1, -1 },
9000bf4c87Ssimonb SBOBIO_DEVTYPE_SYNCSERIAL },
911b5ddfe4Ssimonb #if 0
9200bf4c87Ssimonb { A_IO_EXT_BASE,
9300bf4c87Ssimonb { -1, -1 },
9400bf4c87Ssimonb SBOBIO_DEVTYPE_GBUS },
951b5ddfe4Ssimonb #endif
9600bf4c87Ssimonb { A_MAC_BASE_0,
9700bf4c87Ssimonb { K_INT_MAC_0, -1 },
9800bf4c87Ssimonb SBOBIO_DEVTYPE_MAC },
9900bf4c87Ssimonb { A_MAC_BASE_1,
10000bf4c87Ssimonb { K_INT_MAC_1, -1 },
10100bf4c87Ssimonb SBOBIO_DEVTYPE_MAC },
10200bf4c87Ssimonb { A_MAC_BASE_2,
10300bf4c87Ssimonb { K_INT_MAC_2, -1 },
10400bf4c87Ssimonb SBOBIO_DEVTYPE_MAC },
1051b5ddfe4Ssimonb };
10648164df6Scgd static const int sb1250_rev1_sbobio_dev_count =
10748164df6Scgd sizeof sb1250_rev1_sbobio_devs / sizeof sb1250_rev1_sbobio_devs[0];
10848164df6Scgd
10948164df6Scgd static const struct sbobio_attach_locs sb1250_sbobio_devs[] = {
11000bf4c87Ssimonb { A_SMB_0,
11100bf4c87Ssimonb { K_INT_SMB_0, -1 },
11200bf4c87Ssimonb SBOBIO_DEVTYPE_SMBUS },
11300bf4c87Ssimonb { A_SMB_1,
11400bf4c87Ssimonb { K_INT_SMB_1, -1 },
11500bf4c87Ssimonb SBOBIO_DEVTYPE_SMBUS },
11600bf4c87Ssimonb { A_DUART_CHANREG(0, R_DUART_REGBASE),
11700bf4c87Ssimonb { K_INT_UART_0, K_INT_UART_1},
11800bf4c87Ssimonb SBOBIO_DEVTYPE_DUART },
11900bf4c87Ssimonb { A_SER_BASE_0,
12000bf4c87Ssimonb { K_INT_SER_0, -1 },
12100bf4c87Ssimonb SBOBIO_DEVTYPE_SYNCSERIAL },
12200bf4c87Ssimonb { A_SER_BASE_1,
12300bf4c87Ssimonb { K_INT_SER_1, -1 },
12400bf4c87Ssimonb SBOBIO_DEVTYPE_SYNCSERIAL },
12548164df6Scgd #if 0
12600bf4c87Ssimonb { A_IO_EXT_BASE,
12700bf4c87Ssimonb { -1, -1 },
12800bf4c87Ssimonb SBOBIO_DEVTYPE_GBUS },
12948164df6Scgd #endif
13000bf4c87Ssimonb { A_MAC_BASE_0,
13100bf4c87Ssimonb { K_INT_MAC_0, K_INT_MAC_0_CH1 },
13200bf4c87Ssimonb SBOBIO_DEVTYPE_MAC },
13300bf4c87Ssimonb { A_MAC_BASE_1,
13400bf4c87Ssimonb { K_INT_MAC_1, K_INT_MAC_1_CH1 },
13500bf4c87Ssimonb SBOBIO_DEVTYPE_MAC },
13600bf4c87Ssimonb { A_MAC_BASE_2,
13700bf4c87Ssimonb { K_INT_MAC_2, K_INT_MAC_2_CH1 },
13800bf4c87Ssimonb SBOBIO_DEVTYPE_MAC },
13948164df6Scgd };
1401b5ddfe4Ssimonb static const int sb1250_sbobio_dev_count =
1411b5ddfe4Ssimonb sizeof sb1250_sbobio_devs / sizeof sb1250_sbobio_devs[0];
1421b5ddfe4Ssimonb
14348164df6Scgd static const struct sbobio_attach_locs sb112x_sbobio_devs[] = {
14400bf4c87Ssimonb { A_SMB_0,
14500bf4c87Ssimonb { K_INT_SMB_0, -1 },
14600bf4c87Ssimonb SBOBIO_DEVTYPE_SMBUS },
14700bf4c87Ssimonb { A_SMB_1,
14800bf4c87Ssimonb { K_INT_SMB_1, -1 },
14900bf4c87Ssimonb SBOBIO_DEVTYPE_SMBUS },
15000bf4c87Ssimonb { A_DUART_CHANREG(0, R_DUART_REGBASE),
15100bf4c87Ssimonb { K_INT_UART_0, K_INT_UART_1 },
15200bf4c87Ssimonb SBOBIO_DEVTYPE_DUART },
15300bf4c87Ssimonb { A_SER_BASE_0,
15400bf4c87Ssimonb { K_INT_SER_0, -1 },
15500bf4c87Ssimonb SBOBIO_DEVTYPE_SYNCSERIAL },
15600bf4c87Ssimonb { A_SER_BASE_1,
15700bf4c87Ssimonb { K_INT_SER_1, -1 },
15800bf4c87Ssimonb SBOBIO_DEVTYPE_SYNCSERIAL },
15948164df6Scgd #if 0
16000bf4c87Ssimonb { A_IO_EXT_BASE,
16100bf4c87Ssimonb { -1, -1 },
16200bf4c87Ssimonb SBOBIO_DEVTYPE_GBUS },
16348164df6Scgd #endif
16400bf4c87Ssimonb { A_MAC_BASE_0,
16500bf4c87Ssimonb { K_INT_MAC_0, K_INT_MAC_0_CH1 },
16600bf4c87Ssimonb SBOBIO_DEVTYPE_MAC },
16700bf4c87Ssimonb { A_MAC_BASE_1,
16800bf4c87Ssimonb { K_INT_MAC_1, K_INT_MAC_1_CH1 },
16900bf4c87Ssimonb SBOBIO_DEVTYPE_MAC },
17048164df6Scgd };
17148164df6Scgd static const int sb112x_sbobio_dev_count =
17248164df6Scgd sizeof sb112x_sbobio_devs / sizeof sb112x_sbobio_devs[0];
17348164df6Scgd
1741b5ddfe4Ssimonb static int
sbobio_match(device_t parent,cfdata_t match,void * aux)175916ee5b6Smatt sbobio_match(device_t parent, cfdata_t match, void *aux)
1761b5ddfe4Ssimonb {
1771b5ddfe4Ssimonb struct zbbus_attach_args *zap = aux;
17848164df6Scgd uint64_t sysrev;
1791b5ddfe4Ssimonb
1801b5ddfe4Ssimonb if (zap->za_locs.za_type != ZBBUS_ENTTYPE_OBIO)
1811b5ddfe4Ssimonb return (0);
1821b5ddfe4Ssimonb
18367c90d24Schristos sysrev = mips3_ld((register_t)MIPS_PHYS_TO_KSEG1(A_SCD_SYSTEM_REVISION));
18448164df6Scgd switch (SYS_SOC_TYPE(sysrev)) {
18548164df6Scgd case K_SYS_SOC_TYPE_BCM1120:
18648164df6Scgd case K_SYS_SOC_TYPE_BCM1125:
18748164df6Scgd case K_SYS_SOC_TYPE_BCM1125H:
18848164df6Scgd case K_SYS_SOC_TYPE_BCM1250:
18948164df6Scgd break;
19048164df6Scgd
19148164df6Scgd default:
1926939fedaSsimonb return (0);
19348164df6Scgd }
19448164df6Scgd
1956939fedaSsimonb return (1);
1961b5ddfe4Ssimonb }
1971b5ddfe4Ssimonb
1981b5ddfe4Ssimonb static void
sbobio_attach(device_t parent,device_t self,void * aux)199916ee5b6Smatt sbobio_attach(device_t parent, device_t self, void *aux)
2001b5ddfe4Ssimonb {
2011b5ddfe4Ssimonb struct sbobio_attach_args sa;
20248164df6Scgd const char *dscr;
20348164df6Scgd const struct sbobio_attach_locs *devs;
20448164df6Scgd uint64_t sysrev;
20548164df6Scgd int i, devcount;
206fa3cb84dSdrochner int locs[SBOBIOCF_NLOCS];
2071b5ddfe4Ssimonb
20867c90d24Schristos sysrev = mips3_ld((register_t)MIPS_PHYS_TO_KSEG1(A_SCD_SYSTEM_REVISION));
20948164df6Scgd switch (SYS_SOC_TYPE(sysrev)) {
21048164df6Scgd case K_SYS_SOC_TYPE_BCM1120:
21148164df6Scgd case K_SYS_SOC_TYPE_BCM1125:
21248164df6Scgd case K_SYS_SOC_TYPE_BCM1125H:
21348164df6Scgd dscr = "BCM112x";
21448164df6Scgd devs = sb112x_sbobio_devs;
21548164df6Scgd devcount = sb112x_sbobio_dev_count;
21648164df6Scgd break;
2171b5ddfe4Ssimonb
21848164df6Scgd case K_SYS_SOC_TYPE_BCM1250:
21948164df6Scgd if (G_SYS_REVISION(sysrev) >= K_SYS_REVISION_BCM1250_PASS2) {
22048164df6Scgd dscr = "BCM1250 (rev2 and later)";
22148164df6Scgd devs = sb1250_sbobio_devs;
22248164df6Scgd devcount = sb1250_sbobio_dev_count;
22348164df6Scgd } else {
22448164df6Scgd dscr = "BCM1250 rev1";
22548164df6Scgd devs = sb1250_rev1_sbobio_devs;
22648164df6Scgd devcount = sb1250_rev1_sbobio_dev_count;
22748164df6Scgd }
22848164df6Scgd break;
22948164df6Scgd default:
23048164df6Scgd panic("un-matched in sbobio_attach");
23148164df6Scgd break;
23248164df6Scgd }
23348164df6Scgd
23482bf97dcSmatt aprint_normal(": %s peripherals\n", dscr);
23548164df6Scgd
23648164df6Scgd for (i = 0; i < devcount; i++) {
2371b5ddfe4Ssimonb memset(&sa, 0, sizeof sa);
23848164df6Scgd sa.sa_locs = devs[i];
239a02e2488Sdrochner
2406f35b2ecSmatt locs[SBOBIOCF_OFFSET] = devs[i].sa_offset;
241fa3cb84dSdrochner locs[SBOBIOCF_INTR + 0] = devs[i].sa_intr[0];
242fa3cb84dSdrochner locs[SBOBIOCF_INTR + 1] = devs[i].sa_intr[1];
243a02e2488Sdrochner
2442685996bSthorpej config_found(self, &sa, sbobio_print,
245*c7fb772bSthorpej CFARGS(.submatch = config_stdsubmatch,
246*c7fb772bSthorpej .locators = locs));
2471b5ddfe4Ssimonb }
2481b5ddfe4Ssimonb return;
2491b5ddfe4Ssimonb }
2501b5ddfe4Ssimonb
2511b5ddfe4Ssimonb int
sbobio_print(void * aux,const char * pnp)2521b5ddfe4Ssimonb sbobio_print(void *aux, const char *pnp)
2531b5ddfe4Ssimonb {
2541b5ddfe4Ssimonb struct sbobio_attach_args *sap = aux;
2551b5ddfe4Ssimonb int i;
2561b5ddfe4Ssimonb
2571b5ddfe4Ssimonb if (pnp)
258dbb0f0ebSthorpej aprint_normal("%s at %s",
2591b5ddfe4Ssimonb sbobio_device_type_name(sap->sa_locs.sa_type), pnp);
2606f35b2ecSmatt aprint_normal(" offset 0x%lx", sap->sa_locs.sa_offset);
2611b5ddfe4Ssimonb for (i = 0; i < 2; i++) {
2624cb13fbeSsimonb if (sap->sa_locs.sa_intr[i] != SBOBIOCF_INTR_DEFAULT)
26300bf4c87Ssimonb aprint_normal("%s%d", i == 0 ? " intr " : ",",
26400bf4c87Ssimonb sap->sa_locs.sa_intr[i]);
2651b5ddfe4Ssimonb }
2661b5ddfe4Ssimonb return (UNCONF);
2671b5ddfe4Ssimonb }
2681b5ddfe4Ssimonb
2691b5ddfe4Ssimonb static const char *
sbobio_device_type_name(enum sbobio_device_type type)2701b5ddfe4Ssimonb sbobio_device_type_name(enum sbobio_device_type type)
2711b5ddfe4Ssimonb {
2721b5ddfe4Ssimonb
2731b5ddfe4Ssimonb switch (type) {
2741b5ddfe4Ssimonb case SBOBIO_DEVTYPE_SMBUS:
2751b5ddfe4Ssimonb return ("sbsmbus");
2761b5ddfe4Ssimonb case SBOBIO_DEVTYPE_DUART:
2771b5ddfe4Ssimonb return ("sbscn");
2781b5ddfe4Ssimonb case SBOBIO_DEVTYPE_SYNCSERIAL:
2791b5ddfe4Ssimonb return ("sbsync");
2801b5ddfe4Ssimonb case SBOBIO_DEVTYPE_GBUS:
2811b5ddfe4Ssimonb return ("sbgbus");
2821b5ddfe4Ssimonb case SBOBIO_DEVTYPE_MAC:
2831b5ddfe4Ssimonb return ("sbmac");
2841b5ddfe4Ssimonb }
2851b5ddfe4Ssimonb panic("sbobio_device_type_name");
2861b5ddfe4Ssimonb return ("panic");
2871b5ddfe4Ssimonb }
288