freebsd-skq/sys/dev/siba/siba_core.c
Pedro F. Giffuni 718cf2ccb9 sys/dev: further adoption of SPDX licensing ID tags.
Mainly focus on files that use BSD 2-Clause license, however the tool I
was using misidentified many licenses so this was mostly a manual - error
prone - task.

The Software Package Data Exchange (SPDX) group provides a specification
to make it easier for automated tools to detect and summarize well known
opensource licenses. We are gradually adopting the specification, noting
that the tags are considered only advisory and do not, in any way,
superceed or replace the license texts.
2017-11-27 14:52:40 +00:00

3037 lines
83 KiB
C

/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2009-2010 Weongyo Jeong <weongyo@freebsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
* redistribution must be conditioned upon including a substantially
* similar Disclaimer requirement for further binary redistribution.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGES.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* the Sonics Silicon Backplane driver.
*/
#include "opt_siba.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/kernel.h>
#include <sys/endian.h>
#include <sys/errno.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/bus.h>
#include <sys/rman.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/if_media.h>
#include <net/if_arp.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <dev/siba/siba_ids.h>
#include <dev/siba/sibareg.h>
#include <dev/siba/sibavar.h>
enum {
SIBA_DEBUG_SCAN = 0x00000001, /* scan */
SIBA_DEBUG_PMU = 0x00000002, /* PMU */
SIBA_DEBUG_PLL = 0x00000004, /* PLL */
SIBA_DEBUG_SWITCHCORE = 0x00000008, /* switching core */
SIBA_DEBUG_SPROM = 0x00000010, /* SPROM */
SIBA_DEBUG_CORE = 0x00000020, /* handling cores */
SIBA_DEBUG_DMA = 0x00000040, /* DMA bits */
SIBA_DEBUG_ANY = 0xffffffff
};
#ifdef SIBA_DEBUG
#define DPRINTF(siba, m, ...) do { \
if (siba->siba_debug & (m)) \
device_printf(siba->siba_dev, __VA_ARGS__); \
} while (0)
#else
#define DPRINTF(siba, m, ...) do { (void) siba; } while (0)
#endif
#define N(a) (sizeof(a) / sizeof(a[0]))
static void siba_pci_gpio(struct siba_softc *, uint32_t, int);
static void siba_scan(struct siba_softc *);
static int siba_switchcore(struct siba_softc *, uint8_t);
static int siba_pci_switchcore_sub(struct siba_softc *, uint8_t);
static uint32_t siba_scan_read_4(struct siba_softc *, uint8_t, uint16_t);
static uint16_t siba_dev2chipid(struct siba_softc *);
static uint16_t siba_pci_read_2(struct siba_dev_softc *, uint16_t);
static uint32_t siba_pci_read_4(struct siba_dev_softc *, uint16_t);
static void siba_pci_write_2(struct siba_dev_softc *, uint16_t, uint16_t);
static void siba_pci_write_4(struct siba_dev_softc *, uint16_t, uint32_t);
static void siba_cc_clock(struct siba_cc *,
enum siba_clock);
static void siba_cc_pmu_init(struct siba_cc *);
static void siba_cc_power_init(struct siba_cc *);
static void siba_cc_powerup_delay(struct siba_cc *);
static int siba_cc_clockfreq(struct siba_cc *, int);
static void siba_cc_pmu1_pll0_init(struct siba_cc *, uint32_t);
static void siba_cc_pmu0_pll0_init(struct siba_cc *, uint32_t);
static enum siba_clksrc siba_cc_clksrc(struct siba_cc *);
static const struct siba_cc_pmu1_plltab *siba_cc_pmu1_plltab_find(uint32_t);
static uint32_t siba_cc_pll_read(struct siba_cc *, uint32_t);
static void siba_cc_pll_write(struct siba_cc *, uint32_t,
uint32_t);
static const struct siba_cc_pmu0_plltab *
siba_cc_pmu0_plltab_findentry(uint32_t);
static int siba_pci_sprom(struct siba_softc *, struct siba_sprom *);
static int siba_sprom_read(struct siba_softc *, uint16_t *, uint16_t);
static int sprom_check_crc(const uint16_t *, size_t);
static uint8_t siba_crc8(uint8_t, uint8_t);
static void siba_sprom_r123(struct siba_sprom *, const uint16_t *);
static void siba_sprom_r45(struct siba_sprom *, const uint16_t *);
static void siba_sprom_r8(struct siba_sprom *, const uint16_t *);
static int8_t siba_sprom_r123_antgain(uint8_t, const uint16_t *, uint16_t,
uint16_t);
static uint32_t siba_tmslow_reject_bitmask(struct siba_dev_softc *);
static uint32_t siba_pcicore_read_4(struct siba_pci *, uint16_t);
static void siba_pcicore_write_4(struct siba_pci *, uint16_t, uint32_t);
static uint32_t siba_pcie_read(struct siba_pci *, uint32_t);
static void siba_pcie_write(struct siba_pci *, uint32_t, uint32_t);
static void siba_pcie_mdio_write(struct siba_pci *, uint8_t, uint8_t,
uint16_t);
static void siba_pci_read_multi_1(struct siba_dev_softc *, void *, size_t,
uint16_t);
static void siba_pci_read_multi_2(struct siba_dev_softc *, void *, size_t,
uint16_t);
static void siba_pci_read_multi_4(struct siba_dev_softc *, void *, size_t,
uint16_t);
static void siba_pci_write_multi_1(struct siba_dev_softc *, const void *,
size_t, uint16_t);
static void siba_pci_write_multi_2(struct siba_dev_softc *, const void *,
size_t, uint16_t);
static void siba_pci_write_multi_4(struct siba_dev_softc *, const void *,
size_t, uint16_t);
static const char *siba_core_name(uint16_t);
static void siba_pcicore_init(struct siba_pci *);
static uint32_t siba_read_4_sub(struct siba_dev_softc *, uint16_t);
static void siba_write_4_sub(struct siba_dev_softc *, uint16_t, uint32_t);
static void siba_powerup_sub(struct siba_softc *, int);
static int siba_powerdown_sub(struct siba_softc *);
static int siba_dev_isup_sub(struct siba_dev_softc *);
static void siba_dev_up_sub(struct siba_dev_softc *, uint32_t);
static void siba_dev_down_sub(struct siba_dev_softc *, uint32_t);
int siba_core_attach(struct siba_softc *);
int siba_core_detach(struct siba_softc *);
int siba_core_suspend(struct siba_softc *);
int siba_core_resume(struct siba_softc *);
uint8_t siba_getncores(device_t, uint16_t);
static const struct siba_bus_ops siba_pci_ops = {
.read_2 = siba_pci_read_2,
.read_4 = siba_pci_read_4,
.write_2 = siba_pci_write_2,
.write_4 = siba_pci_write_4,
.read_multi_1 = siba_pci_read_multi_1,
.read_multi_2 = siba_pci_read_multi_2,
.read_multi_4 = siba_pci_read_multi_4,
.write_multi_1 = siba_pci_write_multi_1,
.write_multi_2 = siba_pci_write_multi_2,
.write_multi_4 = siba_pci_write_multi_4,
};
static const struct siba_cc_pmu_res_updown siba_cc_pmu_4325_updown[] =
SIBA_CC_PMU_4325_RES_UPDOWN;
static const struct siba_cc_pmu_res_depend siba_cc_pmu_4325_depend[] =
SIBA_CC_PMU_4325_RES_DEPEND;
static const struct siba_cc_pmu_res_updown siba_cc_pmu_4328_updown[] =
SIBA_CC_PMU_4328_RES_UPDOWN;
static const struct siba_cc_pmu_res_depend siba_cc_pmu_4328_depend[] =
SIBA_CC_PMU_4328_RES_DEPEND;
static const struct siba_cc_pmu0_plltab siba_cc_pmu0_plltab[] =
SIBA_CC_PMU0_PLLTAB_ENTRY;
static const struct siba_cc_pmu1_plltab siba_cc_pmu1_plltab[] =
SIBA_CC_PMU1_PLLTAB_ENTRY;
int
siba_core_attach(struct siba_softc *siba)
{
struct siba_cc *scc;
int error;
KASSERT(siba->siba_type == SIBA_TYPE_PCI,
("unsupported BUS type (%#x)", siba->siba_type));
siba->siba_ops = &siba_pci_ops;
siba_pci_gpio(siba, SIBA_GPIO_CRYSTAL | SIBA_GPIO_PLL, 1);
siba_scan(siba);
/* XXX init PCI or PCMCIA host devices */
siba_powerup_sub(siba, 0);
/* init ChipCommon */
scc = &siba->siba_cc;
if (scc->scc_dev != NULL) {
siba_cc_pmu_init(scc);
siba_cc_power_init(scc);
siba_cc_clock(scc, SIBA_CLOCK_FAST);
siba_cc_powerup_delay(scc);
}
error = siba_pci_sprom(siba, &siba->siba_sprom);
if (error) {
siba_powerdown_sub(siba);
return (error);
}
siba_pcicore_init(&siba->siba_pci);
siba_powerdown_sub(siba);
return (bus_generic_attach(siba->siba_dev));
}
int
siba_core_detach(struct siba_softc *siba)
{
/* detach & delete all children */
device_delete_children(siba->siba_dev);
return (0);
}
static void
siba_pci_gpio(struct siba_softc *siba, uint32_t what, int on)
{
uint32_t in, out;
uint16_t status;
if (siba->siba_type != SIBA_TYPE_PCI)
return;
out = pci_read_config(siba->siba_dev, SIBA_GPIO_OUT, 4);
if (on == 0) {
if (what & SIBA_GPIO_PLL)
out |= SIBA_GPIO_PLL;
if (what & SIBA_GPIO_CRYSTAL)
out &= ~SIBA_GPIO_CRYSTAL;
pci_write_config(siba->siba_dev, SIBA_GPIO_OUT, out, 4);
pci_write_config(siba->siba_dev, SIBA_GPIO_OUT_EN,
pci_read_config(siba->siba_dev,
SIBA_GPIO_OUT_EN, 4) | what, 4);
return;
}
in = pci_read_config(siba->siba_dev, SIBA_GPIO_IN, 4);
if ((in & SIBA_GPIO_CRYSTAL) != SIBA_GPIO_CRYSTAL) {
if (what & SIBA_GPIO_CRYSTAL) {
out |= SIBA_GPIO_CRYSTAL;
if (what & SIBA_GPIO_PLL)
out |= SIBA_GPIO_PLL;
pci_write_config(siba->siba_dev, SIBA_GPIO_OUT, out, 4);
pci_write_config(siba->siba_dev,
SIBA_GPIO_OUT_EN, pci_read_config(siba->siba_dev,
SIBA_GPIO_OUT_EN, 4) | what, 4);
DELAY(1000);
}
if (what & SIBA_GPIO_PLL) {
out &= ~SIBA_GPIO_PLL;
pci_write_config(siba->siba_dev, SIBA_GPIO_OUT, out, 4);
DELAY(5000);
}
}
status = pci_read_config(siba->siba_dev, PCIR_STATUS, 2);
status &= ~PCIM_STATUS_STABORT;
pci_write_config(siba->siba_dev, PCIR_STATUS, status, 2);
}
static void
siba_scan(struct siba_softc *siba)
{
struct siba_dev_softc *sd;
uint32_t idhi, tmp;
device_t child;
int base, dev_i = 0, error, i, is_pcie, n_80211 = 0, n_cc = 0,
n_pci = 0;
KASSERT(siba->siba_type == SIBA_TYPE_PCI,
("unsupported BUS type (%#x)", siba->siba_type));
siba->siba_ndevs = 0;
error = siba_switchcore(siba, 0); /* need the first core */
if (error)
return;
idhi = siba_scan_read_4(siba, 0, SIBA_IDHIGH);
if (SIBA_IDHIGH_CORECODE(idhi) == SIBA_DEVID_CHIPCOMMON) {
tmp = siba_scan_read_4(siba, 0, SIBA_CC_CHIPID);
siba->siba_chipid = SIBA_CC_ID(tmp);
siba->siba_chiprev = SIBA_CC_REV(tmp);
siba->siba_chippkg = SIBA_CC_PKG(tmp);
if (SIBA_IDHIGH_REV(idhi) >= 4)
siba->siba_ndevs = SIBA_CC_NCORES(tmp);
siba->siba_cc.scc_caps = siba_scan_read_4(siba, 0,
SIBA_CC_CAPS);
} else {
if (siba->siba_type == SIBA_TYPE_PCI) {
siba->siba_chipid = siba_dev2chipid(siba);
siba->siba_chiprev = pci_read_config(siba->siba_dev,
PCIR_REVID, 2);
siba->siba_chippkg = 0;
} else {
siba->siba_chipid = 0x4710;
siba->siba_chiprev = 0;
siba->siba_chippkg = 0;
}
}
if (siba->siba_ndevs == 0)
siba->siba_ndevs = siba_getncores(siba->siba_dev,
siba->siba_chipid);
if (siba->siba_ndevs > SIBA_MAX_CORES) {
device_printf(siba->siba_dev,
"too many siba cores (max %d %d)\n",
SIBA_MAX_CORES, siba->siba_ndevs);
return;
}
/* looking basic information about each cores/devices */
for (i = 0; i < siba->siba_ndevs; i++) {
error = siba_switchcore(siba, i);
if (error)
return;
sd = &(siba->siba_devs[dev_i]);
idhi = siba_scan_read_4(siba, i, SIBA_IDHIGH);
sd->sd_bus = siba;
sd->sd_id.sd_device = SIBA_IDHIGH_CORECODE(idhi);
sd->sd_id.sd_rev = SIBA_IDHIGH_REV(idhi);
sd->sd_id.sd_vendor = SIBA_IDHIGH_VENDOR(idhi);
sd->sd_ops = siba->siba_ops;
sd->sd_coreidx = i;
DPRINTF(siba, SIBA_DEBUG_SCAN,
"core %d (%s) found (cc %#x rev %#x vendor %#x)\n",
i, siba_core_name(sd->sd_id.sd_device),
sd->sd_id.sd_device, sd->sd_id.sd_rev,
sd->sd_id.sd_vendor);
switch (sd->sd_id.sd_device) {
case SIBA_DEVID_CHIPCOMMON:
n_cc++;
if (n_cc > 1) {
device_printf(siba->siba_dev,
"warn: multiple ChipCommon\n");
break;
}
siba->siba_cc.scc_dev = sd;
break;
case SIBA_DEVID_80211:
n_80211++;
if (n_80211 > 1) {
device_printf(siba->siba_dev,
"warn: multiple 802.11 core\n");
continue;
}
break;
case SIBA_DEVID_PCI:
case SIBA_DEVID_PCIE:
n_pci++;
error = pci_find_cap(siba->siba_dev, PCIY_EXPRESS,
&base);
is_pcie = (error == 0) ? 1 : 0;
if (n_pci > 1) {
device_printf(siba->siba_dev,
"warn: multiple PCI(E) cores\n");
break;
}
if (sd->sd_id.sd_device == SIBA_DEVID_PCI &&
is_pcie == 1)
continue;
if (sd->sd_id.sd_device == SIBA_DEVID_PCIE &&
is_pcie == 0)
continue;
siba->siba_pci.spc_dev = sd;
break;
case SIBA_DEVID_MODEM:
case SIBA_DEVID_PCMCIA:
break;
default:
device_printf(siba->siba_dev,
"unsupported coreid (%s)\n",
siba_core_name(sd->sd_id.sd_device));
break;
}
dev_i++;
child = device_add_child(siba->siba_dev, NULL, -1);
if (child == NULL) {
device_printf(siba->siba_dev, "child attach failed\n");
continue;
}
device_set_ivars(child, sd);
}
siba->siba_ndevs = dev_i;
}
static int
siba_switchcore(struct siba_softc *siba, uint8_t idx)
{
switch (siba->siba_type) {
case SIBA_TYPE_PCI:
return (siba_pci_switchcore_sub(siba, idx));
default:
KASSERT(0 == 1,
("%s: unsupported bustype %#x", __func__,
siba->siba_type));
}
return (0);
}
static int
siba_pci_switchcore_sub(struct siba_softc *siba, uint8_t idx)
{
#define RETRY_MAX 50
int i;
uint32_t dir;
dir = SIBA_REGWIN(idx);
for (i = 0; i < RETRY_MAX; i++) {
pci_write_config(siba->siba_dev, SIBA_BAR0, dir, 4);
if (pci_read_config(siba->siba_dev, SIBA_BAR0, 4) == dir)
return (0);
DELAY(10);
}
DPRINTF(siba, SIBA_DEBUG_SWITCHCORE, "%s: idx %d, failed\n", __func__, idx);
return (ENODEV);
#undef RETRY_MAX
}
static int
siba_pci_switchcore(struct siba_softc *siba, struct siba_dev_softc *sd)
{
int error;
DPRINTF(siba, SIBA_DEBUG_SWITCHCORE, "Switching to %s core, index %d\n",
siba_core_name(sd->sd_id.sd_device), sd->sd_coreidx);
error = siba_pci_switchcore_sub(siba, sd->sd_coreidx);
if (error == 0)
siba->siba_curdev = sd;
return (error);
}
static uint32_t
siba_scan_read_4(struct siba_softc *siba, uint8_t coreidx,
uint16_t offset)
{
(void)coreidx;
KASSERT(siba->siba_type == SIBA_TYPE_PCI,
("unsupported BUS type (%#x)", siba->siba_type));
return (SIBA_READ_4(siba, offset));
}
static uint16_t
siba_dev2chipid(struct siba_softc *siba)
{
uint16_t chipid = 0;
switch (siba->siba_pci_did) {
case 0x4301:
chipid = 0x4301;
break;
case 0x4305:
case 0x4306:
case 0x4307:
chipid = 0x4307;
break;
case 0x4403:
chipid = 0x4402;
break;
case 0x4610:
case 0x4611:
case 0x4612:
case 0x4613:
case 0x4614:
case 0x4615:
chipid = 0x4610;
break;
case 0x4710:
case 0x4711:
case 0x4712:
case 0x4713:
case 0x4714:
case 0x4715:
chipid = 0x4710;
break;
case 0x4320:
case 0x4321:
case 0x4322:
case 0x4323:
case 0x4324:
case 0x4325:
chipid = 0x4309;
break;
case PCI_DEVICE_ID_BCM4401:
case PCI_DEVICE_ID_BCM4401B0:
case PCI_DEVICE_ID_BCM4401B1:
chipid = 0x4401;
break;
default:
device_printf(siba->siba_dev, "unknown PCI did (%d)\n",
siba->siba_pci_did);
}
return (chipid);
}
/*
* Earlier ChipCommon revisions have hardcoded number of cores
* present dependent on the ChipCommon ID.
*/
uint8_t
siba_getncores(device_t dev, uint16_t chipid)
{
switch (chipid) {
case 0x4401:
case 0x4402:
return (3);
case 0x4301:
case 0x4307:
return (5);
case 0x4306:
return (6);
case SIBA_CCID_SENTRY5:
return (7);
case 0x4310:
return (8);
case SIBA_CCID_BCM4710:
case 0x4610:
case SIBA_CCID_BCM4704:
return (9);
default:
device_printf(dev, "unknown the chipset ID %#x\n", chipid);
}
return (1);
}
static const char *
siba_core_name(uint16_t coreid)
{
switch (coreid) {
case SIBA_DEVID_CHIPCOMMON:
return ("ChipCommon");
case SIBA_DEVID_ILINE20:
return ("ILine 20");
case SIBA_DEVID_SDRAM:
return ("SDRAM");
case SIBA_DEVID_PCI:
return ("PCI");
case SIBA_DEVID_MIPS:
return ("MIPS");
case SIBA_DEVID_ETHERNET:
return ("Fast Ethernet");
case SIBA_DEVID_MODEM:
return ("Modem");
case SIBA_DEVID_USB11_HOSTDEV:
return ("USB 1.1 Hostdev");
case SIBA_DEVID_ADSL:
return ("ADSL");
case SIBA_DEVID_ILINE100:
return ("ILine 100");
case SIBA_DEVID_IPSEC:
return ("IPSEC");
case SIBA_DEVID_PCMCIA:
return ("PCMCIA");
case SIBA_DEVID_INTERNAL_MEM:
return ("Internal Memory");
case SIBA_DEVID_SDRAMDDR:
return ("MEMC SDRAM");
case SIBA_DEVID_EXTIF:
return ("EXTIF");
case SIBA_DEVID_80211:
return ("IEEE 802.11");
case SIBA_DEVID_MIPS_3302:
return ("MIPS 3302");
case SIBA_DEVID_USB11_HOST:
return ("USB 1.1 Host");
case SIBA_DEVID_USB11_DEV:
return ("USB 1.1 Device");
case SIBA_DEVID_USB20_HOST:
return ("USB 2.0 Host");
case SIBA_DEVID_USB20_DEV:
return ("USB 2.0 Device");
case SIBA_DEVID_SDIO_HOST:
return ("SDIO Host");
case SIBA_DEVID_ROBOSWITCH:
return ("Roboswitch");
case SIBA_DEVID_PARA_ATA:
return ("PATA");
case SIBA_DEVID_SATA_XORDMA:
return ("SATA XOR-DMA");
case SIBA_DEVID_ETHERNET_GBIT:
return ("GBit Ethernet");
case SIBA_DEVID_PCIE:
return ("PCI-Express");
case SIBA_DEVID_MIMO_PHY:
return ("MIMO PHY");
case SIBA_DEVID_SRAM_CTRLR:
return ("SRAM Controller");
case SIBA_DEVID_MINI_MACPHY:
return ("Mini MACPHY");
case SIBA_DEVID_ARM_1176:
return ("ARM 1176");
case SIBA_DEVID_ARM_7TDMI:
return ("ARM 7TDMI");
}
return ("unknown");
}
static uint16_t
siba_pci_read_2(struct siba_dev_softc *sd, uint16_t offset)
{
struct siba_softc *siba = sd->sd_bus;
if (siba->siba_curdev != sd && siba_pci_switchcore(siba, sd) != 0)
return (0xffff);
return (SIBA_READ_2(siba, offset));
}
static uint32_t
siba_pci_read_4(struct siba_dev_softc *sd, uint16_t offset)
{
struct siba_softc *siba = sd->sd_bus;
if (siba->siba_curdev != sd && siba_pci_switchcore(siba, sd) != 0)
return (0xffff);
return (SIBA_READ_4(siba, offset));
}
static void
siba_pci_write_2(struct siba_dev_softc *sd, uint16_t offset, uint16_t value)
{
struct siba_softc *siba = sd->sd_bus;
if (siba->siba_curdev != sd && siba_pci_switchcore(siba, sd) != 0)
return;
SIBA_WRITE_2(siba, offset, value);
}
static void
siba_pci_write_4(struct siba_dev_softc *sd, uint16_t offset, uint32_t value)
{
struct siba_softc *siba = sd->sd_bus;
if (siba->siba_curdev != sd && siba_pci_switchcore(siba, sd) != 0)
return;
SIBA_WRITE_4(siba, offset, value);
}
static void
siba_pci_read_multi_1(struct siba_dev_softc *sd, void *buffer, size_t count,
uint16_t offset)
{
struct siba_softc *siba = sd->sd_bus;
if (siba->siba_curdev != sd && siba_pci_switchcore(siba, sd) != 0) {
memset(buffer, 0xff, count);
return;
}
SIBA_READ_MULTI_1(siba, offset, buffer, count);
}
static void
siba_pci_read_multi_2(struct siba_dev_softc *sd, void *buffer, size_t count,
uint16_t offset)
{
struct siba_softc *siba = sd->sd_bus;
if (siba->siba_curdev != sd && siba_pci_switchcore(siba, sd) != 0) {
memset(buffer, 0xff, count);
return;
}
KASSERT(!(count & 1), ("%s:%d: fail", __func__, __LINE__));
SIBA_READ_MULTI_2(siba, offset, buffer, count >> 1);
}
static void
siba_pci_read_multi_4(struct siba_dev_softc *sd, void *buffer, size_t count,
uint16_t offset)
{
struct siba_softc *siba = sd->sd_bus;
if (siba->siba_curdev != sd && siba_pci_switchcore(siba, sd) != 0) {
memset(buffer, 0xff, count);
return;
}
KASSERT(!(count & 3), ("%s:%d: fail", __func__, __LINE__));
SIBA_READ_MULTI_4(siba, offset, buffer, count >> 2);
}
static void
siba_pci_write_multi_1(struct siba_dev_softc *sd, const void *buffer,
size_t count, uint16_t offset)
{
struct siba_softc *siba = sd->sd_bus;
if (siba->siba_curdev != sd && siba_pci_switchcore(siba, sd) != 0)
return;
SIBA_WRITE_MULTI_1(siba, offset, buffer, count);
}
static void
siba_pci_write_multi_2(struct siba_dev_softc *sd, const void *buffer,
size_t count, uint16_t offset)
{
struct siba_softc *siba = sd->sd_bus;
if (siba->siba_curdev != sd && siba_pci_switchcore(siba, sd) != 0)
return;
KASSERT(!(count & 1), ("%s:%d: fail", __func__, __LINE__));
SIBA_WRITE_MULTI_2(siba, offset, buffer, count >> 1);
}
static void
siba_pci_write_multi_4(struct siba_dev_softc *sd, const void *buffer,
size_t count, uint16_t offset)
{
struct siba_softc *siba = sd->sd_bus;
if (siba->siba_curdev != sd && siba_pci_switchcore(siba, sd) != 0)
return;
KASSERT(!(count & 3), ("%s:%d: fail", __func__, __LINE__));
SIBA_WRITE_MULTI_4(siba, offset, buffer, count >> 2);
}
void
siba_powerup(device_t dev, int dynamic)
{
struct siba_dev_softc *sd = device_get_ivars(dev);
struct siba_softc *siba = sd->sd_bus;
siba_powerup_sub(siba, dynamic);
}
static void
siba_powerup_sub(struct siba_softc *siba, int dynamic)
{
siba_pci_gpio(siba, SIBA_GPIO_CRYSTAL | SIBA_GPIO_PLL, 1);
siba_cc_clock(&siba->siba_cc,
(dynamic != 0) ? SIBA_CLOCK_DYNAMIC : SIBA_CLOCK_FAST);
}
static void
siba_cc_clock(struct siba_cc *scc, enum siba_clock clock)
{
struct siba_dev_softc *sd = scc->scc_dev;
struct siba_softc *siba;
uint32_t tmp;
if (sd == NULL)
return;
siba = sd->sd_bus;
/*
* PMU controls clockmode; separate function is needed
*/
if (scc->scc_caps & SIBA_CC_CAPS_PMU)
return;
/*
* chipcommon < r6 (no dynamic clock control)
* chipcommon >= r10 (unknown)
*/
if (sd->sd_id.sd_rev < 6 || sd->sd_id.sd_rev >= 10 ||
(scc->scc_caps & SIBA_CC_CAPS_PWCTL) == 0)
return;
switch (clock) {
case SIBA_CLOCK_DYNAMIC:
tmp = SIBA_CC_READ32(scc, SIBA_CC_CLKSLOW) &
~(SIBA_CC_CLKSLOW_ENXTAL | SIBA_CC_CLKSLOW_FSLOW |
SIBA_CC_CLKSLOW_IPLL);
if ((tmp & SIBA_CC_CLKSLOW_SRC) != SIBA_CC_CLKSLOW_SRC_CRYSTAL)
tmp |= SIBA_CC_CLKSLOW_ENXTAL;
SIBA_CC_WRITE32(scc, SIBA_CC_CLKSLOW, tmp);
if (tmp & SIBA_CC_CLKSLOW_ENXTAL)
siba_pci_gpio(siba, SIBA_GPIO_CRYSTAL, 0);
break;
case SIBA_CLOCK_SLOW:
SIBA_CC_WRITE32(scc, SIBA_CC_CLKSLOW,
SIBA_CC_READ32(scc, SIBA_CC_CLKSLOW) |
SIBA_CC_CLKSLOW_FSLOW);
break;
case SIBA_CLOCK_FAST:
/* crystal on */
siba_pci_gpio(siba, SIBA_GPIO_CRYSTAL, 1);
SIBA_CC_WRITE32(scc, SIBA_CC_CLKSLOW,
(SIBA_CC_READ32(scc, SIBA_CC_CLKSLOW) |
SIBA_CC_CLKSLOW_IPLL) & ~SIBA_CC_CLKSLOW_FSLOW);
break;
default:
KASSERT(0 == 1,
("%s: unsupported clock %#x", __func__, clock));
}
}
uint16_t
siba_read_2(device_t dev, uint16_t offset)
{
struct siba_dev_softc *sd = device_get_ivars(dev);
return (sd->sd_ops->read_2(sd, offset));
}
uint32_t
siba_read_4(device_t dev, uint16_t offset)
{
struct siba_dev_softc *sd = device_get_ivars(dev);
return (siba_read_4_sub(sd, offset));
}
static uint32_t
siba_read_4_sub(struct siba_dev_softc *sd, uint16_t offset)
{
return (sd->sd_ops->read_4(sd, offset));
}
void
siba_write_2(device_t dev, uint16_t offset, uint16_t value)
{
struct siba_dev_softc *sd = device_get_ivars(dev);
sd->sd_ops->write_2(sd, offset, value);
}
void
siba_write_4(device_t dev, uint16_t offset, uint32_t value)
{
struct siba_dev_softc *sd = device_get_ivars(dev);
return (siba_write_4_sub(sd, offset, value));
}
static void
siba_write_4_sub(struct siba_dev_softc *sd, uint16_t offset, uint32_t value)
{
sd->sd_ops->write_4(sd, offset, value);
}
void
siba_read_multi_1(device_t dev, void *buffer, size_t count,
uint16_t offset)
{
struct siba_dev_softc *sd = device_get_ivars(dev);
sd->sd_ops->read_multi_1(sd, buffer, count, offset);
}
void
siba_read_multi_2(device_t dev, void *buffer, size_t count,
uint16_t offset)
{
struct siba_dev_softc *sd = device_get_ivars(dev);
sd->sd_ops->read_multi_2(sd, buffer, count, offset);
}
void
siba_read_multi_4(device_t dev, void *buffer, size_t count,
uint16_t offset)
{
struct siba_dev_softc *sd = device_get_ivars(dev);
sd->sd_ops->read_multi_4(sd, buffer, count, offset);
}
void
siba_write_multi_1(device_t dev, const void *buffer, size_t count,
uint16_t offset)
{
struct siba_dev_softc *sd = device_get_ivars(dev);
sd->sd_ops->write_multi_1(sd, buffer, count, offset);
}
void
siba_write_multi_2(device_t dev, const void *buffer, size_t count,
uint16_t offset)
{
struct siba_dev_softc *sd = device_get_ivars(dev);
sd->sd_ops->write_multi_2(sd, buffer, count, offset);
}
void
siba_write_multi_4(device_t dev, const void *buffer, size_t count,
uint16_t offset)
{
struct siba_dev_softc *sd = device_get_ivars(dev);
sd->sd_ops->write_multi_4(sd, buffer, count, offset);
}
static void
siba_cc_pmu_init(struct siba_cc *scc)
{
const struct siba_cc_pmu_res_updown *updown = NULL;
const struct siba_cc_pmu_res_depend *depend = NULL;
struct siba_dev_softc *sd = scc->scc_dev;
struct siba_softc *siba = sd->sd_bus;
uint32_t min = 0, max = 0, pmucap;
unsigned int i, updown_size, depend_size;
if ((scc->scc_caps & SIBA_CC_CAPS_PMU) == 0)
return;
pmucap = SIBA_CC_READ32(scc, SIBA_CC_PMUCAPS);
scc->scc_pmu.rev = (pmucap & SIBA_CC_PMUCAPS_REV);
DPRINTF(siba, SIBA_DEBUG_PMU, "PMU(r%u) found (caps %#x)\n",
scc->scc_pmu.rev, pmucap);
#if 0
if (scc->scc_pmu.rev >= 1) {
if (siba->siba_chiprev < 2 && siba->siba_chipid == 0x4325)
SIBA_CC_MASK32(scc, SIBA_CC_PMUCTL,
~SIBA_CC_PMUCTL_NOILP);
else
SIBA_CC_SET32(scc, SIBA_CC_PMUCTL,
SIBA_CC_PMUCTL_NOILP);
}
#endif
if (scc->scc_pmu.rev == 1) {
SIBA_CC_MASK32(scc, SIBA_CC_PMUCTL, ~SIBA_CC_PMUCTL_NOILP);
} else {
SIBA_CC_SET32(scc, SIBA_CC_PMUCTL, SIBA_CC_PMUCTL_NOILP);
}
/* initialize PLL & PMU resources */
switch (siba->siba_chipid) {
case 0x4312:
siba_cc_pmu1_pll0_init(scc, 0 /* use default */);
/* use the default: min = 0xcbb max = 0x7ffff */
break;
case 0x4322:
if (scc->scc_pmu.rev == 2) {
DPRINTF(siba, SIBA_DEBUG_PMU, "%s: chipid 0x4322; PLLing\n",
__func__);
SIBA_CC_WRITE32(scc, SIBA_CC_PLLCTL_ADDR, 0x0000000a);
SIBA_CC_WRITE32(scc, SIBA_CC_PLLCTL_DATA, 0x380005c0);
}
/* use the default: min = 0xcbb max = 0x7ffff */
break;
case 43222:
break;
case 0x4325:
siba_cc_pmu1_pll0_init(scc, 0 /* use default */);
updown = siba_cc_pmu_4325_updown;
updown_size = N(siba_cc_pmu_4325_updown);
depend = siba_cc_pmu_4325_depend;
depend_size = N(siba_cc_pmu_4325_depend);
min = (1 << SIBA_CC_PMU_4325_BURST) |
(1 << SIBA_CC_PMU_4325_LN);
if (SIBA_CC_READ32(scc, SIBA_CC_CHIPSTAT) &
SIBA_CC_CHST_4325_PMUTOP_2B)
min |= (1 << SIBA_CC_PMU_4325_CLBURST);
max = 0xfffff;
break;
case 0x4328:
siba_cc_pmu0_pll0_init(scc, 0 /* use default */);
updown = siba_cc_pmu_4328_updown;
updown_size = N(siba_cc_pmu_4328_updown);
depend = siba_cc_pmu_4328_depend;
depend_size = N(siba_cc_pmu_4328_depend);
min = (1 << SIBA_CC_PMU_4328_EXT_SWITCH_PWM) |
(1 << SIBA_CC_PMU_4328_BB_SWITCH_PWM) |
(1 << SIBA_CC_PMU_4328_CRYSTAL_EN);
max = 0xfffff;
break;
case 0x5354:
siba_cc_pmu0_pll0_init(scc, 0 /* use default */);
max = 0xfffff;
break;
default:
device_printf(siba->siba_dev,
"unknown chipid %#x for PLL & PMU init\n",
siba->siba_chipid);
}
if (updown) {
for (i = 0; i < updown_size; i++) {
SIBA_CC_WRITE32(scc, SIBA_CC_PMU_TABSEL,
updown[i].res);
SIBA_CC_WRITE32(scc, SIBA_CC_PMU_UPDNTM,
updown[i].updown);
}
}
if (depend) {
for (i = 0; i < depend_size; i++) {
SIBA_CC_WRITE32(scc, SIBA_CC_PMU_TABSEL,
depend[i].res);
switch (depend[i].task) {
case SIBA_CC_PMU_DEP_SET:
SIBA_CC_WRITE32(scc, SIBA_CC_PMU_DEPMSK,
depend[i].depend);
break;
case SIBA_CC_PMU_DEP_ADD:
SIBA_CC_SET32(scc, SIBA_CC_PMU_DEPMSK,
depend[i].depend);
break;
case SIBA_CC_PMU_DEP_REMOVE:
SIBA_CC_MASK32(scc, SIBA_CC_PMU_DEPMSK,
~(depend[i].depend));
break;
default:
KASSERT(0 == 1,
("%s:%d: assertion failed",
__func__, __LINE__));
}
}
}
if (min)
SIBA_CC_WRITE32(scc, SIBA_CC_PMU_MINRES, min);
if (max)
SIBA_CC_WRITE32(scc, SIBA_CC_PMU_MAXRES, max);
}
static void
siba_cc_power_init(struct siba_cc *scc)
{
struct siba_softc *siba = scc->scc_dev->sd_bus;
int maxfreq;
if (siba->siba_chipid == 0x4321) {
if (siba->siba_chiprev == 0)
SIBA_CC_WRITE32(scc, SIBA_CC_CHIPCTL, 0x3a4);
else if (siba->siba_chiprev == 1)
SIBA_CC_WRITE32(scc, SIBA_CC_CHIPCTL, 0xa4);
}
if ((scc->scc_caps & SIBA_CC_CAPS_PWCTL) == 0)
return;
if (scc->scc_dev->sd_id.sd_rev >= 10)
SIBA_CC_WRITE32(scc, SIBA_CC_CLKSYSCTL,
(SIBA_CC_READ32(scc, SIBA_CC_CLKSYSCTL) &
0xffff) | 0x40000);
else {
maxfreq = siba_cc_clockfreq(scc, 1);
SIBA_CC_WRITE32(scc, SIBA_CC_PLLONDELAY,
(maxfreq * 150 + 999999) / 1000000);
SIBA_CC_WRITE32(scc, SIBA_CC_FREFSELDELAY,
(maxfreq * 15 + 999999) / 1000000);
}
}
static void
siba_cc_powerup_delay(struct siba_cc *scc)
{
struct siba_softc *siba = scc->scc_dev->sd_bus;
int min;
if (siba->siba_type != SIBA_TYPE_PCI)
return;
if (scc->scc_caps & SIBA_CC_CAPS_PMU) {
if ((siba->siba_chipid == 0x4312) ||
(siba->siba_chipid == 0x4322) ||
(siba->siba_chipid == 0x4328)) {
scc->scc_powerup_delay = 7000;
} else {
/* 0x4325 is marked as TODO */
scc->scc_powerup_delay = 15000;
}
return;
}
if (!(scc->scc_caps & SIBA_CC_CAPS_PWCTL))
return;
min = siba_cc_clockfreq(scc, 0);
scc->scc_powerup_delay =
howmany((SIBA_CC_READ32(scc, SIBA_CC_PLLONDELAY) + 2) * 1000000,
min);
}
static int
siba_cc_clockfreq(struct siba_cc *scc, int max)
{
enum siba_clksrc src;
int div = 1, limit = 0;
src = siba_cc_clksrc(scc);
if (scc->scc_dev->sd_id.sd_rev < 6) {
div = (src == SIBA_CC_CLKSRC_PCI) ? 64 :
(src == SIBA_CC_CLKSRC_CRYSTAL) ? 32 : 1;
KASSERT(div != 1,
("%s: unknown clock %d", __func__, src));
} else if (scc->scc_dev->sd_id.sd_rev < 10) {
switch (src) {
case SIBA_CC_CLKSRC_CRYSTAL:
case SIBA_CC_CLKSRC_PCI:
div = ((SIBA_CC_READ32(scc, SIBA_CC_CLKSLOW) >> 16) +
1) * 4;
break;
case SIBA_CC_CLKSRC_LOWPW:
break;
}
} else
div = ((SIBA_CC_READ32(scc, SIBA_CC_CLKSYSCTL) >> 16) + 1) * 4;
switch (src) {
case SIBA_CC_CLKSRC_CRYSTAL:
limit = (max) ? 20200000 : 19800000;
break;
case SIBA_CC_CLKSRC_LOWPW:
limit = (max) ? 43000 : 25000;
break;
case SIBA_CC_CLKSRC_PCI:
limit = (max) ? 34000000 : 25000000;
break;
}
return (limit / div);
}
static void
siba_cc_pmu1_pll0_init(struct siba_cc *scc, uint32_t freq)
{
struct siba_dev_softc *sd = scc->scc_dev;
struct siba_softc *siba = sd->sd_bus;
const struct siba_cc_pmu1_plltab *e = NULL;
uint32_t bufsth = 0, pll, pmu;
unsigned int i;
KASSERT(freq == 0, ("%s:%d: assertion vail", __func__, __LINE__));
if (siba->siba_chipid == 0x4312) {
scc->scc_pmu.freq = 20000;
return;
}
e = siba_cc_pmu1_plltab_find(SIBA_CC_PMU1_DEFAULT_FREQ);
KASSERT(e != NULL, ("%s:%d: assertion vail", __func__, __LINE__));
scc->scc_pmu.freq = e->freq;
pmu = SIBA_CC_READ32(scc, SIBA_CC_PMUCTL);
if (SIBA_CC_PMUCTL_XF_VAL(pmu) == e->xf)
return;
DPRINTF(siba, SIBA_DEBUG_PLL, "change PLL value to %u.%03u MHz\n",
(e->freq / 1000), (e->freq % 1000));
/* turn PLL off */
switch (siba->siba_chipid) {
case 0x4325:
bufsth = 0x222222;
SIBA_CC_MASK32(scc, SIBA_CC_PMU_MINRES,
~((1 << SIBA_CC_PMU_4325_BBPLL_PWR) |
(1 << SIBA_CC_PMU_4325_HT)));
SIBA_CC_MASK32(scc, SIBA_CC_PMU_MAXRES,
~((1 << SIBA_CC_PMU_4325_BBPLL_PWR) |
(1 << SIBA_CC_PMU_4325_HT)));
break;
default:
KASSERT(0 == 1,
("%s:%d: assertion failed", __func__, __LINE__));
}
for (i = 0; i < 1500; i++) {
if (!(SIBA_CC_READ32(scc, SIBA_CC_CLKCTLSTATUS) &
SIBA_CC_CLKCTLSTATUS_HT))
break;
DELAY(10);
}
if (SIBA_CC_READ32(scc, SIBA_CC_CLKCTLSTATUS) & SIBA_CC_CLKCTLSTATUS_HT)
device_printf(siba->siba_dev, "failed to turn PLL off!\n");
pll = siba_cc_pll_read(scc, SIBA_CC_PMU1_PLL0);
pll &= ~(SIBA_CC_PMU1_PLL0_P1DIV | SIBA_CC_PMU1_PLL0_P2DIV);
pll |= ((uint32_t)e->p1div << 20) & SIBA_CC_PMU1_PLL0_P1DIV;
pll |= ((uint32_t)e->p2div << 24) & SIBA_CC_PMU1_PLL0_P2DIV;
siba_cc_pll_write(scc, SIBA_CC_PMU1_PLL0, pll);
pll = siba_cc_pll_read(scc, SIBA_CC_PMU1_PLL2);
pll &= ~(SIBA_CC_PMU1_PLL2_NDIVINT | SIBA_CC_PMU1_PLL2_NDIVMODE);
pll |= ((uint32_t)e->ndiv_int << 20) & SIBA_CC_PMU1_PLL2_NDIVINT;
pll |= (1 << 17) & SIBA_CC_PMU1_PLL2_NDIVMODE;
siba_cc_pll_write(scc, SIBA_CC_PMU1_PLL2, pll);
pll = siba_cc_pll_read(scc, SIBA_CC_PMU1_PLL3);
pll &= ~SIBA_CC_PMU1_PLL3_NDIVFRAC;
pll |= ((uint32_t)e->ndiv_frac << 0) & SIBA_CC_PMU1_PLL3_NDIVFRAC;
siba_cc_pll_write(scc, SIBA_CC_PMU1_PLL3, pll);
if (bufsth) {
pll = siba_cc_pll_read(scc, SIBA_CC_PMU1_PLL5);
pll &= ~SIBA_CC_PMU1_PLL5_CLKDRV;
pll |= (bufsth << 8) & SIBA_CC_PMU1_PLL5_CLKDRV;
siba_cc_pll_write(scc, SIBA_CC_PMU1_PLL5, pll);
}
pmu = SIBA_CC_READ32(scc, SIBA_CC_PMUCTL);
pmu &= ~(SIBA_CC_PMUCTL_ILP | SIBA_CC_PMUCTL_XF);
pmu |= ((((uint32_t)e->freq + 127) / 128 - 1) << 16) &
SIBA_CC_PMUCTL_ILP;
pmu |= ((uint32_t)e->xf << 2) & SIBA_CC_PMUCTL_XF;
SIBA_CC_WRITE32(scc, SIBA_CC_PMUCTL, pmu);
}
static void
siba_cc_pmu0_pll0_init(struct siba_cc *scc, uint32_t xtalfreq)
{
struct siba_dev_softc *sd = scc->scc_dev;
struct siba_softc *siba = sd->sd_bus;
const struct siba_cc_pmu0_plltab *e = NULL;
uint32_t pmu, tmp, pll;
unsigned int i;
if ((siba->siba_chipid == 0x5354) && !xtalfreq)
xtalfreq = 25000;
if (xtalfreq)
e = siba_cc_pmu0_plltab_findentry(xtalfreq);
if (!e)
e = siba_cc_pmu0_plltab_findentry(
SIBA_CC_PMU0_DEFAULT_XTALFREQ);
KASSERT(e != NULL, ("%s:%d: fail", __func__, __LINE__));
xtalfreq = e->freq;
scc->scc_pmu.freq = e->freq;
pmu = SIBA_CC_READ32(scc, SIBA_CC_PMUCTL);
if (((pmu & SIBA_CC_PMUCTL_XF) >> 2) == e->xf)
return;
DPRINTF(siba, SIBA_DEBUG_PLL, "change PLL value to %u.%03u MHz\n",
(xtalfreq / 1000), (xtalfreq % 1000));
KASSERT(siba->siba_chipid == 0x4328 || siba->siba_chipid == 0x5354,
("%s:%d: fail", __func__, __LINE__));
switch (siba->siba_chipid) {
case 0x4328:
SIBA_CC_MASK32(scc, SIBA_CC_PMU_MINRES,
~(1 << SIBA_CC_PMU_4328_BB_PLL_PU));
SIBA_CC_MASK32(scc, SIBA_CC_PMU_MAXRES,
~(1 << SIBA_CC_PMU_4328_BB_PLL_PU));
break;
case 0x5354:
SIBA_CC_MASK32(scc, SIBA_CC_PMU_MINRES,
~(1 << SIBA_CC_PMU_5354_BB_PLL_PU));
SIBA_CC_MASK32(scc, SIBA_CC_PMU_MAXRES,
~(1 << SIBA_CC_PMU_5354_BB_PLL_PU));
break;
}
for (i = 1500; i; i--) {
tmp = SIBA_CC_READ32(scc, SIBA_CC_CLKCTLSTATUS);
if (!(tmp & SIBA_CC_CLKCTLSTATUS_HT))
break;
DELAY(10);
}
tmp = SIBA_CC_READ32(scc, SIBA_CC_CLKCTLSTATUS);
if (tmp & SIBA_CC_CLKCTLSTATUS_HT)
device_printf(siba->siba_dev, "failed to turn PLL off!\n");
/* set PDIV */
pll = siba_cc_pll_read(scc, SIBA_CC_PMU0_PLL0);
if (xtalfreq >= SIBA_CC_PMU0_PLL0_PDIV_FREQ)
pll |= SIBA_CC_PMU0_PLL0_PDIV_MSK;
else
pll &= ~SIBA_CC_PMU0_PLL0_PDIV_MSK;
siba_cc_pll_write(scc, SIBA_CC_PMU0_PLL0, pll);
/* set WILD */
pll = siba_cc_pll_read(scc, SIBA_CC_PMU0_PLL1);
pll &= ~(SIBA_CC_PMU0_PLL1_STOPMOD | SIBA_CC_PMU0_PLL1_IMSK |
SIBA_CC_PMU0_PLL1_FMSK);
pll |= ((uint32_t)e->wb_int << 28) & SIBA_CC_PMU0_PLL1_IMSK;
pll |= ((uint32_t)e->wb_frac << 8) & SIBA_CC_PMU0_PLL1_FMSK;
if (e->wb_frac == 0)
pll |= SIBA_CC_PMU0_PLL1_STOPMOD;
siba_cc_pll_write(scc, SIBA_CC_PMU0_PLL1, pll);
/* set WILD */
pll = siba_cc_pll_read(scc, SIBA_CC_PMU0_PLL2);
pll &= ~SIBA_CC_PMU0_PLL2_IMSKHI;
pll |= (((uint32_t)e->wb_int >> 4) << 0) & SIBA_CC_PMU0_PLL2_IMSKHI;
siba_cc_pll_write(scc, SIBA_CC_PMU0_PLL2, pll);
/* set freq and divisor. */
pmu = SIBA_CC_READ32(scc, SIBA_CC_PMUCTL);
pmu &= ~SIBA_CC_PMUCTL_ILP;
pmu |= (((xtalfreq + 127) / 128 - 1) << 16) & SIBA_CC_PMUCTL_ILP;
pmu &= ~SIBA_CC_PMUCTL_XF;
pmu |= ((uint32_t)e->xf << 2) & SIBA_CC_PMUCTL_XF;
SIBA_CC_WRITE32(scc, SIBA_CC_PMUCTL, pmu);
}
static enum siba_clksrc
siba_cc_clksrc(struct siba_cc *scc)
{
struct siba_dev_softc *sd = scc->scc_dev;
struct siba_softc *siba = sd->sd_bus;
if (sd->sd_id.sd_rev < 6) {
if (siba->siba_type == SIBA_TYPE_PCI) {
if (pci_read_config(siba->siba_dev, SIBA_GPIO_OUT, 4) &
0x10)
return (SIBA_CC_CLKSRC_PCI);
return (SIBA_CC_CLKSRC_CRYSTAL);
}
if (siba->siba_type == SIBA_TYPE_SSB ||
siba->siba_type == SIBA_TYPE_PCMCIA)
return (SIBA_CC_CLKSRC_CRYSTAL);
}
if (sd->sd_id.sd_rev < 10) {
switch (SIBA_CC_READ32(scc, SIBA_CC_CLKSLOW) & 0x7) {
case 0:
return (SIBA_CC_CLKSRC_LOWPW);
case 1:
return (SIBA_CC_CLKSRC_CRYSTAL);
case 2:
return (SIBA_CC_CLKSRC_PCI);
default:
break;
}
}
return (SIBA_CC_CLKSRC_CRYSTAL);
}
static const struct siba_cc_pmu1_plltab *
siba_cc_pmu1_plltab_find(uint32_t crystalfreq)
{
const struct siba_cc_pmu1_plltab *e;
unsigned int i;
for (i = 0; i < N(siba_cc_pmu1_plltab); i++) {
e = &siba_cc_pmu1_plltab[i];
if (crystalfreq == e->freq)
return (e);
}
return (NULL);
}
static uint32_t
siba_cc_pll_read(struct siba_cc *scc, uint32_t offset)
{
SIBA_CC_WRITE32(scc, SIBA_CC_PLLCTL_ADDR, offset);
return (SIBA_CC_READ32(scc, SIBA_CC_PLLCTL_DATA));
}
static void
siba_cc_pll_write(struct siba_cc *scc, uint32_t offset, uint32_t value)
{
SIBA_CC_WRITE32(scc, SIBA_CC_PLLCTL_ADDR, offset);
SIBA_CC_WRITE32(scc, SIBA_CC_PLLCTL_DATA, value);
}
static const struct siba_cc_pmu0_plltab *
siba_cc_pmu0_plltab_findentry(uint32_t crystalfreq)
{
const struct siba_cc_pmu0_plltab *e;
unsigned int i;
for (i = 0; i < N(siba_cc_pmu0_plltab); i++) {
e = &siba_cc_pmu0_plltab[i];
if (e->freq == crystalfreq)
return (e);
}
return (NULL);
}
static int
siba_pci_sprom(struct siba_softc *siba, struct siba_sprom *sprom)
{
int error = ENOMEM;
uint16_t *buf;
buf = malloc(SIBA_SPROMSIZE_R123 * sizeof(uint16_t),
M_DEVBUF, M_NOWAIT | M_ZERO);
if (buf == NULL)
return (ENOMEM);
siba_sprom_read(siba, buf, SIBA_SPROMSIZE_R123);
error = sprom_check_crc(buf, siba->siba_spromsize);
if (error) {
free(buf, M_DEVBUF);
buf = malloc(SIBA_SPROMSIZE_R4 * sizeof(uint16_t),
M_DEVBUF, M_NOWAIT | M_ZERO);
if (buf == NULL)
return (ENOMEM);
siba_sprom_read(siba, buf, SIBA_SPROMSIZE_R4);
error = sprom_check_crc(buf, siba->siba_spromsize);
if (error)
device_printf(siba->siba_dev, "warn: bad SPROM CRC\n");
}
bzero(sprom, sizeof(*sprom));
sprom->rev = buf[siba->siba_spromsize - 1] & 0x00FF;
DPRINTF(siba, SIBA_DEBUG_SPROM, "SPROM rev %d\n",
sprom->rev);
memset(sprom->mac_eth, 0xff, 6);
memset(sprom->mac_80211a, 0xff, 6);
if ((siba->siba_chipid & 0xff00) == 0x4400) {
sprom->rev = 1;
siba_sprom_r123(sprom, buf);
} else if (siba->siba_chipid == 0x4321) {
sprom->rev = 4;
siba_sprom_r45(sprom, buf);
} else {
switch (sprom->rev) {
case 1:
case 2:
case 3:
siba_sprom_r123(sprom, buf);
break;
case 4:
case 5:
siba_sprom_r45(sprom, buf);
break;
case 8:
siba_sprom_r8(sprom, buf);
break;
default:
device_printf(siba->siba_dev,
"unknown SPROM revision %d.\n", sprom->rev);
siba_sprom_r123(sprom, buf);
}
}
if (sprom->bf_lo == 0xffff)
sprom->bf_lo = 0;
if (sprom->bf_hi == 0xffff)
sprom->bf_hi = 0;
free(buf, M_DEVBUF);
return (error);
}
static int
siba_sprom_read(struct siba_softc *siba, uint16_t *sprom, uint16_t len)
{
int i;
for (i = 0; i < len; i++)
sprom[i] = SIBA_READ_2(siba, SIBA_SPROM_BASE + (i * 2));
siba->siba_spromsize = len;
return (0);
}
static int
sprom_check_crc(const uint16_t *sprom, size_t size)
{
int word;
uint8_t crc0, crc1 = 0xff;
crc0 = (sprom[size - 1] & SIBA_SPROM_REV_CRC) >> 8;
for (word = 0; word < size - 1; word++) {
crc1 = siba_crc8(crc1, sprom[word] & 0x00ff);
crc1 = siba_crc8(crc1, (sprom[word] & 0xff00) >> 8);
}
crc1 = siba_crc8(crc1, sprom[size - 1] & 0x00ff);
crc1 ^= 0xff;
return ((crc0 != crc1) ? EPROTO : 0);
}
static uint8_t
siba_crc8(uint8_t crc, uint8_t data)
{
static const uint8_t ct[] = {
0x00, 0xf7, 0xb9, 0x4e, 0x25, 0xd2, 0x9c, 0x6b,
0x4a, 0xbd, 0xf3, 0x04, 0x6f, 0x98, 0xd6, 0x21,
0x94, 0x63, 0x2d, 0xda, 0xb1, 0x46, 0x08, 0xff,
0xde, 0x29, 0x67, 0x90, 0xfb, 0x0c, 0x42, 0xb5,
0x7f, 0x88, 0xc6, 0x31, 0x5a, 0xad, 0xe3, 0x14,
0x35, 0xc2, 0x8c, 0x7b, 0x10, 0xe7, 0xa9, 0x5e,
0xeb, 0x1c, 0x52, 0xa5, 0xce, 0x39, 0x77, 0x80,
0xa1, 0x56, 0x18, 0xef, 0x84, 0x73, 0x3d, 0xca,
0xfe, 0x09, 0x47, 0xb0, 0xdb, 0x2c, 0x62, 0x95,
0xb4, 0x43, 0x0d, 0xfa, 0x91, 0x66, 0x28, 0xdf,
0x6a, 0x9d, 0xd3, 0x24, 0x4f, 0xb8, 0xf6, 0x01,
0x20, 0xd7, 0x99, 0x6e, 0x05, 0xf2, 0xbc, 0x4b,
0x81, 0x76, 0x38, 0xcf, 0xa4, 0x53, 0x1d, 0xea,
0xcb, 0x3c, 0x72, 0x85, 0xee, 0x19, 0x57, 0xa0,
0x15, 0xe2, 0xac, 0x5b, 0x30, 0xc7, 0x89, 0x7e,
0x5f, 0xa8, 0xe6, 0x11, 0x7a, 0x8d, 0xc3, 0x34,
0xab, 0x5c, 0x12, 0xe5, 0x8e, 0x79, 0x37, 0xc0,
0xe1, 0x16, 0x58, 0xaf, 0xc4, 0x33, 0x7d, 0x8a,
0x3f, 0xc8, 0x86, 0x71, 0x1a, 0xed, 0xa3, 0x54,
0x75, 0x82, 0xcc, 0x3b, 0x50, 0xa7, 0xe9, 0x1e,
0xd4, 0x23, 0x6d, 0x9a, 0xf1, 0x06, 0x48, 0xbf,
0x9e, 0x69, 0x27, 0xd0, 0xbb, 0x4c, 0x02, 0xf5,
0x40, 0xb7, 0xf9, 0x0e, 0x65, 0x92, 0xdc, 0x2b,
0x0a, 0xfd, 0xb3, 0x44, 0x2f, 0xd8, 0x96, 0x61,
0x55, 0xa2, 0xec, 0x1b, 0x70, 0x87, 0xc9, 0x3e,
0x1f, 0xe8, 0xa6, 0x51, 0x3a, 0xcd, 0x83, 0x74,
0xc1, 0x36, 0x78, 0x8f, 0xe4, 0x13, 0x5d, 0xaa,
0x8b, 0x7c, 0x32, 0xc5, 0xae, 0x59, 0x17, 0xe0,
0x2a, 0xdd, 0x93, 0x64, 0x0f, 0xf8, 0xb6, 0x41,
0x60, 0x97, 0xd9, 0x2e, 0x45, 0xb2, 0xfc, 0x0b,
0xbe, 0x49, 0x07, 0xf0, 0x9b, 0x6c, 0x22, 0xd5,
0xf4, 0x03, 0x4d, 0xba, 0xd1, 0x26, 0x68, 0x9f,
};
return (ct[crc ^ data]);
}
#define SIBA_LOWEST_SET_BIT(__mask) ((((__mask) - 1) & (__mask)) ^ (__mask))
#define SIBA_OFFSET(offset) \
(((offset) - SIBA_SPROM_BASE) / sizeof(uint16_t))
#define SIBA_SHIFTOUT_SUB(__x, __mask) \
(((__x) & (__mask)) / SIBA_LOWEST_SET_BIT(__mask))
#define SIBA_SHIFTOUT(_var, _offset, _mask) \
out->_var = SIBA_SHIFTOUT_SUB(in[SIBA_OFFSET(_offset)], (_mask))
#define SIBA_SHIFTOUT_4(_var, _offset, _mask, _shift) \
out->_var = ((((uint32_t)in[SIBA_OFFSET((_offset)+2)] << 16 | \
in[SIBA_OFFSET(_offset)]) & (_mask)) >> (_shift))
static void
siba_sprom_r123(struct siba_sprom *out, const uint16_t *in)
{
int i;
uint16_t v;
int8_t gain;
uint16_t loc[3];
if (out->rev == 3)
loc[0] = SIBA_SPROM3_MAC_80211BG;
else {
loc[0] = SIBA_SPROM1_MAC_80211BG;
loc[1] = SIBA_SPROM1_MAC_ETH;
loc[2] = SIBA_SPROM1_MAC_80211A;
}
for (i = 0; i < 3; i++) {
v = in[SIBA_OFFSET(loc[0]) + i];
*(((uint16_t *)out->mac_80211bg) + i) = htobe16(v);
}
if (out->rev < 3) {
for (i = 0; i < 3; i++) {
v = in[SIBA_OFFSET(loc[1]) + i];
*(((uint16_t *)out->mac_eth) + i) = htobe16(v);
}
for (i = 0; i < 3; i++) {
v = in[SIBA_OFFSET(loc[2]) + i];
*(((uint16_t *)out->mac_80211a) + i) = htobe16(v);
}
}
SIBA_SHIFTOUT(mii_eth0, SIBA_SPROM1_ETHPHY,
SIBA_SPROM1_ETHPHY_MII_ETH0);
SIBA_SHIFTOUT(mii_eth1, SIBA_SPROM1_ETHPHY,
SIBA_SPROM1_ETHPHY_MII_ETH1);
SIBA_SHIFTOUT(mdio_eth0, SIBA_SPROM1_ETHPHY,
SIBA_SPROM1_ETHPHY_MDIO_ETH0);
SIBA_SHIFTOUT(mdio_eth1, SIBA_SPROM1_ETHPHY,
SIBA_SPROM1_ETHPHY_MDIO_ETH1);
SIBA_SHIFTOUT(brev, SIBA_SPROM1_BOARDINFO, SIBA_SPROM1_BOARDINFO_BREV);
SIBA_SHIFTOUT(ccode, SIBA_SPROM1_BOARDINFO,
SIBA_SPROM1_BOARDINFO_CCODE);
SIBA_SHIFTOUT(ant_a, SIBA_SPROM1_BOARDINFO, SIBA_SPROM1_BOARDINFO_ANTA);
SIBA_SHIFTOUT(ant_bg, SIBA_SPROM1_BOARDINFO,
SIBA_SPROM1_BOARDINFO_ANTBG);
SIBA_SHIFTOUT(pa0b0, SIBA_SPROM1_PA0B0, 0xffff);
SIBA_SHIFTOUT(pa0b1, SIBA_SPROM1_PA0B1, 0xffff);
SIBA_SHIFTOUT(pa0b2, SIBA_SPROM1_PA0B2, 0xffff);
SIBA_SHIFTOUT(pa1b0, SIBA_SPROM1_PA1B0, 0xffff);
SIBA_SHIFTOUT(pa1b1, SIBA_SPROM1_PA1B1, 0xffff);
SIBA_SHIFTOUT(pa1b2, SIBA_SPROM1_PA1B2, 0xffff);
SIBA_SHIFTOUT(gpio0, SIBA_SPROM1_GPIOA, SIBA_SPROM1_GPIOA_P0);
SIBA_SHIFTOUT(gpio1, SIBA_SPROM1_GPIOA, SIBA_SPROM1_GPIOA_P1);
SIBA_SHIFTOUT(gpio2, SIBA_SPROM1_GPIOB, SIBA_SPROM1_GPIOB_P2);
SIBA_SHIFTOUT(gpio3, SIBA_SPROM1_GPIOB, SIBA_SPROM1_GPIOB_P3);
SIBA_SHIFTOUT(maxpwr_a, SIBA_SPROM1_MAXPWR, SIBA_SPROM1_MAXPWR_A);
SIBA_SHIFTOUT(maxpwr_bg, SIBA_SPROM1_MAXPWR, SIBA_SPROM1_MAXPWR_BG);
SIBA_SHIFTOUT(tssi_a, SIBA_SPROM1_TSSI, SIBA_SPROM1_TSSI_A);
SIBA_SHIFTOUT(tssi_bg, SIBA_SPROM1_TSSI, SIBA_SPROM1_TSSI_BG);
SIBA_SHIFTOUT(bf_lo, SIBA_SPROM1_BFLOW, 0xffff);
if (out->rev >= 2)
SIBA_SHIFTOUT(bf_hi, SIBA_SPROM2_BFHIGH, 0xffff);
/* antenna gain */
gain = siba_sprom_r123_antgain(out->rev, in, SIBA_SPROM1_AGAIN_BG, 0);
out->again.ghz24.a0 = out->again.ghz24.a1 = gain;
out->again.ghz24.a2 = out->again.ghz24.a3 = gain;
gain = siba_sprom_r123_antgain(out->rev, in, SIBA_SPROM1_AGAIN_A, 8);
out->again.ghz5.a0 = out->again.ghz5.a1 = gain;
out->again.ghz5.a2 = out->again.ghz5.a3 = gain;
}
static void
siba_sprom_r458(struct siba_sprom *out, const uint16_t *in)
{
SIBA_SHIFTOUT(txpid2g[0], SIBA_SPROM4_TXPID2G01,
SIBA_SPROM4_TXPID2G0);
SIBA_SHIFTOUT(txpid2g[1], SIBA_SPROM4_TXPID2G01,
SIBA_SPROM4_TXPID2G1);
SIBA_SHIFTOUT(txpid2g[2], SIBA_SPROM4_TXPID2G23,
SIBA_SPROM4_TXPID2G2);
SIBA_SHIFTOUT(txpid2g[3], SIBA_SPROM4_TXPID2G23,
SIBA_SPROM4_TXPID2G3);
SIBA_SHIFTOUT(txpid5gl[0], SIBA_SPROM4_TXPID5GL01,
SIBA_SPROM4_TXPID5GL0);
SIBA_SHIFTOUT(txpid5gl[1], SIBA_SPROM4_TXPID5GL01,
SIBA_SPROM4_TXPID5GL1);
SIBA_SHIFTOUT(txpid5gl[2], SIBA_SPROM4_TXPID5GL23,
SIBA_SPROM4_TXPID5GL2);
SIBA_SHIFTOUT(txpid5gl[3], SIBA_SPROM4_TXPID5GL23,
SIBA_SPROM4_TXPID5GL3);
SIBA_SHIFTOUT(txpid5g[0], SIBA_SPROM4_TXPID5G01,
SIBA_SPROM4_TXPID5G0);
SIBA_SHIFTOUT(txpid5g[1], SIBA_SPROM4_TXPID5G01,
SIBA_SPROM4_TXPID5G1);
SIBA_SHIFTOUT(txpid5g[2], SIBA_SPROM4_TXPID5G23,
SIBA_SPROM4_TXPID5G2);
SIBA_SHIFTOUT(txpid5g[3], SIBA_SPROM4_TXPID5G23,
SIBA_SPROM4_TXPID5G3);
SIBA_SHIFTOUT(txpid5gh[0], SIBA_SPROM4_TXPID5GH01,
SIBA_SPROM4_TXPID5GH0);
SIBA_SHIFTOUT(txpid5gh[1], SIBA_SPROM4_TXPID5GH01,
SIBA_SPROM4_TXPID5GH1);
SIBA_SHIFTOUT(txpid5gh[2], SIBA_SPROM4_TXPID5GH23,
SIBA_SPROM4_TXPID5GH2);
SIBA_SHIFTOUT(txpid5gh[3], SIBA_SPROM4_TXPID5GH23,
SIBA_SPROM4_TXPID5GH3);
}
static void
siba_sprom_r45(struct siba_sprom *out, const uint16_t *in)
{
int i;
uint16_t v;
uint16_t mac_80211bg_offset;
const uint16_t pwr_info_offset[] = {
SIBA_SPROM4_PWR_INFO_CORE0, SIBA_SPROM4_PWR_INFO_CORE1,
SIBA_SPROM4_PWR_INFO_CORE2, SIBA_SPROM4_PWR_INFO_CORE3
};
if (out->rev == 4)
mac_80211bg_offset = SIBA_SPROM4_MAC_80211BG;
else
mac_80211bg_offset = SIBA_SPROM5_MAC_80211BG;
for (i = 0; i < 3; i++) {
v = in[SIBA_OFFSET(mac_80211bg_offset) + i];
*(((uint16_t *)out->mac_80211bg) + i) = htobe16(v);
}
SIBA_SHIFTOUT(mii_eth0, SIBA_SPROM4_ETHPHY, SIBA_SPROM4_ETHPHY_ET0A);
SIBA_SHIFTOUT(mii_eth1, SIBA_SPROM4_ETHPHY, SIBA_SPROM4_ETHPHY_ET1A);
if (out->rev == 4) {
SIBA_SHIFTOUT(ccode, SIBA_SPROM4_CCODE, 0xffff);
SIBA_SHIFTOUT(bf_lo, SIBA_SPROM4_BFLOW, 0xffff);
SIBA_SHIFTOUT(bf_hi, SIBA_SPROM4_BFHIGH, 0xffff);
} else {
SIBA_SHIFTOUT(ccode, SIBA_SPROM5_CCODE, 0xffff);
SIBA_SHIFTOUT(bf_lo, SIBA_SPROM5_BFLOW, 0xffff);
SIBA_SHIFTOUT(bf_hi, SIBA_SPROM5_BFHIGH, 0xffff);
}
SIBA_SHIFTOUT(ant_a, SIBA_SPROM4_ANTAVAIL, SIBA_SPROM4_ANTAVAIL_A);
SIBA_SHIFTOUT(ant_bg, SIBA_SPROM4_ANTAVAIL, SIBA_SPROM4_ANTAVAIL_BG);
SIBA_SHIFTOUT(maxpwr_bg, SIBA_SPROM4_MAXP_BG, SIBA_SPROM4_MAXP_BG_MASK);
SIBA_SHIFTOUT(tssi_bg, SIBA_SPROM4_MAXP_BG, SIBA_SPROM4_TSSI_BG);
SIBA_SHIFTOUT(maxpwr_a, SIBA_SPROM4_MAXP_A, SIBA_SPROM4_MAXP_A_MASK);
SIBA_SHIFTOUT(tssi_a, SIBA_SPROM4_MAXP_A, SIBA_SPROM4_TSSI_A);
if (out->rev == 4) {
SIBA_SHIFTOUT(gpio0, SIBA_SPROM4_GPIOA, SIBA_SPROM4_GPIOA_P0);
SIBA_SHIFTOUT(gpio1, SIBA_SPROM4_GPIOA, SIBA_SPROM4_GPIOA_P1);
SIBA_SHIFTOUT(gpio2, SIBA_SPROM4_GPIOB, SIBA_SPROM4_GPIOB_P2);
SIBA_SHIFTOUT(gpio3, SIBA_SPROM4_GPIOB, SIBA_SPROM4_GPIOB_P3);
} else {
SIBA_SHIFTOUT(gpio0, SIBA_SPROM5_GPIOA, SIBA_SPROM5_GPIOA_P0);
SIBA_SHIFTOUT(gpio1, SIBA_SPROM5_GPIOA, SIBA_SPROM5_GPIOA_P1);
SIBA_SHIFTOUT(gpio2, SIBA_SPROM5_GPIOB, SIBA_SPROM5_GPIOB_P2);
SIBA_SHIFTOUT(gpio3, SIBA_SPROM5_GPIOB, SIBA_SPROM5_GPIOB_P3);
}
/* antenna gain */
SIBA_SHIFTOUT(again.ghz24.a0, SIBA_SPROM4_AGAIN01, SIBA_SPROM4_AGAIN0);
SIBA_SHIFTOUT(again.ghz24.a1, SIBA_SPROM4_AGAIN01, SIBA_SPROM4_AGAIN1);
SIBA_SHIFTOUT(again.ghz24.a2, SIBA_SPROM4_AGAIN23, SIBA_SPROM4_AGAIN2);
SIBA_SHIFTOUT(again.ghz24.a3, SIBA_SPROM4_AGAIN23, SIBA_SPROM4_AGAIN3);
bcopy(&out->again.ghz24, &out->again.ghz5, sizeof(out->again.ghz5));
/* Extract core power info */
for (i = 0; i < nitems(pwr_info_offset); i++) {
uint16_t o = pwr_info_offset[i];
SIBA_SHIFTOUT(core_pwr_info[i].itssi_2g, o + SIBA_SPROM4_2G_MAXP_ITSSI,
SIBA_SPROM4_2G_ITSSI);
SIBA_SHIFTOUT(core_pwr_info[i].maxpwr_2g, o + SIBA_SPROM4_2G_MAXP_ITSSI,
SIBA_SPROM4_2G_MAXP);
SIBA_SHIFTOUT(core_pwr_info[i].pa_2g[0], o + SIBA_SPROM4_2G_PA_0, ~0);
SIBA_SHIFTOUT(core_pwr_info[i].pa_2g[1], o + SIBA_SPROM4_2G_PA_1, ~0);
SIBA_SHIFTOUT(core_pwr_info[i].pa_2g[2], o + SIBA_SPROM4_2G_PA_2, ~0);
SIBA_SHIFTOUT(core_pwr_info[i].pa_2g[3], o + SIBA_SPROM4_2G_PA_3, ~0);
SIBA_SHIFTOUT(core_pwr_info[i].itssi_5g, o + SIBA_SPROM4_5G_MAXP_ITSSI,
SIBA_SPROM4_5G_ITSSI);
SIBA_SHIFTOUT(core_pwr_info[i].maxpwr_5g, o + SIBA_SPROM4_5G_MAXP_ITSSI,
SIBA_SPROM4_5G_MAXP);
SIBA_SHIFTOUT(core_pwr_info[i].maxpwr_5gh, o + SIBA_SPROM4_5GHL_MAXP,
SIBA_SPROM4_5GH_MAXP);
SIBA_SHIFTOUT(core_pwr_info[i].maxpwr_5gl, o + SIBA_SPROM4_5GHL_MAXP,
SIBA_SPROM4_5GL_MAXP);
SIBA_SHIFTOUT(core_pwr_info[i].pa_5gl[0], o + SIBA_SPROM4_5GL_PA_0, ~0);
SIBA_SHIFTOUT(core_pwr_info[i].pa_5gl[1], o + SIBA_SPROM4_5GL_PA_1, ~0);
SIBA_SHIFTOUT(core_pwr_info[i].pa_5gl[2], o + SIBA_SPROM4_5GL_PA_2, ~0);
SIBA_SHIFTOUT(core_pwr_info[i].pa_5gl[3], o + SIBA_SPROM4_5GL_PA_3, ~0);
SIBA_SHIFTOUT(core_pwr_info[i].pa_5g[0], o + SIBA_SPROM4_5G_PA_0, ~0);
SIBA_SHIFTOUT(core_pwr_info[i].pa_5g[1], o + SIBA_SPROM4_5G_PA_1, ~0);
SIBA_SHIFTOUT(core_pwr_info[i].pa_5g[2], o + SIBA_SPROM4_5G_PA_2, ~0);
SIBA_SHIFTOUT(core_pwr_info[i].pa_5g[3], o + SIBA_SPROM4_5G_PA_3, ~0);
SIBA_SHIFTOUT(core_pwr_info[i].pa_5gh[0], o + SIBA_SPROM4_5GH_PA_0, ~0);
SIBA_SHIFTOUT(core_pwr_info[i].pa_5gh[1], o + SIBA_SPROM4_5GH_PA_1, ~0);
SIBA_SHIFTOUT(core_pwr_info[i].pa_5gh[2], o + SIBA_SPROM4_5GH_PA_2, ~0);
SIBA_SHIFTOUT(core_pwr_info[i].pa_5gh[3], o + SIBA_SPROM4_5GH_PA_3, ~0);
}
siba_sprom_r458(out, in);
}
static void
siba_sprom_r8(struct siba_sprom *out, const uint16_t *in)
{
int i;
uint16_t v;
uint16_t pwr_info_offset[] = {
SIBA_SROM8_PWR_INFO_CORE0, SIBA_SROM8_PWR_INFO_CORE1,
SIBA_SROM8_PWR_INFO_CORE2, SIBA_SROM8_PWR_INFO_CORE3
};
for (i = 0; i < 3; i++) {
v = in[SIBA_OFFSET(SIBA_SPROM8_MAC_80211BG) + i];
*(((uint16_t *)out->mac_80211bg) + i) = htobe16(v);
}
SIBA_SHIFTOUT(ccode, SIBA_SPROM8_CCODE, 0xffff);
SIBA_SHIFTOUT(bf_lo, SIBA_SPROM8_BFLOW, 0xffff);
SIBA_SHIFTOUT(bf_hi, SIBA_SPROM8_BFHIGH, 0xffff);
SIBA_SHIFTOUT(bf2_lo, SIBA_SPROM8_BFL2LO, 0xffff);
SIBA_SHIFTOUT(bf2_hi, SIBA_SPROM8_BFL2HI, 0xffff);
SIBA_SHIFTOUT(ant_a, SIBA_SPROM8_ANTAVAIL, SIBA_SPROM8_ANTAVAIL_A);
SIBA_SHIFTOUT(ant_bg, SIBA_SPROM8_ANTAVAIL, SIBA_SPROM8_ANTAVAIL_BG);
SIBA_SHIFTOUT(maxpwr_bg, SIBA_SPROM8_MAXP_BG, SIBA_SPROM8_MAXP_BG_MASK);
SIBA_SHIFTOUT(tssi_bg, SIBA_SPROM8_MAXP_BG, SIBA_SPROM8_TSSI_BG);
SIBA_SHIFTOUT(maxpwr_a, SIBA_SPROM8_MAXP_A, SIBA_SPROM8_MAXP_A_MASK);
SIBA_SHIFTOUT(tssi_a, SIBA_SPROM8_MAXP_A, SIBA_SPROM8_TSSI_A);
SIBA_SHIFTOUT(maxpwr_ah, SIBA_SPROM8_MAXP_AHL,
SIBA_SPROM8_MAXP_AH_MASK);
SIBA_SHIFTOUT(maxpwr_al, SIBA_SPROM8_MAXP_AHL,
SIBA_SPROM8_MAXP_AL_MASK);
SIBA_SHIFTOUT(gpio0, SIBA_SPROM8_GPIOA, SIBA_SPROM8_GPIOA_P0);
SIBA_SHIFTOUT(gpio1, SIBA_SPROM8_GPIOA, SIBA_SPROM8_GPIOA_P1);
SIBA_SHIFTOUT(gpio2, SIBA_SPROM8_GPIOB, SIBA_SPROM8_GPIOB_P2);
SIBA_SHIFTOUT(gpio3, SIBA_SPROM8_GPIOB, SIBA_SPROM8_GPIOB_P3);
SIBA_SHIFTOUT(tri2g, SIBA_SPROM8_TRI25G, SIBA_SPROM8_TRI2G);
SIBA_SHIFTOUT(tri5g, SIBA_SPROM8_TRI25G, SIBA_SPROM8_TRI5G);
SIBA_SHIFTOUT(tri5gl, SIBA_SPROM8_TRI5GHL, SIBA_SPROM8_TRI5GL);
SIBA_SHIFTOUT(tri5gh, SIBA_SPROM8_TRI5GHL, SIBA_SPROM8_TRI5GH);
SIBA_SHIFTOUT(rxpo2g, SIBA_SPROM8_RXPO, SIBA_SPROM8_RXPO2G);
SIBA_SHIFTOUT(rxpo5g, SIBA_SPROM8_RXPO, SIBA_SPROM8_RXPO5G);
SIBA_SHIFTOUT(rssismf2g, SIBA_SPROM8_RSSIPARM2G, SIBA_SPROM8_RSSISMF2G);
SIBA_SHIFTOUT(rssismc2g, SIBA_SPROM8_RSSIPARM2G, SIBA_SPROM8_RSSISMC2G);
SIBA_SHIFTOUT(rssisav2g, SIBA_SPROM8_RSSIPARM2G, SIBA_SPROM8_RSSISAV2G);
SIBA_SHIFTOUT(bxa2g, SIBA_SPROM8_RSSIPARM2G, SIBA_SPROM8_BXA2G);
SIBA_SHIFTOUT(rssismf5g, SIBA_SPROM8_RSSIPARM5G, SIBA_SPROM8_RSSISMF5G);
SIBA_SHIFTOUT(rssismc5g, SIBA_SPROM8_RSSIPARM5G, SIBA_SPROM8_RSSISMC5G);
SIBA_SHIFTOUT(rssisav5g, SIBA_SPROM8_RSSIPARM5G, SIBA_SPROM8_RSSISAV5G);
SIBA_SHIFTOUT(bxa5g, SIBA_SPROM8_RSSIPARM5G, SIBA_SPROM8_BXA5G);
SIBA_SHIFTOUT(pa0b0, SIBA_SPROM8_PA0B0, 0xffff);
SIBA_SHIFTOUT(pa0b1, SIBA_SPROM8_PA0B1, 0xffff);
SIBA_SHIFTOUT(pa0b2, SIBA_SPROM8_PA0B2, 0xffff);
SIBA_SHIFTOUT(pa1b0, SIBA_SPROM8_PA1B0, 0xffff);
SIBA_SHIFTOUT(pa1b1, SIBA_SPROM8_PA1B1, 0xffff);
SIBA_SHIFTOUT(pa1b2, SIBA_SPROM8_PA1B2, 0xffff);
SIBA_SHIFTOUT(pa1lob0, SIBA_SPROM8_PA1LOB0, 0xffff);
SIBA_SHIFTOUT(pa1lob1, SIBA_SPROM8_PA1LOB1, 0xffff);
SIBA_SHIFTOUT(pa1lob2, SIBA_SPROM8_PA1LOB2, 0xffff);
SIBA_SHIFTOUT(pa1hib0, SIBA_SPROM8_PA1HIB0, 0xffff);
SIBA_SHIFTOUT(pa1hib1, SIBA_SPROM8_PA1HIB1, 0xffff);
SIBA_SHIFTOUT(pa1hib2, SIBA_SPROM8_PA1HIB2, 0xffff);
SIBA_SHIFTOUT(cck2gpo, SIBA_SPROM8_CCK2GPO, 0xffff);
SIBA_SHIFTOUT_4(ofdm2gpo, SIBA_SPROM8_OFDM2GPO, 0xffffffff, 0);
SIBA_SHIFTOUT_4(ofdm5glpo, SIBA_SPROM8_OFDM5GLPO, 0xffffffff, 0);
SIBA_SHIFTOUT_4(ofdm5gpo, SIBA_SPROM8_OFDM5GPO, 0xffffffff, 0);
SIBA_SHIFTOUT_4(ofdm5ghpo, SIBA_SPROM8_OFDM5GHPO, 0xffffffff, 0);
/* antenna gain */
SIBA_SHIFTOUT(again.ghz24.a0, SIBA_SPROM8_AGAIN01, SIBA_SPROM8_AGAIN0);
SIBA_SHIFTOUT(again.ghz24.a1, SIBA_SPROM8_AGAIN01, SIBA_SPROM8_AGAIN1);
SIBA_SHIFTOUT(again.ghz24.a2, SIBA_SPROM8_AGAIN23, SIBA_SPROM8_AGAIN2);
SIBA_SHIFTOUT(again.ghz24.a3, SIBA_SPROM8_AGAIN23, SIBA_SPROM8_AGAIN3);
bcopy(&out->again.ghz24, &out->again.ghz5, sizeof(out->again.ghz5));
/* FEM */
SIBA_SHIFTOUT(fem.ghz2.tssipos, SIBA_SPROM8_FEM2G,
SIBA_SROM8_FEM_TSSIPOS);
SIBA_SHIFTOUT(fem.ghz2.extpa_gain, SIBA_SPROM8_FEM2G,
SIBA_SROM8_FEM_EXTPA_GAIN);
SIBA_SHIFTOUT(fem.ghz2.pdet_range, SIBA_SPROM8_FEM2G,
SIBA_SROM8_FEM_PDET_RANGE);
SIBA_SHIFTOUT(fem.ghz2.tr_iso, SIBA_SPROM8_FEM2G,
SIBA_SROM8_FEM_TR_ISO);
SIBA_SHIFTOUT(fem.ghz2.antswlut, SIBA_SPROM8_FEM2G,
SIBA_SROM8_FEM_ANTSWLUT);
SIBA_SHIFTOUT(fem.ghz5.tssipos, SIBA_SPROM8_FEM5G,
SIBA_SROM8_FEM_TSSIPOS);
SIBA_SHIFTOUT(fem.ghz5.extpa_gain, SIBA_SPROM8_FEM5G,
SIBA_SROM8_FEM_EXTPA_GAIN);
SIBA_SHIFTOUT(fem.ghz5.pdet_range, SIBA_SPROM8_FEM5G,
SIBA_SROM8_FEM_PDET_RANGE);
SIBA_SHIFTOUT(fem.ghz5.tr_iso, SIBA_SPROM8_FEM5G,
SIBA_SROM8_FEM_TR_ISO);
SIBA_SHIFTOUT(fem.ghz5.antswlut, SIBA_SPROM8_FEM5G,
SIBA_SROM8_FEM_ANTSWLUT);
/* Extract cores power info info */
for (i = 0; i < nitems(pwr_info_offset); i++) {
uint16_t o = pwr_info_offset[i];
SIBA_SHIFTOUT(core_pwr_info[i].itssi_2g, o + SIBA_SROM8_2G_MAXP_ITSSI,
SIBA_SPROM8_2G_ITSSI);
SIBA_SHIFTOUT(core_pwr_info[i].maxpwr_2g, o + SIBA_SROM8_2G_MAXP_ITSSI,
SIBA_SPROM8_2G_MAXP);
SIBA_SHIFTOUT(core_pwr_info[i].pa_2g[0], o + SIBA_SROM8_2G_PA_0, ~0);
SIBA_SHIFTOUT(core_pwr_info[i].pa_2g[1], o + SIBA_SROM8_2G_PA_1, ~0);
SIBA_SHIFTOUT(core_pwr_info[i].pa_2g[2], o + SIBA_SROM8_2G_PA_2, ~0);
SIBA_SHIFTOUT(core_pwr_info[i].itssi_5g, o + SIBA_SROM8_5G_MAXP_ITSSI,
SIBA_SPROM8_5G_ITSSI);
SIBA_SHIFTOUT(core_pwr_info[i].maxpwr_5g, o + SIBA_SROM8_5G_MAXP_ITSSI,
SIBA_SPROM8_5G_MAXP);
SIBA_SHIFTOUT(core_pwr_info[i].maxpwr_5gh, o + SIBA_SPROM8_5GHL_MAXP,
SIBA_SPROM8_5GH_MAXP);
SIBA_SHIFTOUT(core_pwr_info[i].maxpwr_5gl, o + SIBA_SPROM8_5GHL_MAXP,
SIBA_SPROM8_5GL_MAXP);
SIBA_SHIFTOUT(core_pwr_info[i].pa_5gl[0], o + SIBA_SROM8_5GL_PA_0, ~0);
SIBA_SHIFTOUT(core_pwr_info[i].pa_5gl[1], o + SIBA_SROM8_5GL_PA_1, ~0);
SIBA_SHIFTOUT(core_pwr_info[i].pa_5gl[2], o + SIBA_SROM8_5GL_PA_2, ~0);
SIBA_SHIFTOUT(core_pwr_info[i].pa_5g[0], o + SIBA_SROM8_5G_PA_0, ~0);
SIBA_SHIFTOUT(core_pwr_info[i].pa_5g[1], o + SIBA_SROM8_5G_PA_1, ~0);
SIBA_SHIFTOUT(core_pwr_info[i].pa_5g[2], o + SIBA_SROM8_5G_PA_2, ~0);
SIBA_SHIFTOUT(core_pwr_info[i].pa_5gh[0], o + SIBA_SROM8_5GH_PA_0, ~0);
SIBA_SHIFTOUT(core_pwr_info[i].pa_5gh[1], o + SIBA_SROM8_5GH_PA_1, ~0);
SIBA_SHIFTOUT(core_pwr_info[i].pa_5gh[2], o + SIBA_SROM8_5GH_PA_2, ~0);
}
SIBA_SHIFTOUT(cddpo, SIBA_SPROM8_CDDPO, ~0);
SIBA_SHIFTOUT(stbcpo, SIBA_SPROM8_STBCPO, ~0);
siba_sprom_r458(out, in);
}
static int8_t
siba_sprom_r123_antgain(uint8_t sprom_revision, const uint16_t *in,
uint16_t mask, uint16_t shift)
{
uint16_t v;
uint8_t gain;
v = in[SIBA_OFFSET(SIBA_SPROM1_AGAIN)];
gain = (v & mask) >> shift;
gain = (gain == 0xff) ? 2 : (sprom_revision == 1) ? gain << 2 :
((gain & 0xc0) >> 6) | ((gain & 0x3f) << 2);
return ((int8_t)gain);
}
#undef SIBA_LOWEST_SET_BIT
#undef SIBA_OFFSET
#undef SIBA_SHIFTOUT_SUB
#undef SIBA_SHIFTOUT
int
siba_powerdown(device_t dev)
{
struct siba_dev_softc *sd = device_get_ivars(dev);
struct siba_softc *siba = sd->sd_bus;
return (siba_powerdown_sub(siba));
}
static int
siba_powerdown_sub(struct siba_softc *siba)
{
struct siba_cc *scc;
if (siba->siba_type == SIBA_TYPE_SSB)
return (0);
scc = &siba->siba_cc;
if (!scc->scc_dev || scc->scc_dev->sd_id.sd_rev < 5)
return (0);
siba_cc_clock(scc, SIBA_CLOCK_SLOW);
siba_pci_gpio(siba, SIBA_GPIO_CRYSTAL | SIBA_GPIO_PLL, 0);
return (0);
}
static void
siba_pcicore_init(struct siba_pci *spc)
{
struct siba_dev_softc *sd = spc->spc_dev;
if (sd == NULL)
return;
if (!siba_dev_isup_sub(sd))
siba_dev_up_sub(sd, 0);
KASSERT(spc->spc_hostmode == 0,
("%s:%d: hostmode", __func__, __LINE__));
/* disable PCI interrupt */
siba_write_4_sub(spc->spc_dev, SIBA_INTR_MASK, 0);
}
int
siba_dev_isup(device_t dev)
{
struct siba_dev_softc *sd = device_get_ivars(dev);
return (siba_dev_isup_sub(sd));
}
static int
siba_dev_isup_sub(struct siba_dev_softc *sd)
{
uint32_t reject, val;
reject = siba_tmslow_reject_bitmask(sd);
val = siba_read_4_sub(sd, SIBA_TGSLOW);
val &= SIBA_TGSLOW_CLOCK | SIBA_TGSLOW_RESET | reject;
return (val == SIBA_TGSLOW_CLOCK);
}
void
siba_dev_up(device_t dev, uint32_t flags)
{
struct siba_dev_softc *sd = device_get_ivars(dev);
siba_dev_up_sub(sd, flags);
}
static void
siba_dev_up_sub(struct siba_dev_softc *sd, uint32_t flags)
{
uint32_t val;
siba_dev_down_sub(sd, flags);
siba_write_4_sub(sd, SIBA_TGSLOW,
SIBA_TGSLOW_RESET | SIBA_TGSLOW_CLOCK | SIBA_TGSLOW_FGC | flags);
siba_read_4_sub(sd, SIBA_TGSLOW);
DELAY(1);
if (siba_read_4_sub(sd, SIBA_TGSHIGH) & SIBA_TGSHIGH_SERR)
siba_write_4_sub(sd, SIBA_TGSHIGH, 0);
val = siba_read_4_sub(sd, SIBA_IAS);
if (val & (SIBA_IAS_INBAND_ERR | SIBA_IAS_TIMEOUT)) {
val &= ~(SIBA_IAS_INBAND_ERR | SIBA_IAS_TIMEOUT);
siba_write_4_sub(sd, SIBA_IAS, val);
}
siba_write_4_sub(sd, SIBA_TGSLOW,
SIBA_TGSLOW_CLOCK | SIBA_TGSLOW_FGC | flags);
siba_read_4_sub(sd, SIBA_TGSLOW);
DELAY(1);
siba_write_4_sub(sd, SIBA_TGSLOW, SIBA_TGSLOW_CLOCK | flags);
siba_read_4_sub(sd, SIBA_TGSLOW);
DELAY(1);
}
static uint32_t
siba_tmslow_reject_bitmask(struct siba_dev_softc *sd)
{
uint32_t rev = siba_read_4_sub(sd, SIBA_IDLOW) & SIBA_IDLOW_SSBREV;
switch (rev) {
case SIBA_IDLOW_SSBREV_22:
return (SIBA_TGSLOW_REJECT_22);
case SIBA_IDLOW_SSBREV_23:
return (SIBA_TGSLOW_REJECT_23);
case SIBA_IDLOW_SSBREV_24:
case SIBA_IDLOW_SSBREV_25:
case SIBA_IDLOW_SSBREV_26:
case SIBA_IDLOW_SSBREV_27:
return (SIBA_TGSLOW_REJECT_23);
default:
KASSERT(0 == 1,
("%s:%d: unknown backplane rev %#x\n",
__func__, __LINE__, rev));
}
return (SIBA_TGSLOW_REJECT_22 | SIBA_TGSLOW_REJECT_23);
}
void
siba_dev_down(device_t dev, uint32_t flags)
{
struct siba_dev_softc *sd = device_get_ivars(dev);
siba_dev_down_sub(sd, flags);
}
static void
siba_dev_down_sub(struct siba_dev_softc *sd, uint32_t flags)
{
struct siba_softc *siba = sd->sd_bus;
uint32_t reject, val;
int i;
if (siba_read_4_sub(sd, SIBA_TGSLOW) & SIBA_TGSLOW_RESET)
return;
reject = siba_tmslow_reject_bitmask(sd);
siba_write_4_sub(sd, SIBA_TGSLOW, reject | SIBA_TGSLOW_CLOCK);
for (i = 0; i < 1000; i++) {
val = siba_read_4_sub(sd, SIBA_TGSLOW);
if (val & reject)
break;
DELAY(10);
}
if ((val & reject) == 0) {
device_printf(siba->siba_dev, "timeout (bit %#x reg %#x)\n",
reject, SIBA_TGSLOW);
}
for (i = 0; i < 1000; i++) {
val = siba_read_4_sub(sd, SIBA_TGSHIGH);
if (!(val & SIBA_TGSHIGH_BUSY))
break;
DELAY(10);
}
if ((val & SIBA_TGSHIGH_BUSY) != 0) {
device_printf(siba->siba_dev, "timeout (bit %#x reg %#x)\n",
SIBA_TGSHIGH_BUSY, SIBA_TGSHIGH);
}
siba_write_4_sub(sd, SIBA_TGSLOW, SIBA_TGSLOW_FGC | SIBA_TGSLOW_CLOCK |
reject | SIBA_TGSLOW_RESET | flags);
siba_read_4_sub(sd, SIBA_TGSLOW);
DELAY(1);
siba_write_4_sub(sd, SIBA_TGSLOW, reject | SIBA_TGSLOW_RESET | flags);
siba_read_4_sub(sd, SIBA_TGSLOW);
DELAY(1);
}
static void
siba_pcicore_setup(struct siba_pci *spc, struct siba_dev_softc *sd)
{
struct siba_dev_softc *psd = spc->spc_dev;
struct siba_softc *siba = psd->sd_bus;
uint32_t tmp;
if (psd->sd_id.sd_device == SIBA_DEVID_PCI) {
siba_pcicore_write_4(spc, SIBA_PCICORE_SBTOPCI2,
siba_pcicore_read_4(spc, SIBA_PCICORE_SBTOPCI2) |
SIBA_PCICORE_SBTOPCI_PREF | SIBA_PCICORE_SBTOPCI_BURST);
if (psd->sd_id.sd_rev < 5) {
tmp = siba_read_4_sub(psd, SIBA_IMCFGLO);
tmp &= ~SIBA_IMCFGLO_SERTO;
tmp = (tmp | 2) & ~SIBA_IMCFGLO_REQTO;
tmp |= 3 << 4 /* SIBA_IMCFGLO_REQTO_SHIFT */;
siba_write_4_sub(psd, SIBA_IMCFGLO, tmp);
/* broadcast value */
sd = (siba->siba_cc.scc_dev != NULL) ?
siba->siba_cc.scc_dev : siba->siba_pci.spc_dev;
if (sd != NULL) {
siba_write_4_sub(sd, SIBA_PCICORE_BCAST_ADDR,
0xfd8);
siba_read_4_sub(sd, SIBA_PCICORE_BCAST_ADDR);
siba_write_4_sub(sd,
SIBA_PCICORE_BCAST_DATA, 0);
siba_read_4_sub(sd, SIBA_PCICORE_BCAST_DATA);
}
} else if (psd->sd_id.sd_rev >= 11) {
tmp = siba_pcicore_read_4(spc, SIBA_PCICORE_SBTOPCI2);
tmp |= SIBA_PCICORE_SBTOPCI_MRM;
siba_pcicore_write_4(spc, SIBA_PCICORE_SBTOPCI2, tmp);
}
} else {
KASSERT(psd->sd_id.sd_device == SIBA_DEVID_PCIE, ("only PCIE"));
if ((psd->sd_id.sd_rev == 0) || (psd->sd_id.sd_rev == 1))
siba_pcie_write(spc, 0x4,
siba_pcie_read(spc, 0x4) | 0x8);
if (psd->sd_id.sd_rev == 0) {
siba_pcie_mdio_write(spc, 0x1f, 2, 0x8128); /* Timer */
siba_pcie_mdio_write(spc, 0x1f, 6, 0x0100); /* CDR */
siba_pcie_mdio_write(spc, 0x1f, 7, 0x1466); /* CDR BW */
} else if (psd->sd_id.sd_rev == 1)
siba_pcie_write(spc, 0x100,
siba_pcie_read(spc, 0x100) | 0x40);
}
spc->spc_inited = 1;
}
void
siba_pcicore_intr(device_t dev)
{
struct siba_dev_softc *sd = device_get_ivars(dev);
struct siba_softc *siba = sd->sd_bus;
struct siba_pci *spc = &siba->siba_pci;
struct siba_dev_softc *psd = spc->spc_dev;
uint32_t tmp;
if (siba->siba_type != SIBA_TYPE_PCI || !psd)
return;
KASSERT(siba == psd->sd_bus, ("different pointers"));
/* enable interrupts */
if (siba->siba_dev != NULL &&
(psd->sd_id.sd_rev >= 6 ||
psd->sd_id.sd_device == SIBA_DEVID_PCIE)) {
tmp = pci_read_config(siba->siba_dev, SIBA_IRQMASK, 4);
tmp |= (1 << sd->sd_coreidx) << 8;
pci_write_config(siba->siba_dev, SIBA_IRQMASK, tmp, 4);
} else {
tmp = siba_read_4_sub(sd, SIBA_TPS);
tmp &= SIBA_TPS_BPFLAG;
siba_write_4_sub(psd, SIBA_INTR_MASK,
siba_read_4_sub(psd, SIBA_INTR_MASK) | (1 << tmp));
}
/* setup PCIcore */
if (spc->spc_inited == 0)
siba_pcicore_setup(spc, sd);
}
static uint32_t
siba_pcicore_read_4(struct siba_pci *spc, uint16_t offset)
{
return (siba_read_4_sub(spc->spc_dev, offset));
}
static void
siba_pcicore_write_4(struct siba_pci *spc, uint16_t offset, uint32_t value)
{
siba_write_4_sub(spc->spc_dev, offset, value);
}
static uint32_t
siba_pcie_read(struct siba_pci *spc, uint32_t address)
{
siba_pcicore_write_4(spc, 0x130, address);
return (siba_pcicore_read_4(spc, 0x134));
}
static void
siba_pcie_write(struct siba_pci *spc, uint32_t address, uint32_t data)
{
siba_pcicore_write_4(spc, 0x130, address);
siba_pcicore_write_4(spc, 0x134, data);
}
static void
siba_pcie_mdio_write(struct siba_pci *spc, uint8_t device, uint8_t address,
uint16_t data)
{
int i;
siba_pcicore_write_4(spc, SIBA_PCICORE_MDIO_CTL, 0x80 | 0x2);
siba_pcicore_write_4(spc, SIBA_PCICORE_MDIO_DATA,
(1 << 30) | (1 << 28) |
((uint32_t)device << 22) | ((uint32_t)address << 18) |
(1 << 17) | data);
DELAY(10);
for (i = 0; i < 10; i++) {
if (siba_pcicore_read_4(spc, SIBA_PCICORE_MDIO_CTL) & 0x100)
break;
DELAY(1000);
}
siba_pcicore_write_4(spc, SIBA_PCICORE_MDIO_CTL, 0);
}
uint32_t
siba_dma_translation(device_t dev)
{
#ifdef INVARIANTS
struct siba_dev_softc *sd = device_get_ivars(dev);
struct siba_softc *siba = sd->sd_bus;
KASSERT(siba->siba_type == SIBA_TYPE_PCI,
("unsupported bustype %d\n", siba->siba_type));
#endif
/* Default */
return (SIBA_PCI_DMA);
}
void
siba_barrier(device_t dev, int flags)
{
struct siba_dev_softc *sd = device_get_ivars(dev);
struct siba_softc *siba = sd->sd_bus;
SIBA_BARRIER(siba, flags);
}
static void
siba_cc_suspend(struct siba_cc *scc)
{
siba_cc_clock(scc, SIBA_CLOCK_SLOW);
}
static void
siba_cc_resume(struct siba_cc *scc)
{
siba_cc_power_init(scc);
siba_cc_clock(scc, SIBA_CLOCK_FAST);
}
int
siba_core_suspend(struct siba_softc *siba)
{
siba_cc_suspend(&siba->siba_cc);
siba_pci_gpio(siba, SIBA_GPIO_CRYSTAL | SIBA_GPIO_PLL, 0);
return (0);
}
int
siba_core_resume(struct siba_softc *siba)
{
siba->siba_pci.spc_inited = 0;
siba->siba_curdev = NULL;
siba_powerup_sub(siba, 0);
/* XXX setup H/W for PCMCIA??? */
siba_cc_resume(&siba->siba_cc);
siba_powerdown_sub(siba);
return (0);
}
static void
siba_cc_regctl_setmask(struct siba_cc *cc, uint32_t offset, uint32_t mask,
uint32_t set)
{
SIBA_CC_READ32(cc, SIBA_CC_REGCTL_ADDR);
SIBA_CC_WRITE32(cc, SIBA_CC_REGCTL_ADDR, offset);
SIBA_CC_READ32(cc, SIBA_CC_REGCTL_ADDR);
SIBA_CC_WRITE32(cc, SIBA_CC_REGCTL_DATA,
(SIBA_CC_READ32(cc, SIBA_CC_REGCTL_DATA) & mask) | set);
SIBA_CC_READ32(cc, SIBA_CC_REGCTL_DATA);
}
void
siba_cc_pmu_set_ldovolt(device_t dev, int id, uint32_t volt)
{
struct siba_dev_softc *sd = device_get_ivars(dev);
struct siba_softc *siba = sd->sd_bus;
struct siba_cc *scc = &siba->siba_cc;
uint32_t *p = NULL, info[5][3] = {
{ 2, 25, 0xf },
{ 3, 1, 0xf },
{ 3, 9, 0xf },
{ 3, 17, 0x3f },
{ 0, 21, 0x3f }
};
if (siba->siba_chipid == 0x4312) {
if (id != SIBA_LDO_PAREF)
return;
p = info[4];
siba_cc_regctl_setmask(scc, p[0], ~(p[2] << p[1]),
(volt & p[2]) << p[1]);
return;
}
if (siba->siba_chipid == 0x4328 || siba->siba_chipid == 0x5354) {
switch (id) {
case SIBA_LDO_PAREF:
p = info[3];
break;
case SIBA_LDO_VOLT1:
p = info[0];
break;
case SIBA_LDO_VOLT2:
p = info[1];
break;
case SIBA_LDO_VOLT3:
p = info[2];
break;
default:
KASSERT(0 == 1,
("%s: unsupported voltage ID %#x", __func__, id));
return;
}
siba_cc_regctl_setmask(scc, p[0], ~(p[2] << p[1]),
(volt & p[2]) << p[1]);
}
}
void
siba_cc_pmu_set_ldoparef(device_t dev, uint8_t on)
{
struct siba_dev_softc *sd = device_get_ivars(dev);
struct siba_softc *siba = sd->sd_bus;
struct siba_cc *scc = &siba->siba_cc;
int ldo;
ldo = ((siba->siba_chipid == 0x4312) ? SIBA_CC_PMU_4312_PA_REF :
((siba->siba_chipid == 0x4328) ? SIBA_CC_PMU_4328_PA_REF :
((siba->siba_chipid == 0x5354) ? SIBA_CC_PMU_5354_PA_REF : -1)));
if (ldo == -1)
return;
if (on)
SIBA_CC_SET32(scc, SIBA_CC_PMU_MINRES, 1 << ldo);
else
SIBA_CC_MASK32(scc, SIBA_CC_PMU_MINRES, ~(1 << ldo));
SIBA_CC_READ32(scc, SIBA_CC_PMU_MINRES);
}
int
siba_read_sprom(device_t dev, device_t child, int which, uintptr_t *result)
{
struct siba_dev_softc *sd = device_get_ivars(child);
struct siba_softc *siba = sd->sd_bus;
switch (which) {
case SIBA_SPROMVAR_REV:
*result = siba->siba_sprom.rev;
break;
case SIBA_SPROMVAR_MAC_80211BG:
*((uint8_t **) result) = siba->siba_sprom.mac_80211bg;
break;
case SIBA_SPROMVAR_MAC_ETH:
*((uint8_t **) result) = siba->siba_sprom.mac_eth;
break;
case SIBA_SPROMVAR_MAC_80211A:
*((uint8_t **) result) = siba->siba_sprom.mac_80211a;
break;
case SIBA_SPROMVAR_MII_ETH0:
*result = siba->siba_sprom.mii_eth0;
break;
case SIBA_SPROMVAR_MII_ETH1:
*result = siba->siba_sprom.mii_eth1;
break;
case SIBA_SPROMVAR_MDIO_ETH0:
*result = siba->siba_sprom.mdio_eth0;
break;
case SIBA_SPROMVAR_MDIO_ETH1:
*result = siba->siba_sprom.mdio_eth1;
break;
case SIBA_SPROMVAR_BREV:
*result = siba->siba_sprom.brev;
break;
case SIBA_SPROMVAR_CCODE:
*result = siba->siba_sprom.ccode;
break;
case SIBA_SPROMVAR_ANT_A:
*result = siba->siba_sprom.ant_a;
break;
case SIBA_SPROMVAR_ANT_BG:
*result = siba->siba_sprom.ant_bg;
break;
case SIBA_SPROMVAR_PA0B0:
*result = siba->siba_sprom.pa0b0;
break;
case SIBA_SPROMVAR_PA0B1:
*result = siba->siba_sprom.pa0b1;
break;
case SIBA_SPROMVAR_PA0B2:
*result = siba->siba_sprom.pa0b2;
break;
case SIBA_SPROMVAR_PA1B0:
*result = siba->siba_sprom.pa1b0;
break;
case SIBA_SPROMVAR_PA1B1:
*result = siba->siba_sprom.pa1b1;
break;
case SIBA_SPROMVAR_PA1B2:
*result = siba->siba_sprom.pa1b2;
break;
case SIBA_SPROMVAR_PA1LOB0:
*result = siba->siba_sprom.pa1lob0;
break;
case SIBA_SPROMVAR_PA1LOB1:
*result = siba->siba_sprom.pa1lob1;
break;
case SIBA_SPROMVAR_PA1LOB2:
*result = siba->siba_sprom.pa1lob2;
break;
case SIBA_SPROMVAR_PA1HIB0:
*result = siba->siba_sprom.pa1hib0;
break;
case SIBA_SPROMVAR_PA1HIB1:
*result = siba->siba_sprom.pa1hib1;
break;
case SIBA_SPROMVAR_PA1HIB2:
*result = siba->siba_sprom.pa1hib2;
break;
case SIBA_SPROMVAR_GPIO0:
*result = siba->siba_sprom.gpio0;
break;
case SIBA_SPROMVAR_GPIO1:
*result = siba->siba_sprom.gpio1;
break;
case SIBA_SPROMVAR_GPIO2:
*result = siba->siba_sprom.gpio2;
break;
case SIBA_SPROMVAR_GPIO3:
*result = siba->siba_sprom.gpio3;
break;
case SIBA_SPROMVAR_MAXPWR_AL:
*result = siba->siba_sprom.maxpwr_al;
break;
case SIBA_SPROMVAR_MAXPWR_A:
*result = siba->siba_sprom.maxpwr_a;
break;
case SIBA_SPROMVAR_MAXPWR_AH:
*result = siba->siba_sprom.maxpwr_ah;
break;
case SIBA_SPROMVAR_MAXPWR_BG:
*result = siba->siba_sprom.maxpwr_bg;
break;
case SIBA_SPROMVAR_RXPO2G:
*result = siba->siba_sprom.rxpo2g;
break;
case SIBA_SPROMVAR_RXPO5G:
*result = siba->siba_sprom.rxpo5g;
break;
case SIBA_SPROMVAR_TSSI_A:
*result = siba->siba_sprom.tssi_a;
break;
case SIBA_SPROMVAR_TSSI_BG:
*result = siba->siba_sprom.tssi_bg;
break;
case SIBA_SPROMVAR_TRI2G:
*result = siba->siba_sprom.tri2g;
break;
case SIBA_SPROMVAR_TRI5GL:
*result = siba->siba_sprom.tri5gl;
break;
case SIBA_SPROMVAR_TRI5G:
*result = siba->siba_sprom.tri5g;
break;
case SIBA_SPROMVAR_TRI5GH:
*result = siba->siba_sprom.tri5gh;
break;
case SIBA_SPROMVAR_RSSISAV2G:
*result = siba->siba_sprom.rssisav2g;
break;
case SIBA_SPROMVAR_RSSISMC2G:
*result = siba->siba_sprom.rssismc2g;
break;
case SIBA_SPROMVAR_RSSISMF2G:
*result = siba->siba_sprom.rssismf2g;
break;
case SIBA_SPROMVAR_BXA2G:
*result = siba->siba_sprom.bxa2g;
break;
case SIBA_SPROMVAR_RSSISAV5G:
*result = siba->siba_sprom.rssisav5g;
break;
case SIBA_SPROMVAR_RSSISMC5G:
*result = siba->siba_sprom.rssismc5g;
break;
case SIBA_SPROMVAR_RSSISMF5G:
*result = siba->siba_sprom.rssismf5g;
break;
case SIBA_SPROMVAR_BXA5G:
*result = siba->siba_sprom.bxa5g;
break;
case SIBA_SPROMVAR_CCK2GPO:
*result = siba->siba_sprom.cck2gpo;
break;
case SIBA_SPROMVAR_OFDM2GPO:
*result = siba->siba_sprom.ofdm2gpo;
break;
case SIBA_SPROMVAR_OFDM5GLPO:
*result = siba->siba_sprom.ofdm5glpo;
break;
case SIBA_SPROMVAR_OFDM5GPO:
*result = siba->siba_sprom.ofdm5gpo;
break;
case SIBA_SPROMVAR_OFDM5GHPO:
*result = siba->siba_sprom.ofdm5ghpo;
break;
case SIBA_SPROMVAR_BF_LO:
*result = siba->siba_sprom.bf_lo;
break;
case SIBA_SPROMVAR_BF_HI:
*result = siba->siba_sprom.bf_hi;
break;
case SIBA_SPROMVAR_BF2_LO:
*result = siba->siba_sprom.bf2_lo;
break;
case SIBA_SPROMVAR_BF2_HI:
*result = siba->siba_sprom.bf2_hi;
break;
case SIBA_SPROMVAR_FEM_2GHZ_TSSIPOS:
*result = siba->siba_sprom.fem.ghz2.tssipos;
break;
case SIBA_SPROMVAR_FEM_2GHZ_EXTPAGAIN:
*result = siba->siba_sprom.fem.ghz2.extpa_gain;
break;
case SIBA_SPROMVAR_FEM_2GHZ_PDET_RANGE:
*result = siba->siba_sprom.fem.ghz2.pdet_range;
break;
case SIBA_SPROMVAR_FEM_2GHZ_TR_ISO:
*result = siba->siba_sprom.fem.ghz2.tr_iso;
break;
case SIBA_SPROMVAR_FEM_2GHZ_ANTSWLUT:
*result = siba->siba_sprom.fem.ghz2.antswlut;
break;
case SIBA_SPROMVAR_FEM_5GHZ_TSSIPOS:
*result = siba->siba_sprom.fem.ghz5.tssipos;
break;
case SIBA_SPROMVAR_FEM_5GHZ_EXTPAGAIN:
*result = siba->siba_sprom.fem.ghz5.extpa_gain;
break;
case SIBA_SPROMVAR_FEM_5GHZ_PDET_RANGE:
*result = siba->siba_sprom.fem.ghz5.pdet_range;
break;
case SIBA_SPROMVAR_FEM_5GHZ_TR_ISO:
*result = siba->siba_sprom.fem.ghz5.tr_iso;
break;
case SIBA_SPROMVAR_FEM_5GHZ_ANTSWLUT:
*result = siba->siba_sprom.fem.ghz5.antswlut;
break;
case SIBA_SPROMVAR_TXPID_2G_0:
*result = siba->siba_sprom.txpid2g[0];
break;
case SIBA_SPROMVAR_TXPID_2G_1:
*result = siba->siba_sprom.txpid2g[1];
break;
case SIBA_SPROMVAR_TXPID_2G_2:
*result = siba->siba_sprom.txpid2g[2];
break;
case SIBA_SPROMVAR_TXPID_2G_3:
*result = siba->siba_sprom.txpid2g[3];
break;
case SIBA_SPROMVAR_TXPID_5GL_0:
*result = siba->siba_sprom.txpid5gl[0];
break;
case SIBA_SPROMVAR_TXPID_5GL_1:
*result = siba->siba_sprom.txpid5gl[1];
break;
case SIBA_SPROMVAR_TXPID_5GL_2:
*result = siba->siba_sprom.txpid5gl[2];
break;
case SIBA_SPROMVAR_TXPID_5GL_3:
*result = siba->siba_sprom.txpid5gl[3];
break;
case SIBA_SPROMVAR_TXPID_5G_0:
*result = siba->siba_sprom.txpid5g[0];
break;
case SIBA_SPROMVAR_TXPID_5G_1:
*result = siba->siba_sprom.txpid5g[1];
break;
case SIBA_SPROMVAR_TXPID_5G_2:
*result = siba->siba_sprom.txpid5g[2];
break;
case SIBA_SPROMVAR_TXPID_5G_3:
*result = siba->siba_sprom.txpid5g[3];
break;
case SIBA_SPROMVAR_TXPID_5GH_0:
*result = siba->siba_sprom.txpid5gh[0];
break;
case SIBA_SPROMVAR_TXPID_5GH_1:
*result = siba->siba_sprom.txpid5gh[1];
break;
case SIBA_SPROMVAR_TXPID_5GH_2:
*result = siba->siba_sprom.txpid5gh[2];
break;
case SIBA_SPROMVAR_TXPID_5GH_3:
*result = siba->siba_sprom.txpid5gh[3];
break;
case SIBA_SPROMVAR_STBCPO:
*result = siba->siba_sprom.stbcpo;
break;
case SIBA_SPROMVAR_CDDPO:
*result = siba->siba_sprom.cddpo;
break;
default:
return (ENOENT);
}
return (0);
}
int
siba_write_sprom(device_t dev, device_t child, int which, uintptr_t value)
{
struct siba_dev_softc *sd = device_get_ivars(child);
struct siba_softc *siba = sd->sd_bus;
switch (which) {
case SIBA_SPROMVAR_REV:
siba->siba_sprom.rev = value;
break;
case SIBA_SPROMVAR_MII_ETH0:
siba->siba_sprom.mii_eth0 = value;
break;
case SIBA_SPROMVAR_MII_ETH1:
siba->siba_sprom.mii_eth1 = value;
break;
case SIBA_SPROMVAR_MDIO_ETH0:
siba->siba_sprom.mdio_eth0 = value;
break;
case SIBA_SPROMVAR_MDIO_ETH1:
siba->siba_sprom.mdio_eth1 = value;
break;
case SIBA_SPROMVAR_BREV:
siba->siba_sprom.brev = value;
break;
case SIBA_SPROMVAR_CCODE:
siba->siba_sprom.ccode = value;
break;
case SIBA_SPROMVAR_ANT_A:
siba->siba_sprom.ant_a = value;
break;
case SIBA_SPROMVAR_ANT_BG:
siba->siba_sprom.ant_bg = value;
break;
case SIBA_SPROMVAR_PA0B0:
siba->siba_sprom.pa0b0 = value;
break;
case SIBA_SPROMVAR_PA0B1:
siba->siba_sprom.pa0b1 = value;
break;
case SIBA_SPROMVAR_PA0B2:
siba->siba_sprom.pa0b2 = value;
break;
case SIBA_SPROMVAR_PA1B0:
siba->siba_sprom.pa1b0 = value;
break;
case SIBA_SPROMVAR_PA1B1:
siba->siba_sprom.pa1b1 = value;
break;
case SIBA_SPROMVAR_PA1B2:
siba->siba_sprom.pa1b2 = value;
break;
case SIBA_SPROMVAR_PA1LOB0:
siba->siba_sprom.pa1lob0 = value;
break;
case SIBA_SPROMVAR_PA1LOB1:
siba->siba_sprom.pa1lob1 = value;
break;
case SIBA_SPROMVAR_PA1LOB2:
siba->siba_sprom.pa1lob2 = value;
break;
case SIBA_SPROMVAR_PA1HIB0:
siba->siba_sprom.pa1hib0 = value;
break;
case SIBA_SPROMVAR_PA1HIB1:
siba->siba_sprom.pa1hib1 = value;
break;
case SIBA_SPROMVAR_PA1HIB2:
siba->siba_sprom.pa1hib2 = value;
break;
case SIBA_SPROMVAR_GPIO0:
siba->siba_sprom.gpio0 = value;
break;
case SIBA_SPROMVAR_GPIO1:
siba->siba_sprom.gpio1 = value;
break;
case SIBA_SPROMVAR_GPIO2:
siba->siba_sprom.gpio2 = value;
break;
case SIBA_SPROMVAR_GPIO3:
siba->siba_sprom.gpio3 = value;
break;
case SIBA_SPROMVAR_MAXPWR_AL:
siba->siba_sprom.maxpwr_al = value;
break;
case SIBA_SPROMVAR_MAXPWR_A:
siba->siba_sprom.maxpwr_a = value;
break;
case SIBA_SPROMVAR_MAXPWR_AH:
siba->siba_sprom.maxpwr_ah = value;
break;
case SIBA_SPROMVAR_MAXPWR_BG:
siba->siba_sprom.maxpwr_bg = value;
break;
case SIBA_SPROMVAR_RXPO2G:
siba->siba_sprom.rxpo2g = value;
break;
case SIBA_SPROMVAR_RXPO5G:
siba->siba_sprom.rxpo5g = value;
break;
case SIBA_SPROMVAR_TSSI_A:
siba->siba_sprom.tssi_a = value;
break;
case SIBA_SPROMVAR_TSSI_BG:
siba->siba_sprom.tssi_bg = value;
break;
case SIBA_SPROMVAR_TRI2G:
siba->siba_sprom.tri2g = value;
break;
case SIBA_SPROMVAR_TRI5GL:
siba->siba_sprom.tri5gl = value;
break;
case SIBA_SPROMVAR_TRI5G:
siba->siba_sprom.tri5g = value;
break;
case SIBA_SPROMVAR_TRI5GH:
siba->siba_sprom.tri5gh = value;
break;
case SIBA_SPROMVAR_RSSISAV2G:
siba->siba_sprom.rssisav2g = value;
break;
case SIBA_SPROMVAR_RSSISMC2G:
siba->siba_sprom.rssismc2g = value;
break;
case SIBA_SPROMVAR_RSSISMF2G:
siba->siba_sprom.rssismf2g = value;
break;
case SIBA_SPROMVAR_BXA2G:
siba->siba_sprom.bxa2g = value;
break;
case SIBA_SPROMVAR_RSSISAV5G:
siba->siba_sprom.rssisav5g = value;
break;
case SIBA_SPROMVAR_RSSISMC5G:
siba->siba_sprom.rssismc5g = value;
break;
case SIBA_SPROMVAR_RSSISMF5G:
siba->siba_sprom.rssismf5g = value;
break;
case SIBA_SPROMVAR_BXA5G:
siba->siba_sprom.bxa5g = value;
break;
case SIBA_SPROMVAR_CCK2GPO:
siba->siba_sprom.cck2gpo = value;
break;
case SIBA_SPROMVAR_OFDM2GPO:
siba->siba_sprom.ofdm2gpo = value;
break;
case SIBA_SPROMVAR_OFDM5GLPO:
siba->siba_sprom.ofdm5glpo = value;
break;
case SIBA_SPROMVAR_OFDM5GPO:
siba->siba_sprom.ofdm5gpo = value;
break;
case SIBA_SPROMVAR_OFDM5GHPO:
siba->siba_sprom.ofdm5ghpo = value;
break;
case SIBA_SPROMVAR_BF_LO:
siba->siba_sprom.bf_lo = value;
break;
case SIBA_SPROMVAR_BF_HI:
siba->siba_sprom.bf_hi = value;
break;
case SIBA_SPROMVAR_BF2_LO:
siba->siba_sprom.bf2_lo = value;
break;
case SIBA_SPROMVAR_BF2_HI:
siba->siba_sprom.bf2_hi = value;
break;
default:
return (ENOENT);
}
return (0);
}
#define SIBA_GPIOCTL 0x06c
uint32_t
siba_gpio_get(device_t dev)
{
struct siba_dev_softc *sd = device_get_ivars(dev);
struct siba_softc *siba = sd->sd_bus;
struct siba_dev_softc *gpiodev, *pcidev = NULL;
pcidev = siba->siba_pci.spc_dev;
gpiodev = siba->siba_cc.scc_dev ? siba->siba_cc.scc_dev : pcidev;
if (!gpiodev)
return (-1);
return (siba_read_4_sub(gpiodev, SIBA_GPIOCTL));
}
void
siba_gpio_set(device_t dev, uint32_t value)
{
struct siba_dev_softc *sd = device_get_ivars(dev);
struct siba_softc *siba = sd->sd_bus;
struct siba_dev_softc *gpiodev, *pcidev = NULL;
pcidev = siba->siba_pci.spc_dev;
gpiodev = siba->siba_cc.scc_dev ? siba->siba_cc.scc_dev : pcidev;
if (!gpiodev)
return;
siba_write_4_sub(gpiodev, SIBA_GPIOCTL, value);
}
void
siba_fix_imcfglobug(device_t dev)
{
struct siba_dev_softc *sd = device_get_ivars(dev);
struct siba_softc *siba = sd->sd_bus;
uint32_t tmp;
if (siba->siba_pci.spc_dev == NULL)
return;
if (siba->siba_pci.spc_dev->sd_id.sd_device != SIBA_DEVID_PCI ||
siba->siba_pci.spc_dev->sd_id.sd_rev > 5)
return;
tmp = siba_read_4_sub(sd, SIBA_IMCFGLO) &
~(SIBA_IMCFGLO_REQTO | SIBA_IMCFGLO_SERTO);
switch (siba->siba_type) {
case SIBA_TYPE_PCI:
case SIBA_TYPE_PCMCIA:
tmp |= 0x32;
break;
case SIBA_TYPE_SSB:
tmp |= 0x53;
break;
}
siba_write_4_sub(sd, SIBA_IMCFGLO, tmp);
}
int
siba_sprom_get_core_power_info(device_t dev, int core,
struct siba_sprom_core_pwr_info *c)
{
struct siba_dev_softc *sd = device_get_ivars(dev);
struct siba_softc *siba = sd->sd_bus;
if (core < 0 || core > 3) {
return (EINVAL);
}
memcpy(c, &siba->siba_sprom.core_pwr_info[core], sizeof(*c));
return (0);
}
int
siba_sprom_get_mcs2gpo(device_t dev, uint16_t *c)
{
struct siba_dev_softc *sd = device_get_ivars(dev);
struct siba_softc *siba = sd->sd_bus;
memcpy(c, &siba->siba_sprom.mcs2gpo, sizeof(uint16_t) * 8);
return (0);
}
int
siba_sprom_get_mcs5glpo(device_t dev, uint16_t *c)
{
struct siba_dev_softc *sd = device_get_ivars(dev);
struct siba_softc *siba = sd->sd_bus;
memcpy(c, &siba->siba_sprom.mcs5glpo, sizeof(uint16_t) * 8);
return (0);
}
int
siba_sprom_get_mcs5gpo(device_t dev, uint16_t *c)
{
struct siba_dev_softc *sd = device_get_ivars(dev);
struct siba_softc *siba = sd->sd_bus;
memcpy(c, &siba->siba_sprom.mcs5gpo, sizeof(uint16_t) * 8);
return (0);
}
int
siba_sprom_get_mcs5ghpo(device_t dev, uint16_t *c)
{
struct siba_dev_softc *sd = device_get_ivars(dev);
struct siba_softc *siba = sd->sd_bus;
memcpy(c, &siba->siba_sprom.mcs5ghpo, sizeof(uint16_t) * 8);
return (0);
}
void
siba_pmu_spuravoid_pllupdate(device_t dev, int spur_avoid)
{
struct siba_dev_softc *sd = device_get_ivars(dev);
struct siba_softc *siba = sd->sd_bus;
struct siba_cc *scc;
scc = &siba->siba_cc;
if (scc->scc_dev == NULL) {
device_printf(dev, "%s: called; no pmu\n", __func__);
return;
}
switch (siba_get_chipid(dev)) {
case 0x4322:
siba_cc_pll_write(scc, SIBA_CC_PMU1_PLL0, 0x11100070);
siba_cc_pll_write(scc, SIBA_CC_PMU1_PLL1, 0x1014140a);
siba_cc_pll_write(scc, SIBA_CC_PMU1_PLL5, 0x88888854);
if (spur_avoid == 1)
siba_cc_pll_write(scc, SIBA_CC_PMU1_PLL2, 0x05201828);
else
siba_cc_pll_write(scc, SIBA_CC_PMU1_PLL2, 0x05001828);
break;
case 43222:
if (spur_avoid == 1) {
siba_cc_pll_write(scc, SIBA_CC_PMU1_PLL0, 0x11500008);
siba_cc_pll_write(scc, SIBA_CC_PMU1_PLL1, 0x0C000C06);
siba_cc_pll_write(scc, SIBA_CC_PMU1_PLL2, 0x0F600a08);
siba_cc_pll_write(scc, SIBA_CC_PMU1_PLL3, 0x00000000);
siba_cc_pll_write(scc, SIBA_CC_PMU1_PLL4, 0x2001E920);
siba_cc_pll_write(scc, SIBA_CC_PMU1_PLL5, 0x88888815);
} else {
siba_cc_pll_write(scc, SIBA_CC_PMU1_PLL0, 0x11100008);
siba_cc_pll_write(scc, SIBA_CC_PMU1_PLL1, 0x0c000c06);
siba_cc_pll_write(scc, SIBA_CC_PMU1_PLL2, 0x03000a08);
siba_cc_pll_write(scc, SIBA_CC_PMU1_PLL3, 0x00000000);
siba_cc_pll_write(scc, SIBA_CC_PMU1_PLL4, 0x200005c0);
siba_cc_pll_write(scc, SIBA_CC_PMU1_PLL5, 0x88888855);
}
break;
default:
device_printf(dev,
"%s: unknown spur avoidance settings for chip 0x%04x\n",
__func__,
siba_get_chipid(dev));
return;
}
/* Both chips above use the same update */
SIBA_CC_SET32(scc, SIBA_CC_PMUCTL, SIBA_CC_PMUCTL_PLL_UPD);
}
void
siba_cc_set32(device_t dev, uint32_t reg, uint32_t val)
{
struct siba_dev_softc *sd = device_get_ivars(dev);
struct siba_softc *siba = sd->sd_bus;
struct siba_cc *scc;
scc = &siba->siba_cc;
if (scc->scc_dev == NULL) {
device_printf(dev, "%s: called; no pmu\n", __func__);
return;
}
SIBA_CC_SET32(scc, reg, val);
}
void
siba_cc_mask32(device_t dev, uint32_t reg, uint32_t mask)
{
struct siba_dev_softc *sd = device_get_ivars(dev);
struct siba_softc *siba = sd->sd_bus;
struct siba_cc *scc;
scc = &siba->siba_cc;
if (scc->scc_dev == NULL) {
device_printf(dev, "%s: called; no pmu\n", __func__);
return;
}
SIBA_CC_MASK32(scc, reg, mask);
}
uint32_t
siba_cc_read32(device_t dev, uint32_t reg)
{
struct siba_dev_softc *sd = device_get_ivars(dev);
struct siba_softc *siba = sd->sd_bus;
struct siba_cc *scc;
scc = &siba->siba_cc;
if (scc->scc_dev == NULL) {
device_printf(dev, "%s: called; no pmu\n", __func__);
return 0xffffffff;
}
return SIBA_CC_READ32(scc, reg);
}
void
siba_cc_write32(device_t dev, uint32_t reg, uint32_t val)
{
struct siba_dev_softc *sd = device_get_ivars(dev);
struct siba_softc *siba = sd->sd_bus;
struct siba_cc *scc;
scc = &siba->siba_cc;
if (scc->scc_dev == NULL) {
device_printf(dev, "%s: called; no pmu\n", __func__);
return;
}
SIBA_CC_WRITE32(scc, reg, val);
}