1*c7fb772bSthorpej /* $NetBSD: opb.c,v 1.29 2021/08/07 16:19:03 thorpej Exp $ */
26bf1aaf8Ssimonb
36bf1aaf8Ssimonb /*
46bf1aaf8Ssimonb * Copyright 2001,2002 Wasabi Systems, Inc.
56bf1aaf8Ssimonb * All rights reserved.
66bf1aaf8Ssimonb *
76bf1aaf8Ssimonb * Written by Eduardo Horvath and Simon Burge for Wasabi Systems, Inc.
86bf1aaf8Ssimonb *
96bf1aaf8Ssimonb * Redistribution and use in source and binary forms, with or without
106bf1aaf8Ssimonb * modification, are permitted provided that the following conditions
116bf1aaf8Ssimonb * are met:
126bf1aaf8Ssimonb * 1. Redistributions of source code must retain the above copyright
136bf1aaf8Ssimonb * notice, this list of conditions and the following disclaimer.
146bf1aaf8Ssimonb * 2. Redistributions in binary form must reproduce the above copyright
156bf1aaf8Ssimonb * notice, this list of conditions and the following disclaimer in the
166bf1aaf8Ssimonb * documentation and/or other materials provided with the distribution.
176bf1aaf8Ssimonb * 3. All advertising materials mentioning features or use of this software
186bf1aaf8Ssimonb * must display the following acknowledgement:
196bf1aaf8Ssimonb * This product includes software developed for the NetBSD Project by
206bf1aaf8Ssimonb * Wasabi Systems, Inc.
216bf1aaf8Ssimonb * 4. The name of Wasabi Systems, Inc. may not be used to endorse
226bf1aaf8Ssimonb * or promote products derived from this software without specific prior
236bf1aaf8Ssimonb * written permission.
246bf1aaf8Ssimonb *
256bf1aaf8Ssimonb * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
266bf1aaf8Ssimonb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
276bf1aaf8Ssimonb * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
286bf1aaf8Ssimonb * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
296bf1aaf8Ssimonb * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
306bf1aaf8Ssimonb * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
316bf1aaf8Ssimonb * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
326bf1aaf8Ssimonb * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
336bf1aaf8Ssimonb * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
346bf1aaf8Ssimonb * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
356bf1aaf8Ssimonb * POSSIBILITY OF SUCH DAMAGE.
366bf1aaf8Ssimonb */
376bf1aaf8Ssimonb
386bf1aaf8Ssimonb /*
396bf1aaf8Ssimonb * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
406bf1aaf8Ssimonb *
416bf1aaf8Ssimonb * Redistribution and use in source and binary forms, with or without
426bf1aaf8Ssimonb * modification, are permitted provided that the following conditions
436bf1aaf8Ssimonb * are met:
446bf1aaf8Ssimonb * 1. Redistributions of source code must retain the above copyright
456bf1aaf8Ssimonb * notice, this list of conditions and the following disclaimer.
466bf1aaf8Ssimonb * 2. Redistributions in binary form must reproduce the above copyright
476bf1aaf8Ssimonb * notice, this list of conditions and the following disclaimer in the
486bf1aaf8Ssimonb * documentation and/or other materials provided with the distribution.
496bf1aaf8Ssimonb * 3. All advertising materials mentioning features or use of this software
506bf1aaf8Ssimonb * must display the following acknowledgement:
516bf1aaf8Ssimonb * This product includes software developed by Christopher G. Demetriou
526bf1aaf8Ssimonb * for the NetBSD Project.
536bf1aaf8Ssimonb * 4. The name of the author may not be used to endorse or promote products
546bf1aaf8Ssimonb * derived from this software without specific prior written permission
556bf1aaf8Ssimonb *
566bf1aaf8Ssimonb * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
576bf1aaf8Ssimonb * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
586bf1aaf8Ssimonb * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
596bf1aaf8Ssimonb * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
606bf1aaf8Ssimonb * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
616bf1aaf8Ssimonb * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
626bf1aaf8Ssimonb * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
636bf1aaf8Ssimonb * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
646bf1aaf8Ssimonb * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
656bf1aaf8Ssimonb * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
666bf1aaf8Ssimonb */
676bf1aaf8Ssimonb
68ed517291Slukem #include <sys/cdefs.h>
69*c7fb772bSthorpej __KERNEL_RCSID(0, "$NetBSD: opb.c,v 1.29 2021/08/07 16:19:03 thorpej Exp $");
70ed517291Slukem
716bf1aaf8Ssimonb #include "locators.h"
7216031f7dSrin
7316031f7dSrin #ifdef _KERNEL_OPT
742692e2e2Skiyohara #include "opt_emac.h"
7516031f7dSrin #endif
766bf1aaf8Ssimonb
776bf1aaf8Ssimonb #include <sys/param.h>
786bf1aaf8Ssimonb #include <sys/systm.h>
796bf1aaf8Ssimonb #include <sys/device.h>
80728102e6Sscw #include <sys/extent.h>
811fd2c684Smatt #include <sys/cpu.h>
826bf1aaf8Ssimonb
832692e2e2Skiyohara #include <powerpc/ibm4xx/cpu.h>
841fd2c684Smatt #include <powerpc/ibm4xx/dcr4xx.h>
851fd2c684Smatt
862692e2e2Skiyohara #include <powerpc/ibm4xx/dev/opbreg.h>
876bf1aaf8Ssimonb #include <powerpc/ibm4xx/dev/opbvar.h>
882f766ff3Ssimonb #include <powerpc/ibm4xx/dev/plbvar.h>
892692e2e2Skiyohara #include <powerpc/ibm4xx/dev/rgmiireg.h>
902692e2e2Skiyohara #include <powerpc/ibm4xx/dev/zmiireg.h>
911fd2c684Smatt
922692e2e2Skiyohara #include <powerpc/spr.h>
931fd2c684Smatt #include <powerpc/ibm4xx/spr.h>
942692e2e2Skiyohara
956bf1aaf8Ssimonb #include <powerpc/ibm4xx/ibm405gp.h>
962692e2e2Skiyohara #include <powerpc/ibm4xx/amcc405ex.h>
972692e2e2Skiyohara
982692e2e2Skiyohara static int opb_get_frequency_405gp(void);
992692e2e2Skiyohara static int opb_get_frequency_405ex(void);
1002692e2e2Skiyohara
1016bf1aaf8Ssimonb
1026bf1aaf8Ssimonb /*
1032692e2e2Skiyohara * The devices on the On-chip Peripheral Bus to the 405GP/EX CPU.
1046bf1aaf8Ssimonb */
1056bf1aaf8Ssimonb const struct opb_dev {
106b16f7fe1Ssimonb int pvr;
1076bf1aaf8Ssimonb const char *name;
1086bf1aaf8Ssimonb bus_addr_t addr;
109b636d491Sthorpej int instance;
1106bf1aaf8Ssimonb int irq;
1112692e2e2Skiyohara int flags;
1126bf1aaf8Ssimonb } opb_devs [] = {
11303467d74Sshige /* IBM405GP */
1142692e2e2Skiyohara { IBM405GP, "com", IBM405GP_UART0_BASE, 0, 0, 0 },
1152692e2e2Skiyohara { IBM405GP, "com", IBM405GP_UART1_BASE, 1, 1, 0 },
1162692e2e2Skiyohara { IBM405GP, "emac", IBM405GP_EMAC0_BASE, 0, 15, 0 },
1172692e2e2Skiyohara { IBM405GP, "opbgpio", IBM405GP_GPIO0_BASE, 0, -1, 0 },
1182692e2e2Skiyohara { IBM405GP, "gpiic",IBM405GP_IIC0_BASE, 0, 2, 0 },
1192692e2e2Skiyohara { IBM405GP, "wdog", -1, 0, -1, 0 },
12003467d74Sshige
12103467d74Sshige /* IBM405GPR */
1222692e2e2Skiyohara { IBM405GPR, "com", IBM405GP_UART0_BASE, 0, 0, 0 },
1232692e2e2Skiyohara { IBM405GPR, "com", IBM405GP_UART1_BASE, 1, 1, 0 },
1242692e2e2Skiyohara { IBM405GPR, "emac", IBM405GP_EMAC0_BASE, 0, 15, 0 },
1252692e2e2Skiyohara { IBM405GPR, "opbgpio", IBM405GP_GPIO0_BASE, 0, -1, 0 },
1262692e2e2Skiyohara { IBM405GPR, "gpiic",IBM405GP_IIC0_BASE, 0, 2, 0 },
1272692e2e2Skiyohara { IBM405GPR, "wdog", -1, 0, -1, 0 },
1282692e2e2Skiyohara
1292692e2e2Skiyohara /* AMCC405EX */
1302692e2e2Skiyohara { AMCC405EX, "gpt", AMCC405EX_GPT0_BASE, 0, -1, 0 },
1312692e2e2Skiyohara { AMCC405EX, "com", AMCC405EX_UART0_BASE, 0, 26, 0 },
1322692e2e2Skiyohara { AMCC405EX, "com", AMCC405EX_UART1_BASE, 1, 1, 0 },
1332692e2e2Skiyohara { AMCC405EX, "gpiic",AMCC405EX_IIC0_BASE, 0, 2, 0 },
1342692e2e2Skiyohara { AMCC405EX, "gpiic",AMCC405EX_IIC1_BASE, 1, 7, 0 },
1352692e2e2Skiyohara { AMCC405EX, "scp", AMCC405EX_SCP0_BASE, 0, 8, 0 }, /* SPI */
1362692e2e2Skiyohara { AMCC405EX, "opbgpio", AMCC405EX_GPIO0_BASE, -1, -1, 0 },
1372692e2e2Skiyohara { AMCC405EX, "emac", AMCC405EX_EMAC0_BASE, 0, 24,
1382692e2e2Skiyohara OPB_FLAGS_EMAC_GBE | OPB_FLAGS_EMAC_STACV2 | OPB_FLAGS_EMAC_HT256 |\
1392692e2e2Skiyohara OPB_FLAGS_EMAC_RMII_RGMII },
1402692e2e2Skiyohara { AMCC405EX, "emac", AMCC405EX_EMAC1_BASE, 1, 25,
1412692e2e2Skiyohara OPB_FLAGS_EMAC_GBE | OPB_FLAGS_EMAC_STACV2 | OPB_FLAGS_EMAC_HT256 |\
1422692e2e2Skiyohara OPB_FLAGS_EMAC_RMII_RGMII },
1432692e2e2Skiyohara { AMCC405EX, "wdog", -1, 0, -1, 0 },
1442692e2e2Skiyohara
145b16f7fe1Ssimonb { 0, NULL }
1466bf1aaf8Ssimonb };
1476bf1aaf8Ssimonb
1482692e2e2Skiyohara int (*opb_get_frequency)(void);
1492692e2e2Skiyohara const struct opb_param {
150728102e6Sscw int pvr;
151728102e6Sscw bus_addr_t base;
152728102e6Sscw bus_addr_t limit;
1532692e2e2Skiyohara int (*opb_get_frequency)(void);
1542692e2e2Skiyohara bus_addr_t zmii_base;
1552692e2e2Skiyohara bus_addr_t rgmii_base;
1562692e2e2Skiyohara } opb_params[] = {
1572692e2e2Skiyohara { IBM405GP,
1582692e2e2Skiyohara IBM405GP_IP_BASE, IBM405GP_IP_BASE + OPBREG_SIZE,
1592692e2e2Skiyohara opb_get_frequency_405gp,
1602692e2e2Skiyohara 0, 0 },
1612692e2e2Skiyohara { IBM405GPR,
1622692e2e2Skiyohara IBM405GP_IP_BASE, IBM405GP_IP_BASE + OPBREG_SIZE,
1632692e2e2Skiyohara opb_get_frequency_405gp,
1642692e2e2Skiyohara 0, 0 },
1652692e2e2Skiyohara { AMCC405EX,
1662692e2e2Skiyohara AMCC405EX_OPB_BASE, AMCC405EX_OPB_BASE + OPBREG_SIZE,
1672692e2e2Skiyohara opb_get_frequency_405ex,
1682692e2e2Skiyohara 0, AMCC405EX_RGMIIB0_BASE},
1692692e2e2Skiyohara
1702692e2e2Skiyohara { 0 }
171728102e6Sscw };
172728102e6Sscw
1732692e2e2Skiyohara static int opb_match(device_t, cfdata_t, void *);
1742692e2e2Skiyohara static void opb_attach(device_t, device_t, void *);
1752692e2e2Skiyohara static int opb_submatch(device_t, cfdata_t, const int *, void *);
1766bf1aaf8Ssimonb static int opb_print(void *, const char *);
1776bf1aaf8Ssimonb
1782692e2e2Skiyohara CFATTACH_DECL_NEW(opb, sizeof(struct opb_softc),
17989bf5a8fSthorpej opb_match, opb_attach, NULL, NULL);
1806bf1aaf8Ssimonb
181728102e6Sscw static struct powerpc_bus_space opb_tag = {
18217629c72Sshige _BUS_SPACE_BIG_ENDIAN|_BUS_SPACE_MEM_TYPE,
1832692e2e2Skiyohara 0x00000000,
184728102e6Sscw };
185728102e6Sscw static char ex_storage[EXTENT_FIXED_STORAGE_SIZE(8)]
186728102e6Sscw __attribute__((aligned(8)));
187728102e6Sscw static int opb_tag_init_done;
188728102e6Sscw
1896bf1aaf8Ssimonb /*
1906bf1aaf8Ssimonb * Probe for the opb; always succeeds.
1916bf1aaf8Ssimonb */
1926bf1aaf8Ssimonb static int
opb_match(device_t parent,cfdata_t cf,void * aux)1932692e2e2Skiyohara opb_match(device_t parent, cfdata_t cf, void *aux)
1946bf1aaf8Ssimonb {
1956bf1aaf8Ssimonb struct opb_attach_args *oaa = aux;
1966bf1aaf8Ssimonb
1976bf1aaf8Ssimonb /* match only opb devices */
198d1ad2ac4Sthorpej if (strcmp(oaa->opb_name, cf->cf_name) != 0)
1992692e2e2Skiyohara return 0;
2006bf1aaf8Ssimonb
2012692e2e2Skiyohara return 1;
2026bf1aaf8Ssimonb }
2036bf1aaf8Ssimonb
2046bf1aaf8Ssimonb static int
opb_submatch(device_t parent,cfdata_t cf,const int * ldesc,void * aux)2052692e2e2Skiyohara opb_submatch(device_t parent, cfdata_t cf, const int *ldesc, void *aux)
2066bf1aaf8Ssimonb {
2076bf1aaf8Ssimonb struct opb_attach_args *oaa = aux;
2086bf1aaf8Ssimonb
2096bf1aaf8Ssimonb if (cf->cf_loc[OPBCF_ADDR] != OPBCF_ADDR_DEFAULT &&
2106bf1aaf8Ssimonb cf->cf_loc[OPBCF_ADDR] != oaa->opb_addr)
2112692e2e2Skiyohara return 0;
2126bf1aaf8Ssimonb
2132692e2e2Skiyohara return config_match(parent, cf, aux);
2146bf1aaf8Ssimonb }
2156bf1aaf8Ssimonb
2166bf1aaf8Ssimonb /*
2176bf1aaf8Ssimonb * Attach the on-chip peripheral bus.
2186bf1aaf8Ssimonb */
2196bf1aaf8Ssimonb static void
opb_attach(device_t parent,device_t self,void * aux)2202692e2e2Skiyohara opb_attach(device_t parent, device_t self, void *aux)
2216bf1aaf8Ssimonb {
2222692e2e2Skiyohara struct opb_softc *sc = device_private(self);
2232f766ff3Ssimonb struct plb_attach_args *paa = aux;
2246bf1aaf8Ssimonb struct opb_attach_args oaa;
225b16f7fe1Ssimonb int i, pvr;
2266bf1aaf8Ssimonb
2272692e2e2Skiyohara aprint_naive("\n");
2282692e2e2Skiyohara aprint_normal("\n");
229b16f7fe1Ssimonb pvr = mfpvr() >> 16;
2306bf1aaf8Ssimonb
2312692e2e2Skiyohara sc->sc_dev = self;
2322692e2e2Skiyohara sc->sc_iot = opb_get_bus_space_tag();
2332692e2e2Skiyohara
2342692e2e2Skiyohara for (i = 0; opb_params[i].pvr != 0 && opb_params[i].pvr != pvr; i++)
2352692e2e2Skiyohara ;
2362692e2e2Skiyohara if (opb_params[i].pvr == 0)
2372692e2e2Skiyohara panic("opb_get_bus_space_tag: no params for this CPU!");
2382692e2e2Skiyohara opb_get_frequency = opb_params[i].opb_get_frequency;
2392692e2e2Skiyohara #ifdef EMAC_ZMII_PHY
2402692e2e2Skiyohara if (opb_params[i].zmii_base != 0)
2412692e2e2Skiyohara bus_space_map(sc->sc_iot, opb_params[i].zmii_base, ZMII0_SIZE,
2422692e2e2Skiyohara 0, &sc->sc_zmiih);
2432692e2e2Skiyohara #endif
2442692e2e2Skiyohara #ifdef EMAC_RGMII_PHY
2452692e2e2Skiyohara if (opb_params[i].rgmii_base != 0)
2462692e2e2Skiyohara bus_space_map(sc->sc_iot, opb_params[i].rgmii_base, RGMII0_SIZE,
2472692e2e2Skiyohara 0, &sc->sc_rgmiih);
2482692e2e2Skiyohara #endif
249728102e6Sscw
2506bf1aaf8Ssimonb for (i = 0; opb_devs[i].name != NULL; i++) {
251b16f7fe1Ssimonb if (opb_devs[i].pvr != pvr)
252b16f7fe1Ssimonb continue;
2536bf1aaf8Ssimonb oaa.opb_name = opb_devs[i].name;
2546bf1aaf8Ssimonb oaa.opb_addr = opb_devs[i].addr;
255b636d491Sthorpej oaa.opb_instance = opb_devs[i].instance;
2566bf1aaf8Ssimonb oaa.opb_irq = opb_devs[i].irq;
2572692e2e2Skiyohara oaa.opb_bt = sc->sc_iot;
2582f766ff3Ssimonb oaa.opb_dmat = paa->plb_dmat;
2592692e2e2Skiyohara oaa.opb_flags = opb_devs[i].flags;
2606bf1aaf8Ssimonb
2612685996bSthorpej config_found(self, &oaa, opb_print,
262*c7fb772bSthorpej CFARGS(.submatch = opb_submatch));
2636bf1aaf8Ssimonb }
2646bf1aaf8Ssimonb }
2656bf1aaf8Ssimonb
2666bf1aaf8Ssimonb static int
opb_print(void * aux,const char * pnp)2676bf1aaf8Ssimonb opb_print(void *aux, const char *pnp)
2686bf1aaf8Ssimonb {
2696bf1aaf8Ssimonb struct opb_attach_args *oaa = aux;
2706bf1aaf8Ssimonb
2716bf1aaf8Ssimonb if (pnp)
27295fa2e14Sthorpej aprint_normal("%s at %s", oaa->opb_name, pnp);
2736bf1aaf8Ssimonb
2746bf1aaf8Ssimonb if (oaa->opb_addr != OPBCF_ADDR_DEFAULT)
27595fa2e14Sthorpej aprint_normal(" addr 0x%08lx", oaa->opb_addr);
2766bf1aaf8Ssimonb if (oaa->opb_irq != OPBCF_IRQ_DEFAULT)
27795fa2e14Sthorpej aprint_normal(" irq %d", oaa->opb_irq);
2786bf1aaf8Ssimonb
2792692e2e2Skiyohara return UNCONF;
2806bf1aaf8Ssimonb }
281728102e6Sscw
282728102e6Sscw bus_space_tag_t
opb_get_bus_space_tag(void)283728102e6Sscw opb_get_bus_space_tag(void)
284728102e6Sscw {
285728102e6Sscw int i, pvr;
286728102e6Sscw
287728102e6Sscw if (!opb_tag_init_done) {
288728102e6Sscw pvr = mfpvr() >> 16;
289728102e6Sscw
2902692e2e2Skiyohara for (i = 0; opb_params[i].pvr != 0 && opb_params[i].pvr != pvr;
2912692e2e2Skiyohara i++)
292728102e6Sscw ;
2932692e2e2Skiyohara if (opb_params[i].pvr == 0)
2942692e2e2Skiyohara panic("opb_get_bus_space_tag: no params for this CPU!");
295728102e6Sscw
2962692e2e2Skiyohara opb_tag.pbs_base = opb_params[i].base;
2972692e2e2Skiyohara opb_tag.pbs_limit = opb_params[i].limit;
298728102e6Sscw
299728102e6Sscw if (bus_space_init(&opb_tag, "opbtag",
300728102e6Sscw ex_storage, sizeof(ex_storage)))
301728102e6Sscw panic("opb_attach: Failed to initialise opb_tag");
302728102e6Sscw opb_tag_init_done = 1;
303728102e6Sscw }
304728102e6Sscw
3052692e2e2Skiyohara return &opb_tag;
3062692e2e2Skiyohara }
3072692e2e2Skiyohara
3082692e2e2Skiyohara static int
opb_get_frequency_405gp(void)3092692e2e2Skiyohara opb_get_frequency_405gp(void)
3102692e2e2Skiyohara {
3112692e2e2Skiyohara prop_number_t pn;
3122692e2e2Skiyohara uint32_t pllmr;
3132692e2e2Skiyohara unsigned int processor_freq, plb_freq, opb_freq;
3142692e2e2Skiyohara
3152692e2e2Skiyohara pn = prop_dictionary_get(board_properties, "processor-frequency");
3162692e2e2Skiyohara KASSERT(pn != NULL);
3172692e2e2Skiyohara processor_freq = (unsigned int) prop_number_integer_value(pn);
3182692e2e2Skiyohara pllmr = mfdcr(DCR_CPC0_PLLMR);
3192692e2e2Skiyohara plb_freq = processor_freq / CPC0_PLLMR_CBDV(pllmr);
3202692e2e2Skiyohara opb_freq = plb_freq / CPC0_PLLMR_OPDV(pllmr);
3212692e2e2Skiyohara
3222692e2e2Skiyohara return opb_freq;
3232692e2e2Skiyohara }
3242692e2e2Skiyohara
3252692e2e2Skiyohara static int
opb_get_frequency_405ex(void)3262692e2e2Skiyohara opb_get_frequency_405ex(void)
3272692e2e2Skiyohara {
3282692e2e2Skiyohara prop_number_t pn;
3292692e2e2Skiyohara unsigned int processor_freq, plb_freq, opb_freq;
3302692e2e2Skiyohara
3312692e2e2Skiyohara pn = prop_dictionary_get(board_properties, "processor-frequency");
3322692e2e2Skiyohara KASSERT(pn != NULL);
3332692e2e2Skiyohara processor_freq = (unsigned int) prop_number_integer_value(pn);
3342692e2e2Skiyohara plb_freq = processor_freq / CPR0_PLBDV0(mfcpr(DCR_CPR0_PLBD));
3352692e2e2Skiyohara opb_freq = plb_freq / CPR0_OPBDV0(mfcpr(DCR_CPR0_OPBD));
3362692e2e2Skiyohara
3372692e2e2Skiyohara return opb_freq;
338728102e6Sscw }
339