siba_core.c revision 204657
1203319Sweongyo/*- 2203319Sweongyo * Copyright (c) 2009-2010 Weongyo Jeong <weongyo@freebsd.org> 3203319Sweongyo * All rights reserved. 4203319Sweongyo * 5203319Sweongyo * Redistribution and use in source and binary forms, with or without 6203319Sweongyo * modification, are permitted provided that the following conditions 7203319Sweongyo * are met: 8203319Sweongyo * 1. Redistributions of source code must retain the above copyright 9203319Sweongyo * notice, this list of conditions and the following disclaimer, 10203319Sweongyo * without modification. 11203319Sweongyo * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12203319Sweongyo * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 13203319Sweongyo * redistribution must be conditioned upon including a substantially 14203319Sweongyo * similar Disclaimer requirement for further binary redistribution. 15203319Sweongyo * 16203319Sweongyo * NO WARRANTY 17203319Sweongyo * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18203319Sweongyo * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19203319Sweongyo * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 20203319Sweongyo * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21203319Sweongyo * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 22203319Sweongyo * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23203319Sweongyo * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24203319Sweongyo * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25203319Sweongyo * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26203319Sweongyo * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27203319Sweongyo * THE POSSIBILITY OF SUCH DAMAGES. 28203319Sweongyo */ 29203319Sweongyo 30203319Sweongyo#include <sys/cdefs.h> 31203319Sweongyo__FBSDID("$FreeBSD: head/sys/dev/siba/siba_core.c 204657 2010-03-03 20:06:09Z weongyo $"); 32203319Sweongyo 33203319Sweongyo/* 34203319Sweongyo * the Sonics Silicon Backplane driver. 35203319Sweongyo */ 36203319Sweongyo 37203319Sweongyo#include <sys/param.h> 38203319Sweongyo#include <sys/systm.h> 39203319Sweongyo#include <sys/module.h> 40203319Sweongyo#include <sys/kernel.h> 41203319Sweongyo#include <sys/endian.h> 42203319Sweongyo#include <sys/errno.h> 43203319Sweongyo#include <sys/lock.h> 44203319Sweongyo#include <sys/mutex.h> 45203319Sweongyo#include <machine/bus.h> 46203319Sweongyo#include <machine/resource.h> 47203319Sweongyo#include <sys/bus.h> 48203319Sweongyo#include <sys/rman.h> 49203319Sweongyo#include <sys/socket.h> 50203319Sweongyo 51203319Sweongyo#include <net/if.h> 52203319Sweongyo#include <net/if_media.h> 53203319Sweongyo#include <net/if_arp.h> 54203319Sweongyo 55203319Sweongyo#include <dev/pci/pcivar.h> 56203319Sweongyo#include <dev/pci/pcireg.h> 57203319Sweongyo 58203319Sweongyo#include <dev/siba/siba_ids.h> 59203319Sweongyo#include <dev/siba/sibareg.h> 60203319Sweongyo#include <dev/siba/sibavar.h> 61203319Sweongyo 62203319Sweongyo#ifdef SIBA_DEBUG 63203319Sweongyoenum { 64203319Sweongyo SIBA_DEBUG_SCAN = 0x00000001, /* scan */ 65203319Sweongyo SIBA_DEBUG_PMU = 0x00000002, /* PMU */ 66203319Sweongyo SIBA_DEBUG_PLL = 0x00000004, /* PLL */ 67203319Sweongyo SIBA_DEBUG_SWITCHCORE = 0x00000008, /* switching core */ 68203319Sweongyo SIBA_DEBUG_SPROM = 0x00000010, /* SPROM */ 69203319Sweongyo SIBA_DEBUG_CORE = 0x00000020, /* handling cores */ 70203319Sweongyo SIBA_DEBUG_ANY = 0xffffffff 71203319Sweongyo}; 72203319Sweongyo#define DPRINTF(siba, m, fmt, ...) do { \ 73203319Sweongyo if (siba->siba_debug & (m)) \ 74203319Sweongyo printf(fmt, __VA_ARGS__); \ 75203319Sweongyo} while (0) 76203319Sweongyo#else 77203319Sweongyo#define DPRINTF(siba, m, fmt, ...) do { (void) siba; } while (0) 78203319Sweongyo#endif 79203319Sweongyo#define N(a) (sizeof(a) / sizeof(a[0])) 80203319Sweongyo 81203319Sweongyostatic void siba_pci_gpio(struct siba_softc *, uint32_t, int); 82203319Sweongyostatic void siba_scan(struct siba_softc *); 83203319Sweongyostatic int siba_switchcore(struct siba_softc *, uint8_t); 84203319Sweongyostatic int siba_pci_switchcore_sub(struct siba_softc *, uint8_t); 85203319Sweongyostatic uint32_t siba_scan_read_4(struct siba_softc *, uint8_t, uint16_t); 86203319Sweongyostatic uint16_t siba_dev2chipid(struct siba_softc *); 87203319Sweongyostatic uint16_t siba_pci_read_2(struct siba_dev_softc *, uint16_t); 88203319Sweongyostatic uint32_t siba_pci_read_4(struct siba_dev_softc *, uint16_t); 89203319Sweongyostatic void siba_pci_write_2(struct siba_dev_softc *, uint16_t, uint16_t); 90203319Sweongyostatic void siba_pci_write_4(struct siba_dev_softc *, uint16_t, uint32_t); 91203319Sweongyostatic void siba_cc_clock(struct siba_cc *, 92203319Sweongyo enum siba_clock); 93203319Sweongyostatic void siba_cc_pmu_init(struct siba_cc *); 94203319Sweongyostatic void siba_cc_power_init(struct siba_cc *); 95203319Sweongyostatic void siba_cc_powerup_delay(struct siba_cc *); 96203319Sweongyostatic int siba_cc_clockfreq(struct siba_cc *, int); 97203319Sweongyostatic void siba_cc_pmu1_pll0_init(struct siba_cc *, uint32_t); 98203319Sweongyostatic void siba_cc_pmu0_pll0_init(struct siba_cc *, uint32_t); 99203319Sweongyostatic enum siba_clksrc siba_cc_clksrc(struct siba_cc *); 100203319Sweongyostatic const struct siba_cc_pmu1_plltab *siba_cc_pmu1_plltab_find(uint32_t); 101203319Sweongyostatic uint32_t siba_cc_pll_read(struct siba_cc *, uint32_t); 102203319Sweongyostatic void siba_cc_pll_write(struct siba_cc *, uint32_t, 103203319Sweongyo uint32_t); 104203319Sweongyostatic const struct siba_cc_pmu0_plltab * 105203319Sweongyo siba_cc_pmu0_plltab_findentry(uint32_t); 106203319Sweongyostatic int siba_pci_sprom(struct siba_softc *, struct siba_sprom *); 107203319Sweongyostatic int siba_sprom_read(struct siba_softc *, uint16_t *, uint16_t); 108203319Sweongyostatic int sprom_check_crc(const uint16_t *, size_t); 109203319Sweongyostatic uint8_t siba_crc8(uint8_t, uint8_t); 110203319Sweongyostatic void siba_sprom_r123(struct siba_sprom *, const uint16_t *); 111203319Sweongyostatic void siba_sprom_r45(struct siba_sprom *, const uint16_t *); 112203319Sweongyostatic void siba_sprom_r8(struct siba_sprom *, const uint16_t *); 113203319Sweongyostatic int8_t siba_sprom_r123_antgain(uint8_t, const uint16_t *, uint16_t, 114203319Sweongyo uint16_t); 115203319Sweongyostatic uint32_t siba_tmslow_reject_bitmask(struct siba_dev_softc *); 116203319Sweongyostatic uint32_t siba_pcicore_read_4(struct siba_pci *, uint16_t); 117203319Sweongyostatic void siba_pcicore_write_4(struct siba_pci *, uint16_t, uint32_t); 118203319Sweongyostatic uint32_t siba_pcie_read(struct siba_pci *, uint32_t); 119203319Sweongyostatic void siba_pcie_write(struct siba_pci *, uint32_t, uint32_t); 120203319Sweongyostatic void siba_pcie_mdio_write(struct siba_pci *, uint8_t, uint8_t, 121203319Sweongyo uint16_t); 122203319Sweongyostatic void siba_pci_read_multi_1(struct siba_dev_softc *, void *, size_t, 123203319Sweongyo uint16_t); 124203319Sweongyostatic void siba_pci_read_multi_2(struct siba_dev_softc *, void *, size_t, 125203319Sweongyo uint16_t); 126203319Sweongyostatic void siba_pci_read_multi_4(struct siba_dev_softc *, void *, size_t, 127203319Sweongyo uint16_t); 128203319Sweongyostatic void siba_pci_write_multi_1(struct siba_dev_softc *, const void *, 129203319Sweongyo size_t, uint16_t); 130203319Sweongyostatic void siba_pci_write_multi_2(struct siba_dev_softc *, const void *, 131203319Sweongyo size_t, uint16_t); 132203319Sweongyostatic void siba_pci_write_multi_4(struct siba_dev_softc *, const void *, 133203319Sweongyo size_t, uint16_t); 134203319Sweongyostatic const char *siba_core_name(uint16_t); 135203319Sweongyostatic void siba_pcicore_init(struct siba_pci *); 136203319Sweongyoint siba_core_attach(struct siba_softc *); 137203319Sweongyoint siba_core_detach(struct siba_softc *); 138203319Sweongyoint siba_core_suspend(struct siba_softc *); 139203319Sweongyoint siba_core_resume(struct siba_softc *); 140203319Sweongyouint8_t siba_getncores(device_t, uint16_t); 141203319Sweongyo 142203319Sweongyostatic const struct siba_bus_ops siba_pci_ops = { 143203319Sweongyo .read_2 = siba_pci_read_2, 144203319Sweongyo .read_4 = siba_pci_read_4, 145203319Sweongyo .write_2 = siba_pci_write_2, 146203319Sweongyo .write_4 = siba_pci_write_4, 147203319Sweongyo .read_multi_1 = siba_pci_read_multi_1, 148203319Sweongyo .read_multi_2 = siba_pci_read_multi_2, 149203319Sweongyo .read_multi_4 = siba_pci_read_multi_4, 150203319Sweongyo .write_multi_1 = siba_pci_write_multi_1, 151203319Sweongyo .write_multi_2 = siba_pci_write_multi_2, 152203319Sweongyo .write_multi_4 = siba_pci_write_multi_4, 153203319Sweongyo}; 154203319Sweongyo 155203319Sweongyostatic const struct siba_cc_pmu_res_updown siba_cc_pmu_4325_updown[] = 156203319Sweongyo SIBA_CC_PMU_4325_RES_UPDOWN; 157203319Sweongyostatic const struct siba_cc_pmu_res_depend siba_cc_pmu_4325_depend[] = 158203319Sweongyo SIBA_CC_PMU_4325_RES_DEPEND; 159203319Sweongyostatic const struct siba_cc_pmu_res_updown siba_cc_pmu_4328_updown[] = 160203319Sweongyo SIBA_CC_PMU_4328_RES_UPDOWN; 161203319Sweongyostatic const struct siba_cc_pmu_res_depend siba_cc_pmu_4328_depend[] = 162203319Sweongyo SIBA_CC_PMU_4328_RES_DEPEND; 163203319Sweongyostatic const struct siba_cc_pmu0_plltab siba_cc_pmu0_plltab[] = 164203319Sweongyo SIBA_CC_PMU0_PLLTAB_ENTRY; 165203319Sweongyostatic const struct siba_cc_pmu1_plltab siba_cc_pmu1_plltab[] = 166203319Sweongyo SIBA_CC_PMU1_PLLTAB_ENTRY; 167203319Sweongyo 168203319Sweongyoint 169203319Sweongyosiba_core_attach(struct siba_softc *siba) 170203319Sweongyo{ 171203319Sweongyo struct siba_cc *scc; 172203319Sweongyo int error; 173203319Sweongyo 174203319Sweongyo KASSERT(siba->siba_type == SIBA_TYPE_PCI, 175203319Sweongyo ("unsupported BUS type (%#x)", siba->siba_type)); 176203319Sweongyo 177203319Sweongyo siba->siba_ops = &siba_pci_ops; 178203319Sweongyo 179203319Sweongyo siba_pci_gpio(siba, SIBA_GPIO_CRYSTAL | SIBA_GPIO_PLL, 1); 180203319Sweongyo siba_scan(siba); 181203319Sweongyo 182203319Sweongyo /* XXX init PCI or PCMCIA host devices */ 183203319Sweongyo 184203319Sweongyo siba_powerup(siba, 0); 185203319Sweongyo 186203319Sweongyo /* init ChipCommon */ 187203319Sweongyo scc = &siba->siba_cc; 188203319Sweongyo if (scc->scc_dev != NULL) { 189203319Sweongyo siba_cc_pmu_init(scc); 190203319Sweongyo siba_cc_power_init(scc); 191203319Sweongyo siba_cc_clock(scc, SIBA_CLOCK_FAST); 192203319Sweongyo siba_cc_powerup_delay(scc); 193203319Sweongyo } 194203319Sweongyo 195203319Sweongyo /* fetch various internal informations for PCI */ 196203319Sweongyo siba->siba_board_vendor = pci_read_config(siba->siba_dev, 197203319Sweongyo PCIR_SUBVEND_0, 2); 198203319Sweongyo siba->siba_board_type = pci_read_config(siba->siba_dev, PCIR_SUBDEV_0, 199203319Sweongyo 2); 200203319Sweongyo siba->siba_board_rev = pci_read_config(siba->siba_dev, PCIR_REVID, 2); 201203319Sweongyo error = siba_pci_sprom(siba, &siba->siba_sprom); 202203319Sweongyo if (error) { 203203319Sweongyo siba_powerdown(siba); 204203319Sweongyo return (error); 205203319Sweongyo } 206203319Sweongyo 207204657Sweongyo siba_pcicore_init(&siba->siba_pci); 208203319Sweongyo siba_powerdown(siba); 209204657Sweongyo 210204657Sweongyo return (bus_generic_attach(siba->siba_dev)); 211203319Sweongyo} 212203319Sweongyo 213203319Sweongyoint 214203319Sweongyosiba_core_detach(struct siba_softc *siba) 215203319Sweongyo{ 216203319Sweongyo device_t *devlistp; 217203319Sweongyo int devcnt, error = 0, i; 218203319Sweongyo 219203319Sweongyo error = device_get_children(siba->siba_dev, &devlistp, &devcnt); 220203319Sweongyo if (error != 0) 221203319Sweongyo return (0); 222203319Sweongyo 223203319Sweongyo for ( i = 0 ; i < devcnt ; i++) 224203319Sweongyo device_delete_child(siba->siba_dev, devlistp[i]); 225203319Sweongyo free(devlistp, M_TEMP); 226203319Sweongyo return (0); 227203319Sweongyo} 228203319Sweongyo 229203319Sweongyostatic void 230203319Sweongyosiba_pci_gpio(struct siba_softc *siba, uint32_t what, int on) 231203319Sweongyo{ 232203319Sweongyo uint32_t in, out; 233203319Sweongyo uint16_t status; 234203319Sweongyo 235203319Sweongyo if (siba->siba_type != SIBA_TYPE_PCI) 236203319Sweongyo return; 237203319Sweongyo 238203319Sweongyo out = pci_read_config(siba->siba_dev, SIBA_GPIO_OUT, 4); 239203319Sweongyo if (on == 0) { 240203319Sweongyo if (what & SIBA_GPIO_PLL) 241203319Sweongyo out |= SIBA_GPIO_PLL; 242203319Sweongyo if (what & SIBA_GPIO_CRYSTAL) 243203319Sweongyo out &= ~SIBA_GPIO_CRYSTAL; 244203319Sweongyo pci_write_config(siba->siba_dev, SIBA_GPIO_OUT, out, 4); 245203319Sweongyo pci_write_config(siba->siba_dev, SIBA_GPIO_OUT_EN, 246203319Sweongyo pci_read_config(siba->siba_dev, 247203319Sweongyo SIBA_GPIO_OUT_EN, 4) | what, 4); 248203319Sweongyo return; 249203319Sweongyo } 250203319Sweongyo 251203319Sweongyo in = pci_read_config(siba->siba_dev, SIBA_GPIO_IN, 4); 252203319Sweongyo if ((in & SIBA_GPIO_CRYSTAL) != SIBA_GPIO_CRYSTAL) { 253203319Sweongyo if (what & SIBA_GPIO_CRYSTAL) { 254203319Sweongyo out |= SIBA_GPIO_CRYSTAL; 255203319Sweongyo if (what & SIBA_GPIO_PLL) 256203319Sweongyo out |= SIBA_GPIO_PLL; 257203319Sweongyo pci_write_config(siba->siba_dev, SIBA_GPIO_OUT, out, 4); 258203319Sweongyo pci_write_config(siba->siba_dev, 259203319Sweongyo SIBA_GPIO_OUT_EN, pci_read_config(siba->siba_dev, 260203319Sweongyo SIBA_GPIO_OUT_EN, 4) | what, 4); 261203319Sweongyo DELAY(1000); 262203319Sweongyo } 263203319Sweongyo if (what & SIBA_GPIO_PLL) { 264203319Sweongyo out &= ~SIBA_GPIO_PLL; 265203319Sweongyo pci_write_config(siba->siba_dev, SIBA_GPIO_OUT, out, 4); 266203319Sweongyo DELAY(5000); 267203319Sweongyo } 268203319Sweongyo } 269203319Sweongyo 270203319Sweongyo status = pci_read_config(siba->siba_dev, PCIR_STATUS, 2); 271203319Sweongyo status &= ~PCIM_STATUS_STABORT; 272203319Sweongyo pci_write_config(siba->siba_dev, PCIR_STATUS, status, 2); 273203319Sweongyo} 274203319Sweongyo 275203319Sweongyostatic void 276203319Sweongyosiba_scan(struct siba_softc *siba) 277203319Sweongyo{ 278203319Sweongyo struct siba_dev_softc *sd; 279203319Sweongyo uint32_t idhi, tmp; 280204657Sweongyo device_t child; 281203319Sweongyo int base, dev_i = 0, error, i, is_pcie, n_80211 = 0, n_cc = 0, 282203319Sweongyo n_pci = 0; 283203319Sweongyo 284203319Sweongyo KASSERT(siba->siba_type == SIBA_TYPE_PCI, 285203319Sweongyo ("unsupported BUS type (%#x)", siba->siba_type)); 286203319Sweongyo 287203319Sweongyo siba->siba_ndevs = 0; 288203319Sweongyo error = siba_switchcore(siba, 0); /* need the first core */ 289203319Sweongyo if (error) 290203319Sweongyo return; 291203319Sweongyo 292203319Sweongyo idhi = siba_scan_read_4(siba, 0, SIBA_IDHIGH); 293203319Sweongyo if (SIBA_IDHIGH_CORECODE(idhi) == SIBA_DEVID_CHIPCOMMON) { 294203319Sweongyo tmp = siba_scan_read_4(siba, 0, SIBA_CC_CHIPID); 295203319Sweongyo siba->siba_chipid = SIBA_CC_ID(tmp); 296203319Sweongyo siba->siba_chiprev = SIBA_CC_REV(tmp); 297203319Sweongyo siba->siba_chippkg = SIBA_CC_PKG(tmp); 298203319Sweongyo if (SIBA_IDHIGH_REV(idhi) >= 4) 299203319Sweongyo siba->siba_ndevs = SIBA_CC_NCORES(tmp); 300203319Sweongyo siba->siba_cc.scc_caps = siba_scan_read_4(siba, 0, 301203319Sweongyo SIBA_CC_CAPS); 302203319Sweongyo } else { 303203319Sweongyo if (siba->siba_type == SIBA_TYPE_PCI) { 304203319Sweongyo siba->siba_chipid = siba_dev2chipid(siba); 305203319Sweongyo siba->siba_chiprev = pci_read_config(siba->siba_dev, 306203319Sweongyo PCIR_REVID, 2); 307203319Sweongyo siba->siba_chippkg = 0; 308203319Sweongyo } else { 309203319Sweongyo siba->siba_chipid = 0x4710; 310203319Sweongyo siba->siba_chiprev = 0; 311203319Sweongyo siba->siba_chippkg = 0; 312203319Sweongyo } 313203319Sweongyo } 314203319Sweongyo if (siba->siba_ndevs == 0) 315203319Sweongyo siba->siba_ndevs = siba_getncores(siba->siba_dev, 316203319Sweongyo siba->siba_chipid); 317203319Sweongyo if (siba->siba_ndevs > SIBA_MAX_CORES) { 318203319Sweongyo device_printf(siba->siba_dev, 319203319Sweongyo "too many siba cores (max %d %d)\n", 320203319Sweongyo SIBA_MAX_CORES, siba->siba_ndevs); 321203319Sweongyo return; 322203319Sweongyo } 323203319Sweongyo 324203319Sweongyo /* looking basic information about each cores/devices */ 325203319Sweongyo for (i = 0; i < siba->siba_ndevs; i++) { 326203319Sweongyo error = siba_switchcore(siba, i); 327203319Sweongyo if (error) 328203319Sweongyo return; 329203319Sweongyo sd = &(siba->siba_devs[dev_i]); 330203319Sweongyo idhi = siba_scan_read_4(siba, i, SIBA_IDHIGH); 331203319Sweongyo sd->sd_bus = siba; 332203319Sweongyo sd->sd_id.sd_device = SIBA_IDHIGH_CORECODE(idhi); 333203319Sweongyo sd->sd_id.sd_rev = SIBA_IDHIGH_REV(idhi); 334203319Sweongyo sd->sd_id.sd_vendor = SIBA_IDHIGH_VENDOR(idhi); 335203319Sweongyo sd->sd_ops = siba->siba_ops; 336203319Sweongyo sd->sd_coreidx = i; 337203319Sweongyo 338203319Sweongyo DPRINTF(siba, SIBA_DEBUG_SCAN, 339203319Sweongyo "core %d (%s) found (cc %#xrev %#x vendor %#x)\n", 340203319Sweongyo i, siba_core_name(sd->sd_id.sd_device), 341203319Sweongyo sd->sd_id.sd_device, sd->sd_id.sd_rev, sd->sd_id.vendor); 342203319Sweongyo 343203319Sweongyo switch (sd->sd_id.sd_device) { 344203319Sweongyo case SIBA_DEVID_CHIPCOMMON: 345203319Sweongyo n_cc++; 346203319Sweongyo if (n_cc > 1) { 347203319Sweongyo device_printf(siba->siba_dev, 348203319Sweongyo "warn: multiple ChipCommon\n"); 349203319Sweongyo break; 350203319Sweongyo } 351203319Sweongyo siba->siba_cc.scc_dev = sd; 352203319Sweongyo break; 353203319Sweongyo case SIBA_DEVID_80211: 354203319Sweongyo n_80211++; 355203319Sweongyo if (n_80211 > 1) { 356203319Sweongyo device_printf(siba->siba_dev, 357203319Sweongyo "warn: multiple 802.11 core\n"); 358203319Sweongyo continue; 359203319Sweongyo } 360203319Sweongyo break; 361203319Sweongyo case SIBA_DEVID_PCI: 362203319Sweongyo case SIBA_DEVID_PCIE: 363203319Sweongyo n_pci++; 364203319Sweongyo error = pci_find_extcap(siba->siba_dev, PCIY_EXPRESS, 365203319Sweongyo &base); 366203319Sweongyo is_pcie = (error == 0) ? 1 : 0; 367203319Sweongyo 368203319Sweongyo if (n_pci > 1) { 369203319Sweongyo device_printf(siba->siba_dev, 370203319Sweongyo "warn: multiple PCI(E) cores\n"); 371203319Sweongyo break; 372203319Sweongyo } 373203319Sweongyo if (sd->sd_id.sd_device == SIBA_DEVID_PCI && 374203319Sweongyo is_pcie == 1) 375203319Sweongyo continue; 376203319Sweongyo if (sd->sd_id.sd_device == SIBA_DEVID_PCIE && 377203319Sweongyo is_pcie == 0) 378203319Sweongyo continue; 379203319Sweongyo siba->siba_pci.spc_dev = sd; 380203319Sweongyo break; 381203319Sweongyo case SIBA_DEVID_MODEM: 382203319Sweongyo case SIBA_DEVID_PCMCIA: 383203319Sweongyo break; 384203319Sweongyo default: 385203319Sweongyo device_printf(siba->siba_dev, 386203319Sweongyo "unsupported coreid (%s)\n", 387203319Sweongyo siba_core_name(sd->sd_id.sd_device)); 388203319Sweongyo break; 389203319Sweongyo } 390203319Sweongyo dev_i++; 391204657Sweongyo 392204657Sweongyo child = device_add_child(siba->siba_dev, NULL, -1); 393204657Sweongyo if (child == NULL) { 394204657Sweongyo device_printf(siba->siba_dev, "child attach failed\n"); 395204657Sweongyo continue; 396204657Sweongyo } 397204657Sweongyo 398204657Sweongyo device_set_ivars(child, sd); 399203319Sweongyo } 400203319Sweongyo siba->siba_ndevs = dev_i; 401203319Sweongyo} 402203319Sweongyo 403203319Sweongyostatic int 404203319Sweongyosiba_switchcore(struct siba_softc *siba, uint8_t idx) 405203319Sweongyo{ 406203319Sweongyo 407203319Sweongyo switch (siba->siba_type) { 408203319Sweongyo case SIBA_TYPE_PCI: 409203319Sweongyo return (siba_pci_switchcore_sub(siba, idx)); 410203319Sweongyo default: 411203319Sweongyo KASSERT(0 == 1, 412203319Sweongyo ("%s: unsupported bustype %#x", __func__, 413203319Sweongyo siba->siba_type)); 414203319Sweongyo } 415203319Sweongyo return (0); 416203319Sweongyo} 417203319Sweongyo 418203319Sweongyostatic int 419203319Sweongyosiba_pci_switchcore_sub(struct siba_softc *siba, uint8_t idx) 420203319Sweongyo{ 421203319Sweongyo#define RETRY_MAX 50 422203319Sweongyo int i; 423203319Sweongyo uint32_t dir; 424203319Sweongyo 425203319Sweongyo dir = SIBA_REGWIN(idx); 426203319Sweongyo 427203319Sweongyo for (i = 0; i < RETRY_MAX; i++) { 428203319Sweongyo pci_write_config(siba->siba_dev, SIBA_BAR0, dir, 4); 429203319Sweongyo if (pci_read_config(siba->siba_dev, SIBA_BAR0, 4) == dir) 430203319Sweongyo return (0); 431203319Sweongyo DELAY(10); 432203319Sweongyo } 433203319Sweongyo return (ENODEV); 434203319Sweongyo#undef RETRY_MAX 435203319Sweongyo} 436203319Sweongyo 437203319Sweongyostatic int 438203319Sweongyosiba_pci_switchcore(struct siba_softc *siba, struct siba_dev_softc *sd) 439203319Sweongyo{ 440203319Sweongyo int error; 441203319Sweongyo 442203319Sweongyo DPRINTF(siba, SIBA_DEBUG_SWITCHCORE, "Switching to %s core, index %d\n", 443203319Sweongyo siba_core_name(sd->sd_id.sd_device), sd->sd_coreidx); 444203319Sweongyo 445203319Sweongyo error = siba_pci_switchcore_sub(siba, sd->sd_coreidx); 446203319Sweongyo if (error == 0) 447203319Sweongyo siba->siba_curdev = sd; 448203319Sweongyo 449203319Sweongyo return (error); 450203319Sweongyo} 451203319Sweongyo 452203319Sweongyostatic uint32_t 453203319Sweongyosiba_scan_read_4(struct siba_softc *siba, uint8_t coreidx, 454203319Sweongyo uint16_t offset) 455203319Sweongyo{ 456203319Sweongyo 457203319Sweongyo (void)coreidx; 458203319Sweongyo KASSERT(siba->siba_type == SIBA_TYPE_PCI, 459203319Sweongyo ("unsupported BUS type (%#x)", siba->siba_type)); 460203319Sweongyo 461203319Sweongyo return (SIBA_READ_4(siba, offset)); 462203319Sweongyo} 463203319Sweongyo 464203319Sweongyostatic uint16_t 465203319Sweongyosiba_dev2chipid(struct siba_softc *siba) 466203319Sweongyo{ 467203319Sweongyo uint16_t chipid = 0; 468203319Sweongyo 469203319Sweongyo switch (siba->siba_pci_did) { 470203319Sweongyo case 0x4301: 471203319Sweongyo chipid = 0x4301; 472203319Sweongyo break; 473203319Sweongyo case 0x4305: 474203319Sweongyo case 0x4306: 475203319Sweongyo case 0x4307: 476203319Sweongyo chipid = 0x4307; 477203319Sweongyo break; 478203319Sweongyo case 0x4403: 479203319Sweongyo chipid = 0x4402; 480203319Sweongyo break; 481203319Sweongyo case 0x4610: 482203319Sweongyo case 0x4611: 483203319Sweongyo case 0x4612: 484203319Sweongyo case 0x4613: 485203319Sweongyo case 0x4614: 486203319Sweongyo case 0x4615: 487203319Sweongyo chipid = 0x4610; 488203319Sweongyo break; 489203319Sweongyo case 0x4710: 490203319Sweongyo case 0x4711: 491203319Sweongyo case 0x4712: 492203319Sweongyo case 0x4713: 493203319Sweongyo case 0x4714: 494203319Sweongyo case 0x4715: 495203319Sweongyo chipid = 0x4710; 496203319Sweongyo break; 497203319Sweongyo case 0x4320: 498203319Sweongyo case 0x4321: 499203319Sweongyo case 0x4322: 500203319Sweongyo case 0x4323: 501203319Sweongyo case 0x4324: 502203319Sweongyo case 0x4325: 503203319Sweongyo chipid = 0x4309; 504203319Sweongyo break; 505203319Sweongyo case PCI_DEVICE_ID_BCM4401: 506203319Sweongyo case PCI_DEVICE_ID_BCM4401B0: 507203319Sweongyo case PCI_DEVICE_ID_BCM4401B1: 508203319Sweongyo chipid = 0x4401; 509203319Sweongyo break; 510203319Sweongyo default: 511203319Sweongyo device_printf(siba->siba_dev, "unknown PCI did (%d)\n", 512203319Sweongyo siba->siba_pci_did); 513203319Sweongyo } 514203319Sweongyo 515203319Sweongyo return (chipid); 516203319Sweongyo} 517203319Sweongyo 518203319Sweongyo/* 519203319Sweongyo * Earlier ChipCommon revisions have hardcoded number of cores 520203319Sweongyo * present dependent on the ChipCommon ID. 521203319Sweongyo */ 522203319Sweongyouint8_t 523203319Sweongyosiba_getncores(device_t dev, uint16_t chipid) 524203319Sweongyo{ 525203319Sweongyo switch (chipid) { 526203319Sweongyo case 0x4401: 527203319Sweongyo case 0x4402: 528203319Sweongyo return (3); 529203319Sweongyo case 0x4301: 530203319Sweongyo case 0x4307: 531203319Sweongyo return (5); 532203319Sweongyo case 0x4306: 533203319Sweongyo return (6); 534203319Sweongyo case SIBA_CCID_SENTRY5: 535203319Sweongyo return (7); 536203319Sweongyo case 0x4310: 537203319Sweongyo return (8); 538203319Sweongyo case SIBA_CCID_BCM4710: 539203319Sweongyo case 0x4610: 540203319Sweongyo case SIBA_CCID_BCM4704: 541203319Sweongyo return (9); 542203319Sweongyo default: 543203319Sweongyo device_printf(dev, "unknown the chipset ID %#x\n", chipid); 544203319Sweongyo } 545203319Sweongyo 546203319Sweongyo return (1); 547203319Sweongyo} 548203319Sweongyo 549203319Sweongyostatic const char * 550203319Sweongyosiba_core_name(uint16_t coreid) 551203319Sweongyo{ 552203319Sweongyo 553203319Sweongyo switch (coreid) { 554203319Sweongyo case SIBA_DEVID_CHIPCOMMON: 555203319Sweongyo return ("ChipCommon"); 556203319Sweongyo case SIBA_DEVID_ILINE20: 557203319Sweongyo return ("ILine 20"); 558203319Sweongyo case SIBA_DEVID_SDRAM: 559203319Sweongyo return ("SDRAM"); 560203319Sweongyo case SIBA_DEVID_PCI: 561203319Sweongyo return ("PCI"); 562203319Sweongyo case SIBA_DEVID_MIPS: 563203319Sweongyo return ("MIPS"); 564203319Sweongyo case SIBA_DEVID_ETHERNET: 565203319Sweongyo return ("Fast Ethernet"); 566203319Sweongyo case SIBA_DEVID_MODEM: 567203319Sweongyo return ("Modem"); 568203319Sweongyo case SIBA_DEVID_USB11_HOSTDEV: 569203319Sweongyo return ("USB 1.1 Hostdev"); 570203319Sweongyo case SIBA_DEVID_ADSL: 571203319Sweongyo return ("ADSL"); 572203319Sweongyo case SIBA_DEVID_ILINE100: 573203319Sweongyo return ("ILine 100"); 574203319Sweongyo case SIBA_DEVID_IPSEC: 575203319Sweongyo return ("IPSEC"); 576203319Sweongyo case SIBA_DEVID_PCMCIA: 577203319Sweongyo return ("PCMCIA"); 578203319Sweongyo case SIBA_DEVID_INTERNAL_MEM: 579203319Sweongyo return ("Internal Memory"); 580203319Sweongyo case SIBA_DEVID_SDRAMDDR: 581203319Sweongyo return ("MEMC SDRAM"); 582203319Sweongyo case SIBA_DEVID_EXTIF: 583203319Sweongyo return ("EXTIF"); 584203319Sweongyo case SIBA_DEVID_80211: 585203319Sweongyo return ("IEEE 802.11"); 586203319Sweongyo case SIBA_DEVID_MIPS_3302: 587203319Sweongyo return ("MIPS 3302"); 588203319Sweongyo case SIBA_DEVID_USB11_HOST: 589203319Sweongyo return ("USB 1.1 Host"); 590203319Sweongyo case SIBA_DEVID_USB11_DEV: 591203319Sweongyo return ("USB 1.1 Device"); 592203319Sweongyo case SIBA_DEVID_USB20_HOST: 593203319Sweongyo return ("USB 2.0 Host"); 594203319Sweongyo case SIBA_DEVID_USB20_DEV: 595203319Sweongyo return ("USB 2.0 Device"); 596203319Sweongyo case SIBA_DEVID_SDIO_HOST: 597203319Sweongyo return ("SDIO Host"); 598203319Sweongyo case SIBA_DEVID_ROBOSWITCH: 599203319Sweongyo return ("Roboswitch"); 600203319Sweongyo case SIBA_DEVID_PARA_ATA: 601203319Sweongyo return ("PATA"); 602203319Sweongyo case SIBA_DEVID_SATA_XORDMA: 603203319Sweongyo return ("SATA XOR-DMA"); 604203319Sweongyo case SIBA_DEVID_ETHERNET_GBIT: 605203319Sweongyo return ("GBit Ethernet"); 606203319Sweongyo case SIBA_DEVID_PCIE: 607203319Sweongyo return ("PCI-Express"); 608203319Sweongyo case SIBA_DEVID_MIMO_PHY: 609203319Sweongyo return ("MIMO PHY"); 610203319Sweongyo case SIBA_DEVID_SRAM_CTRLR: 611203319Sweongyo return ("SRAM Controller"); 612203319Sweongyo case SIBA_DEVID_MINI_MACPHY: 613203319Sweongyo return ("Mini MACPHY"); 614203319Sweongyo case SIBA_DEVID_ARM_1176: 615203319Sweongyo return ("ARM 1176"); 616203319Sweongyo case SIBA_DEVID_ARM_7TDMI: 617203319Sweongyo return ("ARM 7TDMI"); 618203319Sweongyo } 619203319Sweongyo return ("unknown"); 620203319Sweongyo} 621203319Sweongyo 622203319Sweongyostatic uint16_t 623203319Sweongyosiba_pci_read_2(struct siba_dev_softc *sd, uint16_t offset) 624203319Sweongyo{ 625203319Sweongyo struct siba_softc *siba = sd->sd_bus; 626203319Sweongyo 627203319Sweongyo if (siba->siba_curdev != sd && siba_pci_switchcore(siba, sd) != 0) 628203319Sweongyo return (0xffff); 629203319Sweongyo 630203319Sweongyo return (SIBA_READ_2(siba, offset)); 631203319Sweongyo} 632203319Sweongyo 633203319Sweongyostatic uint32_t 634203319Sweongyosiba_pci_read_4(struct siba_dev_softc *sd, uint16_t offset) 635203319Sweongyo{ 636203319Sweongyo struct siba_softc *siba = sd->sd_bus; 637203319Sweongyo 638203319Sweongyo if (siba->siba_curdev != sd && siba_pci_switchcore(siba, sd) != 0) 639203319Sweongyo return (0xffff); 640203319Sweongyo 641203319Sweongyo return (SIBA_READ_4(siba, offset)); 642203319Sweongyo} 643203319Sweongyo 644203319Sweongyostatic void 645203319Sweongyosiba_pci_write_2(struct siba_dev_softc *sd, uint16_t offset, uint16_t value) 646203319Sweongyo{ 647203319Sweongyo struct siba_softc *siba = sd->sd_bus; 648203319Sweongyo 649203319Sweongyo if (siba->siba_curdev != sd && siba_pci_switchcore(siba, sd) != 0) 650203319Sweongyo return; 651203319Sweongyo 652203319Sweongyo SIBA_WRITE_2(siba, offset, value); 653203319Sweongyo} 654203319Sweongyo 655203319Sweongyostatic void 656203319Sweongyosiba_pci_write_4(struct siba_dev_softc *sd, uint16_t offset, uint32_t value) 657203319Sweongyo{ 658203319Sweongyo struct siba_softc *siba = sd->sd_bus; 659203319Sweongyo 660203319Sweongyo if (siba->siba_curdev != sd && siba_pci_switchcore(siba, sd) != 0) 661203319Sweongyo return; 662203319Sweongyo 663203319Sweongyo SIBA_WRITE_4(siba, offset, value); 664203319Sweongyo} 665203319Sweongyo 666203319Sweongyostatic void 667203319Sweongyosiba_pci_read_multi_1(struct siba_dev_softc *sd, void *buffer, size_t count, 668203319Sweongyo uint16_t offset) 669203319Sweongyo{ 670203319Sweongyo struct siba_softc *siba = sd->sd_bus; 671203319Sweongyo 672203319Sweongyo if (siba->siba_curdev != sd && siba_pci_switchcore(siba, sd) != 0) { 673203319Sweongyo memset(buffer, 0xff, count); 674203319Sweongyo return; 675203319Sweongyo } 676203319Sweongyo 677203319Sweongyo SIBA_READ_MULTI_1(siba, offset, buffer, count); 678203319Sweongyo} 679203319Sweongyo 680203319Sweongyostatic void 681203319Sweongyosiba_pci_read_multi_2(struct siba_dev_softc *sd, void *buffer, size_t count, 682203319Sweongyo uint16_t offset) 683203319Sweongyo{ 684203319Sweongyo struct siba_softc *siba = sd->sd_bus; 685203319Sweongyo 686203319Sweongyo if (siba->siba_curdev != sd && siba_pci_switchcore(siba, sd) != 0) { 687203319Sweongyo memset(buffer, 0xff, count); 688203319Sweongyo return; 689203319Sweongyo } 690203319Sweongyo 691203319Sweongyo KASSERT(!(count & 1), ("%s:%d: fail", __func__, __LINE__)); 692203319Sweongyo SIBA_READ_MULTI_2(siba, offset, buffer, count >> 1); 693203319Sweongyo} 694203319Sweongyo 695203319Sweongyostatic void 696203319Sweongyosiba_pci_read_multi_4(struct siba_dev_softc *sd, void *buffer, size_t count, 697203319Sweongyo uint16_t offset) 698203319Sweongyo{ 699203319Sweongyo struct siba_softc *siba = sd->sd_bus; 700203319Sweongyo 701203319Sweongyo if (siba->siba_curdev != sd && siba_pci_switchcore(siba, sd) != 0) { 702203319Sweongyo memset(buffer, 0xff, count); 703203319Sweongyo return; 704203319Sweongyo } 705203319Sweongyo 706203319Sweongyo KASSERT(!(count & 3), ("%s:%d: fail", __func__, __LINE__)); 707203319Sweongyo SIBA_READ_MULTI_4(siba, offset, buffer, count >> 2); 708203319Sweongyo} 709203319Sweongyo 710203319Sweongyostatic void 711203319Sweongyosiba_pci_write_multi_1(struct siba_dev_softc *sd, const void *buffer, 712203319Sweongyo size_t count, uint16_t offset) 713203319Sweongyo{ 714203319Sweongyo struct siba_softc *siba = sd->sd_bus; 715203319Sweongyo 716203319Sweongyo if (siba->siba_curdev != sd && siba_pci_switchcore(siba, sd) != 0) 717203319Sweongyo return; 718203319Sweongyo 719203319Sweongyo SIBA_WRITE_MULTI_1(siba, offset, buffer, count); 720203319Sweongyo} 721203319Sweongyo 722203319Sweongyostatic void 723203319Sweongyosiba_pci_write_multi_2(struct siba_dev_softc *sd, const void *buffer, 724203319Sweongyo size_t count, uint16_t offset) 725203319Sweongyo{ 726203319Sweongyo struct siba_softc *siba = sd->sd_bus; 727203319Sweongyo 728203319Sweongyo if (siba->siba_curdev != sd && siba_pci_switchcore(siba, sd) != 0) 729203319Sweongyo return; 730203319Sweongyo 731203319Sweongyo KASSERT(!(count & 1), ("%s:%d: fail", __func__, __LINE__)); 732203319Sweongyo SIBA_WRITE_MULTI_2(siba, offset, buffer, count >> 1); 733203319Sweongyo} 734203319Sweongyo 735203319Sweongyostatic void 736203319Sweongyosiba_pci_write_multi_4(struct siba_dev_softc *sd, const void *buffer, 737203319Sweongyo size_t count, uint16_t offset) 738203319Sweongyo{ 739203319Sweongyo struct siba_softc *siba = sd->sd_bus; 740203319Sweongyo 741203319Sweongyo if (siba->siba_curdev != sd && siba_pci_switchcore(siba, sd) != 0) 742203319Sweongyo return; 743203319Sweongyo 744203319Sweongyo KASSERT(!(count & 3), ("%s:%d: fail", __func__, __LINE__)); 745203319Sweongyo SIBA_WRITE_MULTI_4(siba, offset, buffer, count >> 2); 746203319Sweongyo} 747203319Sweongyo 748203319Sweongyovoid 749203319Sweongyosiba_powerup(struct siba_softc *siba, int dynamic) 750203319Sweongyo{ 751203319Sweongyo 752203319Sweongyo siba_pci_gpio(siba, SIBA_GPIO_CRYSTAL | SIBA_GPIO_PLL, 1); 753203319Sweongyo siba_cc_clock(&siba->siba_cc, 754203319Sweongyo (dynamic != 0) ? SIBA_CLOCK_DYNAMIC : SIBA_CLOCK_FAST); 755203319Sweongyo} 756203319Sweongyo 757203319Sweongyostatic void 758203319Sweongyosiba_cc_clock(struct siba_cc *scc, enum siba_clock clock) 759203319Sweongyo{ 760203319Sweongyo struct siba_dev_softc *sd = scc->scc_dev; 761203319Sweongyo struct siba_softc *siba; 762203319Sweongyo uint32_t tmp; 763203319Sweongyo 764203319Sweongyo if (sd == NULL) 765203319Sweongyo return; 766203319Sweongyo siba = sd->sd_bus; 767203319Sweongyo /* 768203319Sweongyo * chipcommon < r6 (no dynamic clock control) 769203319Sweongyo * chipcommon >= r10 (unknown) 770203319Sweongyo */ 771203319Sweongyo if (sd->sd_id.sd_rev < 6 || sd->sd_id.sd_rev >= 10 || 772203319Sweongyo (scc->scc_caps & SIBA_CC_CAPS_PWCTL) == 0) 773203319Sweongyo return; 774203319Sweongyo 775203319Sweongyo switch (clock) { 776203319Sweongyo case SIBA_CLOCK_DYNAMIC: 777203319Sweongyo tmp = SIBA_CC_READ32(scc, SIBA_CC_CLKSLOW) & 778203319Sweongyo ~(SIBA_CC_CLKSLOW_ENXTAL | SIBA_CC_CLKSLOW_FSLOW | 779203319Sweongyo SIBA_CC_CLKSLOW_IPLL); 780203319Sweongyo if ((tmp & SIBA_CC_CLKSLOW_SRC) != SIBA_CC_CLKSLOW_SRC_CRYSTAL) 781203319Sweongyo tmp |= SIBA_CC_CLKSLOW_ENXTAL; 782203319Sweongyo SIBA_CC_WRITE32(scc, SIBA_CC_CLKSLOW, tmp); 783203319Sweongyo if (tmp & SIBA_CC_CLKSLOW_ENXTAL) 784203319Sweongyo siba_pci_gpio(siba, SIBA_GPIO_CRYSTAL, 0); 785203319Sweongyo break; 786203319Sweongyo case SIBA_CLOCK_SLOW: 787203319Sweongyo SIBA_CC_WRITE32(scc, SIBA_CC_CLKSLOW, 788203319Sweongyo SIBA_CC_READ32(scc, SIBA_CC_CLKSLOW) | 789203319Sweongyo SIBA_CC_CLKSLOW_FSLOW); 790203319Sweongyo break; 791203319Sweongyo case SIBA_CLOCK_FAST: 792203319Sweongyo /* crystal on */ 793203319Sweongyo siba_pci_gpio(siba, SIBA_GPIO_CRYSTAL, 1); 794203319Sweongyo SIBA_CC_WRITE32(scc, SIBA_CC_CLKSLOW, 795203319Sweongyo (SIBA_CC_READ32(scc, SIBA_CC_CLKSLOW) | 796203319Sweongyo SIBA_CC_CLKSLOW_IPLL) & ~SIBA_CC_CLKSLOW_FSLOW); 797203319Sweongyo break; 798203319Sweongyo default: 799203319Sweongyo KASSERT(0 == 1, 800203319Sweongyo ("%s: unsupported clock %#x", __func__, clock)); 801203319Sweongyo } 802203319Sweongyo} 803203319Sweongyo 804203319Sweongyouint16_t 805203319Sweongyosiba_read_2(struct siba_dev_softc *sd, uint16_t offset) 806203319Sweongyo{ 807203319Sweongyo 808203319Sweongyo return (sd->sd_ops->read_2(sd, offset)); 809203319Sweongyo} 810203319Sweongyo 811203319Sweongyouint32_t 812203319Sweongyosiba_read_4(struct siba_dev_softc *sd, uint16_t offset) 813203319Sweongyo{ 814203319Sweongyo 815203319Sweongyo return (sd->sd_ops->read_4(sd, offset)); 816203319Sweongyo} 817203319Sweongyo 818203319Sweongyovoid 819203319Sweongyosiba_write_2(struct siba_dev_softc *sd, uint16_t offset, uint16_t value) 820203319Sweongyo{ 821203319Sweongyo 822203319Sweongyo sd->sd_ops->write_2(sd, offset, value); 823203319Sweongyo} 824203319Sweongyo 825203319Sweongyovoid 826203319Sweongyosiba_write_4(struct siba_dev_softc *sd, uint16_t offset, uint32_t value) 827203319Sweongyo{ 828203319Sweongyo 829203319Sweongyo sd->sd_ops->write_4(sd, offset, value); 830203319Sweongyo} 831203319Sweongyo 832203319Sweongyovoid 833203319Sweongyosiba_read_multi_1(struct siba_dev_softc *sd, void *buffer, size_t count, 834203319Sweongyo uint16_t offset) 835203319Sweongyo{ 836203319Sweongyo 837203319Sweongyo sd->sd_ops->read_multi_1(sd, buffer, count, offset); 838203319Sweongyo} 839203319Sweongyo 840203319Sweongyovoid 841203319Sweongyosiba_read_multi_2(struct siba_dev_softc *sd, void *buffer, size_t count, 842203319Sweongyo uint16_t offset) 843203319Sweongyo{ 844203319Sweongyo 845203319Sweongyo sd->sd_ops->read_multi_2(sd, buffer, count, offset); 846203319Sweongyo} 847203319Sweongyo 848203319Sweongyovoid 849203319Sweongyosiba_read_multi_4(struct siba_dev_softc *sd, void *buffer, size_t count, 850203319Sweongyo uint16_t offset) 851203319Sweongyo{ 852203319Sweongyo 853203319Sweongyo sd->sd_ops->read_multi_4(sd, buffer, count, offset); 854203319Sweongyo} 855203319Sweongyo 856203319Sweongyovoid 857203319Sweongyosiba_write_multi_1(struct siba_dev_softc *sd, const void *buffer, 858203319Sweongyo size_t count, uint16_t offset) 859203319Sweongyo{ 860203319Sweongyo 861203319Sweongyo sd->sd_ops->write_multi_1(sd, buffer, count, offset); 862203319Sweongyo} 863203319Sweongyo 864203319Sweongyovoid 865203319Sweongyosiba_write_multi_2(struct siba_dev_softc *sd, const void *buffer, 866203319Sweongyo size_t count, uint16_t offset) 867203319Sweongyo{ 868203319Sweongyo 869203319Sweongyo sd->sd_ops->write_multi_2(sd, buffer, count, offset); 870203319Sweongyo} 871203319Sweongyo 872203319Sweongyovoid 873203319Sweongyosiba_write_multi_4(struct siba_dev_softc *sd, const void *buffer, 874203319Sweongyo size_t count, uint16_t offset) 875203319Sweongyo{ 876203319Sweongyo 877203319Sweongyo sd->sd_ops->write_multi_4(sd, buffer, count, offset); 878203319Sweongyo} 879203319Sweongyo 880203319Sweongyostatic void 881203319Sweongyosiba_cc_pmu_init(struct siba_cc *scc) 882203319Sweongyo{ 883203319Sweongyo const struct siba_cc_pmu_res_updown *updown = NULL; 884203319Sweongyo const struct siba_cc_pmu_res_depend *depend = NULL; 885203319Sweongyo struct siba_dev_softc *sd = scc->scc_dev; 886203319Sweongyo struct siba_softc *siba = sd->sd_bus; 887203319Sweongyo uint32_t min = 0, max = 0, pmucap; 888203319Sweongyo unsigned int i, updown_size, depend_size; 889203319Sweongyo 890203319Sweongyo if ((scc->scc_caps & SIBA_CC_CAPS_PMU) == 0) 891203319Sweongyo return; 892203319Sweongyo 893203319Sweongyo pmucap = SIBA_CC_READ32(scc, SIBA_CC_PMUCAPS); 894203319Sweongyo scc->scc_pmu.rev = (pmucap & SIBA_CC_PMUCAPS_REV); 895203319Sweongyo 896203319Sweongyo DPRINTF(siba, SIBA_DEBUG_PMU, "PMU(r%u) found (caps %#x)\n", 897203319Sweongyo scc->scc_pmu.rev, pmucap); 898203319Sweongyo 899203319Sweongyo if (scc->scc_pmu.rev >= 1) { 900203319Sweongyo if (siba->siba_chiprev < 2 && siba->siba_chipid == 0x4325) 901203319Sweongyo SIBA_CC_MASK32(scc, SIBA_CC_PMUCTL, 902203319Sweongyo ~SIBA_CC_PMUCTL_NOILP); 903203319Sweongyo else 904203319Sweongyo SIBA_CC_SET32(scc, SIBA_CC_PMUCTL, 905203319Sweongyo SIBA_CC_PMUCTL_NOILP); 906203319Sweongyo } 907203319Sweongyo 908203319Sweongyo /* initialize PLL & PMU resources */ 909203319Sweongyo switch (siba->siba_chipid) { 910203319Sweongyo case 0x4312: 911203319Sweongyo siba_cc_pmu1_pll0_init(scc, 0 /* use default */); 912203319Sweongyo /* use the default: min = 0xcbb max = 0x7ffff */ 913203319Sweongyo break; 914203319Sweongyo case 0x4325: 915203319Sweongyo siba_cc_pmu1_pll0_init(scc, 0 /* use default */); 916203319Sweongyo 917203319Sweongyo updown = siba_cc_pmu_4325_updown; 918203319Sweongyo updown_size = N(siba_cc_pmu_4325_updown); 919203319Sweongyo depend = siba_cc_pmu_4325_depend; 920203319Sweongyo depend_size = N(siba_cc_pmu_4325_depend); 921203319Sweongyo 922203319Sweongyo min = (1 << SIBA_CC_PMU_4325_BURST) | 923203319Sweongyo (1 << SIBA_CC_PMU_4325_LN); 924203319Sweongyo if (SIBA_CC_READ32(scc, SIBA_CC_CHIPSTAT) & 925203319Sweongyo SIBA_CC_CHST_4325_PMUTOP_2B) 926203319Sweongyo min |= (1 << SIBA_CC_PMU_4325_CLBURST); 927203319Sweongyo max = 0xfffff; 928203319Sweongyo break; 929203319Sweongyo case 0x4328: 930203319Sweongyo siba_cc_pmu0_pll0_init(scc, 0 /* use default */); 931203319Sweongyo 932203319Sweongyo updown = siba_cc_pmu_4328_updown; 933203319Sweongyo updown_size = N(siba_cc_pmu_4328_updown); 934203319Sweongyo depend = siba_cc_pmu_4328_depend; 935203319Sweongyo depend_size = N(siba_cc_pmu_4328_depend); 936203319Sweongyo 937203319Sweongyo min = (1 << SIBA_CC_PMU_4328_EXT_SWITCH_PWM) | 938203319Sweongyo (1 << SIBA_CC_PMU_4328_BB_SWITCH_PWM) | 939203319Sweongyo (1 << SIBA_CC_PMU_4328_CRYSTAL_EN); 940203319Sweongyo 941203319Sweongyo max = 0xfffff; 942203319Sweongyo break; 943203319Sweongyo case 0x5354: 944203319Sweongyo siba_cc_pmu0_pll0_init(scc, 0 /* use default */); 945203319Sweongyo 946203319Sweongyo max = 0xfffff; 947203319Sweongyo break; 948203319Sweongyo default: 949203319Sweongyo device_printf(siba->siba_dev, 950203319Sweongyo "unknown chipid %#x for PLL & PMU init\n", 951203319Sweongyo siba->siba_chipid); 952203319Sweongyo } 953203319Sweongyo 954203319Sweongyo if (updown) { 955203319Sweongyo for (i = 0; i < updown_size; i++) { 956203319Sweongyo SIBA_CC_WRITE32(scc, SIBA_CC_PMU_TABSEL, 957203319Sweongyo updown[i].res); 958203319Sweongyo SIBA_CC_WRITE32(scc, SIBA_CC_PMU_UPDNTM, 959203319Sweongyo updown[i].updown); 960203319Sweongyo } 961203319Sweongyo } 962203319Sweongyo if (depend) { 963203319Sweongyo for (i = 0; i < depend_size; i++) { 964203319Sweongyo SIBA_CC_WRITE32(scc, SIBA_CC_PMU_TABSEL, 965203319Sweongyo depend[i].res); 966203319Sweongyo switch (depend[i].task) { 967203319Sweongyo case SIBA_CC_PMU_DEP_SET: 968203319Sweongyo SIBA_CC_WRITE32(scc, SIBA_CC_PMU_DEPMSK, 969203319Sweongyo depend[i].depend); 970203319Sweongyo break; 971203319Sweongyo case SIBA_CC_PMU_DEP_ADD: 972203319Sweongyo SIBA_CC_SET32(scc, SIBA_CC_PMU_DEPMSK, 973203319Sweongyo depend[i].depend); 974203319Sweongyo break; 975203319Sweongyo case SIBA_CC_PMU_DEP_REMOVE: 976203319Sweongyo SIBA_CC_MASK32(scc, SIBA_CC_PMU_DEPMSK, 977203319Sweongyo ~(depend[i].depend)); 978203319Sweongyo break; 979203319Sweongyo default: 980203319Sweongyo KASSERT(0 == 1, 981203319Sweongyo ("%s:%d: assertion failed", 982203319Sweongyo __func__, __LINE__)); 983203319Sweongyo } 984203319Sweongyo } 985203319Sweongyo } 986203319Sweongyo 987203319Sweongyo if (min) 988203319Sweongyo SIBA_CC_WRITE32(scc, SIBA_CC_PMU_MINRES, min); 989203319Sweongyo if (max) 990203319Sweongyo SIBA_CC_WRITE32(scc, SIBA_CC_PMU_MAXRES, max); 991203319Sweongyo} 992203319Sweongyo 993203319Sweongyostatic void 994203319Sweongyosiba_cc_power_init(struct siba_cc *scc) 995203319Sweongyo{ 996203319Sweongyo struct siba_softc *siba = scc->scc_dev->sd_bus; 997203319Sweongyo int maxfreq; 998203319Sweongyo 999203319Sweongyo if (siba->siba_chipid == 0x4321) { 1000203319Sweongyo if (siba->siba_chiprev == 0) 1001203319Sweongyo SIBA_CC_WRITE32(scc, SIBA_CC_CHIPCTL, 0x3a4); 1002203319Sweongyo else if (siba->siba_chiprev == 1) 1003203319Sweongyo SIBA_CC_WRITE32(scc, SIBA_CC_CHIPCTL, 0xa4); 1004203319Sweongyo } 1005203319Sweongyo 1006203319Sweongyo if ((scc->scc_caps & SIBA_CC_CAPS_PWCTL) == 0) 1007203319Sweongyo return; 1008203319Sweongyo 1009203319Sweongyo if (scc->scc_dev->sd_id.sd_rev >= 10) 1010203319Sweongyo SIBA_CC_WRITE32(scc, SIBA_CC_CLKSYSCTL, 1011203319Sweongyo (SIBA_CC_READ32(scc, SIBA_CC_CLKSYSCTL) & 1012203319Sweongyo 0xffff) | 0x40000); 1013203319Sweongyo else { 1014203319Sweongyo maxfreq = siba_cc_clockfreq(scc, 1); 1015203319Sweongyo SIBA_CC_WRITE32(scc, SIBA_CC_PLLONDELAY, 1016203319Sweongyo (maxfreq * 150 + 999999) / 1000000); 1017203319Sweongyo SIBA_CC_WRITE32(scc, SIBA_CC_FREFSELDELAY, 1018203319Sweongyo (maxfreq * 15 + 999999) / 1000000); 1019203319Sweongyo } 1020203319Sweongyo} 1021203319Sweongyo 1022203319Sweongyostatic void 1023203319Sweongyosiba_cc_powerup_delay(struct siba_cc *scc) 1024203319Sweongyo{ 1025203319Sweongyo struct siba_softc *siba = scc->scc_dev->sd_bus; 1026203319Sweongyo int min; 1027203319Sweongyo 1028203319Sweongyo if (siba->siba_type != SIBA_TYPE_PCI || 1029203319Sweongyo !(scc->scc_caps & SIBA_CC_CAPS_PWCTL)) 1030203319Sweongyo return; 1031203319Sweongyo 1032203319Sweongyo min = siba_cc_clockfreq(scc, 0); 1033203319Sweongyo scc->scc_powerup_delay = 1034203319Sweongyo (((SIBA_CC_READ32(scc, SIBA_CC_PLLONDELAY) + 2) * 1000000) + 1035203319Sweongyo (min - 1)) / min; 1036203319Sweongyo} 1037203319Sweongyo 1038203319Sweongyostatic int 1039203319Sweongyosiba_cc_clockfreq(struct siba_cc *scc, int max) 1040203319Sweongyo{ 1041203319Sweongyo enum siba_clksrc src; 1042203319Sweongyo int div = 1, limit = 0; 1043203319Sweongyo 1044203319Sweongyo src = siba_cc_clksrc(scc); 1045203319Sweongyo if (scc->scc_dev->sd_id.sd_rev < 6) { 1046203319Sweongyo div = (src == SIBA_CC_CLKSRC_PCI) ? 64 : 1047203319Sweongyo (src == SIBA_CC_CLKSRC_CRYSTAL) ? 32 : 1; 1048203319Sweongyo KASSERT(div != 1, 1049203319Sweongyo ("%s: unknown clock %d", __func__, src)); 1050203319Sweongyo } else if (scc->scc_dev->sd_id.sd_rev < 10) { 1051203319Sweongyo switch (src) { 1052203319Sweongyo case SIBA_CC_CLKSRC_CRYSTAL: 1053203319Sweongyo case SIBA_CC_CLKSRC_PCI: 1054203319Sweongyo div = ((SIBA_CC_READ32(scc, SIBA_CC_CLKSLOW) >> 16) + 1055203319Sweongyo 1) * 4; 1056203319Sweongyo break; 1057203319Sweongyo case SIBA_CC_CLKSRC_LOWPW: 1058203319Sweongyo break; 1059203319Sweongyo } 1060203319Sweongyo } else 1061203319Sweongyo div = ((SIBA_CC_READ32(scc, SIBA_CC_CLKSYSCTL) >> 16) + 1) * 4; 1062203319Sweongyo 1063203319Sweongyo switch (src) { 1064203319Sweongyo case SIBA_CC_CLKSRC_CRYSTAL: 1065203319Sweongyo limit = (max) ? 20200000 : 19800000; 1066203319Sweongyo break; 1067203319Sweongyo case SIBA_CC_CLKSRC_LOWPW: 1068203319Sweongyo limit = (max) ? 43000 : 25000; 1069203319Sweongyo break; 1070203319Sweongyo case SIBA_CC_CLKSRC_PCI: 1071203319Sweongyo limit = (max) ? 34000000 : 25000000; 1072203319Sweongyo break; 1073203319Sweongyo } 1074203319Sweongyo 1075203319Sweongyo return (limit / div); 1076203319Sweongyo} 1077203319Sweongyo 1078203319Sweongyostatic void 1079203319Sweongyosiba_cc_pmu1_pll0_init(struct siba_cc *scc, uint32_t freq) 1080203319Sweongyo{ 1081203319Sweongyo struct siba_dev_softc *sd = scc->scc_dev; 1082203319Sweongyo struct siba_softc *siba = sd->sd_bus; 1083203319Sweongyo const struct siba_cc_pmu1_plltab *e = NULL; 1084203319Sweongyo uint32_t bufsth = 0, pll, pmu; 1085203319Sweongyo unsigned int i; 1086203319Sweongyo 1087203319Sweongyo KASSERT(freq == 0, ("%s:%d: assertion vail", __func__, __LINE__)); 1088203319Sweongyo if (siba->siba_chipid == 0x4312) { 1089203319Sweongyo scc->scc_pmu.freq = 20000; 1090203319Sweongyo return; 1091203319Sweongyo } 1092203319Sweongyo 1093203319Sweongyo e = siba_cc_pmu1_plltab_find(SIBA_CC_PMU1_DEFAULT_FREQ); 1094203319Sweongyo KASSERT(e != NULL, ("%s:%d: assertion vail", __func__, __LINE__)); 1095203319Sweongyo scc->scc_pmu.freq = e->freq; 1096203319Sweongyo 1097203319Sweongyo pmu = SIBA_CC_READ32(scc, SIBA_CC_PMUCTL); 1098203319Sweongyo if (SIBA_CC_PMUCTL_XF_VAL(pmu) == e->xf) 1099203319Sweongyo return; 1100203319Sweongyo 1101203319Sweongyo DPRINTF(siba, SIBA_DEBUG_PLL, "change PLL value to %u.%03u MHz\n", 1102203319Sweongyo (e->freq / 1000), (e->freq % 1000)); 1103203319Sweongyo 1104203319Sweongyo /* turn PLL off */ 1105203319Sweongyo switch (siba->siba_chipid) { 1106203319Sweongyo case 0x4325: 1107203319Sweongyo bufsth = 0x222222; 1108203319Sweongyo SIBA_CC_MASK32(scc, SIBA_CC_PMU_MINRES, 1109203319Sweongyo ~((1 << SIBA_CC_PMU_4325_BBPLL_PWR) | 1110203319Sweongyo (1 << SIBA_CC_PMU_4325_HT))); 1111203319Sweongyo SIBA_CC_MASK32(scc, SIBA_CC_PMU_MAXRES, 1112203319Sweongyo ~((1 << SIBA_CC_PMU_4325_BBPLL_PWR) | 1113203319Sweongyo (1 << SIBA_CC_PMU_4325_HT))); 1114203319Sweongyo break; 1115203319Sweongyo default: 1116203319Sweongyo KASSERT(0 == 1, 1117203319Sweongyo ("%s:%d: assertion failed", __func__, __LINE__)); 1118203319Sweongyo } 1119203319Sweongyo for (i = 0; i < 1500; i++) { 1120203319Sweongyo if (!(SIBA_CC_READ32(scc, SIBA_CC_CLKCTLSTATUS) & 1121203319Sweongyo SIBA_CC_CLKCTLSTATUS_HT)) 1122203319Sweongyo break; 1123203319Sweongyo DELAY(10); 1124203319Sweongyo } 1125203319Sweongyo if (SIBA_CC_READ32(scc, SIBA_CC_CLKCTLSTATUS) & SIBA_CC_CLKCTLSTATUS_HT) 1126203319Sweongyo device_printf(siba->siba_dev, "failed to turn PLL off!\n"); 1127203319Sweongyo 1128203319Sweongyo pll = siba_cc_pll_read(scc, SIBA_CC_PMU1_PLL0); 1129203319Sweongyo pll &= ~(SIBA_CC_PMU1_PLL0_P1DIV | SIBA_CC_PMU1_PLL0_P2DIV); 1130203319Sweongyo pll |= ((uint32_t)e->p1div << 20) & SIBA_CC_PMU1_PLL0_P1DIV; 1131203319Sweongyo pll |= ((uint32_t)e->p2div << 24) & SIBA_CC_PMU1_PLL0_P2DIV; 1132203319Sweongyo siba_cc_pll_write(scc, SIBA_CC_PMU1_PLL0, pll); 1133203319Sweongyo 1134203319Sweongyo pll = siba_cc_pll_read(scc, SIBA_CC_PMU1_PLL2); 1135203319Sweongyo pll &= ~(SIBA_CC_PMU1_PLL2_NDIVINT | SIBA_CC_PMU1_PLL2_NDIVMODE); 1136203319Sweongyo pll |= ((uint32_t)e->ndiv_int << 20) & SIBA_CC_PMU1_PLL2_NDIVINT; 1137203319Sweongyo pll |= (1 << 17) & SIBA_CC_PMU1_PLL2_NDIVMODE; 1138203319Sweongyo siba_cc_pll_write(scc, SIBA_CC_PMU1_PLL2, pll); 1139203319Sweongyo 1140203319Sweongyo pll = siba_cc_pll_read(scc, SIBA_CC_PMU1_PLL3); 1141203319Sweongyo pll &= ~SIBA_CC_PMU1_PLL3_NDIVFRAC; 1142203319Sweongyo pll |= ((uint32_t)e->ndiv_frac << 0) & SIBA_CC_PMU1_PLL3_NDIVFRAC; 1143203319Sweongyo siba_cc_pll_write(scc, SIBA_CC_PMU1_PLL3, pll); 1144203319Sweongyo 1145203319Sweongyo if (bufsth) { 1146203319Sweongyo pll = siba_cc_pll_read(scc, SIBA_CC_PMU1_PLL5); 1147203319Sweongyo pll &= ~SIBA_CC_PMU1_PLL5_CLKDRV; 1148203319Sweongyo pll |= (bufsth << 8) & SIBA_CC_PMU1_PLL5_CLKDRV; 1149203319Sweongyo siba_cc_pll_write(scc, SIBA_CC_PMU1_PLL5, pll); 1150203319Sweongyo } 1151203319Sweongyo 1152203319Sweongyo pmu = SIBA_CC_READ32(scc, SIBA_CC_PMUCTL); 1153203319Sweongyo pmu &= ~(SIBA_CC_PMUCTL_ILP | SIBA_CC_PMUCTL_XF); 1154203319Sweongyo pmu |= ((((uint32_t)e->freq + 127) / 128 - 1) << 16) & 1155203319Sweongyo SIBA_CC_PMUCTL_ILP; 1156203319Sweongyo pmu |= ((uint32_t)e->xf << 2) & SIBA_CC_PMUCTL_XF; 1157203319Sweongyo SIBA_CC_WRITE32(scc, SIBA_CC_PMUCTL, pmu); 1158203319Sweongyo} 1159203319Sweongyo 1160203319Sweongyostatic void 1161203319Sweongyosiba_cc_pmu0_pll0_init(struct siba_cc *scc, uint32_t xtalfreq) 1162203319Sweongyo{ 1163203319Sweongyo struct siba_dev_softc *sd = scc->scc_dev; 1164203319Sweongyo struct siba_softc *siba = sd->sd_bus; 1165203319Sweongyo const struct siba_cc_pmu0_plltab *e = NULL; 1166203319Sweongyo uint32_t pmu, tmp, pll; 1167203319Sweongyo unsigned int i; 1168203319Sweongyo 1169203319Sweongyo if ((siba->siba_chipid == 0x5354) && !xtalfreq) 1170203319Sweongyo xtalfreq = 25000; 1171203319Sweongyo if (xtalfreq) 1172203319Sweongyo e = siba_cc_pmu0_plltab_findentry(xtalfreq); 1173203319Sweongyo if (!e) 1174203319Sweongyo e = siba_cc_pmu0_plltab_findentry( 1175203319Sweongyo SIBA_CC_PMU0_DEFAULT_XTALFREQ); 1176203319Sweongyo KASSERT(e != NULL, ("%s:%d: fail", __func__, __LINE__)); 1177203319Sweongyo xtalfreq = e->freq; 1178203319Sweongyo scc->scc_pmu.freq = e->freq; 1179203319Sweongyo 1180203319Sweongyo pmu = SIBA_CC_READ32(scc, SIBA_CC_PMUCTL); 1181203319Sweongyo if (((pmu & SIBA_CC_PMUCTL_XF) >> 2) == e->xf) 1182203319Sweongyo return; 1183203319Sweongyo 1184203319Sweongyo DPRINTF(siba, SIBA_DEBUG_PLL, "change PLL value to %u.%03u mhz\n", 1185203319Sweongyo (xtalfreq / 1000), (xtalfreq % 1000)); 1186203319Sweongyo 1187203319Sweongyo KASSERT(siba->siba_chipid == 0x4328 || siba->siba_chipid == 0x5354, 1188203319Sweongyo ("%s:%d: fail", __func__, __LINE__)); 1189203319Sweongyo 1190203319Sweongyo switch (siba->siba_chipid) { 1191203319Sweongyo case 0x4328: 1192203319Sweongyo SIBA_CC_MASK32(scc, SIBA_CC_PMU_MINRES, 1193203319Sweongyo ~(1 << SIBA_CC_PMU_4328_BB_PLL_PU)); 1194203319Sweongyo SIBA_CC_MASK32(scc, SIBA_CC_PMU_MAXRES, 1195203319Sweongyo ~(1 << SIBA_CC_PMU_4328_BB_PLL_PU)); 1196203319Sweongyo break; 1197203319Sweongyo case 0x5354: 1198203319Sweongyo SIBA_CC_MASK32(scc, SIBA_CC_PMU_MINRES, 1199203319Sweongyo ~(1 << SIBA_CC_PMU_5354_BB_PLL_PU)); 1200203319Sweongyo SIBA_CC_MASK32(scc, SIBA_CC_PMU_MAXRES, 1201203319Sweongyo ~(1 << SIBA_CC_PMU_5354_BB_PLL_PU)); 1202203319Sweongyo break; 1203203319Sweongyo } 1204203319Sweongyo for (i = 1500; i; i--) { 1205203319Sweongyo tmp = SIBA_CC_READ32(scc, SIBA_CC_CLKCTLSTATUS); 1206203319Sweongyo if (!(tmp & SIBA_CC_CLKCTLSTATUS_HT)) 1207203319Sweongyo break; 1208203319Sweongyo DELAY(10); 1209203319Sweongyo } 1210203319Sweongyo tmp = SIBA_CC_READ32(scc, SIBA_CC_CLKCTLSTATUS); 1211203319Sweongyo if (tmp & SIBA_CC_CLKCTLSTATUS_HT) 1212203319Sweongyo device_printf(siba->siba_dev, "failed to turn PLL off!\n"); 1213203319Sweongyo 1214203319Sweongyo /* set PDIV */ 1215203319Sweongyo pll = siba_cc_pll_read(scc, SIBA_CC_PMU0_PLL0); 1216203319Sweongyo if (xtalfreq >= SIBA_CC_PMU0_PLL0_PDIV_FREQ) 1217203319Sweongyo pll |= SIBA_CC_PMU0_PLL0_PDIV_MSK; 1218203319Sweongyo else 1219203319Sweongyo pll &= ~SIBA_CC_PMU0_PLL0_PDIV_MSK; 1220203319Sweongyo siba_cc_pll_write(scc, SIBA_CC_PMU0_PLL0, pll); 1221203319Sweongyo 1222203319Sweongyo /* set WILD */ 1223203319Sweongyo pll = siba_cc_pll_read(scc, SIBA_CC_PMU0_PLL1); 1224203319Sweongyo pll &= ~(SIBA_CC_PMU0_PLL1_STOPMOD | SIBA_CC_PMU0_PLL1_IMSK | 1225203319Sweongyo SIBA_CC_PMU0_PLL1_FMSK); 1226203319Sweongyo pll |= ((uint32_t)e->wb_int << 28) & SIBA_CC_PMU0_PLL1_IMSK; 1227203319Sweongyo pll |= ((uint32_t)e->wb_frac << 8) & SIBA_CC_PMU0_PLL1_FMSK; 1228203319Sweongyo if (e->wb_frac == 0) 1229203319Sweongyo pll |= SIBA_CC_PMU0_PLL1_STOPMOD; 1230203319Sweongyo siba_cc_pll_write(scc, SIBA_CC_PMU0_PLL1, pll); 1231203319Sweongyo 1232203319Sweongyo /* set WILD */ 1233203319Sweongyo pll = siba_cc_pll_read(scc, SIBA_CC_PMU0_PLL2); 1234203319Sweongyo pll &= ~SIBA_CC_PMU0_PLL2_IMSKHI; 1235203319Sweongyo pll |= (((uint32_t)e->wb_int >> 4) << 0) & SIBA_CC_PMU0_PLL2_IMSKHI; 1236203319Sweongyo siba_cc_pll_write(scc, SIBA_CC_PMU0_PLL2, pll); 1237203319Sweongyo 1238203319Sweongyo /* set freq and divisor. */ 1239203319Sweongyo pmu = SIBA_CC_READ32(scc, SIBA_CC_PMUCTL); 1240203319Sweongyo pmu &= ~SIBA_CC_PMUCTL_ILP; 1241203319Sweongyo pmu |= (((xtalfreq + 127) / 128 - 1) << 16) & SIBA_CC_PMUCTL_ILP; 1242203319Sweongyo pmu &= ~SIBA_CC_PMUCTL_XF; 1243203319Sweongyo pmu |= ((uint32_t)e->xf << 2) & SIBA_CC_PMUCTL_XF; 1244203319Sweongyo SIBA_CC_WRITE32(scc, SIBA_CC_PMUCTL, pmu); 1245203319Sweongyo} 1246203319Sweongyo 1247203319Sweongyostatic enum siba_clksrc 1248203319Sweongyosiba_cc_clksrc(struct siba_cc *scc) 1249203319Sweongyo{ 1250203319Sweongyo struct siba_dev_softc *sd = scc->scc_dev; 1251203319Sweongyo struct siba_softc *siba = sd->sd_bus; 1252203319Sweongyo 1253203319Sweongyo if (sd->sd_id.sd_rev < 6) { 1254203319Sweongyo if (siba->siba_type == SIBA_TYPE_PCI) { 1255203319Sweongyo if (pci_read_config(siba->siba_dev, SIBA_GPIO_OUT, 4) & 1256203319Sweongyo 0x10) 1257203319Sweongyo return (SIBA_CC_CLKSRC_PCI); 1258203319Sweongyo return (SIBA_CC_CLKSRC_CRYSTAL); 1259203319Sweongyo } 1260203319Sweongyo if (siba->siba_type == SIBA_TYPE_SSB || 1261203319Sweongyo siba->siba_type == SIBA_TYPE_PCMCIA) 1262203319Sweongyo return (SIBA_CC_CLKSRC_CRYSTAL); 1263203319Sweongyo } 1264203319Sweongyo if (sd->sd_id.sd_rev < 10) { 1265203319Sweongyo switch (SIBA_CC_READ32(scc, SIBA_CC_CLKSLOW) & 0x7) { 1266203319Sweongyo case 0: 1267203319Sweongyo return (SIBA_CC_CLKSRC_LOWPW); 1268203319Sweongyo case 1: 1269203319Sweongyo return (SIBA_CC_CLKSRC_CRYSTAL); 1270203319Sweongyo case 2: 1271203319Sweongyo return (SIBA_CC_CLKSRC_PCI); 1272203319Sweongyo default: 1273203319Sweongyo break; 1274203319Sweongyo } 1275203319Sweongyo } 1276203319Sweongyo 1277203319Sweongyo return (SIBA_CC_CLKSRC_CRYSTAL); 1278203319Sweongyo} 1279203319Sweongyo 1280203319Sweongyostatic const struct siba_cc_pmu1_plltab * 1281203319Sweongyosiba_cc_pmu1_plltab_find(uint32_t crystalfreq) 1282203319Sweongyo{ 1283203319Sweongyo const struct siba_cc_pmu1_plltab *e; 1284203319Sweongyo unsigned int i; 1285203319Sweongyo 1286203319Sweongyo for (i = 0; i < N(siba_cc_pmu1_plltab); i++) { 1287203319Sweongyo e = &siba_cc_pmu1_plltab[i]; 1288203319Sweongyo if (crystalfreq == e->freq) 1289203319Sweongyo return (e); 1290203319Sweongyo } 1291203319Sweongyo 1292203319Sweongyo return (NULL); 1293203319Sweongyo} 1294203319Sweongyo 1295203319Sweongyostatic uint32_t 1296203319Sweongyosiba_cc_pll_read(struct siba_cc *scc, uint32_t offset) 1297203319Sweongyo{ 1298203319Sweongyo 1299203319Sweongyo SIBA_CC_WRITE32(scc, SIBA_CC_PLLCTL_ADDR, offset); 1300203319Sweongyo return (SIBA_CC_READ32(scc, SIBA_CC_PLLCTL_DATA)); 1301203319Sweongyo} 1302203319Sweongyo 1303203319Sweongyostatic void 1304203319Sweongyosiba_cc_pll_write(struct siba_cc *scc, uint32_t offset, uint32_t value) 1305203319Sweongyo{ 1306203319Sweongyo 1307203319Sweongyo SIBA_CC_WRITE32(scc, SIBA_CC_PLLCTL_ADDR, offset); 1308203319Sweongyo SIBA_CC_WRITE32(scc, SIBA_CC_PLLCTL_DATA, value); 1309203319Sweongyo} 1310203319Sweongyo 1311203319Sweongyostatic const struct siba_cc_pmu0_plltab * 1312203319Sweongyosiba_cc_pmu0_plltab_findentry(uint32_t crystalfreq) 1313203319Sweongyo{ 1314203319Sweongyo const struct siba_cc_pmu0_plltab *e; 1315203319Sweongyo unsigned int i; 1316203319Sweongyo 1317203319Sweongyo for (i = 0; i < N(siba_cc_pmu0_plltab); i++) { 1318203319Sweongyo e = &siba_cc_pmu0_plltab[i]; 1319203319Sweongyo if (e->freq == crystalfreq) 1320203319Sweongyo return (e); 1321203319Sweongyo } 1322203319Sweongyo 1323203319Sweongyo return (NULL); 1324203319Sweongyo} 1325203319Sweongyo 1326203319Sweongyostatic int 1327203319Sweongyosiba_pci_sprom(struct siba_softc *siba, struct siba_sprom *sprom) 1328203319Sweongyo{ 1329203319Sweongyo int error = ENOMEM; 1330203319Sweongyo uint16_t *buf; 1331203319Sweongyo 1332203319Sweongyo buf = malloc(SIBA_SPROMSIZE_R123 * sizeof(uint16_t), 1333203319Sweongyo M_DEVBUF, M_NOWAIT | M_ZERO); 1334203319Sweongyo if (buf == NULL) 1335203319Sweongyo return (ENOMEM); 1336203319Sweongyo siba_sprom_read(siba, buf, SIBA_SPROMSIZE_R123); 1337203319Sweongyo error = sprom_check_crc(buf, siba->siba_spromsize); 1338203319Sweongyo if (error) { 1339203319Sweongyo free(buf, M_DEVBUF); 1340203319Sweongyo buf = malloc(SIBA_SPROMSIZE_R4 * sizeof(uint16_t), 1341203319Sweongyo M_DEVBUF, M_NOWAIT | M_ZERO); 1342203319Sweongyo if (buf == NULL) 1343203319Sweongyo return (ENOMEM); 1344203319Sweongyo siba_sprom_read(siba, buf, SIBA_SPROMSIZE_R4); 1345203319Sweongyo error = sprom_check_crc(buf, siba->siba_spromsize); 1346203319Sweongyo if (error) 1347203319Sweongyo device_printf(siba->siba_dev, "warn: bad SPROM CRC\n"); 1348203319Sweongyo } 1349203319Sweongyo 1350203319Sweongyo bzero(sprom, sizeof(*sprom)); 1351203319Sweongyo 1352203319Sweongyo sprom->rev = buf[siba->siba_spromsize - 1] & 0x00FF; 1353203319Sweongyo DPRINTF(siba, SIBA_DEBUG_SPROM, "SPROM rev %d\n", 1354203319Sweongyo sprom->rev); 1355203319Sweongyo memset(sprom->mac_eth, 0xff, 6); 1356203319Sweongyo memset(sprom->mac_80211a, 0xff, 6); 1357203319Sweongyo if ((siba->siba_chipid & 0xff00) == 0x4400) { 1358203319Sweongyo sprom->rev = 1; 1359203319Sweongyo siba_sprom_r123(sprom, buf); 1360203319Sweongyo } else if (siba->siba_chipid == 0x4321) { 1361203319Sweongyo sprom->rev = 4; 1362203319Sweongyo siba_sprom_r45(sprom, buf); 1363203319Sweongyo } else { 1364203319Sweongyo switch (sprom->rev) { 1365203319Sweongyo case 1: 1366203319Sweongyo case 2: 1367203319Sweongyo case 3: 1368203319Sweongyo siba_sprom_r123(sprom, buf); 1369203319Sweongyo break; 1370203319Sweongyo case 4: 1371203319Sweongyo case 5: 1372203319Sweongyo siba_sprom_r45(sprom, buf); 1373203319Sweongyo break; 1374203319Sweongyo case 8: 1375203319Sweongyo siba_sprom_r8(sprom, buf); 1376203319Sweongyo break; 1377203319Sweongyo default: 1378203319Sweongyo device_printf(siba->siba_dev, 1379203319Sweongyo "unknown SPROM revision %d.\n", sprom->rev); 1380203319Sweongyo siba_sprom_r123(sprom, buf); 1381203319Sweongyo } 1382203319Sweongyo } 1383203319Sweongyo 1384203319Sweongyo if (sprom->bf_lo == 0xffff) 1385203319Sweongyo sprom->bf_lo = 0; 1386203319Sweongyo if (sprom->bf_hi == 0xffff) 1387203319Sweongyo sprom->bf_hi = 0; 1388203319Sweongyo 1389203319Sweongyo free(buf, M_DEVBUF); 1390203319Sweongyo return (error); 1391203319Sweongyo} 1392203319Sweongyo 1393203319Sweongyostatic int 1394203319Sweongyosiba_sprom_read(struct siba_softc *siba, uint16_t *sprom, uint16_t len) 1395203319Sweongyo{ 1396203319Sweongyo int i; 1397203319Sweongyo 1398203319Sweongyo for (i = 0; i < len; i++) 1399203319Sweongyo sprom[i] = SIBA_READ_2(siba, SIBA_SPROM_BASE + (i * 2)); 1400203319Sweongyo 1401203319Sweongyo siba->siba_spromsize = len; 1402203319Sweongyo return (0); 1403203319Sweongyo} 1404203319Sweongyo 1405203319Sweongyostatic int 1406203319Sweongyosprom_check_crc(const uint16_t *sprom, size_t size) 1407203319Sweongyo{ 1408203319Sweongyo int word; 1409203319Sweongyo uint8_t crc0, crc1 = 0xff; 1410203319Sweongyo 1411203319Sweongyo crc0 = (sprom[size - 1] & SIBA_SPROM_REV_CRC) >> 8; 1412203319Sweongyo for (word = 0; word < size - 1; word++) { 1413203319Sweongyo crc1 = siba_crc8(crc1, sprom[word] & 0x00ff); 1414203319Sweongyo crc1 = siba_crc8(crc1, (sprom[word] & 0xff00) >> 8); 1415203319Sweongyo } 1416203319Sweongyo crc1 = siba_crc8(crc1, sprom[size - 1] & 0x00ff); 1417203319Sweongyo crc1 ^= 0xff; 1418203319Sweongyo 1419203319Sweongyo return ((crc0 != crc1) ? EPROTO : 0); 1420203319Sweongyo} 1421203319Sweongyo 1422203319Sweongyostatic uint8_t 1423203319Sweongyosiba_crc8(uint8_t crc, uint8_t data) 1424203319Sweongyo{ 1425203319Sweongyo static const uint8_t ct[] = { 1426203319Sweongyo 0x00, 0xf7, 0xb9, 0x4e, 0x25, 0xd2, 0x9c, 0x6b, 1427203319Sweongyo 0x4a, 0xbd, 0xf3, 0x04, 0x6f, 0x98, 0xd6, 0x21, 1428203319Sweongyo 0x94, 0x63, 0x2d, 0xda, 0xb1, 0x46, 0x08, 0xff, 1429203319Sweongyo 0xde, 0x29, 0x67, 0x90, 0xfb, 0x0c, 0x42, 0xb5, 1430203319Sweongyo 0x7f, 0x88, 0xc6, 0x31, 0x5a, 0xad, 0xe3, 0x14, 1431203319Sweongyo 0x35, 0xc2, 0x8c, 0x7b, 0x10, 0xe7, 0xa9, 0x5e, 1432203319Sweongyo 0xeb, 0x1c, 0x52, 0xa5, 0xce, 0x39, 0x77, 0x80, 1433203319Sweongyo 0xa1, 0x56, 0x18, 0xef, 0x84, 0x73, 0x3d, 0xca, 1434203319Sweongyo 0xfe, 0x09, 0x47, 0xb0, 0xdb, 0x2c, 0x62, 0x95, 1435203319Sweongyo 0xb4, 0x43, 0x0d, 0xfa, 0x91, 0x66, 0x28, 0xdf, 1436203319Sweongyo 0x6a, 0x9d, 0xd3, 0x24, 0x4f, 0xb8, 0xf6, 0x01, 1437203319Sweongyo 0x20, 0xd7, 0x99, 0x6e, 0x05, 0xf2, 0xbc, 0x4b, 1438203319Sweongyo 0x81, 0x76, 0x38, 0xcf, 0xa4, 0x53, 0x1d, 0xea, 1439203319Sweongyo 0xcb, 0x3c, 0x72, 0x85, 0xee, 0x19, 0x57, 0xa0, 1440203319Sweongyo 0x15, 0xe2, 0xac, 0x5b, 0x30, 0xc7, 0x89, 0x7e, 1441203319Sweongyo 0x5f, 0xa8, 0xe6, 0x11, 0x7a, 0x8d, 0xc3, 0x34, 1442203319Sweongyo 0xab, 0x5c, 0x12, 0xe5, 0x8e, 0x79, 0x37, 0xc0, 1443203319Sweongyo 0xe1, 0x16, 0x58, 0xaf, 0xc4, 0x33, 0x7d, 0x8a, 1444203319Sweongyo 0x3f, 0xc8, 0x86, 0x71, 0x1a, 0xed, 0xa3, 0x54, 1445203319Sweongyo 0x75, 0x82, 0xcc, 0x3b, 0x50, 0xa7, 0xe9, 0x1e, 1446203319Sweongyo 0xd4, 0x23, 0x6d, 0x9a, 0xf1, 0x06, 0x48, 0xbf, 1447203319Sweongyo 0x9e, 0x69, 0x27, 0xd0, 0xbb, 0x4c, 0x02, 0xf5, 1448203319Sweongyo 0x40, 0xb7, 0xf9, 0x0e, 0x65, 0x92, 0xdc, 0x2b, 1449203319Sweongyo 0x0a, 0xfd, 0xb3, 0x44, 0x2f, 0xd8, 0x96, 0x61, 1450203319Sweongyo 0x55, 0xa2, 0xec, 0x1b, 0x70, 0x87, 0xc9, 0x3e, 1451203319Sweongyo 0x1f, 0xe8, 0xa6, 0x51, 0x3a, 0xcd, 0x83, 0x74, 1452203319Sweongyo 0xc1, 0x36, 0x78, 0x8f, 0xe4, 0x13, 0x5d, 0xaa, 1453203319Sweongyo 0x8b, 0x7c, 0x32, 0xc5, 0xae, 0x59, 0x17, 0xe0, 1454203319Sweongyo 0x2a, 0xdd, 0x93, 0x64, 0x0f, 0xf8, 0xb6, 0x41, 1455203319Sweongyo 0x60, 0x97, 0xd9, 0x2e, 0x45, 0xb2, 0xfc, 0x0b, 1456203319Sweongyo 0xbe, 0x49, 0x07, 0xf0, 0x9b, 0x6c, 0x22, 0xd5, 1457203319Sweongyo 0xf4, 0x03, 0x4d, 0xba, 0xd1, 0x26, 0x68, 0x9f, 1458203319Sweongyo }; 1459203319Sweongyo return (ct[crc ^ data]); 1460203319Sweongyo} 1461203319Sweongyo 1462203319Sweongyo#define SIBA_LOWEST_SET_BIT(__mask) ((((__mask) - 1) & (__mask)) ^ (__mask)) 1463203319Sweongyo#define SIBA_OFFSET(offset) \ 1464203319Sweongyo (((offset) - SIBA_SPROM_BASE) / sizeof(uint16_t)) 1465203319Sweongyo#define SIBA_SHIFTOUT_SUB(__x, __mask) \ 1466203319Sweongyo (((__x) & (__mask)) / SIBA_LOWEST_SET_BIT(__mask)) 1467203319Sweongyo#define SIBA_SHIFTOUT(_var, _offset, _mask) \ 1468203319Sweongyo out->_var = SIBA_SHIFTOUT_SUB(in[SIBA_OFFSET(_offset)], (_mask)) 1469203944Sweongyo#define SIBA_SHIFTOUT_4(_var, _offset, _mask, _shift) \ 1470203944Sweongyo out->_var = ((((uint32_t)in[SIBA_OFFSET((_offset)+2)] << 16 | \ 1471203944Sweongyo in[SIBA_OFFSET(_offset)]) & (_mask)) >> (_shift)) 1472203319Sweongyo 1473203319Sweongyostatic void 1474203319Sweongyosiba_sprom_r123(struct siba_sprom *out, const uint16_t *in) 1475203319Sweongyo{ 1476203319Sweongyo int i; 1477203319Sweongyo uint16_t v; 1478203319Sweongyo int8_t gain; 1479203319Sweongyo uint16_t loc[3]; 1480203319Sweongyo 1481203319Sweongyo if (out->rev == 3) 1482203319Sweongyo loc[0] = SIBA_SPROM3_MAC_80211BG; 1483203319Sweongyo else { 1484203319Sweongyo loc[0] = SIBA_SPROM1_MAC_80211BG; 1485203319Sweongyo loc[1] = SIBA_SPROM1_MAC_ETH; 1486203319Sweongyo loc[2] = SIBA_SPROM1_MAC_80211A; 1487203319Sweongyo } 1488203319Sweongyo for (i = 0; i < 3; i++) { 1489203319Sweongyo v = in[SIBA_OFFSET(loc[0]) + i]; 1490203319Sweongyo *(((uint16_t *)out->mac_80211bg) + i) = htobe16(v); 1491203319Sweongyo } 1492203319Sweongyo if (out->rev < 3) { 1493203319Sweongyo for (i = 0; i < 3; i++) { 1494203319Sweongyo v = in[SIBA_OFFSET(loc[1]) + i]; 1495203319Sweongyo *(((uint16_t *)out->mac_eth) + i) = htobe16(v); 1496203319Sweongyo } 1497203319Sweongyo for (i = 0; i < 3; i++) { 1498203319Sweongyo v = in[SIBA_OFFSET(loc[2]) + i]; 1499203319Sweongyo *(((uint16_t *)out->mac_80211a) + i) = htobe16(v); 1500203319Sweongyo } 1501203319Sweongyo } 1502203319Sweongyo SIBA_SHIFTOUT(mii_eth0, SIBA_SPROM1_ETHPHY, 1503203319Sweongyo SIBA_SPROM1_ETHPHY_MII_ETH0); 1504203319Sweongyo SIBA_SHIFTOUT(mii_eth1, SIBA_SPROM1_ETHPHY, 1505203319Sweongyo SIBA_SPROM1_ETHPHY_MII_ETH1); 1506203319Sweongyo SIBA_SHIFTOUT(mdio_eth0, SIBA_SPROM1_ETHPHY, 1507203319Sweongyo SIBA_SPROM1_ETHPHY_MDIO_ETH0); 1508203319Sweongyo SIBA_SHIFTOUT(mdio_eth1, SIBA_SPROM1_ETHPHY, 1509203319Sweongyo SIBA_SPROM1_ETHPHY_MDIO_ETH1); 1510203319Sweongyo SIBA_SHIFTOUT(brev, SIBA_SPROM1_BOARDINFO, SIBA_SPROM1_BOARDINFO_BREV); 1511203319Sweongyo SIBA_SHIFTOUT(ccode, SIBA_SPROM1_BOARDINFO, 1512203319Sweongyo SIBA_SPROM1_BOARDINFO_CCODE); 1513203319Sweongyo SIBA_SHIFTOUT(ant_a, SIBA_SPROM1_BOARDINFO, SIBA_SPROM1_BOARDINFO_ANTA); 1514203319Sweongyo SIBA_SHIFTOUT(ant_bg, SIBA_SPROM1_BOARDINFO, 1515203319Sweongyo SIBA_SPROM1_BOARDINFO_ANTBG); 1516203319Sweongyo SIBA_SHIFTOUT(pa0b0, SIBA_SPROM1_PA0B0, 0xffff); 1517203319Sweongyo SIBA_SHIFTOUT(pa0b1, SIBA_SPROM1_PA0B1, 0xffff); 1518203319Sweongyo SIBA_SHIFTOUT(pa0b2, SIBA_SPROM1_PA0B2, 0xffff); 1519203319Sweongyo SIBA_SHIFTOUT(pa1b0, SIBA_SPROM1_PA1B0, 0xffff); 1520203319Sweongyo SIBA_SHIFTOUT(pa1b1, SIBA_SPROM1_PA1B1, 0xffff); 1521203319Sweongyo SIBA_SHIFTOUT(pa1b2, SIBA_SPROM1_PA1B2, 0xffff); 1522203319Sweongyo SIBA_SHIFTOUT(gpio0, SIBA_SPROM1_GPIOA, SIBA_SPROM1_GPIOA_P0); 1523203319Sweongyo SIBA_SHIFTOUT(gpio1, SIBA_SPROM1_GPIOA, SIBA_SPROM1_GPIOA_P1); 1524203319Sweongyo SIBA_SHIFTOUT(gpio2, SIBA_SPROM1_GPIOB, SIBA_SPROM1_GPIOB_P2); 1525203319Sweongyo SIBA_SHIFTOUT(gpio3, SIBA_SPROM1_GPIOB, SIBA_SPROM1_GPIOB_P3); 1526203944Sweongyo 1527203319Sweongyo SIBA_SHIFTOUT(maxpwr_a, SIBA_SPROM1_MAXPWR, SIBA_SPROM1_MAXPWR_A); 1528203319Sweongyo SIBA_SHIFTOUT(maxpwr_bg, SIBA_SPROM1_MAXPWR, SIBA_SPROM1_MAXPWR_BG); 1529203319Sweongyo SIBA_SHIFTOUT(tssi_a, SIBA_SPROM1_TSSI, SIBA_SPROM1_TSSI_A); 1530203319Sweongyo SIBA_SHIFTOUT(tssi_bg, SIBA_SPROM1_TSSI, SIBA_SPROM1_TSSI_BG); 1531203319Sweongyo SIBA_SHIFTOUT(bf_lo, SIBA_SPROM1_BFLOW, 0xffff); 1532203319Sweongyo if (out->rev >= 2) 1533203319Sweongyo SIBA_SHIFTOUT(bf_hi, SIBA_SPROM2_BFHIGH, 0xffff); 1534203319Sweongyo 1535203319Sweongyo /* antenna gain */ 1536203319Sweongyo gain = siba_sprom_r123_antgain(out->rev, in, SIBA_SPROM1_AGAIN_BG, 0); 1537203319Sweongyo out->again.ghz24.a0 = out->again.ghz24.a1 = gain; 1538203319Sweongyo out->again.ghz24.a2 = out->again.ghz24.a3 = gain; 1539203319Sweongyo gain = siba_sprom_r123_antgain(out->rev, in, SIBA_SPROM1_AGAIN_A, 8); 1540203319Sweongyo out->again.ghz5.a0 = out->again.ghz5.a1 = gain; 1541203319Sweongyo out->again.ghz5.a2 = out->again.ghz5.a3 = gain; 1542203319Sweongyo} 1543203319Sweongyo 1544203319Sweongyostatic void 1545203319Sweongyosiba_sprom_r45(struct siba_sprom *out, const uint16_t *in) 1546203319Sweongyo{ 1547203319Sweongyo int i; 1548203319Sweongyo uint16_t v; 1549203319Sweongyo uint16_t mac_80211bg_offset; 1550203319Sweongyo 1551203319Sweongyo if (out->rev == 4) 1552203319Sweongyo mac_80211bg_offset = SIBA_SPROM4_MAC_80211BG; 1553203319Sweongyo else 1554203319Sweongyo mac_80211bg_offset = SIBA_SPROM5_MAC_80211BG; 1555203319Sweongyo for (i = 0; i < 3; i++) { 1556203319Sweongyo v = in[SIBA_OFFSET(mac_80211bg_offset) + i]; 1557203319Sweongyo *(((uint16_t *)out->mac_80211bg) + i) = htobe16(v); 1558203319Sweongyo } 1559203319Sweongyo SIBA_SHIFTOUT(mii_eth0, SIBA_SPROM4_ETHPHY, SIBA_SPROM4_ETHPHY_ET0A); 1560203319Sweongyo SIBA_SHIFTOUT(mii_eth1, SIBA_SPROM4_ETHPHY, SIBA_SPROM4_ETHPHY_ET1A); 1561203319Sweongyo if (out->rev == 4) { 1562203319Sweongyo SIBA_SHIFTOUT(ccode, SIBA_SPROM4_CCODE, 0xffff); 1563203319Sweongyo SIBA_SHIFTOUT(bf_lo, SIBA_SPROM4_BFLOW, 0xffff); 1564203319Sweongyo SIBA_SHIFTOUT(bf_hi, SIBA_SPROM4_BFHIGH, 0xffff); 1565203319Sweongyo } else { 1566203319Sweongyo SIBA_SHIFTOUT(ccode, SIBA_SPROM5_CCODE, 0xffff); 1567203319Sweongyo SIBA_SHIFTOUT(bf_lo, SIBA_SPROM5_BFLOW, 0xffff); 1568203319Sweongyo SIBA_SHIFTOUT(bf_hi, SIBA_SPROM5_BFHIGH, 0xffff); 1569203319Sweongyo } 1570203319Sweongyo SIBA_SHIFTOUT(ant_a, SIBA_SPROM4_ANTAVAIL, SIBA_SPROM4_ANTAVAIL_A); 1571203319Sweongyo SIBA_SHIFTOUT(ant_bg, SIBA_SPROM4_ANTAVAIL, SIBA_SPROM4_ANTAVAIL_BG); 1572203319Sweongyo SIBA_SHIFTOUT(maxpwr_bg, SIBA_SPROM4_MAXP_BG, SIBA_SPROM4_MAXP_BG_MASK); 1573203319Sweongyo SIBA_SHIFTOUT(tssi_bg, SIBA_SPROM4_MAXP_BG, SIBA_SPROM4_TSSI_BG); 1574203319Sweongyo SIBA_SHIFTOUT(maxpwr_a, SIBA_SPROM4_MAXP_A, SIBA_SPROM4_MAXP_A_MASK); 1575203319Sweongyo SIBA_SHIFTOUT(tssi_a, SIBA_SPROM4_MAXP_A, SIBA_SPROM4_TSSI_A); 1576203319Sweongyo if (out->rev == 4) { 1577203319Sweongyo SIBA_SHIFTOUT(gpio0, SIBA_SPROM4_GPIOA, SIBA_SPROM4_GPIOA_P0); 1578203319Sweongyo SIBA_SHIFTOUT(gpio1, SIBA_SPROM4_GPIOA, SIBA_SPROM4_GPIOA_P1); 1579203319Sweongyo SIBA_SHIFTOUT(gpio2, SIBA_SPROM4_GPIOB, SIBA_SPROM4_GPIOB_P2); 1580203319Sweongyo SIBA_SHIFTOUT(gpio3, SIBA_SPROM4_GPIOB, SIBA_SPROM4_GPIOB_P3); 1581203319Sweongyo } else { 1582203319Sweongyo SIBA_SHIFTOUT(gpio0, SIBA_SPROM5_GPIOA, SIBA_SPROM5_GPIOA_P0); 1583203319Sweongyo SIBA_SHIFTOUT(gpio1, SIBA_SPROM5_GPIOA, SIBA_SPROM5_GPIOA_P1); 1584203319Sweongyo SIBA_SHIFTOUT(gpio2, SIBA_SPROM5_GPIOB, SIBA_SPROM5_GPIOB_P2); 1585203319Sweongyo SIBA_SHIFTOUT(gpio3, SIBA_SPROM5_GPIOB, SIBA_SPROM5_GPIOB_P3); 1586203319Sweongyo } 1587203319Sweongyo 1588203319Sweongyo /* antenna gain */ 1589203319Sweongyo SIBA_SHIFTOUT(again.ghz24.a0, SIBA_SPROM4_AGAIN01, SIBA_SPROM4_AGAIN0); 1590203319Sweongyo SIBA_SHIFTOUT(again.ghz24.a1, SIBA_SPROM4_AGAIN01, SIBA_SPROM4_AGAIN1); 1591203319Sweongyo SIBA_SHIFTOUT(again.ghz24.a2, SIBA_SPROM4_AGAIN23, SIBA_SPROM4_AGAIN2); 1592203319Sweongyo SIBA_SHIFTOUT(again.ghz24.a3, SIBA_SPROM4_AGAIN23, SIBA_SPROM4_AGAIN3); 1593203319Sweongyo bcopy(&out->again.ghz24, &out->again.ghz5, sizeof(out->again.ghz5)); 1594203319Sweongyo} 1595203319Sweongyo 1596203319Sweongyostatic void 1597203319Sweongyosiba_sprom_r8(struct siba_sprom *out, const uint16_t *in) 1598203319Sweongyo{ 1599203319Sweongyo int i; 1600203319Sweongyo uint16_t v; 1601203319Sweongyo 1602203319Sweongyo for (i = 0; i < 3; i++) { 1603203944Sweongyo v = in[SIBA_OFFSET(SIBA_SPROM8_MAC_80211BG) + i]; 1604203319Sweongyo *(((uint16_t *)out->mac_80211bg) + i) = htobe16(v); 1605203319Sweongyo } 1606203319Sweongyo SIBA_SHIFTOUT(ccode, SIBA_SPROM8_CCODE, 0xffff); 1607203319Sweongyo SIBA_SHIFTOUT(bf_lo, SIBA_SPROM8_BFLOW, 0xffff); 1608203319Sweongyo SIBA_SHIFTOUT(bf_hi, SIBA_SPROM8_BFHIGH, 0xffff); 1609203944Sweongyo SIBA_SHIFTOUT(bf2_lo, SIBA_SPROM8_BFL2LO, 0xffff); 1610203944Sweongyo SIBA_SHIFTOUT(bf2_hi, SIBA_SPROM8_BFL2HI, 0xffff); 1611203319Sweongyo SIBA_SHIFTOUT(ant_a, SIBA_SPROM8_ANTAVAIL, SIBA_SPROM8_ANTAVAIL_A); 1612203319Sweongyo SIBA_SHIFTOUT(ant_bg, SIBA_SPROM8_ANTAVAIL, SIBA_SPROM8_ANTAVAIL_BG); 1613203319Sweongyo SIBA_SHIFTOUT(maxpwr_bg, SIBA_SPROM8_MAXP_BG, SIBA_SPROM8_MAXP_BG_MASK); 1614203319Sweongyo SIBA_SHIFTOUT(tssi_bg, SIBA_SPROM8_MAXP_BG, SIBA_SPROM8_TSSI_BG); 1615203319Sweongyo SIBA_SHIFTOUT(maxpwr_a, SIBA_SPROM8_MAXP_A, SIBA_SPROM8_MAXP_A_MASK); 1616203319Sweongyo SIBA_SHIFTOUT(tssi_a, SIBA_SPROM8_MAXP_A, SIBA_SPROM8_TSSI_A); 1617203944Sweongyo SIBA_SHIFTOUT(maxpwr_ah, SIBA_SPROM8_MAXP_AHL, 1618203944Sweongyo SIBA_SPROM8_MAXP_AH_MASK); 1619203944Sweongyo SIBA_SHIFTOUT(maxpwr_al, SIBA_SPROM8_MAXP_AHL, 1620203944Sweongyo SIBA_SPROM8_MAXP_AL_MASK); 1621203319Sweongyo SIBA_SHIFTOUT(gpio0, SIBA_SPROM8_GPIOA, SIBA_SPROM8_GPIOA_P0); 1622203319Sweongyo SIBA_SHIFTOUT(gpio1, SIBA_SPROM8_GPIOA, SIBA_SPROM8_GPIOA_P1); 1623203319Sweongyo SIBA_SHIFTOUT(gpio2, SIBA_SPROM8_GPIOB, SIBA_SPROM8_GPIOB_P2); 1624203319Sweongyo SIBA_SHIFTOUT(gpio3, SIBA_SPROM8_GPIOB, SIBA_SPROM8_GPIOB_P3); 1625203944Sweongyo SIBA_SHIFTOUT(tri2g, SIBA_SPROM8_TRI25G, SIBA_SPROM8_TRI2G); 1626203944Sweongyo SIBA_SHIFTOUT(tri5g, SIBA_SPROM8_TRI25G, SIBA_SPROM8_TRI5G); 1627203944Sweongyo SIBA_SHIFTOUT(tri5gl, SIBA_SPROM8_TRI5GHL, SIBA_SPROM8_TRI5GL); 1628203944Sweongyo SIBA_SHIFTOUT(tri5gh, SIBA_SPROM8_TRI5GHL, SIBA_SPROM8_TRI5GH); 1629203944Sweongyo SIBA_SHIFTOUT(rxpo2g, SIBA_SPROM8_RXPO, SIBA_SPROM8_RXPO2G); 1630203944Sweongyo SIBA_SHIFTOUT(rxpo5g, SIBA_SPROM8_RXPO, SIBA_SPROM8_RXPO5G); 1631203944Sweongyo SIBA_SHIFTOUT(rssismf2g, SIBA_SPROM8_RSSIPARM2G, SIBA_SPROM8_RSSISMF2G); 1632203944Sweongyo SIBA_SHIFTOUT(rssismc2g, SIBA_SPROM8_RSSIPARM2G, SIBA_SPROM8_RSSISMC2G); 1633203944Sweongyo SIBA_SHIFTOUT(rssisav2g, SIBA_SPROM8_RSSIPARM2G, SIBA_SPROM8_RSSISAV2G); 1634203944Sweongyo SIBA_SHIFTOUT(bxa2g, SIBA_SPROM8_RSSIPARM2G, SIBA_SPROM8_BXA2G); 1635203944Sweongyo SIBA_SHIFTOUT(rssismf5g, SIBA_SPROM8_RSSIPARM5G, SIBA_SPROM8_RSSISMF5G); 1636203944Sweongyo SIBA_SHIFTOUT(rssismc5g, SIBA_SPROM8_RSSIPARM5G, SIBA_SPROM8_RSSISMC5G); 1637203944Sweongyo SIBA_SHIFTOUT(rssisav5g, SIBA_SPROM8_RSSIPARM5G, SIBA_SPROM8_RSSISAV5G); 1638203944Sweongyo SIBA_SHIFTOUT(bxa5g, SIBA_SPROM8_RSSIPARM5G, SIBA_SPROM8_BXA5G); 1639203319Sweongyo 1640203944Sweongyo SIBA_SHIFTOUT(pa0b0, SIBA_SPROM8_PA0B0, 0xffff); 1641203944Sweongyo SIBA_SHIFTOUT(pa0b1, SIBA_SPROM8_PA0B1, 0xffff); 1642203944Sweongyo SIBA_SHIFTOUT(pa0b2, SIBA_SPROM8_PA0B2, 0xffff); 1643203944Sweongyo SIBA_SHIFTOUT(pa1b0, SIBA_SPROM8_PA1B0, 0xffff); 1644203944Sweongyo SIBA_SHIFTOUT(pa1b1, SIBA_SPROM8_PA1B1, 0xffff); 1645203944Sweongyo SIBA_SHIFTOUT(pa1b2, SIBA_SPROM8_PA1B2, 0xffff); 1646203944Sweongyo SIBA_SHIFTOUT(pa1lob0, SIBA_SPROM8_PA1LOB0, 0xffff); 1647203944Sweongyo SIBA_SHIFTOUT(pa1lob1, SIBA_SPROM8_PA1LOB1, 0xffff); 1648203944Sweongyo SIBA_SHIFTOUT(pa1lob2, SIBA_SPROM8_PA1LOB2, 0xffff); 1649203944Sweongyo SIBA_SHIFTOUT(pa1hib0, SIBA_SPROM8_PA1HIB0, 0xffff); 1650203944Sweongyo SIBA_SHIFTOUT(pa1hib1, SIBA_SPROM8_PA1HIB1, 0xffff); 1651203944Sweongyo SIBA_SHIFTOUT(pa1hib2, SIBA_SPROM8_PA1HIB2, 0xffff); 1652203944Sweongyo SIBA_SHIFTOUT(cck2gpo, SIBA_SPROM8_CCK2GPO, 0xffff); 1653203944Sweongyo 1654203944Sweongyo SIBA_SHIFTOUT_4(ofdm2gpo, SIBA_SPROM8_OFDM2GPO, 0xffffffff, 0); 1655203944Sweongyo SIBA_SHIFTOUT_4(ofdm5glpo, SIBA_SPROM8_OFDM5GLPO, 0xffffffff, 0); 1656203944Sweongyo SIBA_SHIFTOUT_4(ofdm5gpo, SIBA_SPROM8_OFDM5GPO, 0xffffffff, 0); 1657203944Sweongyo SIBA_SHIFTOUT_4(ofdm5ghpo, SIBA_SPROM8_OFDM5GHPO, 0xffffffff, 0); 1658203944Sweongyo 1659203319Sweongyo /* antenna gain */ 1660203319Sweongyo SIBA_SHIFTOUT(again.ghz24.a0, SIBA_SPROM8_AGAIN01, SIBA_SPROM8_AGAIN0); 1661203319Sweongyo SIBA_SHIFTOUT(again.ghz24.a1, SIBA_SPROM8_AGAIN01, SIBA_SPROM8_AGAIN1); 1662203319Sweongyo SIBA_SHIFTOUT(again.ghz24.a2, SIBA_SPROM8_AGAIN23, SIBA_SPROM8_AGAIN2); 1663203319Sweongyo SIBA_SHIFTOUT(again.ghz24.a3, SIBA_SPROM8_AGAIN23, SIBA_SPROM8_AGAIN3); 1664203319Sweongyo bcopy(&out->again.ghz24, &out->again.ghz5, sizeof(out->again.ghz5)); 1665203319Sweongyo} 1666203319Sweongyo 1667203319Sweongyostatic int8_t 1668203319Sweongyosiba_sprom_r123_antgain(uint8_t sprom_revision, const uint16_t *in, 1669203319Sweongyo uint16_t mask, uint16_t shift) 1670203319Sweongyo{ 1671203319Sweongyo uint16_t v; 1672203319Sweongyo uint8_t gain; 1673203319Sweongyo 1674203319Sweongyo v = in[SIBA_OFFSET(SIBA_SPROM1_AGAIN)]; 1675203319Sweongyo gain = (v & mask) >> shift; 1676203319Sweongyo gain = (gain == 0xff) ? 2 : (sprom_revision == 1) ? gain << 2 : 1677203319Sweongyo ((gain & 0xc0) >> 6) | ((gain & 0x3f) << 2); 1678203319Sweongyo 1679203319Sweongyo return ((int8_t)gain); 1680203319Sweongyo} 1681203319Sweongyo 1682203319Sweongyo#undef SIBA_LOWEST_SET_BIT 1683203319Sweongyo#undef SIBA_OFFSET 1684203319Sweongyo#undef SIBA_SHIFTOUT_SUB 1685203319Sweongyo#undef SIBA_SHIFTOUT 1686203319Sweongyo 1687203319Sweongyoint 1688203319Sweongyosiba_powerdown(struct siba_softc *siba) 1689203319Sweongyo{ 1690203319Sweongyo struct siba_cc *scc; 1691203319Sweongyo 1692203319Sweongyo if (siba->siba_type == SIBA_TYPE_SSB) 1693203319Sweongyo return (0); 1694203319Sweongyo 1695203319Sweongyo scc = &siba->siba_cc; 1696203319Sweongyo if (!scc->scc_dev || scc->scc_dev->sd_id.sd_rev < 5) 1697203319Sweongyo return (0); 1698203319Sweongyo siba_cc_clock(scc, SIBA_CLOCK_SLOW); 1699203319Sweongyo siba_pci_gpio(siba, SIBA_GPIO_CRYSTAL | SIBA_GPIO_PLL, 0); 1700203319Sweongyo return (0); 1701203319Sweongyo} 1702203319Sweongyo 1703203319Sweongyostatic void 1704203319Sweongyosiba_pcicore_init(struct siba_pci *spc) 1705203319Sweongyo{ 1706203319Sweongyo struct siba_dev_softc *sd = spc->spc_dev; 1707203319Sweongyo struct siba_softc *siba; 1708203319Sweongyo 1709203319Sweongyo if (sd == NULL) 1710203319Sweongyo return; 1711203319Sweongyo 1712203319Sweongyo siba = sd->sd_bus; 1713203319Sweongyo if (!siba_dev_isup(sd)) 1714203319Sweongyo siba_dev_up(sd, 0); 1715203319Sweongyo 1716203319Sweongyo KASSERT(spc->spc_hostmode == 0, 1717203319Sweongyo ("%s:%d: hostmode", __func__, __LINE__)); 1718203319Sweongyo /* disable PCI interrupt */ 1719203319Sweongyo siba_write_4(spc->spc_dev, SIBA_INTR_MASK, 0); 1720203319Sweongyo} 1721203319Sweongyo 1722203319Sweongyoint 1723203319Sweongyosiba_dev_isup(struct siba_dev_softc *sd) 1724203319Sweongyo{ 1725203319Sweongyo uint32_t reject, val; 1726203319Sweongyo 1727203319Sweongyo reject = siba_tmslow_reject_bitmask(sd); 1728203319Sweongyo val = siba_read_4(sd, SIBA_TGSLOW); 1729203319Sweongyo val &= SIBA_TGSLOW_CLOCK | SIBA_TGSLOW_RESET | reject; 1730203319Sweongyo 1731203319Sweongyo return (val == SIBA_TGSLOW_CLOCK); 1732203319Sweongyo} 1733203319Sweongyo 1734203319Sweongyovoid 1735203319Sweongyosiba_dev_up(struct siba_dev_softc *sd, uint32_t flags) 1736203319Sweongyo{ 1737203319Sweongyo uint32_t val; 1738203319Sweongyo 1739203319Sweongyo siba_dev_down(sd, flags); 1740203319Sweongyo siba_write_4(sd, SIBA_TGSLOW, SIBA_TGSLOW_RESET | SIBA_TGSLOW_CLOCK | 1741203319Sweongyo SIBA_TGSLOW_FGC | flags); 1742203319Sweongyo siba_read_4(sd, SIBA_TGSLOW); 1743203319Sweongyo DELAY(1); 1744203319Sweongyo 1745203319Sweongyo if (siba_read_4(sd, SIBA_TGSHIGH) & SIBA_TGSHIGH_SERR) 1746203319Sweongyo siba_write_4(sd, SIBA_TGSHIGH, 0); 1747203319Sweongyo 1748203319Sweongyo val = siba_read_4(sd, SIBA_IAS); 1749203319Sweongyo if (val & (SIBA_IAS_INBAND_ERR | SIBA_IAS_TIMEOUT)) { 1750203319Sweongyo val &= ~(SIBA_IAS_INBAND_ERR | SIBA_IAS_TIMEOUT); 1751203319Sweongyo siba_write_4(sd, SIBA_IAS, val); 1752203319Sweongyo } 1753203319Sweongyo 1754203319Sweongyo siba_write_4(sd, SIBA_TGSLOW, 1755203319Sweongyo SIBA_TGSLOW_CLOCK | SIBA_TGSLOW_FGC | flags); 1756203319Sweongyo siba_read_4(sd, SIBA_TGSLOW); 1757203319Sweongyo DELAY(1); 1758203319Sweongyo 1759203319Sweongyo siba_write_4(sd, SIBA_TGSLOW, SIBA_TGSLOW_CLOCK | flags); 1760203319Sweongyo siba_read_4(sd, SIBA_TGSLOW); 1761203319Sweongyo DELAY(1); 1762203319Sweongyo} 1763203319Sweongyo 1764203319Sweongyostatic uint32_t 1765203319Sweongyosiba_tmslow_reject_bitmask(struct siba_dev_softc *sd) 1766203319Sweongyo{ 1767203319Sweongyo uint32_t rev = siba_read_4(sd, SIBA_IDLOW) & SIBA_IDLOW_SSBREV; 1768203319Sweongyo 1769203319Sweongyo switch (rev) { 1770203319Sweongyo case SIBA_IDLOW_SSBREV_22: 1771203319Sweongyo return (SIBA_TGSLOW_REJECT_22); 1772203319Sweongyo case SIBA_IDLOW_SSBREV_23: 1773203319Sweongyo return (SIBA_TGSLOW_REJECT_23); 1774203319Sweongyo case SIBA_IDLOW_SSBREV_24: 1775203319Sweongyo case SIBA_IDLOW_SSBREV_25: 1776203319Sweongyo case SIBA_IDLOW_SSBREV_26: 1777203319Sweongyo case SIBA_IDLOW_SSBREV_27: 1778203319Sweongyo return (SIBA_TGSLOW_REJECT_23); 1779203319Sweongyo default: 1780203319Sweongyo KASSERT(0 == 1, 1781203319Sweongyo ("%s:%d: unknown backplane rev %#x\n", 1782203319Sweongyo __func__, __LINE__, rev)); 1783203319Sweongyo } 1784203319Sweongyo return (SIBA_TGSLOW_REJECT_22 | SIBA_TGSLOW_REJECT_23); 1785203319Sweongyo} 1786203319Sweongyo 1787203319Sweongyovoid 1788203319Sweongyosiba_dev_down(struct siba_dev_softc *sd, uint32_t flags) 1789203319Sweongyo{ 1790203319Sweongyo struct siba_softc *siba = sd->sd_bus; 1791203319Sweongyo uint32_t reject, val; 1792203319Sweongyo int i; 1793203319Sweongyo 1794203319Sweongyo if (siba_read_4(sd, SIBA_TGSLOW) & SIBA_TGSLOW_RESET) 1795203319Sweongyo return; 1796203319Sweongyo 1797203319Sweongyo reject = siba_tmslow_reject_bitmask(sd); 1798203319Sweongyo siba_write_4(sd, SIBA_TGSLOW, reject | SIBA_TGSLOW_CLOCK); 1799203319Sweongyo 1800203319Sweongyo for (i = 0; i < 1000; i++) { 1801203319Sweongyo val = siba_read_4(sd, SIBA_TGSLOW); 1802203319Sweongyo if (val & reject) 1803203319Sweongyo break; 1804203319Sweongyo DELAY(10); 1805203319Sweongyo } 1806203319Sweongyo if ((val & reject) == 0) { 1807203319Sweongyo device_printf(siba->siba_dev, "timeout (bit %#x reg %#x)\n", 1808203319Sweongyo reject, SIBA_TGSLOW); 1809203319Sweongyo } 1810203319Sweongyo for (i = 0; i < 1000; i++) { 1811203319Sweongyo val = siba_read_4(sd, SIBA_TGSHIGH); 1812203319Sweongyo if (!(val & SIBA_TGSHIGH_BUSY)) 1813203319Sweongyo break; 1814203319Sweongyo DELAY(10); 1815203319Sweongyo } 1816203319Sweongyo if ((val & SIBA_TGSHIGH_BUSY) != 0) { 1817203319Sweongyo device_printf(siba->siba_dev, "timeout (bit %#x reg %#x)\n", 1818203319Sweongyo SIBA_TGSHIGH_BUSY, SIBA_TGSHIGH); 1819203319Sweongyo } 1820203319Sweongyo 1821203319Sweongyo siba_write_4(sd, SIBA_TGSLOW, SIBA_TGSLOW_FGC | SIBA_TGSLOW_CLOCK | 1822203319Sweongyo reject | SIBA_TGSLOW_RESET | flags); 1823203319Sweongyo siba_read_4(sd, SIBA_TGSLOW); 1824203319Sweongyo DELAY(1); 1825203319Sweongyo siba_write_4(sd, SIBA_TGSLOW, reject | SIBA_TGSLOW_RESET | flags); 1826203319Sweongyo siba_read_4(sd, SIBA_TGSLOW); 1827203319Sweongyo DELAY(1); 1828203319Sweongyo} 1829203319Sweongyo 1830203319Sweongyostatic void 1831203319Sweongyosiba_pcicore_setup(struct siba_pci *spc, struct siba_dev_softc *sd) 1832203319Sweongyo{ 1833203319Sweongyo struct siba_dev_softc *psd = spc->spc_dev; 1834203319Sweongyo struct siba_softc *siba = psd->sd_bus; 1835203319Sweongyo uint32_t tmp; 1836203319Sweongyo 1837203319Sweongyo if (psd->sd_id.sd_device == SIBA_DEVID_PCI) { 1838203319Sweongyo siba_pcicore_write_4(spc, SIBA_PCICORE_SBTOPCI2, 1839203319Sweongyo siba_pcicore_read_4(spc, SIBA_PCICORE_SBTOPCI2) | 1840203319Sweongyo SIBA_PCICORE_SBTOPCI_PREF | SIBA_PCICORE_SBTOPCI_BURST); 1841203319Sweongyo 1842203319Sweongyo if (psd->sd_id.sd_rev < 5) { 1843203319Sweongyo tmp = siba_read_4(psd, SIBA_IMCFGLO); 1844203319Sweongyo tmp &= ~SIBA_IMCFGLO_SERTO; 1845203319Sweongyo tmp = (tmp | 2) & ~SIBA_IMCFGLO_REQTO; 1846203319Sweongyo tmp |= 3 << 4 /* SIBA_IMCFGLO_REQTO_SHIFT */; 1847203319Sweongyo siba_write_4(psd, SIBA_IMCFGLO, tmp); 1848203319Sweongyo 1849203319Sweongyo /* broadcast value */ 1850203319Sweongyo sd = (siba->siba_cc.scc_dev != NULL) ? 1851203319Sweongyo siba->siba_cc.scc_dev : siba->siba_pci.spc_dev; 1852203319Sweongyo if (sd != NULL) { 1853203319Sweongyo siba_write_4(sd, SIBA_PCICORE_BCAST_ADDR, 1854203319Sweongyo 0xfd8); 1855203319Sweongyo siba_read_4(sd, SIBA_PCICORE_BCAST_ADDR); 1856203319Sweongyo siba_write_4(sd, SIBA_PCICORE_BCAST_DATA, 0); 1857203319Sweongyo siba_read_4(sd, SIBA_PCICORE_BCAST_DATA); 1858203319Sweongyo } 1859203319Sweongyo } else if (psd->sd_id.sd_rev >= 11) { 1860203319Sweongyo tmp = siba_pcicore_read_4(spc, SIBA_PCICORE_SBTOPCI2); 1861203319Sweongyo tmp |= SIBA_PCICORE_SBTOPCI_MRM; 1862203319Sweongyo siba_pcicore_write_4(spc, SIBA_PCICORE_SBTOPCI2, tmp); 1863203319Sweongyo } 1864203319Sweongyo } else { 1865203319Sweongyo KASSERT(psd->sd_id.sd_device == SIBA_DEVID_PCIE, ("only PCIE")); 1866203319Sweongyo if ((psd->sd_id.sd_rev == 0) || (psd->sd_id.sd_rev == 1)) 1867203319Sweongyo siba_pcie_write(spc, 0x4, 1868203319Sweongyo siba_pcie_read(spc, 0x4) | 0x8); 1869203319Sweongyo if (psd->sd_id.sd_rev == 0) { 1870203319Sweongyo siba_pcie_mdio_write(spc, 0x1f, 2, 0x8128); /* Timer */ 1871203319Sweongyo siba_pcie_mdio_write(spc, 0x1f, 6, 0x0100); /* CDR */ 1872203319Sweongyo siba_pcie_mdio_write(spc, 0x1f, 7, 0x1466); /* CDR BW */ 1873203319Sweongyo } else if (psd->sd_id.sd_rev == 1) 1874203319Sweongyo siba_pcie_write(spc, 0x100, 1875203319Sweongyo siba_pcie_read(spc, 0x100) | 0x40); 1876203319Sweongyo } 1877203319Sweongyo spc->spc_inited = 1; 1878203319Sweongyo} 1879203319Sweongyo 1880203319Sweongyovoid 1881203319Sweongyosiba_pcicore_intr(struct siba_pci *spc, struct siba_dev_softc *sd) 1882203319Sweongyo{ 1883203319Sweongyo struct siba_dev_softc *psd = spc->spc_dev; 1884203319Sweongyo struct siba_softc *siba; 1885203319Sweongyo uint32_t tmp; 1886203319Sweongyo 1887203319Sweongyo if (sd->sd_bus->siba_type != SIBA_TYPE_PCI || !psd) 1888203319Sweongyo return; 1889203319Sweongyo 1890203319Sweongyo siba = psd->sd_bus; 1891203319Sweongyo /* enable interrupts */ 1892203319Sweongyo if (siba->siba_dev != NULL && 1893203319Sweongyo (psd->sd_id.sd_rev >= 6 || psd->sd_id.sd_device == SIBA_DEVID_PCIE)) { 1894203319Sweongyo tmp = pci_read_config(siba->siba_dev, SIBA_IRQMASK, 4); 1895203319Sweongyo tmp |= (1 << sd->sd_coreidx) << 8; 1896203319Sweongyo pci_write_config(siba->siba_dev, SIBA_IRQMASK, tmp, 4); 1897203319Sweongyo } else { 1898203319Sweongyo tmp = siba_read_4(sd, SIBA_TPS); 1899203319Sweongyo tmp &= SIBA_TPS_BPFLAG; 1900203319Sweongyo siba_write_4(psd, SIBA_INTR_MASK, 1901203319Sweongyo siba_read_4(psd, SIBA_INTR_MASK) | (1 << tmp)); 1902203319Sweongyo } 1903203319Sweongyo 1904203319Sweongyo /* setup PCIcore */ 1905203319Sweongyo if (spc->spc_inited == 0) 1906203319Sweongyo siba_pcicore_setup(spc, sd); 1907203319Sweongyo} 1908203319Sweongyo 1909203319Sweongyostatic uint32_t 1910203319Sweongyosiba_pcicore_read_4(struct siba_pci *spc, uint16_t offset) 1911203319Sweongyo{ 1912203319Sweongyo 1913203319Sweongyo return (siba_read_4(spc->spc_dev, offset)); 1914203319Sweongyo} 1915203319Sweongyo 1916203319Sweongyostatic void 1917203319Sweongyosiba_pcicore_write_4(struct siba_pci *spc, uint16_t offset, uint32_t value) 1918203319Sweongyo{ 1919203319Sweongyo 1920203319Sweongyo siba_write_4(spc->spc_dev, offset, value); 1921203319Sweongyo} 1922203319Sweongyo 1923203319Sweongyostatic uint32_t 1924203319Sweongyosiba_pcie_read(struct siba_pci *spc, uint32_t address) 1925203319Sweongyo{ 1926203319Sweongyo 1927203319Sweongyo siba_pcicore_write_4(spc, 0x130, address); 1928203319Sweongyo return (siba_pcicore_read_4(spc, 0x134)); 1929203319Sweongyo} 1930203319Sweongyo 1931203319Sweongyostatic void 1932203319Sweongyosiba_pcie_write(struct siba_pci *spc, uint32_t address, uint32_t data) 1933203319Sweongyo{ 1934203319Sweongyo 1935203319Sweongyo siba_pcicore_write_4(spc, 0x130, address); 1936203319Sweongyo siba_pcicore_write_4(spc, 0x134, data); 1937203319Sweongyo} 1938203319Sweongyo 1939203319Sweongyostatic void 1940203319Sweongyosiba_pcie_mdio_write(struct siba_pci *spc, uint8_t device, uint8_t address, 1941203319Sweongyo uint16_t data) 1942203319Sweongyo{ 1943203319Sweongyo int i; 1944203319Sweongyo 1945203319Sweongyo siba_pcicore_write_4(spc, SIBA_PCICORE_MDIO_CTL, 0x80 | 0x2); 1946203319Sweongyo siba_pcicore_write_4(spc, SIBA_PCICORE_MDIO_DATA, 1947203319Sweongyo (1 << 30) | (1 << 28) | 1948203319Sweongyo ((uint32_t)device << 22) | ((uint32_t)address << 18) | 1949203319Sweongyo (1 << 17) | data); 1950203319Sweongyo DELAY(10); 1951203319Sweongyo for (i = 0; i < 10; i++) { 1952203319Sweongyo if (siba_pcicore_read_4(spc, SIBA_PCICORE_MDIO_CTL) & 0x100) 1953203319Sweongyo break; 1954203319Sweongyo DELAY(1000); 1955203319Sweongyo } 1956203319Sweongyo siba_pcicore_write_4(spc, SIBA_PCICORE_MDIO_CTL, 0); 1957203319Sweongyo} 1958203319Sweongyo 1959203319Sweongyouint32_t 1960203319Sweongyosiba_dma_translation(struct siba_dev_softc *sd) 1961203319Sweongyo{ 1962203319Sweongyo 1963203319Sweongyo KASSERT(sd->sd_bus->siba_type == SIBA_TYPE_PCI, 1964203319Sweongyo ("unsupported bustype %d\n", sd->sd_bus->siba_type)); 1965203319Sweongyo return (SIBA_PCI_DMA); 1966203319Sweongyo} 1967203319Sweongyo 1968203319Sweongyovoid 1969203319Sweongyosiba_barrier(struct siba_dev_softc *sd, int flags) 1970203319Sweongyo{ 1971203319Sweongyo struct siba_softc *siba = sd->sd_bus; 1972203319Sweongyo 1973203319Sweongyo SIBA_BARRIER(siba, flags); 1974203319Sweongyo} 1975203319Sweongyo 1976203319Sweongyostatic void 1977203319Sweongyosiba_cc_suspend(struct siba_cc *scc) 1978203319Sweongyo{ 1979203319Sweongyo 1980203319Sweongyo siba_cc_clock(scc, SIBA_CLOCK_SLOW); 1981203319Sweongyo} 1982203319Sweongyo 1983203319Sweongyostatic void 1984203319Sweongyosiba_cc_resume(struct siba_cc *scc) 1985203319Sweongyo{ 1986203319Sweongyo 1987203319Sweongyo siba_cc_power_init(scc); 1988203319Sweongyo siba_cc_clock(scc, SIBA_CLOCK_FAST); 1989203319Sweongyo} 1990203319Sweongyo 1991203319Sweongyoint 1992203319Sweongyosiba_core_suspend(struct siba_softc *siba) 1993203319Sweongyo{ 1994203319Sweongyo 1995203319Sweongyo siba_cc_suspend(&siba->siba_cc); 1996203319Sweongyo siba_pci_gpio(siba, SIBA_GPIO_CRYSTAL | SIBA_GPIO_PLL, 0); 1997203319Sweongyo return (0); 1998203319Sweongyo} 1999203319Sweongyo 2000203319Sweongyoint 2001203319Sweongyosiba_core_resume(struct siba_softc *siba) 2002203319Sweongyo{ 2003203319Sweongyo 2004203319Sweongyo siba->siba_pci.spc_inited = 0; 2005203319Sweongyo siba->siba_curdev = NULL; 2006203319Sweongyo 2007203319Sweongyo siba_powerup(siba, 0); 2008203319Sweongyo /* XXX setup H/W for PCMCIA??? */ 2009203319Sweongyo siba_cc_resume(&siba->siba_cc); 2010203319Sweongyo siba_powerdown(siba); 2011203319Sweongyo 2012203319Sweongyo return (0); 2013203319Sweongyo} 2014203944Sweongyo 2015203944Sweongyostatic void 2016203944Sweongyosiba_cc_regctl_setmask(struct siba_cc *cc, uint32_t offset, uint32_t mask, 2017203944Sweongyo uint32_t set) 2018203944Sweongyo{ 2019203944Sweongyo 2020203944Sweongyo SIBA_CC_READ32(cc, SIBA_CC_REGCTL_ADDR); 2021203944Sweongyo SIBA_CC_WRITE32(cc, SIBA_CC_REGCTL_ADDR, offset); 2022203944Sweongyo SIBA_CC_READ32(cc, SIBA_CC_REGCTL_ADDR); 2023203944Sweongyo SIBA_CC_WRITE32(cc, SIBA_CC_REGCTL_DATA, 2024203944Sweongyo (SIBA_CC_READ32(cc, SIBA_CC_REGCTL_DATA) & mask) | set); 2025203944Sweongyo SIBA_CC_READ32(cc, SIBA_CC_REGCTL_DATA); 2026203944Sweongyo} 2027203944Sweongyo 2028203944Sweongyovoid 2029203944Sweongyosiba_cc_pmu_set_ldovolt(struct siba_cc *scc, int id, uint32_t volt) 2030203944Sweongyo{ 2031203944Sweongyo struct siba_softc *siba = scc->scc_dev->sd_bus; 2032203944Sweongyo uint32_t *p = NULL, info[5][3] = { 2033203944Sweongyo { 2, 25, 0xf }, 2034203944Sweongyo { 3, 1, 0xf }, 2035203944Sweongyo { 3, 9, 0xf }, 2036203944Sweongyo { 3, 17, 0x3f }, 2037203944Sweongyo { 0, 21, 0x3f } 2038203944Sweongyo }; 2039203944Sweongyo 2040203944Sweongyo if (siba->siba_chipid == 0x4312) { 2041203944Sweongyo if (id != SIBA_LDO_PAREF) 2042203944Sweongyo return; 2043203944Sweongyo p = info[4]; 2044203944Sweongyo siba_cc_regctl_setmask(scc, p[0], ~(p[2] << p[1]), 2045203944Sweongyo (volt & p[2]) << p[1]); 2046203944Sweongyo return; 2047203944Sweongyo } 2048203944Sweongyo if (siba->siba_chipid == 0x4328 || siba->siba_chipid == 0x5354) { 2049203944Sweongyo switch (id) { 2050203944Sweongyo case SIBA_LDO_PAREF: 2051203944Sweongyo p = info[3]; 2052203944Sweongyo break; 2053203944Sweongyo case SIBA_LDO_VOLT1: 2054203944Sweongyo p = info[0]; 2055203944Sweongyo break; 2056203944Sweongyo case SIBA_LDO_VOLT2: 2057203944Sweongyo p = info[1]; 2058203944Sweongyo break; 2059203944Sweongyo case SIBA_LDO_VOLT3: 2060203944Sweongyo p = info[2]; 2061203944Sweongyo break; 2062203944Sweongyo default: 2063203944Sweongyo KASSERT(0 == 1, 2064203944Sweongyo ("%s: unsupported voltage ID %#x", __func__, id)); 2065203944Sweongyo return; 2066203944Sweongyo } 2067203944Sweongyo siba_cc_regctl_setmask(scc, p[0], ~(p[2] << p[1]), 2068203944Sweongyo (volt & p[2]) << p[1]); 2069203944Sweongyo } 2070203944Sweongyo} 2071203944Sweongyo 2072203944Sweongyovoid 2073203944Sweongyosiba_cc_pmu_set_ldoparef(struct siba_cc *scc, uint8_t on) 2074203944Sweongyo{ 2075203944Sweongyo struct siba_softc *siba = scc->scc_dev->sd_bus; 2076203944Sweongyo int ldo; 2077203944Sweongyo 2078203944Sweongyo ldo = ((siba->siba_chipid == 0x4312) ? SIBA_CC_PMU_4312_PA_REF : 2079203944Sweongyo ((siba->siba_chipid == 0x4328) ? SIBA_CC_PMU_4328_PA_REF : 2080203944Sweongyo ((siba->siba_chipid == 0x5354) ? SIBA_CC_PMU_5354_PA_REF : -1))); 2081203944Sweongyo if (ldo == -1) 2082203944Sweongyo return; 2083203944Sweongyo 2084203944Sweongyo if (on) 2085203944Sweongyo SIBA_CC_SET32(scc, SIBA_CC_PMU_MINRES, 1 << ldo); 2086203944Sweongyo else 2087203944Sweongyo SIBA_CC_MASK32(scc, SIBA_CC_PMU_MINRES, ~(1 << ldo)); 2088203944Sweongyo SIBA_CC_READ32(scc, SIBA_CC_PMU_MINRES); 2089203944Sweongyo} 2090