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$");
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 *);
136204922Sweongyostatic uint32_t	siba_read_4_sub(struct siba_dev_softc *, uint16_t);
137204922Sweongyostatic void	siba_write_4_sub(struct siba_dev_softc *, uint16_t, uint32_t);
138204922Sweongyostatic void	siba_powerup_sub(struct siba_softc *, int);
139204922Sweongyostatic int	siba_powerdown_sub(struct siba_softc *);
140204922Sweongyostatic int	siba_dev_isup_sub(struct siba_dev_softc *);
141204922Sweongyostatic void	siba_dev_up_sub(struct siba_dev_softc *, uint32_t);
142204922Sweongyostatic void	siba_dev_down_sub(struct siba_dev_softc *, uint32_t);
143203319Sweongyoint		siba_core_attach(struct siba_softc *);
144203319Sweongyoint		siba_core_detach(struct siba_softc *);
145203319Sweongyoint		siba_core_suspend(struct siba_softc *);
146203319Sweongyoint		siba_core_resume(struct siba_softc *);
147203319Sweongyouint8_t		siba_getncores(device_t, uint16_t);
148203319Sweongyo
149203319Sweongyostatic const struct siba_bus_ops siba_pci_ops = {
150203319Sweongyo	.read_2		= siba_pci_read_2,
151203319Sweongyo	.read_4		= siba_pci_read_4,
152203319Sweongyo	.write_2	= siba_pci_write_2,
153203319Sweongyo	.write_4	= siba_pci_write_4,
154203319Sweongyo	.read_multi_1	= siba_pci_read_multi_1,
155203319Sweongyo	.read_multi_2	= siba_pci_read_multi_2,
156203319Sweongyo	.read_multi_4	= siba_pci_read_multi_4,
157203319Sweongyo	.write_multi_1	= siba_pci_write_multi_1,
158203319Sweongyo	.write_multi_2	= siba_pci_write_multi_2,
159203319Sweongyo	.write_multi_4	= siba_pci_write_multi_4,
160203319Sweongyo};
161203319Sweongyo
162203319Sweongyostatic const struct siba_cc_pmu_res_updown siba_cc_pmu_4325_updown[] =
163203319Sweongyo    SIBA_CC_PMU_4325_RES_UPDOWN;
164203319Sweongyostatic const struct siba_cc_pmu_res_depend siba_cc_pmu_4325_depend[] =
165203319Sweongyo    SIBA_CC_PMU_4325_RES_DEPEND;
166203319Sweongyostatic const struct siba_cc_pmu_res_updown siba_cc_pmu_4328_updown[] =
167203319Sweongyo    SIBA_CC_PMU_4328_RES_UPDOWN;
168203319Sweongyostatic const struct siba_cc_pmu_res_depend siba_cc_pmu_4328_depend[] =
169203319Sweongyo    SIBA_CC_PMU_4328_RES_DEPEND;
170203319Sweongyostatic const struct siba_cc_pmu0_plltab siba_cc_pmu0_plltab[] =
171203319Sweongyo    SIBA_CC_PMU0_PLLTAB_ENTRY;
172203319Sweongyostatic const struct siba_cc_pmu1_plltab siba_cc_pmu1_plltab[] =
173203319Sweongyo    SIBA_CC_PMU1_PLLTAB_ENTRY;
174203319Sweongyo
175203319Sweongyoint
176203319Sweongyosiba_core_attach(struct siba_softc *siba)
177203319Sweongyo{
178203319Sweongyo	struct siba_cc *scc;
179203319Sweongyo	int error;
180203319Sweongyo
181203319Sweongyo	KASSERT(siba->siba_type == SIBA_TYPE_PCI,
182203319Sweongyo	    ("unsupported BUS type (%#x)", siba->siba_type));
183203319Sweongyo
184203319Sweongyo	siba->siba_ops = &siba_pci_ops;
185203319Sweongyo
186203319Sweongyo	siba_pci_gpio(siba, SIBA_GPIO_CRYSTAL | SIBA_GPIO_PLL, 1);
187203319Sweongyo	siba_scan(siba);
188203319Sweongyo
189203319Sweongyo	/* XXX init PCI or PCMCIA host devices */
190203319Sweongyo
191204922Sweongyo	siba_powerup_sub(siba, 0);
192203319Sweongyo
193203319Sweongyo	/* init ChipCommon */
194203319Sweongyo	scc = &siba->siba_cc;
195203319Sweongyo	if (scc->scc_dev != NULL) {
196203319Sweongyo		siba_cc_pmu_init(scc);
197203319Sweongyo		siba_cc_power_init(scc);
198203319Sweongyo		siba_cc_clock(scc, SIBA_CLOCK_FAST);
199203319Sweongyo		siba_cc_powerup_delay(scc);
200203319Sweongyo	}
201203319Sweongyo
202203319Sweongyo	error = siba_pci_sprom(siba, &siba->siba_sprom);
203203319Sweongyo	if (error) {
204204922Sweongyo		siba_powerdown_sub(siba);
205203319Sweongyo		return (error);
206203319Sweongyo	}
207203319Sweongyo
208204657Sweongyo	siba_pcicore_init(&siba->siba_pci);
209204922Sweongyo	siba_powerdown_sub(siba);
210204922Sweongyo
211204657Sweongyo	return (bus_generic_attach(siba->siba_dev));
212203319Sweongyo}
213203319Sweongyo
214203319Sweongyoint
215203319Sweongyosiba_core_detach(struct siba_softc *siba)
216203319Sweongyo{
217227701Shselasky	/* detach & delete all children */
218227849Shselasky	device_delete_children(siba->siba_dev);
219203319Sweongyo	return (0);
220203319Sweongyo}
221203319Sweongyo
222203319Sweongyostatic void
223203319Sweongyosiba_pci_gpio(struct siba_softc *siba, uint32_t what, int on)
224203319Sweongyo{
225203319Sweongyo	uint32_t in, out;
226203319Sweongyo	uint16_t status;
227203319Sweongyo
228203319Sweongyo	if (siba->siba_type != SIBA_TYPE_PCI)
229203319Sweongyo		return;
230203319Sweongyo
231203319Sweongyo	out = pci_read_config(siba->siba_dev, SIBA_GPIO_OUT, 4);
232203319Sweongyo	if (on == 0) {
233203319Sweongyo		if (what & SIBA_GPIO_PLL)
234203319Sweongyo			out |= SIBA_GPIO_PLL;
235203319Sweongyo		if (what & SIBA_GPIO_CRYSTAL)
236203319Sweongyo			out &= ~SIBA_GPIO_CRYSTAL;
237203319Sweongyo		pci_write_config(siba->siba_dev, SIBA_GPIO_OUT, out, 4);
238203319Sweongyo		pci_write_config(siba->siba_dev, SIBA_GPIO_OUT_EN,
239203319Sweongyo		    pci_read_config(siba->siba_dev,
240203319Sweongyo			SIBA_GPIO_OUT_EN, 4) | what, 4);
241203319Sweongyo		return;
242203319Sweongyo	}
243203319Sweongyo
244203319Sweongyo	in = pci_read_config(siba->siba_dev, SIBA_GPIO_IN, 4);
245203319Sweongyo	if ((in & SIBA_GPIO_CRYSTAL) != SIBA_GPIO_CRYSTAL) {
246203319Sweongyo		if (what & SIBA_GPIO_CRYSTAL) {
247203319Sweongyo			out |= SIBA_GPIO_CRYSTAL;
248203319Sweongyo			if (what & SIBA_GPIO_PLL)
249203319Sweongyo				out |= SIBA_GPIO_PLL;
250203319Sweongyo			pci_write_config(siba->siba_dev, SIBA_GPIO_OUT, out, 4);
251203319Sweongyo			pci_write_config(siba->siba_dev,
252203319Sweongyo			    SIBA_GPIO_OUT_EN, pci_read_config(siba->siba_dev,
253203319Sweongyo				SIBA_GPIO_OUT_EN, 4) | what, 4);
254203319Sweongyo			DELAY(1000);
255203319Sweongyo		}
256203319Sweongyo		if (what & SIBA_GPIO_PLL) {
257203319Sweongyo			out &= ~SIBA_GPIO_PLL;
258203319Sweongyo			pci_write_config(siba->siba_dev, SIBA_GPIO_OUT, out, 4);
259203319Sweongyo			DELAY(5000);
260203319Sweongyo		}
261203319Sweongyo	}
262203319Sweongyo
263203319Sweongyo	status = pci_read_config(siba->siba_dev, PCIR_STATUS, 2);
264203319Sweongyo	status &= ~PCIM_STATUS_STABORT;
265203319Sweongyo	pci_write_config(siba->siba_dev, PCIR_STATUS, status, 2);
266203319Sweongyo}
267203319Sweongyo
268203319Sweongyostatic void
269203319Sweongyosiba_scan(struct siba_softc *siba)
270203319Sweongyo{
271203319Sweongyo	struct siba_dev_softc *sd;
272203319Sweongyo	uint32_t idhi, tmp;
273204657Sweongyo	device_t child;
274203319Sweongyo	int base, dev_i = 0, error, i, is_pcie, n_80211 = 0, n_cc = 0,
275203319Sweongyo	    n_pci = 0;
276203319Sweongyo
277203319Sweongyo	KASSERT(siba->siba_type == SIBA_TYPE_PCI,
278203319Sweongyo	    ("unsupported BUS type (%#x)", siba->siba_type));
279203319Sweongyo
280203319Sweongyo	siba->siba_ndevs = 0;
281203319Sweongyo	error = siba_switchcore(siba, 0); /* need the first core */
282203319Sweongyo	if (error)
283203319Sweongyo		return;
284203319Sweongyo
285203319Sweongyo	idhi = siba_scan_read_4(siba, 0, SIBA_IDHIGH);
286203319Sweongyo	if (SIBA_IDHIGH_CORECODE(idhi) == SIBA_DEVID_CHIPCOMMON) {
287203319Sweongyo		tmp = siba_scan_read_4(siba, 0, SIBA_CC_CHIPID);
288203319Sweongyo		siba->siba_chipid = SIBA_CC_ID(tmp);
289203319Sweongyo		siba->siba_chiprev = SIBA_CC_REV(tmp);
290203319Sweongyo		siba->siba_chippkg = SIBA_CC_PKG(tmp);
291203319Sweongyo		if (SIBA_IDHIGH_REV(idhi) >= 4)
292203319Sweongyo			siba->siba_ndevs = SIBA_CC_NCORES(tmp);
293203319Sweongyo		siba->siba_cc.scc_caps = siba_scan_read_4(siba, 0,
294203319Sweongyo		    SIBA_CC_CAPS);
295203319Sweongyo	} else {
296203319Sweongyo		if (siba->siba_type == SIBA_TYPE_PCI) {
297203319Sweongyo			siba->siba_chipid = siba_dev2chipid(siba);
298203319Sweongyo			siba->siba_chiprev = pci_read_config(siba->siba_dev,
299203319Sweongyo			    PCIR_REVID, 2);
300203319Sweongyo			siba->siba_chippkg = 0;
301203319Sweongyo		} else {
302203319Sweongyo			siba->siba_chipid = 0x4710;
303203319Sweongyo			siba->siba_chiprev = 0;
304203319Sweongyo			siba->siba_chippkg = 0;
305203319Sweongyo		}
306203319Sweongyo	}
307203319Sweongyo	if (siba->siba_ndevs == 0)
308203319Sweongyo		siba->siba_ndevs = siba_getncores(siba->siba_dev,
309203319Sweongyo		    siba->siba_chipid);
310203319Sweongyo	if (siba->siba_ndevs > SIBA_MAX_CORES) {
311203319Sweongyo		device_printf(siba->siba_dev,
312203319Sweongyo		    "too many siba cores (max %d %d)\n",
313203319Sweongyo		    SIBA_MAX_CORES, siba->siba_ndevs);
314203319Sweongyo		return;
315203319Sweongyo	}
316203319Sweongyo
317203319Sweongyo	/* looking basic information about each cores/devices */
318203319Sweongyo	for (i = 0; i < siba->siba_ndevs; i++) {
319203319Sweongyo		error = siba_switchcore(siba, i);
320203319Sweongyo		if (error)
321203319Sweongyo			return;
322203319Sweongyo		sd = &(siba->siba_devs[dev_i]);
323203319Sweongyo		idhi = siba_scan_read_4(siba, i, SIBA_IDHIGH);
324203319Sweongyo		sd->sd_bus = siba;
325203319Sweongyo		sd->sd_id.sd_device = SIBA_IDHIGH_CORECODE(idhi);
326203319Sweongyo		sd->sd_id.sd_rev = SIBA_IDHIGH_REV(idhi);
327203319Sweongyo		sd->sd_id.sd_vendor = SIBA_IDHIGH_VENDOR(idhi);
328203319Sweongyo		sd->sd_ops = siba->siba_ops;
329203319Sweongyo		sd->sd_coreidx = i;
330203319Sweongyo
331203319Sweongyo		DPRINTF(siba, SIBA_DEBUG_SCAN,
332203319Sweongyo		    "core %d (%s) found (cc %#xrev %#x vendor %#x)\n",
333203319Sweongyo		    i, siba_core_name(sd->sd_id.sd_device),
334203319Sweongyo		    sd->sd_id.sd_device, sd->sd_id.sd_rev, sd->sd_id.vendor);
335203319Sweongyo
336203319Sweongyo		switch (sd->sd_id.sd_device) {
337203319Sweongyo		case SIBA_DEVID_CHIPCOMMON:
338203319Sweongyo			n_cc++;
339203319Sweongyo			if (n_cc > 1) {
340203319Sweongyo				device_printf(siba->siba_dev,
341203319Sweongyo				    "warn: multiple ChipCommon\n");
342203319Sweongyo				break;
343203319Sweongyo			}
344203319Sweongyo			siba->siba_cc.scc_dev = sd;
345203319Sweongyo			break;
346203319Sweongyo		case SIBA_DEVID_80211:
347203319Sweongyo			n_80211++;
348203319Sweongyo			if (n_80211 > 1) {
349203319Sweongyo				device_printf(siba->siba_dev,
350203319Sweongyo				    "warn: multiple 802.11 core\n");
351203319Sweongyo				continue;
352203319Sweongyo			}
353203319Sweongyo			break;
354203319Sweongyo		case SIBA_DEVID_PCI:
355203319Sweongyo		case SIBA_DEVID_PCIE:
356203319Sweongyo			n_pci++;
357219902Sjhb			error = pci_find_cap(siba->siba_dev, PCIY_EXPRESS,
358203319Sweongyo			    &base);
359203319Sweongyo			is_pcie = (error == 0) ? 1 : 0;
360203319Sweongyo
361203319Sweongyo			if (n_pci > 1) {
362203319Sweongyo				device_printf(siba->siba_dev,
363203319Sweongyo				    "warn: multiple PCI(E) cores\n");
364203319Sweongyo				break;
365203319Sweongyo			}
366203319Sweongyo			if (sd->sd_id.sd_device == SIBA_DEVID_PCI &&
367203319Sweongyo			    is_pcie == 1)
368203319Sweongyo				continue;
369203319Sweongyo			if (sd->sd_id.sd_device == SIBA_DEVID_PCIE &&
370203319Sweongyo			    is_pcie == 0)
371203319Sweongyo				continue;
372203319Sweongyo			siba->siba_pci.spc_dev = sd;
373203319Sweongyo			break;
374203319Sweongyo		case SIBA_DEVID_MODEM:
375203319Sweongyo		case SIBA_DEVID_PCMCIA:
376203319Sweongyo			break;
377203319Sweongyo		default:
378203319Sweongyo			device_printf(siba->siba_dev,
379203319Sweongyo			    "unsupported coreid (%s)\n",
380203319Sweongyo			    siba_core_name(sd->sd_id.sd_device));
381203319Sweongyo			break;
382203319Sweongyo		}
383203319Sweongyo		dev_i++;
384204657Sweongyo
385204657Sweongyo		child = device_add_child(siba->siba_dev, NULL, -1);
386204657Sweongyo		if (child == NULL) {
387204657Sweongyo			device_printf(siba->siba_dev, "child attach failed\n");
388204657Sweongyo			continue;
389204657Sweongyo		}
390204657Sweongyo
391204657Sweongyo		device_set_ivars(child, sd);
392203319Sweongyo	}
393203319Sweongyo	siba->siba_ndevs = dev_i;
394203319Sweongyo}
395203319Sweongyo
396203319Sweongyostatic int
397203319Sweongyosiba_switchcore(struct siba_softc *siba, uint8_t idx)
398203319Sweongyo{
399203319Sweongyo
400203319Sweongyo	switch (siba->siba_type) {
401203319Sweongyo	case SIBA_TYPE_PCI:
402203319Sweongyo		return (siba_pci_switchcore_sub(siba, idx));
403203319Sweongyo	default:
404203319Sweongyo		KASSERT(0 == 1,
405203319Sweongyo		    ("%s: unsupported bustype %#x", __func__,
406203319Sweongyo		    siba->siba_type));
407203319Sweongyo	}
408203319Sweongyo	return (0);
409203319Sweongyo}
410203319Sweongyo
411203319Sweongyostatic int
412203319Sweongyosiba_pci_switchcore_sub(struct siba_softc *siba, uint8_t idx)
413203319Sweongyo{
414203319Sweongyo#define RETRY_MAX	50
415203319Sweongyo	int i;
416203319Sweongyo	uint32_t dir;
417203319Sweongyo
418203319Sweongyo	dir = SIBA_REGWIN(idx);
419203319Sweongyo
420203319Sweongyo	for (i = 0; i < RETRY_MAX; i++) {
421203319Sweongyo		pci_write_config(siba->siba_dev, SIBA_BAR0, dir, 4);
422203319Sweongyo		if (pci_read_config(siba->siba_dev, SIBA_BAR0, 4) == dir)
423203319Sweongyo			return (0);
424203319Sweongyo		DELAY(10);
425203319Sweongyo	}
426203319Sweongyo	return (ENODEV);
427203319Sweongyo#undef RETRY_MAX
428203319Sweongyo}
429203319Sweongyo
430203319Sweongyostatic int
431203319Sweongyosiba_pci_switchcore(struct siba_softc *siba, struct siba_dev_softc *sd)
432203319Sweongyo{
433203319Sweongyo	int error;
434203319Sweongyo
435203319Sweongyo	DPRINTF(siba, SIBA_DEBUG_SWITCHCORE, "Switching to %s core, index %d\n",
436203319Sweongyo	    siba_core_name(sd->sd_id.sd_device), sd->sd_coreidx);
437203319Sweongyo
438203319Sweongyo	error = siba_pci_switchcore_sub(siba, sd->sd_coreidx);
439203319Sweongyo	if (error == 0)
440203319Sweongyo		siba->siba_curdev = sd;
441203319Sweongyo
442203319Sweongyo	return (error);
443203319Sweongyo}
444203319Sweongyo
445203319Sweongyostatic uint32_t
446203319Sweongyosiba_scan_read_4(struct siba_softc *siba, uint8_t coreidx,
447203319Sweongyo    uint16_t offset)
448203319Sweongyo{
449203319Sweongyo
450203319Sweongyo	(void)coreidx;
451203319Sweongyo	KASSERT(siba->siba_type == SIBA_TYPE_PCI,
452203319Sweongyo	    ("unsupported BUS type (%#x)", siba->siba_type));
453203319Sweongyo
454203319Sweongyo	return (SIBA_READ_4(siba, offset));
455203319Sweongyo}
456203319Sweongyo
457203319Sweongyostatic uint16_t
458203319Sweongyosiba_dev2chipid(struct siba_softc *siba)
459203319Sweongyo{
460203319Sweongyo	uint16_t chipid = 0;
461203319Sweongyo
462203319Sweongyo	switch (siba->siba_pci_did) {
463203319Sweongyo	case 0x4301:
464203319Sweongyo		chipid = 0x4301;
465203319Sweongyo		break;
466203319Sweongyo	case 0x4305:
467203319Sweongyo	case 0x4306:
468203319Sweongyo	case 0x4307:
469203319Sweongyo		chipid = 0x4307;
470203319Sweongyo		break;
471203319Sweongyo	case 0x4403:
472203319Sweongyo		chipid = 0x4402;
473203319Sweongyo		break;
474203319Sweongyo	case 0x4610:
475203319Sweongyo	case 0x4611:
476203319Sweongyo	case 0x4612:
477203319Sweongyo	case 0x4613:
478203319Sweongyo	case 0x4614:
479203319Sweongyo	case 0x4615:
480203319Sweongyo		chipid = 0x4610;
481203319Sweongyo		break;
482203319Sweongyo	case 0x4710:
483203319Sweongyo	case 0x4711:
484203319Sweongyo	case 0x4712:
485203319Sweongyo	case 0x4713:
486203319Sweongyo	case 0x4714:
487203319Sweongyo	case 0x4715:
488203319Sweongyo		chipid = 0x4710;
489203319Sweongyo		break;
490203319Sweongyo	case 0x4320:
491203319Sweongyo	case 0x4321:
492203319Sweongyo	case 0x4322:
493203319Sweongyo	case 0x4323:
494203319Sweongyo	case 0x4324:
495203319Sweongyo	case 0x4325:
496203319Sweongyo		chipid = 0x4309;
497203319Sweongyo		break;
498203319Sweongyo	case PCI_DEVICE_ID_BCM4401:
499203319Sweongyo	case PCI_DEVICE_ID_BCM4401B0:
500203319Sweongyo	case PCI_DEVICE_ID_BCM4401B1:
501203319Sweongyo		chipid = 0x4401;
502203319Sweongyo		break;
503203319Sweongyo	default:
504203319Sweongyo		device_printf(siba->siba_dev, "unknown PCI did (%d)\n",
505203319Sweongyo		    siba->siba_pci_did);
506203319Sweongyo	}
507203319Sweongyo
508203319Sweongyo	return (chipid);
509203319Sweongyo}
510203319Sweongyo
511203319Sweongyo/*
512203319Sweongyo * Earlier ChipCommon revisions have hardcoded number of cores
513203319Sweongyo * present dependent on the ChipCommon ID.
514203319Sweongyo */
515203319Sweongyouint8_t
516203319Sweongyosiba_getncores(device_t dev, uint16_t chipid)
517203319Sweongyo{
518203319Sweongyo	switch (chipid) {
519203319Sweongyo	case 0x4401:
520203319Sweongyo	case 0x4402:
521203319Sweongyo		return (3);
522203319Sweongyo	case 0x4301:
523203319Sweongyo	case 0x4307:
524203319Sweongyo		return (5);
525203319Sweongyo	case 0x4306:
526203319Sweongyo		return (6);
527203319Sweongyo	case SIBA_CCID_SENTRY5:
528203319Sweongyo		return (7);
529203319Sweongyo	case 0x4310:
530203319Sweongyo		return (8);
531203319Sweongyo	case SIBA_CCID_BCM4710:
532203319Sweongyo	case 0x4610:
533203319Sweongyo	case SIBA_CCID_BCM4704:
534203319Sweongyo		return (9);
535203319Sweongyo	default:
536203319Sweongyo		device_printf(dev, "unknown the chipset ID %#x\n", chipid);
537203319Sweongyo	}
538203319Sweongyo
539203319Sweongyo	return (1);
540203319Sweongyo}
541203319Sweongyo
542203319Sweongyostatic const char *
543203319Sweongyosiba_core_name(uint16_t coreid)
544203319Sweongyo{
545203319Sweongyo
546203319Sweongyo	switch (coreid) {
547203319Sweongyo	case SIBA_DEVID_CHIPCOMMON:
548203319Sweongyo		return ("ChipCommon");
549203319Sweongyo	case SIBA_DEVID_ILINE20:
550203319Sweongyo		return ("ILine 20");
551203319Sweongyo	case SIBA_DEVID_SDRAM:
552203319Sweongyo		return ("SDRAM");
553203319Sweongyo	case SIBA_DEVID_PCI:
554203319Sweongyo		return ("PCI");
555203319Sweongyo	case SIBA_DEVID_MIPS:
556203319Sweongyo		return ("MIPS");
557203319Sweongyo	case SIBA_DEVID_ETHERNET:
558203319Sweongyo		return ("Fast Ethernet");
559203319Sweongyo	case SIBA_DEVID_MODEM:
560203319Sweongyo		return ("Modem");
561203319Sweongyo	case SIBA_DEVID_USB11_HOSTDEV:
562203319Sweongyo		return ("USB 1.1 Hostdev");
563203319Sweongyo	case SIBA_DEVID_ADSL:
564203319Sweongyo		return ("ADSL");
565203319Sweongyo	case SIBA_DEVID_ILINE100:
566203319Sweongyo		return ("ILine 100");
567203319Sweongyo	case SIBA_DEVID_IPSEC:
568203319Sweongyo		return ("IPSEC");
569203319Sweongyo	case SIBA_DEVID_PCMCIA:
570203319Sweongyo		return ("PCMCIA");
571203319Sweongyo	case SIBA_DEVID_INTERNAL_MEM:
572203319Sweongyo		return ("Internal Memory");
573203319Sweongyo	case SIBA_DEVID_SDRAMDDR:
574203319Sweongyo		return ("MEMC SDRAM");
575203319Sweongyo	case SIBA_DEVID_EXTIF:
576203319Sweongyo		return ("EXTIF");
577203319Sweongyo	case SIBA_DEVID_80211:
578203319Sweongyo		return ("IEEE 802.11");
579203319Sweongyo	case SIBA_DEVID_MIPS_3302:
580203319Sweongyo		return ("MIPS 3302");
581203319Sweongyo	case SIBA_DEVID_USB11_HOST:
582203319Sweongyo		return ("USB 1.1 Host");
583203319Sweongyo	case SIBA_DEVID_USB11_DEV:
584203319Sweongyo		return ("USB 1.1 Device");
585203319Sweongyo	case SIBA_DEVID_USB20_HOST:
586203319Sweongyo		return ("USB 2.0 Host");
587203319Sweongyo	case SIBA_DEVID_USB20_DEV:
588203319Sweongyo		return ("USB 2.0 Device");
589203319Sweongyo	case SIBA_DEVID_SDIO_HOST:
590203319Sweongyo		return ("SDIO Host");
591203319Sweongyo	case SIBA_DEVID_ROBOSWITCH:
592203319Sweongyo		return ("Roboswitch");
593203319Sweongyo	case SIBA_DEVID_PARA_ATA:
594203319Sweongyo		return ("PATA");
595203319Sweongyo	case SIBA_DEVID_SATA_XORDMA:
596203319Sweongyo		return ("SATA XOR-DMA");
597203319Sweongyo	case SIBA_DEVID_ETHERNET_GBIT:
598203319Sweongyo		return ("GBit Ethernet");
599203319Sweongyo	case SIBA_DEVID_PCIE:
600203319Sweongyo		return ("PCI-Express");
601203319Sweongyo	case SIBA_DEVID_MIMO_PHY:
602203319Sweongyo		return ("MIMO PHY");
603203319Sweongyo	case SIBA_DEVID_SRAM_CTRLR:
604203319Sweongyo		return ("SRAM Controller");
605203319Sweongyo	case SIBA_DEVID_MINI_MACPHY:
606203319Sweongyo		return ("Mini MACPHY");
607203319Sweongyo	case SIBA_DEVID_ARM_1176:
608203319Sweongyo		return ("ARM 1176");
609203319Sweongyo	case SIBA_DEVID_ARM_7TDMI:
610203319Sweongyo		return ("ARM 7TDMI");
611203319Sweongyo	}
612203319Sweongyo	return ("unknown");
613203319Sweongyo}
614203319Sweongyo
615203319Sweongyostatic uint16_t
616203319Sweongyosiba_pci_read_2(struct siba_dev_softc *sd, uint16_t offset)
617203319Sweongyo{
618203319Sweongyo	struct siba_softc *siba = sd->sd_bus;
619203319Sweongyo
620203319Sweongyo	if (siba->siba_curdev != sd && siba_pci_switchcore(siba, sd) != 0)
621203319Sweongyo		return (0xffff);
622203319Sweongyo
623203319Sweongyo	return (SIBA_READ_2(siba, offset));
624203319Sweongyo}
625203319Sweongyo
626203319Sweongyostatic uint32_t
627203319Sweongyosiba_pci_read_4(struct siba_dev_softc *sd, uint16_t offset)
628203319Sweongyo{
629203319Sweongyo	struct siba_softc *siba = sd->sd_bus;
630203319Sweongyo
631203319Sweongyo	if (siba->siba_curdev != sd && siba_pci_switchcore(siba, sd) != 0)
632203319Sweongyo		return (0xffff);
633203319Sweongyo
634203319Sweongyo	return (SIBA_READ_4(siba, offset));
635203319Sweongyo}
636203319Sweongyo
637203319Sweongyostatic void
638203319Sweongyosiba_pci_write_2(struct siba_dev_softc *sd, uint16_t offset, uint16_t value)
639203319Sweongyo{
640203319Sweongyo	struct siba_softc *siba = sd->sd_bus;
641203319Sweongyo
642203319Sweongyo	if (siba->siba_curdev != sd && siba_pci_switchcore(siba, sd) != 0)
643203319Sweongyo		return;
644203319Sweongyo
645203319Sweongyo	SIBA_WRITE_2(siba, offset, value);
646203319Sweongyo}
647203319Sweongyo
648203319Sweongyostatic void
649203319Sweongyosiba_pci_write_4(struct siba_dev_softc *sd, uint16_t offset, uint32_t value)
650203319Sweongyo{
651203319Sweongyo	struct siba_softc *siba = sd->sd_bus;
652203319Sweongyo
653203319Sweongyo	if (siba->siba_curdev != sd && siba_pci_switchcore(siba, sd) != 0)
654203319Sweongyo		return;
655203319Sweongyo
656203319Sweongyo	SIBA_WRITE_4(siba, offset, value);
657203319Sweongyo}
658203319Sweongyo
659203319Sweongyostatic void
660203319Sweongyosiba_pci_read_multi_1(struct siba_dev_softc *sd, void *buffer, size_t count,
661203319Sweongyo    uint16_t offset)
662203319Sweongyo{
663203319Sweongyo	struct siba_softc *siba = sd->sd_bus;
664203319Sweongyo
665203319Sweongyo	if (siba->siba_curdev != sd && siba_pci_switchcore(siba, sd) != 0) {
666203319Sweongyo		memset(buffer, 0xff, count);
667203319Sweongyo		return;
668203319Sweongyo	}
669203319Sweongyo
670203319Sweongyo	SIBA_READ_MULTI_1(siba, offset, buffer, count);
671203319Sweongyo}
672203319Sweongyo
673203319Sweongyostatic void
674203319Sweongyosiba_pci_read_multi_2(struct siba_dev_softc *sd, void *buffer, size_t count,
675203319Sweongyo    uint16_t offset)
676203319Sweongyo{
677203319Sweongyo	struct siba_softc *siba = sd->sd_bus;
678203319Sweongyo
679203319Sweongyo	if (siba->siba_curdev != sd && siba_pci_switchcore(siba, sd) != 0) {
680203319Sweongyo		memset(buffer, 0xff, count);
681203319Sweongyo		return;
682203319Sweongyo	}
683203319Sweongyo
684203319Sweongyo	KASSERT(!(count & 1), ("%s:%d: fail", __func__, __LINE__));
685203319Sweongyo	SIBA_READ_MULTI_2(siba, offset, buffer, count >> 1);
686203319Sweongyo}
687203319Sweongyo
688203319Sweongyostatic void
689203319Sweongyosiba_pci_read_multi_4(struct siba_dev_softc *sd, void *buffer, size_t count,
690203319Sweongyo    uint16_t offset)
691203319Sweongyo{
692203319Sweongyo	struct siba_softc *siba = sd->sd_bus;
693203319Sweongyo
694203319Sweongyo	if (siba->siba_curdev != sd && siba_pci_switchcore(siba, sd) != 0) {
695203319Sweongyo		memset(buffer, 0xff, count);
696203319Sweongyo		return;
697203319Sweongyo	}
698203319Sweongyo
699203319Sweongyo	KASSERT(!(count & 3), ("%s:%d: fail", __func__, __LINE__));
700203319Sweongyo	SIBA_READ_MULTI_4(siba, offset, buffer, count >> 2);
701203319Sweongyo}
702203319Sweongyo
703203319Sweongyostatic void
704203319Sweongyosiba_pci_write_multi_1(struct siba_dev_softc *sd, const void *buffer,
705203319Sweongyo    size_t count, uint16_t offset)
706203319Sweongyo{
707203319Sweongyo	struct siba_softc *siba = sd->sd_bus;
708203319Sweongyo
709203319Sweongyo	if (siba->siba_curdev != sd && siba_pci_switchcore(siba, sd) != 0)
710203319Sweongyo		return;
711203319Sweongyo
712203319Sweongyo	SIBA_WRITE_MULTI_1(siba, offset, buffer, count);
713203319Sweongyo}
714203319Sweongyo
715203319Sweongyostatic void
716203319Sweongyosiba_pci_write_multi_2(struct siba_dev_softc *sd, const void *buffer,
717203319Sweongyo    size_t count, uint16_t offset)
718203319Sweongyo{
719203319Sweongyo	struct siba_softc *siba = sd->sd_bus;
720203319Sweongyo
721203319Sweongyo	if (siba->siba_curdev != sd && siba_pci_switchcore(siba, sd) != 0)
722203319Sweongyo		return;
723203319Sweongyo
724203319Sweongyo	KASSERT(!(count & 1), ("%s:%d: fail", __func__, __LINE__));
725203319Sweongyo	SIBA_WRITE_MULTI_2(siba, offset, buffer, count >> 1);
726203319Sweongyo}
727203319Sweongyo
728203319Sweongyostatic void
729203319Sweongyosiba_pci_write_multi_4(struct siba_dev_softc *sd, const void *buffer,
730203319Sweongyo    size_t count, uint16_t offset)
731203319Sweongyo{
732203319Sweongyo	struct siba_softc *siba = sd->sd_bus;
733203319Sweongyo
734203319Sweongyo	if (siba->siba_curdev != sd && siba_pci_switchcore(siba, sd) != 0)
735203319Sweongyo		return;
736203319Sweongyo
737203319Sweongyo	KASSERT(!(count & 3), ("%s:%d: fail", __func__, __LINE__));
738203319Sweongyo	SIBA_WRITE_MULTI_4(siba, offset, buffer, count >> 2);
739203319Sweongyo}
740203319Sweongyo
741203319Sweongyovoid
742204922Sweongyosiba_powerup(device_t dev, int dynamic)
743203319Sweongyo{
744204922Sweongyo	struct siba_dev_softc *sd = device_get_ivars(dev);
745204922Sweongyo	struct siba_softc *siba = sd->sd_bus;
746203319Sweongyo
747204922Sweongyo	siba_powerup_sub(siba, dynamic);
748204922Sweongyo}
749204922Sweongyo
750204922Sweongyostatic void
751204922Sweongyosiba_powerup_sub(struct siba_softc *siba, int dynamic)
752204922Sweongyo{
753204922Sweongyo
754203319Sweongyo	siba_pci_gpio(siba, SIBA_GPIO_CRYSTAL | SIBA_GPIO_PLL, 1);
755203319Sweongyo	siba_cc_clock(&siba->siba_cc,
756203319Sweongyo	    (dynamic != 0) ? SIBA_CLOCK_DYNAMIC : SIBA_CLOCK_FAST);
757203319Sweongyo}
758203319Sweongyo
759203319Sweongyostatic void
760203319Sweongyosiba_cc_clock(struct siba_cc *scc, enum siba_clock clock)
761203319Sweongyo{
762203319Sweongyo	struct siba_dev_softc *sd = scc->scc_dev;
763203319Sweongyo	struct siba_softc *siba;
764203319Sweongyo	uint32_t tmp;
765203319Sweongyo
766203319Sweongyo	if (sd == NULL)
767203319Sweongyo		return;
768203319Sweongyo	siba = sd->sd_bus;
769203319Sweongyo	/*
770203319Sweongyo	 * chipcommon < r6 (no dynamic clock control)
771203319Sweongyo	 * chipcommon >= r10 (unknown)
772203319Sweongyo	 */
773203319Sweongyo	if (sd->sd_id.sd_rev < 6 || sd->sd_id.sd_rev >= 10 ||
774203319Sweongyo	    (scc->scc_caps & SIBA_CC_CAPS_PWCTL) == 0)
775203319Sweongyo		return;
776203319Sweongyo
777203319Sweongyo	switch (clock) {
778203319Sweongyo	case SIBA_CLOCK_DYNAMIC:
779203319Sweongyo		tmp = SIBA_CC_READ32(scc, SIBA_CC_CLKSLOW) &
780203319Sweongyo		    ~(SIBA_CC_CLKSLOW_ENXTAL | SIBA_CC_CLKSLOW_FSLOW |
781203319Sweongyo		    SIBA_CC_CLKSLOW_IPLL);
782203319Sweongyo		if ((tmp & SIBA_CC_CLKSLOW_SRC) != SIBA_CC_CLKSLOW_SRC_CRYSTAL)
783203319Sweongyo			tmp |= SIBA_CC_CLKSLOW_ENXTAL;
784203319Sweongyo		SIBA_CC_WRITE32(scc, SIBA_CC_CLKSLOW, tmp);
785203319Sweongyo		if (tmp & SIBA_CC_CLKSLOW_ENXTAL)
786203319Sweongyo			siba_pci_gpio(siba, SIBA_GPIO_CRYSTAL, 0);
787203319Sweongyo		break;
788203319Sweongyo	case SIBA_CLOCK_SLOW:
789203319Sweongyo		SIBA_CC_WRITE32(scc, SIBA_CC_CLKSLOW,
790203319Sweongyo		    SIBA_CC_READ32(scc, SIBA_CC_CLKSLOW) |
791203319Sweongyo		    SIBA_CC_CLKSLOW_FSLOW);
792203319Sweongyo		break;
793203319Sweongyo	case SIBA_CLOCK_FAST:
794203319Sweongyo		/* crystal on */
795203319Sweongyo		siba_pci_gpio(siba, SIBA_GPIO_CRYSTAL, 1);
796203319Sweongyo		SIBA_CC_WRITE32(scc, SIBA_CC_CLKSLOW,
797203319Sweongyo		    (SIBA_CC_READ32(scc, SIBA_CC_CLKSLOW) |
798203319Sweongyo			SIBA_CC_CLKSLOW_IPLL) & ~SIBA_CC_CLKSLOW_FSLOW);
799203319Sweongyo		break;
800203319Sweongyo	default:
801203319Sweongyo		KASSERT(0 == 1,
802203319Sweongyo		    ("%s: unsupported clock %#x", __func__, clock));
803203319Sweongyo	}
804203319Sweongyo}
805203319Sweongyo
806203319Sweongyouint16_t
807204922Sweongyosiba_read_2(device_t dev, uint16_t offset)
808203319Sweongyo{
809204922Sweongyo	struct siba_dev_softc *sd = device_get_ivars(dev);
810203319Sweongyo
811203319Sweongyo	return (sd->sd_ops->read_2(sd, offset));
812203319Sweongyo}
813203319Sweongyo
814203319Sweongyouint32_t
815204922Sweongyosiba_read_4(device_t dev, uint16_t offset)
816203319Sweongyo{
817204922Sweongyo	struct siba_dev_softc *sd = device_get_ivars(dev);
818203319Sweongyo
819204922Sweongyo	return (siba_read_4_sub(sd, offset));
820204922Sweongyo}
821204922Sweongyo
822204922Sweongyostatic uint32_t
823204922Sweongyosiba_read_4_sub(struct siba_dev_softc *sd, uint16_t offset)
824204922Sweongyo{
825204922Sweongyo
826203319Sweongyo	return (sd->sd_ops->read_4(sd, offset));
827203319Sweongyo}
828203319Sweongyo
829203319Sweongyovoid
830204922Sweongyosiba_write_2(device_t dev, uint16_t offset, uint16_t value)
831203319Sweongyo{
832204922Sweongyo	struct siba_dev_softc *sd = device_get_ivars(dev);
833203319Sweongyo
834203319Sweongyo	sd->sd_ops->write_2(sd, offset, value);
835203319Sweongyo}
836203319Sweongyo
837203319Sweongyovoid
838204922Sweongyosiba_write_4(device_t dev, uint16_t offset, uint32_t value)
839203319Sweongyo{
840204922Sweongyo	struct siba_dev_softc *sd = device_get_ivars(dev);
841203319Sweongyo
842204922Sweongyo	return (siba_write_4_sub(sd, offset, value));
843204922Sweongyo}
844204922Sweongyo
845204922Sweongyostatic void
846204922Sweongyosiba_write_4_sub(struct siba_dev_softc *sd, uint16_t offset, uint32_t value)
847204922Sweongyo{
848204922Sweongyo
849203319Sweongyo	sd->sd_ops->write_4(sd, offset, value);
850203319Sweongyo}
851203319Sweongyo
852203319Sweongyovoid
853204922Sweongyosiba_read_multi_1(device_t dev, void *buffer, size_t count,
854203319Sweongyo    uint16_t offset)
855203319Sweongyo{
856204922Sweongyo	struct siba_dev_softc *sd = device_get_ivars(dev);
857203319Sweongyo
858203319Sweongyo	sd->sd_ops->read_multi_1(sd, buffer, count, offset);
859203319Sweongyo}
860203319Sweongyo
861203319Sweongyovoid
862204922Sweongyosiba_read_multi_2(device_t dev, void *buffer, size_t count,
863203319Sweongyo    uint16_t offset)
864203319Sweongyo{
865204922Sweongyo	struct siba_dev_softc *sd = device_get_ivars(dev);
866203319Sweongyo
867203319Sweongyo	sd->sd_ops->read_multi_2(sd, buffer, count, offset);
868203319Sweongyo}
869203319Sweongyo
870203319Sweongyovoid
871204922Sweongyosiba_read_multi_4(device_t dev, void *buffer, size_t count,
872203319Sweongyo    uint16_t offset)
873203319Sweongyo{
874204922Sweongyo	struct siba_dev_softc *sd = device_get_ivars(dev);
875203319Sweongyo
876203319Sweongyo	sd->sd_ops->read_multi_4(sd, buffer, count, offset);
877203319Sweongyo}
878203319Sweongyo
879203319Sweongyovoid
880204922Sweongyosiba_write_multi_1(device_t dev, const void *buffer, size_t count,
881204922Sweongyo    uint16_t offset)
882203319Sweongyo{
883204922Sweongyo	struct siba_dev_softc *sd = device_get_ivars(dev);
884203319Sweongyo
885203319Sweongyo	sd->sd_ops->write_multi_1(sd, buffer, count, offset);
886203319Sweongyo}
887203319Sweongyo
888203319Sweongyovoid
889204922Sweongyosiba_write_multi_2(device_t dev, const void *buffer, size_t count,
890204922Sweongyo    uint16_t offset)
891203319Sweongyo{
892204922Sweongyo	struct siba_dev_softc *sd = device_get_ivars(dev);
893203319Sweongyo
894203319Sweongyo	sd->sd_ops->write_multi_2(sd, buffer, count, offset);
895203319Sweongyo}
896203319Sweongyo
897203319Sweongyovoid
898204922Sweongyosiba_write_multi_4(device_t dev, const void *buffer, size_t count,
899204922Sweongyo    uint16_t offset)
900203319Sweongyo{
901204922Sweongyo	struct siba_dev_softc *sd = device_get_ivars(dev);
902203319Sweongyo
903203319Sweongyo	sd->sd_ops->write_multi_4(sd, buffer, count, offset);
904203319Sweongyo}
905203319Sweongyo
906203319Sweongyostatic void
907203319Sweongyosiba_cc_pmu_init(struct siba_cc *scc)
908203319Sweongyo{
909203319Sweongyo	const struct siba_cc_pmu_res_updown *updown = NULL;
910203319Sweongyo	const struct siba_cc_pmu_res_depend *depend = NULL;
911203319Sweongyo	struct siba_dev_softc *sd = scc->scc_dev;
912203319Sweongyo	struct siba_softc *siba = sd->sd_bus;
913203319Sweongyo	uint32_t min = 0, max = 0, pmucap;
914203319Sweongyo	unsigned int i, updown_size, depend_size;
915203319Sweongyo
916203319Sweongyo	if ((scc->scc_caps & SIBA_CC_CAPS_PMU) == 0)
917203319Sweongyo		return;
918203319Sweongyo
919203319Sweongyo	pmucap = SIBA_CC_READ32(scc, SIBA_CC_PMUCAPS);
920203319Sweongyo	scc->scc_pmu.rev = (pmucap & SIBA_CC_PMUCAPS_REV);
921203319Sweongyo
922203319Sweongyo	DPRINTF(siba, SIBA_DEBUG_PMU, "PMU(r%u) found (caps %#x)\n",
923203319Sweongyo	    scc->scc_pmu.rev, pmucap);
924203319Sweongyo
925203319Sweongyo	if (scc->scc_pmu.rev >= 1) {
926203319Sweongyo		if (siba->siba_chiprev < 2 && siba->siba_chipid == 0x4325)
927203319Sweongyo			SIBA_CC_MASK32(scc, SIBA_CC_PMUCTL,
928203319Sweongyo			    ~SIBA_CC_PMUCTL_NOILP);
929203319Sweongyo		else
930203319Sweongyo			SIBA_CC_SET32(scc, SIBA_CC_PMUCTL,
931203319Sweongyo			    SIBA_CC_PMUCTL_NOILP);
932203319Sweongyo	}
933203319Sweongyo
934203319Sweongyo	/* initialize PLL & PMU resources */
935203319Sweongyo	switch (siba->siba_chipid) {
936203319Sweongyo	case 0x4312:
937203319Sweongyo		siba_cc_pmu1_pll0_init(scc, 0 /* use default */);
938203319Sweongyo		/* use the default: min = 0xcbb max = 0x7ffff */
939203319Sweongyo		break;
940203319Sweongyo	case 0x4325:
941203319Sweongyo		siba_cc_pmu1_pll0_init(scc, 0 /* use default */);
942203319Sweongyo
943203319Sweongyo		updown = siba_cc_pmu_4325_updown;
944203319Sweongyo		updown_size = N(siba_cc_pmu_4325_updown);
945203319Sweongyo		depend = siba_cc_pmu_4325_depend;
946203319Sweongyo		depend_size = N(siba_cc_pmu_4325_depend);
947203319Sweongyo
948203319Sweongyo		min = (1 << SIBA_CC_PMU_4325_BURST) |
949203319Sweongyo		    (1 << SIBA_CC_PMU_4325_LN);
950203319Sweongyo		if (SIBA_CC_READ32(scc, SIBA_CC_CHIPSTAT) &
951203319Sweongyo		    SIBA_CC_CHST_4325_PMUTOP_2B)
952203319Sweongyo			min |= (1 << SIBA_CC_PMU_4325_CLBURST);
953203319Sweongyo		max = 0xfffff;
954203319Sweongyo		break;
955203319Sweongyo	case 0x4328:
956203319Sweongyo		siba_cc_pmu0_pll0_init(scc, 0 /* use default */);
957203319Sweongyo
958203319Sweongyo		updown = siba_cc_pmu_4328_updown;
959203319Sweongyo		updown_size = N(siba_cc_pmu_4328_updown);
960203319Sweongyo		depend = siba_cc_pmu_4328_depend;
961203319Sweongyo		depend_size = N(siba_cc_pmu_4328_depend);
962203319Sweongyo
963203319Sweongyo		min = (1 << SIBA_CC_PMU_4328_EXT_SWITCH_PWM) |
964203319Sweongyo			  (1 << SIBA_CC_PMU_4328_BB_SWITCH_PWM) |
965203319Sweongyo			  (1 << SIBA_CC_PMU_4328_CRYSTAL_EN);
966203319Sweongyo
967203319Sweongyo		max = 0xfffff;
968203319Sweongyo		break;
969203319Sweongyo	case 0x5354:
970203319Sweongyo		siba_cc_pmu0_pll0_init(scc, 0 /* use default */);
971203319Sweongyo
972203319Sweongyo		max = 0xfffff;
973203319Sweongyo		break;
974203319Sweongyo	default:
975203319Sweongyo		device_printf(siba->siba_dev,
976203319Sweongyo		    "unknown chipid %#x for PLL & PMU init\n",
977203319Sweongyo		    siba->siba_chipid);
978203319Sweongyo	}
979203319Sweongyo
980203319Sweongyo	if (updown) {
981203319Sweongyo		for (i = 0; i < updown_size; i++) {
982203319Sweongyo			SIBA_CC_WRITE32(scc, SIBA_CC_PMU_TABSEL,
983203319Sweongyo			    updown[i].res);
984203319Sweongyo			SIBA_CC_WRITE32(scc, SIBA_CC_PMU_UPDNTM,
985203319Sweongyo			    updown[i].updown);
986203319Sweongyo		}
987203319Sweongyo	}
988203319Sweongyo	if (depend) {
989203319Sweongyo		for (i = 0; i < depend_size; i++) {
990203319Sweongyo			SIBA_CC_WRITE32(scc, SIBA_CC_PMU_TABSEL,
991203319Sweongyo			    depend[i].res);
992203319Sweongyo			switch (depend[i].task) {
993203319Sweongyo			case SIBA_CC_PMU_DEP_SET:
994203319Sweongyo				SIBA_CC_WRITE32(scc, SIBA_CC_PMU_DEPMSK,
995203319Sweongyo				    depend[i].depend);
996203319Sweongyo				break;
997203319Sweongyo			case SIBA_CC_PMU_DEP_ADD:
998203319Sweongyo				SIBA_CC_SET32(scc, SIBA_CC_PMU_DEPMSK,
999203319Sweongyo				    depend[i].depend);
1000203319Sweongyo				break;
1001203319Sweongyo			case SIBA_CC_PMU_DEP_REMOVE:
1002203319Sweongyo				SIBA_CC_MASK32(scc, SIBA_CC_PMU_DEPMSK,
1003203319Sweongyo				    ~(depend[i].depend));
1004203319Sweongyo				break;
1005203319Sweongyo			default:
1006203319Sweongyo				KASSERT(0 == 1,
1007203319Sweongyo				    ("%s:%d: assertion failed",
1008203319Sweongyo					__func__, __LINE__));
1009203319Sweongyo			}
1010203319Sweongyo		}
1011203319Sweongyo	}
1012203319Sweongyo
1013203319Sweongyo	if (min)
1014203319Sweongyo		SIBA_CC_WRITE32(scc, SIBA_CC_PMU_MINRES, min);
1015203319Sweongyo	if (max)
1016203319Sweongyo		SIBA_CC_WRITE32(scc, SIBA_CC_PMU_MAXRES, max);
1017203319Sweongyo}
1018203319Sweongyo
1019203319Sweongyostatic void
1020203319Sweongyosiba_cc_power_init(struct siba_cc *scc)
1021203319Sweongyo{
1022203319Sweongyo	struct siba_softc *siba = scc->scc_dev->sd_bus;
1023203319Sweongyo	int maxfreq;
1024203319Sweongyo
1025203319Sweongyo	if (siba->siba_chipid == 0x4321) {
1026203319Sweongyo		if (siba->siba_chiprev == 0)
1027203319Sweongyo			SIBA_CC_WRITE32(scc, SIBA_CC_CHIPCTL, 0x3a4);
1028203319Sweongyo		else if (siba->siba_chiprev == 1)
1029203319Sweongyo			SIBA_CC_WRITE32(scc, SIBA_CC_CHIPCTL, 0xa4);
1030203319Sweongyo	}
1031203319Sweongyo
1032203319Sweongyo	if ((scc->scc_caps & SIBA_CC_CAPS_PWCTL) == 0)
1033203319Sweongyo		return;
1034203319Sweongyo
1035203319Sweongyo	if (scc->scc_dev->sd_id.sd_rev >= 10)
1036203319Sweongyo		SIBA_CC_WRITE32(scc, SIBA_CC_CLKSYSCTL,
1037203319Sweongyo		    (SIBA_CC_READ32(scc, SIBA_CC_CLKSYSCTL) &
1038203319Sweongyo		    0xffff) | 0x40000);
1039203319Sweongyo	else {
1040203319Sweongyo		maxfreq = siba_cc_clockfreq(scc, 1);
1041203319Sweongyo		SIBA_CC_WRITE32(scc, SIBA_CC_PLLONDELAY,
1042203319Sweongyo		    (maxfreq * 150 + 999999) / 1000000);
1043203319Sweongyo		SIBA_CC_WRITE32(scc, SIBA_CC_FREFSELDELAY,
1044203319Sweongyo		    (maxfreq * 15 + 999999) / 1000000);
1045203319Sweongyo	}
1046203319Sweongyo}
1047203319Sweongyo
1048203319Sweongyostatic void
1049203319Sweongyosiba_cc_powerup_delay(struct siba_cc *scc)
1050203319Sweongyo{
1051203319Sweongyo	struct siba_softc *siba = scc->scc_dev->sd_bus;
1052203319Sweongyo	int min;
1053203319Sweongyo
1054203319Sweongyo	if (siba->siba_type != SIBA_TYPE_PCI ||
1055203319Sweongyo	    !(scc->scc_caps & SIBA_CC_CAPS_PWCTL))
1056203319Sweongyo		return;
1057203319Sweongyo
1058203319Sweongyo	min = siba_cc_clockfreq(scc, 0);
1059203319Sweongyo	scc->scc_powerup_delay =
1060203319Sweongyo	    (((SIBA_CC_READ32(scc, SIBA_CC_PLLONDELAY) + 2) * 1000000) +
1061203319Sweongyo	    (min - 1)) / min;
1062203319Sweongyo}
1063203319Sweongyo
1064203319Sweongyostatic int
1065203319Sweongyosiba_cc_clockfreq(struct siba_cc *scc, int max)
1066203319Sweongyo{
1067203319Sweongyo	enum siba_clksrc src;
1068203319Sweongyo	int div = 1, limit = 0;
1069203319Sweongyo
1070203319Sweongyo	src = siba_cc_clksrc(scc);
1071203319Sweongyo	if (scc->scc_dev->sd_id.sd_rev < 6) {
1072203319Sweongyo		div = (src == SIBA_CC_CLKSRC_PCI) ? 64 :
1073203319Sweongyo		    (src == SIBA_CC_CLKSRC_CRYSTAL) ? 32 : 1;
1074203319Sweongyo		KASSERT(div != 1,
1075203319Sweongyo		    ("%s: unknown clock %d", __func__, src));
1076203319Sweongyo	} else if (scc->scc_dev->sd_id.sd_rev < 10) {
1077203319Sweongyo		switch (src) {
1078203319Sweongyo		case SIBA_CC_CLKSRC_CRYSTAL:
1079203319Sweongyo		case SIBA_CC_CLKSRC_PCI:
1080203319Sweongyo			div = ((SIBA_CC_READ32(scc, SIBA_CC_CLKSLOW) >> 16) +
1081203319Sweongyo			    1) * 4;
1082203319Sweongyo			break;
1083203319Sweongyo		case SIBA_CC_CLKSRC_LOWPW:
1084203319Sweongyo			break;
1085203319Sweongyo		}
1086203319Sweongyo	} else
1087203319Sweongyo		div = ((SIBA_CC_READ32(scc, SIBA_CC_CLKSYSCTL) >> 16) + 1) * 4;
1088203319Sweongyo
1089203319Sweongyo	switch (src) {
1090203319Sweongyo	case SIBA_CC_CLKSRC_CRYSTAL:
1091203319Sweongyo		limit = (max) ? 20200000 : 19800000;
1092203319Sweongyo		break;
1093203319Sweongyo	case SIBA_CC_CLKSRC_LOWPW:
1094203319Sweongyo		limit = (max) ? 43000 : 25000;
1095203319Sweongyo		break;
1096203319Sweongyo	case SIBA_CC_CLKSRC_PCI:
1097203319Sweongyo		limit = (max) ? 34000000 : 25000000;
1098203319Sweongyo		break;
1099203319Sweongyo	}
1100203319Sweongyo
1101203319Sweongyo	return (limit / div);
1102203319Sweongyo}
1103203319Sweongyo
1104203319Sweongyostatic void
1105203319Sweongyosiba_cc_pmu1_pll0_init(struct siba_cc *scc, uint32_t freq)
1106203319Sweongyo{
1107203319Sweongyo	struct siba_dev_softc *sd = scc->scc_dev;
1108203319Sweongyo	struct siba_softc *siba = sd->sd_bus;
1109203319Sweongyo	const struct siba_cc_pmu1_plltab *e = NULL;
1110203319Sweongyo	uint32_t bufsth = 0, pll, pmu;
1111203319Sweongyo	unsigned int i;
1112203319Sweongyo
1113203319Sweongyo	KASSERT(freq == 0, ("%s:%d: assertion vail", __func__, __LINE__));
1114203319Sweongyo	if (siba->siba_chipid == 0x4312) {
1115203319Sweongyo		scc->scc_pmu.freq = 20000;
1116203319Sweongyo		return;
1117203319Sweongyo	}
1118203319Sweongyo
1119203319Sweongyo	e = siba_cc_pmu1_plltab_find(SIBA_CC_PMU1_DEFAULT_FREQ);
1120203319Sweongyo	KASSERT(e != NULL, ("%s:%d: assertion vail", __func__, __LINE__));
1121203319Sweongyo	scc->scc_pmu.freq = e->freq;
1122203319Sweongyo
1123203319Sweongyo	pmu = SIBA_CC_READ32(scc, SIBA_CC_PMUCTL);
1124203319Sweongyo	if (SIBA_CC_PMUCTL_XF_VAL(pmu) == e->xf)
1125203319Sweongyo		return;
1126203319Sweongyo
1127203319Sweongyo	DPRINTF(siba, SIBA_DEBUG_PLL, "change PLL value to %u.%03u MHz\n",
1128203319Sweongyo	    (e->freq / 1000), (e->freq % 1000));
1129203319Sweongyo
1130203319Sweongyo	/* turn PLL off */
1131203319Sweongyo	switch (siba->siba_chipid) {
1132203319Sweongyo	case 0x4325:
1133203319Sweongyo		bufsth = 0x222222;
1134203319Sweongyo		SIBA_CC_MASK32(scc, SIBA_CC_PMU_MINRES,
1135203319Sweongyo		    ~((1 << SIBA_CC_PMU_4325_BBPLL_PWR) |
1136203319Sweongyo		      (1 << SIBA_CC_PMU_4325_HT)));
1137203319Sweongyo		SIBA_CC_MASK32(scc, SIBA_CC_PMU_MAXRES,
1138203319Sweongyo		    ~((1 << SIBA_CC_PMU_4325_BBPLL_PWR) |
1139203319Sweongyo		      (1 << SIBA_CC_PMU_4325_HT)));
1140203319Sweongyo		break;
1141203319Sweongyo	default:
1142203319Sweongyo		KASSERT(0 == 1,
1143203319Sweongyo		    ("%s:%d: assertion failed", __func__, __LINE__));
1144203319Sweongyo	}
1145203319Sweongyo	for (i = 0; i < 1500; i++) {
1146203319Sweongyo		if (!(SIBA_CC_READ32(scc, SIBA_CC_CLKCTLSTATUS) &
1147203319Sweongyo		      SIBA_CC_CLKCTLSTATUS_HT))
1148203319Sweongyo			break;
1149203319Sweongyo		DELAY(10);
1150203319Sweongyo	}
1151203319Sweongyo	if (SIBA_CC_READ32(scc, SIBA_CC_CLKCTLSTATUS) & SIBA_CC_CLKCTLSTATUS_HT)
1152203319Sweongyo		device_printf(siba->siba_dev, "failed to turn PLL off!\n");
1153203319Sweongyo
1154203319Sweongyo	pll = siba_cc_pll_read(scc, SIBA_CC_PMU1_PLL0);
1155203319Sweongyo	pll &= ~(SIBA_CC_PMU1_PLL0_P1DIV | SIBA_CC_PMU1_PLL0_P2DIV);
1156203319Sweongyo	pll |= ((uint32_t)e->p1div << 20) & SIBA_CC_PMU1_PLL0_P1DIV;
1157203319Sweongyo	pll |= ((uint32_t)e->p2div << 24) & SIBA_CC_PMU1_PLL0_P2DIV;
1158203319Sweongyo	siba_cc_pll_write(scc, SIBA_CC_PMU1_PLL0, pll);
1159203319Sweongyo
1160203319Sweongyo	pll = siba_cc_pll_read(scc, SIBA_CC_PMU1_PLL2);
1161203319Sweongyo	pll &= ~(SIBA_CC_PMU1_PLL2_NDIVINT | SIBA_CC_PMU1_PLL2_NDIVMODE);
1162203319Sweongyo	pll |= ((uint32_t)e->ndiv_int << 20) & SIBA_CC_PMU1_PLL2_NDIVINT;
1163203319Sweongyo	pll |= (1 << 17) & SIBA_CC_PMU1_PLL2_NDIVMODE;
1164203319Sweongyo	siba_cc_pll_write(scc, SIBA_CC_PMU1_PLL2, pll);
1165203319Sweongyo
1166203319Sweongyo	pll = siba_cc_pll_read(scc, SIBA_CC_PMU1_PLL3);
1167203319Sweongyo	pll &= ~SIBA_CC_PMU1_PLL3_NDIVFRAC;
1168203319Sweongyo	pll |= ((uint32_t)e->ndiv_frac << 0) & SIBA_CC_PMU1_PLL3_NDIVFRAC;
1169203319Sweongyo	siba_cc_pll_write(scc, SIBA_CC_PMU1_PLL3, pll);
1170203319Sweongyo
1171203319Sweongyo	if (bufsth) {
1172203319Sweongyo		pll = siba_cc_pll_read(scc, SIBA_CC_PMU1_PLL5);
1173203319Sweongyo		pll &= ~SIBA_CC_PMU1_PLL5_CLKDRV;
1174203319Sweongyo		pll |= (bufsth << 8) & SIBA_CC_PMU1_PLL5_CLKDRV;
1175203319Sweongyo		siba_cc_pll_write(scc, SIBA_CC_PMU1_PLL5, pll);
1176203319Sweongyo	}
1177203319Sweongyo
1178203319Sweongyo	pmu = SIBA_CC_READ32(scc, SIBA_CC_PMUCTL);
1179203319Sweongyo	pmu &= ~(SIBA_CC_PMUCTL_ILP | SIBA_CC_PMUCTL_XF);
1180203319Sweongyo	pmu |= ((((uint32_t)e->freq + 127) / 128 - 1) << 16) &
1181203319Sweongyo	    SIBA_CC_PMUCTL_ILP;
1182203319Sweongyo	pmu |= ((uint32_t)e->xf << 2) & SIBA_CC_PMUCTL_XF;
1183203319Sweongyo	SIBA_CC_WRITE32(scc, SIBA_CC_PMUCTL, pmu);
1184203319Sweongyo}
1185203319Sweongyo
1186203319Sweongyostatic void
1187203319Sweongyosiba_cc_pmu0_pll0_init(struct siba_cc *scc, uint32_t xtalfreq)
1188203319Sweongyo{
1189203319Sweongyo	struct siba_dev_softc *sd = scc->scc_dev;
1190203319Sweongyo	struct siba_softc *siba = sd->sd_bus;
1191203319Sweongyo	const struct siba_cc_pmu0_plltab *e = NULL;
1192203319Sweongyo	uint32_t pmu, tmp, pll;
1193203319Sweongyo	unsigned int i;
1194203319Sweongyo
1195203319Sweongyo	if ((siba->siba_chipid == 0x5354) && !xtalfreq)
1196203319Sweongyo		xtalfreq = 25000;
1197203319Sweongyo	if (xtalfreq)
1198203319Sweongyo		e = siba_cc_pmu0_plltab_findentry(xtalfreq);
1199203319Sweongyo	if (!e)
1200203319Sweongyo		e = siba_cc_pmu0_plltab_findentry(
1201203319Sweongyo		    SIBA_CC_PMU0_DEFAULT_XTALFREQ);
1202203319Sweongyo	KASSERT(e != NULL, ("%s:%d: fail", __func__, __LINE__));
1203203319Sweongyo	xtalfreq = e->freq;
1204203319Sweongyo	scc->scc_pmu.freq = e->freq;
1205203319Sweongyo
1206203319Sweongyo	pmu = SIBA_CC_READ32(scc, SIBA_CC_PMUCTL);
1207203319Sweongyo	if (((pmu & SIBA_CC_PMUCTL_XF) >> 2) == e->xf)
1208203319Sweongyo		return;
1209203319Sweongyo
1210232250Sgavin	DPRINTF(siba, SIBA_DEBUG_PLL, "change PLL value to %u.%03u MHz\n",
1211203319Sweongyo	    (xtalfreq / 1000), (xtalfreq % 1000));
1212203319Sweongyo
1213203319Sweongyo	KASSERT(siba->siba_chipid == 0x4328 || siba->siba_chipid == 0x5354,
1214203319Sweongyo	    ("%s:%d: fail", __func__, __LINE__));
1215203319Sweongyo
1216203319Sweongyo	switch (siba->siba_chipid) {
1217203319Sweongyo	case 0x4328:
1218203319Sweongyo		SIBA_CC_MASK32(scc, SIBA_CC_PMU_MINRES,
1219203319Sweongyo		    ~(1 << SIBA_CC_PMU_4328_BB_PLL_PU));
1220203319Sweongyo		SIBA_CC_MASK32(scc, SIBA_CC_PMU_MAXRES,
1221203319Sweongyo		    ~(1 << SIBA_CC_PMU_4328_BB_PLL_PU));
1222203319Sweongyo		break;
1223203319Sweongyo	case 0x5354:
1224203319Sweongyo		SIBA_CC_MASK32(scc, SIBA_CC_PMU_MINRES,
1225203319Sweongyo		    ~(1 << SIBA_CC_PMU_5354_BB_PLL_PU));
1226203319Sweongyo		SIBA_CC_MASK32(scc, SIBA_CC_PMU_MAXRES,
1227203319Sweongyo		    ~(1 << SIBA_CC_PMU_5354_BB_PLL_PU));
1228203319Sweongyo		break;
1229203319Sweongyo	}
1230203319Sweongyo	for (i = 1500; i; i--) {
1231203319Sweongyo		tmp = SIBA_CC_READ32(scc, SIBA_CC_CLKCTLSTATUS);
1232203319Sweongyo		if (!(tmp & SIBA_CC_CLKCTLSTATUS_HT))
1233203319Sweongyo			break;
1234203319Sweongyo		DELAY(10);
1235203319Sweongyo	}
1236203319Sweongyo	tmp = SIBA_CC_READ32(scc, SIBA_CC_CLKCTLSTATUS);
1237203319Sweongyo	if (tmp & SIBA_CC_CLKCTLSTATUS_HT)
1238203319Sweongyo		device_printf(siba->siba_dev, "failed to turn PLL off!\n");
1239203319Sweongyo
1240203319Sweongyo	/* set PDIV */
1241203319Sweongyo	pll = siba_cc_pll_read(scc, SIBA_CC_PMU0_PLL0);
1242203319Sweongyo	if (xtalfreq >= SIBA_CC_PMU0_PLL0_PDIV_FREQ)
1243203319Sweongyo		pll |= SIBA_CC_PMU0_PLL0_PDIV_MSK;
1244203319Sweongyo	else
1245203319Sweongyo		pll &= ~SIBA_CC_PMU0_PLL0_PDIV_MSK;
1246203319Sweongyo	siba_cc_pll_write(scc, SIBA_CC_PMU0_PLL0, pll);
1247203319Sweongyo
1248203319Sweongyo	/* set WILD */
1249203319Sweongyo	pll = siba_cc_pll_read(scc, SIBA_CC_PMU0_PLL1);
1250203319Sweongyo	pll &= ~(SIBA_CC_PMU0_PLL1_STOPMOD | SIBA_CC_PMU0_PLL1_IMSK |
1251203319Sweongyo	    SIBA_CC_PMU0_PLL1_FMSK);
1252203319Sweongyo	pll |= ((uint32_t)e->wb_int << 28) & SIBA_CC_PMU0_PLL1_IMSK;
1253203319Sweongyo	pll |= ((uint32_t)e->wb_frac << 8) & SIBA_CC_PMU0_PLL1_FMSK;
1254203319Sweongyo	if (e->wb_frac == 0)
1255203319Sweongyo		pll |= SIBA_CC_PMU0_PLL1_STOPMOD;
1256203319Sweongyo	siba_cc_pll_write(scc, SIBA_CC_PMU0_PLL1, pll);
1257203319Sweongyo
1258203319Sweongyo	/* set WILD */
1259203319Sweongyo	pll = siba_cc_pll_read(scc, SIBA_CC_PMU0_PLL2);
1260203319Sweongyo	pll &= ~SIBA_CC_PMU0_PLL2_IMSKHI;
1261203319Sweongyo	pll |= (((uint32_t)e->wb_int >> 4) << 0) & SIBA_CC_PMU0_PLL2_IMSKHI;
1262203319Sweongyo	siba_cc_pll_write(scc, SIBA_CC_PMU0_PLL2, pll);
1263203319Sweongyo
1264203319Sweongyo	/* set freq and divisor. */
1265203319Sweongyo	pmu = SIBA_CC_READ32(scc, SIBA_CC_PMUCTL);
1266203319Sweongyo	pmu &= ~SIBA_CC_PMUCTL_ILP;
1267203319Sweongyo	pmu |= (((xtalfreq + 127) / 128 - 1) << 16) & SIBA_CC_PMUCTL_ILP;
1268203319Sweongyo	pmu &= ~SIBA_CC_PMUCTL_XF;
1269203319Sweongyo	pmu |= ((uint32_t)e->xf << 2) & SIBA_CC_PMUCTL_XF;
1270203319Sweongyo	SIBA_CC_WRITE32(scc, SIBA_CC_PMUCTL, pmu);
1271203319Sweongyo}
1272203319Sweongyo
1273203319Sweongyostatic enum siba_clksrc
1274203319Sweongyosiba_cc_clksrc(struct siba_cc *scc)
1275203319Sweongyo{
1276203319Sweongyo	struct siba_dev_softc *sd = scc->scc_dev;
1277203319Sweongyo	struct siba_softc *siba = sd->sd_bus;
1278203319Sweongyo
1279203319Sweongyo	if (sd->sd_id.sd_rev < 6) {
1280203319Sweongyo		if (siba->siba_type == SIBA_TYPE_PCI) {
1281203319Sweongyo			if (pci_read_config(siba->siba_dev, SIBA_GPIO_OUT, 4) &
1282203319Sweongyo			    0x10)
1283203319Sweongyo				return (SIBA_CC_CLKSRC_PCI);
1284203319Sweongyo			return (SIBA_CC_CLKSRC_CRYSTAL);
1285203319Sweongyo		}
1286203319Sweongyo		if (siba->siba_type == SIBA_TYPE_SSB ||
1287203319Sweongyo		    siba->siba_type == SIBA_TYPE_PCMCIA)
1288203319Sweongyo			return (SIBA_CC_CLKSRC_CRYSTAL);
1289203319Sweongyo	}
1290203319Sweongyo	if (sd->sd_id.sd_rev < 10) {
1291203319Sweongyo		switch (SIBA_CC_READ32(scc, SIBA_CC_CLKSLOW) & 0x7) {
1292203319Sweongyo		case 0:
1293203319Sweongyo			return (SIBA_CC_CLKSRC_LOWPW);
1294203319Sweongyo		case 1:
1295203319Sweongyo			return (SIBA_CC_CLKSRC_CRYSTAL);
1296203319Sweongyo		case 2:
1297203319Sweongyo			return (SIBA_CC_CLKSRC_PCI);
1298203319Sweongyo		default:
1299203319Sweongyo			break;
1300203319Sweongyo		}
1301203319Sweongyo	}
1302203319Sweongyo
1303203319Sweongyo	return (SIBA_CC_CLKSRC_CRYSTAL);
1304203319Sweongyo}
1305203319Sweongyo
1306203319Sweongyostatic const struct siba_cc_pmu1_plltab *
1307203319Sweongyosiba_cc_pmu1_plltab_find(uint32_t crystalfreq)
1308203319Sweongyo{
1309203319Sweongyo	const struct siba_cc_pmu1_plltab *e;
1310203319Sweongyo	unsigned int i;
1311203319Sweongyo
1312203319Sweongyo	for (i = 0; i < N(siba_cc_pmu1_plltab); i++) {
1313203319Sweongyo		e = &siba_cc_pmu1_plltab[i];
1314203319Sweongyo		if (crystalfreq == e->freq)
1315203319Sweongyo			return (e);
1316203319Sweongyo	}
1317203319Sweongyo
1318203319Sweongyo	return (NULL);
1319203319Sweongyo}
1320203319Sweongyo
1321203319Sweongyostatic uint32_t
1322203319Sweongyosiba_cc_pll_read(struct siba_cc *scc, uint32_t offset)
1323203319Sweongyo{
1324203319Sweongyo
1325203319Sweongyo	SIBA_CC_WRITE32(scc, SIBA_CC_PLLCTL_ADDR, offset);
1326203319Sweongyo	return (SIBA_CC_READ32(scc, SIBA_CC_PLLCTL_DATA));
1327203319Sweongyo}
1328203319Sweongyo
1329203319Sweongyostatic void
1330203319Sweongyosiba_cc_pll_write(struct siba_cc *scc, uint32_t offset, uint32_t value)
1331203319Sweongyo{
1332203319Sweongyo
1333203319Sweongyo	SIBA_CC_WRITE32(scc, SIBA_CC_PLLCTL_ADDR, offset);
1334203319Sweongyo	SIBA_CC_WRITE32(scc, SIBA_CC_PLLCTL_DATA, value);
1335203319Sweongyo}
1336203319Sweongyo
1337203319Sweongyostatic const struct siba_cc_pmu0_plltab *
1338203319Sweongyosiba_cc_pmu0_plltab_findentry(uint32_t crystalfreq)
1339203319Sweongyo{
1340203319Sweongyo	const struct siba_cc_pmu0_plltab *e;
1341203319Sweongyo	unsigned int i;
1342203319Sweongyo
1343203319Sweongyo	for (i = 0; i < N(siba_cc_pmu0_plltab); i++) {
1344203319Sweongyo		e = &siba_cc_pmu0_plltab[i];
1345203319Sweongyo		if (e->freq == crystalfreq)
1346203319Sweongyo			return (e);
1347203319Sweongyo	}
1348203319Sweongyo
1349203319Sweongyo	return (NULL);
1350203319Sweongyo}
1351203319Sweongyo
1352203319Sweongyostatic int
1353203319Sweongyosiba_pci_sprom(struct siba_softc *siba, struct siba_sprom *sprom)
1354203319Sweongyo{
1355203319Sweongyo	int error = ENOMEM;
1356203319Sweongyo	uint16_t *buf;
1357203319Sweongyo
1358203319Sweongyo	buf = malloc(SIBA_SPROMSIZE_R123 * sizeof(uint16_t),
1359203319Sweongyo	    M_DEVBUF, M_NOWAIT | M_ZERO);
1360203319Sweongyo	if (buf == NULL)
1361203319Sweongyo		return (ENOMEM);
1362203319Sweongyo	siba_sprom_read(siba, buf, SIBA_SPROMSIZE_R123);
1363203319Sweongyo	error = sprom_check_crc(buf, siba->siba_spromsize);
1364203319Sweongyo	if (error) {
1365203319Sweongyo		free(buf, M_DEVBUF);
1366203319Sweongyo		buf = malloc(SIBA_SPROMSIZE_R4 * sizeof(uint16_t),
1367203319Sweongyo		    M_DEVBUF, M_NOWAIT | M_ZERO);
1368203319Sweongyo		if (buf == NULL)
1369203319Sweongyo			return (ENOMEM);
1370203319Sweongyo		siba_sprom_read(siba, buf, SIBA_SPROMSIZE_R4);
1371203319Sweongyo		error = sprom_check_crc(buf, siba->siba_spromsize);
1372203319Sweongyo		if (error)
1373203319Sweongyo			device_printf(siba->siba_dev, "warn: bad SPROM CRC\n");
1374203319Sweongyo	}
1375203319Sweongyo
1376203319Sweongyo	bzero(sprom, sizeof(*sprom));
1377203319Sweongyo
1378203319Sweongyo	sprom->rev = buf[siba->siba_spromsize - 1] & 0x00FF;
1379203319Sweongyo	DPRINTF(siba, SIBA_DEBUG_SPROM, "SPROM rev %d\n",
1380203319Sweongyo	    sprom->rev);
1381203319Sweongyo	memset(sprom->mac_eth, 0xff, 6);
1382203319Sweongyo	memset(sprom->mac_80211a, 0xff, 6);
1383203319Sweongyo	if ((siba->siba_chipid & 0xff00) == 0x4400) {
1384203319Sweongyo		sprom->rev = 1;
1385203319Sweongyo		siba_sprom_r123(sprom, buf);
1386203319Sweongyo	} else if (siba->siba_chipid == 0x4321) {
1387203319Sweongyo		sprom->rev = 4;
1388203319Sweongyo		siba_sprom_r45(sprom, buf);
1389203319Sweongyo	} else {
1390203319Sweongyo		switch (sprom->rev) {
1391203319Sweongyo		case 1:
1392203319Sweongyo		case 2:
1393203319Sweongyo		case 3:
1394203319Sweongyo			siba_sprom_r123(sprom, buf);
1395203319Sweongyo			break;
1396203319Sweongyo		case 4:
1397203319Sweongyo		case 5:
1398203319Sweongyo			siba_sprom_r45(sprom, buf);
1399203319Sweongyo			break;
1400203319Sweongyo		case 8:
1401203319Sweongyo			siba_sprom_r8(sprom, buf);
1402203319Sweongyo			break;
1403203319Sweongyo		default:
1404203319Sweongyo			device_printf(siba->siba_dev,
1405203319Sweongyo			    "unknown SPROM revision %d.\n", sprom->rev);
1406203319Sweongyo			siba_sprom_r123(sprom, buf);
1407203319Sweongyo		}
1408203319Sweongyo	}
1409203319Sweongyo
1410203319Sweongyo	if (sprom->bf_lo == 0xffff)
1411203319Sweongyo		sprom->bf_lo = 0;
1412203319Sweongyo	if (sprom->bf_hi == 0xffff)
1413203319Sweongyo		sprom->bf_hi = 0;
1414203319Sweongyo
1415203319Sweongyo	free(buf, M_DEVBUF);
1416203319Sweongyo	return (error);
1417203319Sweongyo}
1418203319Sweongyo
1419203319Sweongyostatic int
1420203319Sweongyosiba_sprom_read(struct siba_softc *siba, uint16_t *sprom, uint16_t len)
1421203319Sweongyo{
1422203319Sweongyo	int i;
1423203319Sweongyo
1424203319Sweongyo	for (i = 0; i < len; i++)
1425203319Sweongyo		sprom[i] = SIBA_READ_2(siba, SIBA_SPROM_BASE + (i * 2));
1426203319Sweongyo
1427203319Sweongyo	siba->siba_spromsize = len;
1428203319Sweongyo	return (0);
1429203319Sweongyo}
1430203319Sweongyo
1431203319Sweongyostatic int
1432203319Sweongyosprom_check_crc(const uint16_t *sprom, size_t size)
1433203319Sweongyo{
1434203319Sweongyo	int word;
1435203319Sweongyo	uint8_t crc0, crc1 = 0xff;
1436203319Sweongyo
1437203319Sweongyo	crc0 = (sprom[size - 1] & SIBA_SPROM_REV_CRC) >> 8;
1438203319Sweongyo	for (word = 0; word < size - 1; word++) {
1439203319Sweongyo		crc1 = siba_crc8(crc1, sprom[word] & 0x00ff);
1440203319Sweongyo		crc1 = siba_crc8(crc1, (sprom[word] & 0xff00) >> 8);
1441203319Sweongyo	}
1442203319Sweongyo	crc1 = siba_crc8(crc1, sprom[size - 1] & 0x00ff);
1443203319Sweongyo	crc1 ^= 0xff;
1444203319Sweongyo
1445203319Sweongyo	return ((crc0 != crc1) ? EPROTO : 0);
1446203319Sweongyo}
1447203319Sweongyo
1448203319Sweongyostatic uint8_t
1449203319Sweongyosiba_crc8(uint8_t crc, uint8_t data)
1450203319Sweongyo{
1451203319Sweongyo	static const uint8_t ct[] = {
1452203319Sweongyo		0x00, 0xf7, 0xb9, 0x4e, 0x25, 0xd2, 0x9c, 0x6b,
1453203319Sweongyo		0x4a, 0xbd, 0xf3, 0x04, 0x6f, 0x98, 0xd6, 0x21,
1454203319Sweongyo		0x94, 0x63, 0x2d, 0xda, 0xb1, 0x46, 0x08, 0xff,
1455203319Sweongyo		0xde, 0x29, 0x67, 0x90, 0xfb, 0x0c, 0x42, 0xb5,
1456203319Sweongyo		0x7f, 0x88, 0xc6, 0x31, 0x5a, 0xad, 0xe3, 0x14,
1457203319Sweongyo		0x35, 0xc2, 0x8c, 0x7b, 0x10, 0xe7, 0xa9, 0x5e,
1458203319Sweongyo		0xeb, 0x1c, 0x52, 0xa5, 0xce, 0x39, 0x77, 0x80,
1459203319Sweongyo		0xa1, 0x56, 0x18, 0xef, 0x84, 0x73, 0x3d, 0xca,
1460203319Sweongyo		0xfe, 0x09, 0x47, 0xb0, 0xdb, 0x2c, 0x62, 0x95,
1461203319Sweongyo		0xb4, 0x43, 0x0d, 0xfa, 0x91, 0x66, 0x28, 0xdf,
1462203319Sweongyo		0x6a, 0x9d, 0xd3, 0x24, 0x4f, 0xb8, 0xf6, 0x01,
1463203319Sweongyo		0x20, 0xd7, 0x99, 0x6e, 0x05, 0xf2, 0xbc, 0x4b,
1464203319Sweongyo		0x81, 0x76, 0x38, 0xcf, 0xa4, 0x53, 0x1d, 0xea,
1465203319Sweongyo		0xcb, 0x3c, 0x72, 0x85, 0xee, 0x19, 0x57, 0xa0,
1466203319Sweongyo		0x15, 0xe2, 0xac, 0x5b, 0x30, 0xc7, 0x89, 0x7e,
1467203319Sweongyo		0x5f, 0xa8, 0xe6, 0x11, 0x7a, 0x8d, 0xc3, 0x34,
1468203319Sweongyo		0xab, 0x5c, 0x12, 0xe5, 0x8e, 0x79, 0x37, 0xc0,
1469203319Sweongyo		0xe1, 0x16, 0x58, 0xaf, 0xc4, 0x33, 0x7d, 0x8a,
1470203319Sweongyo		0x3f, 0xc8, 0x86, 0x71, 0x1a, 0xed, 0xa3, 0x54,
1471203319Sweongyo		0x75, 0x82, 0xcc, 0x3b, 0x50, 0xa7, 0xe9, 0x1e,
1472203319Sweongyo		0xd4, 0x23, 0x6d, 0x9a, 0xf1, 0x06, 0x48, 0xbf,
1473203319Sweongyo		0x9e, 0x69, 0x27, 0xd0, 0xbb, 0x4c, 0x02, 0xf5,
1474203319Sweongyo		0x40, 0xb7, 0xf9, 0x0e, 0x65, 0x92, 0xdc, 0x2b,
1475203319Sweongyo		0x0a, 0xfd, 0xb3, 0x44, 0x2f, 0xd8, 0x96, 0x61,
1476203319Sweongyo		0x55, 0xa2, 0xec, 0x1b, 0x70, 0x87, 0xc9, 0x3e,
1477203319Sweongyo		0x1f, 0xe8, 0xa6, 0x51, 0x3a, 0xcd, 0x83, 0x74,
1478203319Sweongyo		0xc1, 0x36, 0x78, 0x8f, 0xe4, 0x13, 0x5d, 0xaa,
1479203319Sweongyo		0x8b, 0x7c, 0x32, 0xc5, 0xae, 0x59, 0x17, 0xe0,
1480203319Sweongyo		0x2a, 0xdd, 0x93, 0x64, 0x0f, 0xf8, 0xb6, 0x41,
1481203319Sweongyo		0x60, 0x97, 0xd9, 0x2e, 0x45, 0xb2, 0xfc, 0x0b,
1482203319Sweongyo		0xbe, 0x49, 0x07, 0xf0, 0x9b, 0x6c, 0x22, 0xd5,
1483203319Sweongyo		0xf4, 0x03, 0x4d, 0xba, 0xd1, 0x26, 0x68, 0x9f,
1484203319Sweongyo	};
1485203319Sweongyo	return (ct[crc ^ data]);
1486203319Sweongyo}
1487203319Sweongyo
1488203319Sweongyo#define	SIBA_LOWEST_SET_BIT(__mask) ((((__mask) - 1) & (__mask)) ^ (__mask))
1489203319Sweongyo#define SIBA_OFFSET(offset)	\
1490203319Sweongyo	(((offset) - SIBA_SPROM_BASE) / sizeof(uint16_t))
1491203319Sweongyo#define	SIBA_SHIFTOUT_SUB(__x, __mask)					\
1492203319Sweongyo	(((__x) & (__mask)) / SIBA_LOWEST_SET_BIT(__mask))
1493203319Sweongyo#define	SIBA_SHIFTOUT(_var, _offset, _mask)				\
1494203319Sweongyo	out->_var = SIBA_SHIFTOUT_SUB(in[SIBA_OFFSET(_offset)], (_mask))
1495203944Sweongyo#define SIBA_SHIFTOUT_4(_var, _offset, _mask, _shift)			\
1496203944Sweongyo	out->_var = ((((uint32_t)in[SIBA_OFFSET((_offset)+2)] << 16 |	\
1497203944Sweongyo	    in[SIBA_OFFSET(_offset)]) & (_mask)) >> (_shift))
1498203319Sweongyo
1499203319Sweongyostatic void
1500203319Sweongyosiba_sprom_r123(struct siba_sprom *out, const uint16_t *in)
1501203319Sweongyo{
1502203319Sweongyo	int i;
1503203319Sweongyo	uint16_t v;
1504203319Sweongyo	int8_t gain;
1505203319Sweongyo	uint16_t loc[3];
1506203319Sweongyo
1507203319Sweongyo	if (out->rev == 3)
1508203319Sweongyo		loc[0] = SIBA_SPROM3_MAC_80211BG;
1509203319Sweongyo	else {
1510203319Sweongyo		loc[0] = SIBA_SPROM1_MAC_80211BG;
1511203319Sweongyo		loc[1] = SIBA_SPROM1_MAC_ETH;
1512203319Sweongyo		loc[2] = SIBA_SPROM1_MAC_80211A;
1513203319Sweongyo	}
1514203319Sweongyo	for (i = 0; i < 3; i++) {
1515203319Sweongyo		v = in[SIBA_OFFSET(loc[0]) + i];
1516203319Sweongyo		*(((uint16_t *)out->mac_80211bg) + i) = htobe16(v);
1517203319Sweongyo	}
1518203319Sweongyo	if (out->rev < 3) {
1519203319Sweongyo		for (i = 0; i < 3; i++) {
1520203319Sweongyo			v = in[SIBA_OFFSET(loc[1]) + i];
1521203319Sweongyo			*(((uint16_t *)out->mac_eth) + i) = htobe16(v);
1522203319Sweongyo		}
1523203319Sweongyo		for (i = 0; i < 3; i++) {
1524203319Sweongyo			v = in[SIBA_OFFSET(loc[2]) + i];
1525203319Sweongyo			*(((uint16_t *)out->mac_80211a) + i) = htobe16(v);
1526203319Sweongyo		}
1527203319Sweongyo	}
1528203319Sweongyo	SIBA_SHIFTOUT(mii_eth0, SIBA_SPROM1_ETHPHY,
1529203319Sweongyo	    SIBA_SPROM1_ETHPHY_MII_ETH0);
1530203319Sweongyo	SIBA_SHIFTOUT(mii_eth1, SIBA_SPROM1_ETHPHY,
1531203319Sweongyo	    SIBA_SPROM1_ETHPHY_MII_ETH1);
1532203319Sweongyo	SIBA_SHIFTOUT(mdio_eth0, SIBA_SPROM1_ETHPHY,
1533203319Sweongyo	    SIBA_SPROM1_ETHPHY_MDIO_ETH0);
1534203319Sweongyo	SIBA_SHIFTOUT(mdio_eth1, SIBA_SPROM1_ETHPHY,
1535203319Sweongyo	    SIBA_SPROM1_ETHPHY_MDIO_ETH1);
1536203319Sweongyo	SIBA_SHIFTOUT(brev, SIBA_SPROM1_BOARDINFO, SIBA_SPROM1_BOARDINFO_BREV);
1537203319Sweongyo	SIBA_SHIFTOUT(ccode, SIBA_SPROM1_BOARDINFO,
1538203319Sweongyo	    SIBA_SPROM1_BOARDINFO_CCODE);
1539203319Sweongyo	SIBA_SHIFTOUT(ant_a, SIBA_SPROM1_BOARDINFO, SIBA_SPROM1_BOARDINFO_ANTA);
1540203319Sweongyo	SIBA_SHIFTOUT(ant_bg, SIBA_SPROM1_BOARDINFO,
1541203319Sweongyo	    SIBA_SPROM1_BOARDINFO_ANTBG);
1542203319Sweongyo	SIBA_SHIFTOUT(pa0b0, SIBA_SPROM1_PA0B0, 0xffff);
1543203319Sweongyo	SIBA_SHIFTOUT(pa0b1, SIBA_SPROM1_PA0B1, 0xffff);
1544203319Sweongyo	SIBA_SHIFTOUT(pa0b2, SIBA_SPROM1_PA0B2, 0xffff);
1545203319Sweongyo	SIBA_SHIFTOUT(pa1b0, SIBA_SPROM1_PA1B0, 0xffff);
1546203319Sweongyo	SIBA_SHIFTOUT(pa1b1, SIBA_SPROM1_PA1B1, 0xffff);
1547203319Sweongyo	SIBA_SHIFTOUT(pa1b2, SIBA_SPROM1_PA1B2, 0xffff);
1548203319Sweongyo	SIBA_SHIFTOUT(gpio0, SIBA_SPROM1_GPIOA, SIBA_SPROM1_GPIOA_P0);
1549203319Sweongyo	SIBA_SHIFTOUT(gpio1, SIBA_SPROM1_GPIOA, SIBA_SPROM1_GPIOA_P1);
1550203319Sweongyo	SIBA_SHIFTOUT(gpio2, SIBA_SPROM1_GPIOB, SIBA_SPROM1_GPIOB_P2);
1551203319Sweongyo	SIBA_SHIFTOUT(gpio3, SIBA_SPROM1_GPIOB, SIBA_SPROM1_GPIOB_P3);
1552203944Sweongyo
1553203319Sweongyo	SIBA_SHIFTOUT(maxpwr_a, SIBA_SPROM1_MAXPWR, SIBA_SPROM1_MAXPWR_A);
1554203319Sweongyo	SIBA_SHIFTOUT(maxpwr_bg, SIBA_SPROM1_MAXPWR, SIBA_SPROM1_MAXPWR_BG);
1555203319Sweongyo	SIBA_SHIFTOUT(tssi_a, SIBA_SPROM1_TSSI, SIBA_SPROM1_TSSI_A);
1556203319Sweongyo	SIBA_SHIFTOUT(tssi_bg, SIBA_SPROM1_TSSI, SIBA_SPROM1_TSSI_BG);
1557203319Sweongyo	SIBA_SHIFTOUT(bf_lo, SIBA_SPROM1_BFLOW, 0xffff);
1558203319Sweongyo	if (out->rev >= 2)
1559203319Sweongyo		SIBA_SHIFTOUT(bf_hi, SIBA_SPROM2_BFHIGH, 0xffff);
1560203319Sweongyo
1561203319Sweongyo	/* antenna gain */
1562203319Sweongyo	gain = siba_sprom_r123_antgain(out->rev, in, SIBA_SPROM1_AGAIN_BG, 0);
1563203319Sweongyo	out->again.ghz24.a0 = out->again.ghz24.a1 = gain;
1564203319Sweongyo	out->again.ghz24.a2 = out->again.ghz24.a3 = gain;
1565203319Sweongyo	gain = siba_sprom_r123_antgain(out->rev, in, SIBA_SPROM1_AGAIN_A, 8);
1566203319Sweongyo	out->again.ghz5.a0 = out->again.ghz5.a1 = gain;
1567203319Sweongyo	out->again.ghz5.a2 = out->again.ghz5.a3 = gain;
1568203319Sweongyo}
1569203319Sweongyo
1570203319Sweongyostatic void
1571203319Sweongyosiba_sprom_r45(struct siba_sprom *out, const uint16_t *in)
1572203319Sweongyo{
1573203319Sweongyo	int i;
1574203319Sweongyo	uint16_t v;
1575203319Sweongyo	uint16_t mac_80211bg_offset;
1576203319Sweongyo
1577203319Sweongyo	if (out->rev == 4)
1578203319Sweongyo		mac_80211bg_offset = SIBA_SPROM4_MAC_80211BG;
1579203319Sweongyo	else
1580203319Sweongyo		mac_80211bg_offset = SIBA_SPROM5_MAC_80211BG;
1581203319Sweongyo	for (i = 0; i < 3; i++) {
1582203319Sweongyo		v = in[SIBA_OFFSET(mac_80211bg_offset) + i];
1583203319Sweongyo		*(((uint16_t *)out->mac_80211bg) + i) = htobe16(v);
1584203319Sweongyo	}
1585203319Sweongyo	SIBA_SHIFTOUT(mii_eth0, SIBA_SPROM4_ETHPHY, SIBA_SPROM4_ETHPHY_ET0A);
1586203319Sweongyo	SIBA_SHIFTOUT(mii_eth1, SIBA_SPROM4_ETHPHY, SIBA_SPROM4_ETHPHY_ET1A);
1587203319Sweongyo	if (out->rev == 4) {
1588203319Sweongyo		SIBA_SHIFTOUT(ccode, SIBA_SPROM4_CCODE, 0xffff);
1589203319Sweongyo		SIBA_SHIFTOUT(bf_lo, SIBA_SPROM4_BFLOW, 0xffff);
1590203319Sweongyo		SIBA_SHIFTOUT(bf_hi, SIBA_SPROM4_BFHIGH, 0xffff);
1591203319Sweongyo	} else {
1592203319Sweongyo		SIBA_SHIFTOUT(ccode, SIBA_SPROM5_CCODE, 0xffff);
1593203319Sweongyo		SIBA_SHIFTOUT(bf_lo, SIBA_SPROM5_BFLOW, 0xffff);
1594203319Sweongyo		SIBA_SHIFTOUT(bf_hi, SIBA_SPROM5_BFHIGH, 0xffff);
1595203319Sweongyo	}
1596203319Sweongyo	SIBA_SHIFTOUT(ant_a, SIBA_SPROM4_ANTAVAIL, SIBA_SPROM4_ANTAVAIL_A);
1597203319Sweongyo	SIBA_SHIFTOUT(ant_bg, SIBA_SPROM4_ANTAVAIL, SIBA_SPROM4_ANTAVAIL_BG);
1598203319Sweongyo	SIBA_SHIFTOUT(maxpwr_bg, SIBA_SPROM4_MAXP_BG, SIBA_SPROM4_MAXP_BG_MASK);
1599203319Sweongyo	SIBA_SHIFTOUT(tssi_bg, SIBA_SPROM4_MAXP_BG, SIBA_SPROM4_TSSI_BG);
1600203319Sweongyo	SIBA_SHIFTOUT(maxpwr_a, SIBA_SPROM4_MAXP_A, SIBA_SPROM4_MAXP_A_MASK);
1601203319Sweongyo	SIBA_SHIFTOUT(tssi_a, SIBA_SPROM4_MAXP_A, SIBA_SPROM4_TSSI_A);
1602203319Sweongyo	if (out->rev == 4) {
1603203319Sweongyo		SIBA_SHIFTOUT(gpio0, SIBA_SPROM4_GPIOA, SIBA_SPROM4_GPIOA_P0);
1604203319Sweongyo		SIBA_SHIFTOUT(gpio1, SIBA_SPROM4_GPIOA, SIBA_SPROM4_GPIOA_P1);
1605203319Sweongyo		SIBA_SHIFTOUT(gpio2, SIBA_SPROM4_GPIOB, SIBA_SPROM4_GPIOB_P2);
1606203319Sweongyo		SIBA_SHIFTOUT(gpio3, SIBA_SPROM4_GPIOB, SIBA_SPROM4_GPIOB_P3);
1607203319Sweongyo	} else {
1608203319Sweongyo		SIBA_SHIFTOUT(gpio0, SIBA_SPROM5_GPIOA, SIBA_SPROM5_GPIOA_P0);
1609203319Sweongyo		SIBA_SHIFTOUT(gpio1, SIBA_SPROM5_GPIOA, SIBA_SPROM5_GPIOA_P1);
1610203319Sweongyo		SIBA_SHIFTOUT(gpio2, SIBA_SPROM5_GPIOB, SIBA_SPROM5_GPIOB_P2);
1611203319Sweongyo		SIBA_SHIFTOUT(gpio3, SIBA_SPROM5_GPIOB, SIBA_SPROM5_GPIOB_P3);
1612203319Sweongyo	}
1613203319Sweongyo
1614203319Sweongyo	/* antenna gain */
1615203319Sweongyo	SIBA_SHIFTOUT(again.ghz24.a0, SIBA_SPROM4_AGAIN01, SIBA_SPROM4_AGAIN0);
1616203319Sweongyo	SIBA_SHIFTOUT(again.ghz24.a1, SIBA_SPROM4_AGAIN01, SIBA_SPROM4_AGAIN1);
1617203319Sweongyo	SIBA_SHIFTOUT(again.ghz24.a2, SIBA_SPROM4_AGAIN23, SIBA_SPROM4_AGAIN2);
1618203319Sweongyo	SIBA_SHIFTOUT(again.ghz24.a3, SIBA_SPROM4_AGAIN23, SIBA_SPROM4_AGAIN3);
1619203319Sweongyo	bcopy(&out->again.ghz24, &out->again.ghz5, sizeof(out->again.ghz5));
1620203319Sweongyo}
1621203319Sweongyo
1622203319Sweongyostatic void
1623203319Sweongyosiba_sprom_r8(struct siba_sprom *out, const uint16_t *in)
1624203319Sweongyo{
1625203319Sweongyo	int i;
1626203319Sweongyo	uint16_t v;
1627203319Sweongyo
1628203319Sweongyo	for (i = 0; i < 3; i++) {
1629203944Sweongyo		v = in[SIBA_OFFSET(SIBA_SPROM8_MAC_80211BG) + i];
1630203319Sweongyo		*(((uint16_t *)out->mac_80211bg) + i) = htobe16(v);
1631203319Sweongyo	}
1632203319Sweongyo	SIBA_SHIFTOUT(ccode, SIBA_SPROM8_CCODE, 0xffff);
1633203319Sweongyo	SIBA_SHIFTOUT(bf_lo, SIBA_SPROM8_BFLOW, 0xffff);
1634203319Sweongyo	SIBA_SHIFTOUT(bf_hi, SIBA_SPROM8_BFHIGH, 0xffff);
1635203944Sweongyo	SIBA_SHIFTOUT(bf2_lo, SIBA_SPROM8_BFL2LO, 0xffff);
1636203944Sweongyo	SIBA_SHIFTOUT(bf2_hi, SIBA_SPROM8_BFL2HI, 0xffff);
1637203319Sweongyo	SIBA_SHIFTOUT(ant_a, SIBA_SPROM8_ANTAVAIL, SIBA_SPROM8_ANTAVAIL_A);
1638203319Sweongyo	SIBA_SHIFTOUT(ant_bg, SIBA_SPROM8_ANTAVAIL, SIBA_SPROM8_ANTAVAIL_BG);
1639203319Sweongyo	SIBA_SHIFTOUT(maxpwr_bg, SIBA_SPROM8_MAXP_BG, SIBA_SPROM8_MAXP_BG_MASK);
1640203319Sweongyo	SIBA_SHIFTOUT(tssi_bg, SIBA_SPROM8_MAXP_BG, SIBA_SPROM8_TSSI_BG);
1641203319Sweongyo	SIBA_SHIFTOUT(maxpwr_a, SIBA_SPROM8_MAXP_A, SIBA_SPROM8_MAXP_A_MASK);
1642203319Sweongyo	SIBA_SHIFTOUT(tssi_a, SIBA_SPROM8_MAXP_A, SIBA_SPROM8_TSSI_A);
1643203944Sweongyo	SIBA_SHIFTOUT(maxpwr_ah, SIBA_SPROM8_MAXP_AHL,
1644203944Sweongyo	    SIBA_SPROM8_MAXP_AH_MASK);
1645203944Sweongyo	SIBA_SHIFTOUT(maxpwr_al, SIBA_SPROM8_MAXP_AHL,
1646203944Sweongyo	    SIBA_SPROM8_MAXP_AL_MASK);
1647203319Sweongyo	SIBA_SHIFTOUT(gpio0, SIBA_SPROM8_GPIOA, SIBA_SPROM8_GPIOA_P0);
1648203319Sweongyo	SIBA_SHIFTOUT(gpio1, SIBA_SPROM8_GPIOA, SIBA_SPROM8_GPIOA_P1);
1649203319Sweongyo	SIBA_SHIFTOUT(gpio2, SIBA_SPROM8_GPIOB, SIBA_SPROM8_GPIOB_P2);
1650203319Sweongyo	SIBA_SHIFTOUT(gpio3, SIBA_SPROM8_GPIOB, SIBA_SPROM8_GPIOB_P3);
1651203944Sweongyo	SIBA_SHIFTOUT(tri2g, SIBA_SPROM8_TRI25G, SIBA_SPROM8_TRI2G);
1652203944Sweongyo	SIBA_SHIFTOUT(tri5g, SIBA_SPROM8_TRI25G, SIBA_SPROM8_TRI5G);
1653203944Sweongyo	SIBA_SHIFTOUT(tri5gl, SIBA_SPROM8_TRI5GHL, SIBA_SPROM8_TRI5GL);
1654203944Sweongyo	SIBA_SHIFTOUT(tri5gh, SIBA_SPROM8_TRI5GHL, SIBA_SPROM8_TRI5GH);
1655203944Sweongyo	SIBA_SHIFTOUT(rxpo2g, SIBA_SPROM8_RXPO, SIBA_SPROM8_RXPO2G);
1656203944Sweongyo	SIBA_SHIFTOUT(rxpo5g, SIBA_SPROM8_RXPO, SIBA_SPROM8_RXPO5G);
1657203944Sweongyo	SIBA_SHIFTOUT(rssismf2g, SIBA_SPROM8_RSSIPARM2G, SIBA_SPROM8_RSSISMF2G);
1658203944Sweongyo	SIBA_SHIFTOUT(rssismc2g, SIBA_SPROM8_RSSIPARM2G, SIBA_SPROM8_RSSISMC2G);
1659203944Sweongyo	SIBA_SHIFTOUT(rssisav2g, SIBA_SPROM8_RSSIPARM2G, SIBA_SPROM8_RSSISAV2G);
1660203944Sweongyo	SIBA_SHIFTOUT(bxa2g, SIBA_SPROM8_RSSIPARM2G, SIBA_SPROM8_BXA2G);
1661203944Sweongyo	SIBA_SHIFTOUT(rssismf5g, SIBA_SPROM8_RSSIPARM5G, SIBA_SPROM8_RSSISMF5G);
1662203944Sweongyo	SIBA_SHIFTOUT(rssismc5g, SIBA_SPROM8_RSSIPARM5G, SIBA_SPROM8_RSSISMC5G);
1663203944Sweongyo	SIBA_SHIFTOUT(rssisav5g, SIBA_SPROM8_RSSIPARM5G, SIBA_SPROM8_RSSISAV5G);
1664203944Sweongyo	SIBA_SHIFTOUT(bxa5g, SIBA_SPROM8_RSSIPARM5G, SIBA_SPROM8_BXA5G);
1665203319Sweongyo
1666203944Sweongyo	SIBA_SHIFTOUT(pa0b0, SIBA_SPROM8_PA0B0, 0xffff);
1667203944Sweongyo	SIBA_SHIFTOUT(pa0b1, SIBA_SPROM8_PA0B1, 0xffff);
1668203944Sweongyo	SIBA_SHIFTOUT(pa0b2, SIBA_SPROM8_PA0B2, 0xffff);
1669203944Sweongyo	SIBA_SHIFTOUT(pa1b0, SIBA_SPROM8_PA1B0, 0xffff);
1670203944Sweongyo	SIBA_SHIFTOUT(pa1b1, SIBA_SPROM8_PA1B1, 0xffff);
1671203944Sweongyo	SIBA_SHIFTOUT(pa1b2, SIBA_SPROM8_PA1B2, 0xffff);
1672203944Sweongyo	SIBA_SHIFTOUT(pa1lob0, SIBA_SPROM8_PA1LOB0, 0xffff);
1673203944Sweongyo	SIBA_SHIFTOUT(pa1lob1, SIBA_SPROM8_PA1LOB1, 0xffff);
1674203944Sweongyo	SIBA_SHIFTOUT(pa1lob2, SIBA_SPROM8_PA1LOB2, 0xffff);
1675203944Sweongyo	SIBA_SHIFTOUT(pa1hib0, SIBA_SPROM8_PA1HIB0, 0xffff);
1676203944Sweongyo	SIBA_SHIFTOUT(pa1hib1, SIBA_SPROM8_PA1HIB1, 0xffff);
1677203944Sweongyo	SIBA_SHIFTOUT(pa1hib2, SIBA_SPROM8_PA1HIB2, 0xffff);
1678203944Sweongyo	SIBA_SHIFTOUT(cck2gpo, SIBA_SPROM8_CCK2GPO, 0xffff);
1679203944Sweongyo
1680203944Sweongyo	SIBA_SHIFTOUT_4(ofdm2gpo, SIBA_SPROM8_OFDM2GPO, 0xffffffff, 0);
1681203944Sweongyo	SIBA_SHIFTOUT_4(ofdm5glpo, SIBA_SPROM8_OFDM5GLPO, 0xffffffff, 0);
1682203944Sweongyo	SIBA_SHIFTOUT_4(ofdm5gpo, SIBA_SPROM8_OFDM5GPO, 0xffffffff, 0);
1683203944Sweongyo	SIBA_SHIFTOUT_4(ofdm5ghpo, SIBA_SPROM8_OFDM5GHPO, 0xffffffff, 0);
1684203944Sweongyo
1685203319Sweongyo	/* antenna gain */
1686203319Sweongyo	SIBA_SHIFTOUT(again.ghz24.a0, SIBA_SPROM8_AGAIN01, SIBA_SPROM8_AGAIN0);
1687203319Sweongyo	SIBA_SHIFTOUT(again.ghz24.a1, SIBA_SPROM8_AGAIN01, SIBA_SPROM8_AGAIN1);
1688203319Sweongyo	SIBA_SHIFTOUT(again.ghz24.a2, SIBA_SPROM8_AGAIN23, SIBA_SPROM8_AGAIN2);
1689203319Sweongyo	SIBA_SHIFTOUT(again.ghz24.a3, SIBA_SPROM8_AGAIN23, SIBA_SPROM8_AGAIN3);
1690203319Sweongyo	bcopy(&out->again.ghz24, &out->again.ghz5, sizeof(out->again.ghz5));
1691203319Sweongyo}
1692203319Sweongyo
1693203319Sweongyostatic int8_t
1694203319Sweongyosiba_sprom_r123_antgain(uint8_t sprom_revision, const uint16_t *in,
1695203319Sweongyo    uint16_t mask, uint16_t shift)
1696203319Sweongyo{
1697203319Sweongyo	uint16_t v;
1698203319Sweongyo	uint8_t gain;
1699203319Sweongyo
1700203319Sweongyo	v = in[SIBA_OFFSET(SIBA_SPROM1_AGAIN)];
1701203319Sweongyo	gain = (v & mask) >> shift;
1702203319Sweongyo	gain = (gain == 0xff) ? 2 : (sprom_revision == 1) ? gain << 2 :
1703203319Sweongyo	    ((gain & 0xc0) >> 6) | ((gain & 0x3f) << 2);
1704203319Sweongyo
1705203319Sweongyo	return ((int8_t)gain);
1706203319Sweongyo}
1707203319Sweongyo
1708203319Sweongyo#undef SIBA_LOWEST_SET_BIT
1709203319Sweongyo#undef SIBA_OFFSET
1710203319Sweongyo#undef SIBA_SHIFTOUT_SUB
1711203319Sweongyo#undef SIBA_SHIFTOUT
1712203319Sweongyo
1713203319Sweongyoint
1714204922Sweongyosiba_powerdown(device_t dev)
1715203319Sweongyo{
1716204922Sweongyo	struct siba_dev_softc *sd = device_get_ivars(dev);
1717204922Sweongyo	struct siba_softc *siba = sd->sd_bus;
1718204922Sweongyo
1719204922Sweongyo	return (siba_powerdown_sub(siba));
1720204922Sweongyo}
1721204922Sweongyo
1722204922Sweongyostatic int
1723204922Sweongyosiba_powerdown_sub(struct siba_softc *siba)
1724204922Sweongyo{
1725203319Sweongyo	struct siba_cc *scc;
1726203319Sweongyo
1727203319Sweongyo	if (siba->siba_type == SIBA_TYPE_SSB)
1728203319Sweongyo		return (0);
1729203319Sweongyo
1730203319Sweongyo	scc = &siba->siba_cc;
1731203319Sweongyo	if (!scc->scc_dev || scc->scc_dev->sd_id.sd_rev < 5)
1732203319Sweongyo		return (0);
1733203319Sweongyo	siba_cc_clock(scc, SIBA_CLOCK_SLOW);
1734203319Sweongyo	siba_pci_gpio(siba, SIBA_GPIO_CRYSTAL | SIBA_GPIO_PLL, 0);
1735203319Sweongyo	return (0);
1736203319Sweongyo}
1737203319Sweongyo
1738203319Sweongyostatic void
1739203319Sweongyosiba_pcicore_init(struct siba_pci *spc)
1740203319Sweongyo{
1741203319Sweongyo	struct siba_dev_softc *sd = spc->spc_dev;
1742203319Sweongyo
1743203319Sweongyo	if (sd == NULL)
1744203319Sweongyo		return;
1745203319Sweongyo
1746204922Sweongyo	if (!siba_dev_isup_sub(sd))
1747204922Sweongyo		siba_dev_up_sub(sd, 0);
1748203319Sweongyo
1749203319Sweongyo	KASSERT(spc->spc_hostmode == 0,
1750203319Sweongyo	    ("%s:%d: hostmode", __func__, __LINE__));
1751203319Sweongyo	/* disable PCI interrupt */
1752204922Sweongyo	siba_write_4_sub(spc->spc_dev, SIBA_INTR_MASK, 0);
1753203319Sweongyo}
1754203319Sweongyo
1755203319Sweongyoint
1756204922Sweongyosiba_dev_isup(device_t dev)
1757203319Sweongyo{
1758204922Sweongyo	struct siba_dev_softc *sd = device_get_ivars(dev);
1759204922Sweongyo
1760204922Sweongyo	return (siba_dev_isup_sub(sd));
1761204922Sweongyo}
1762204922Sweongyo
1763204922Sweongyostatic int
1764204922Sweongyosiba_dev_isup_sub(struct siba_dev_softc *sd)
1765204922Sweongyo{
1766203319Sweongyo	uint32_t reject, val;
1767203319Sweongyo
1768203319Sweongyo	reject = siba_tmslow_reject_bitmask(sd);
1769204922Sweongyo	val = siba_read_4_sub(sd, SIBA_TGSLOW);
1770203319Sweongyo	val &= SIBA_TGSLOW_CLOCK | SIBA_TGSLOW_RESET | reject;
1771203319Sweongyo
1772203319Sweongyo	return (val == SIBA_TGSLOW_CLOCK);
1773203319Sweongyo}
1774203319Sweongyo
1775203319Sweongyovoid
1776204922Sweongyosiba_dev_up(device_t dev, uint32_t flags)
1777203319Sweongyo{
1778204922Sweongyo	struct siba_dev_softc *sd = device_get_ivars(dev);
1779204922Sweongyo
1780204922Sweongyo	siba_dev_up_sub(sd, flags);
1781204922Sweongyo}
1782204922Sweongyo
1783204922Sweongyostatic void
1784204922Sweongyosiba_dev_up_sub(struct siba_dev_softc *sd, uint32_t flags)
1785204922Sweongyo{
1786203319Sweongyo	uint32_t val;
1787203319Sweongyo
1788204922Sweongyo	siba_dev_down_sub(sd, flags);
1789204922Sweongyo	siba_write_4_sub(sd, SIBA_TGSLOW,
1790204922Sweongyo	    SIBA_TGSLOW_RESET | SIBA_TGSLOW_CLOCK | SIBA_TGSLOW_FGC | flags);
1791204922Sweongyo	siba_read_4_sub(sd, SIBA_TGSLOW);
1792203319Sweongyo	DELAY(1);
1793203319Sweongyo
1794204922Sweongyo	if (siba_read_4_sub(sd, SIBA_TGSHIGH) & SIBA_TGSHIGH_SERR)
1795204922Sweongyo		siba_write_4_sub(sd, SIBA_TGSHIGH, 0);
1796203319Sweongyo
1797204922Sweongyo	val = siba_read_4_sub(sd, SIBA_IAS);
1798203319Sweongyo	if (val & (SIBA_IAS_INBAND_ERR | SIBA_IAS_TIMEOUT)) {
1799203319Sweongyo		val &= ~(SIBA_IAS_INBAND_ERR | SIBA_IAS_TIMEOUT);
1800204922Sweongyo		siba_write_4_sub(sd, SIBA_IAS, val);
1801203319Sweongyo	}
1802203319Sweongyo
1803204922Sweongyo	siba_write_4_sub(sd, SIBA_TGSLOW,
1804203319Sweongyo	    SIBA_TGSLOW_CLOCK | SIBA_TGSLOW_FGC | flags);
1805204922Sweongyo	siba_read_4_sub(sd, SIBA_TGSLOW);
1806203319Sweongyo	DELAY(1);
1807203319Sweongyo
1808204922Sweongyo	siba_write_4_sub(sd, SIBA_TGSLOW, SIBA_TGSLOW_CLOCK | flags);
1809204922Sweongyo	siba_read_4_sub(sd, SIBA_TGSLOW);
1810203319Sweongyo	DELAY(1);
1811203319Sweongyo}
1812203319Sweongyo
1813203319Sweongyostatic uint32_t
1814203319Sweongyosiba_tmslow_reject_bitmask(struct siba_dev_softc *sd)
1815203319Sweongyo{
1816204922Sweongyo	uint32_t rev = siba_read_4_sub(sd, SIBA_IDLOW) & SIBA_IDLOW_SSBREV;
1817203319Sweongyo
1818203319Sweongyo	switch (rev) {
1819203319Sweongyo	case SIBA_IDLOW_SSBREV_22:
1820203319Sweongyo		return (SIBA_TGSLOW_REJECT_22);
1821203319Sweongyo	case SIBA_IDLOW_SSBREV_23:
1822203319Sweongyo		return (SIBA_TGSLOW_REJECT_23);
1823203319Sweongyo	case SIBA_IDLOW_SSBREV_24:
1824203319Sweongyo	case SIBA_IDLOW_SSBREV_25:
1825203319Sweongyo	case SIBA_IDLOW_SSBREV_26:
1826203319Sweongyo	case SIBA_IDLOW_SSBREV_27:
1827203319Sweongyo		return (SIBA_TGSLOW_REJECT_23);
1828203319Sweongyo	default:
1829203319Sweongyo		KASSERT(0 == 1,
1830203319Sweongyo		    ("%s:%d: unknown backplane rev %#x\n",
1831203319Sweongyo			__func__, __LINE__, rev));
1832203319Sweongyo	}
1833203319Sweongyo	return (SIBA_TGSLOW_REJECT_22 | SIBA_TGSLOW_REJECT_23);
1834203319Sweongyo}
1835203319Sweongyo
1836203319Sweongyovoid
1837204922Sweongyosiba_dev_down(device_t dev, uint32_t flags)
1838203319Sweongyo{
1839204922Sweongyo	struct siba_dev_softc *sd = device_get_ivars(dev);
1840204922Sweongyo
1841204922Sweongyo	siba_dev_down_sub(sd, flags);
1842204922Sweongyo}
1843204922Sweongyo
1844204922Sweongyostatic void
1845204922Sweongyosiba_dev_down_sub(struct siba_dev_softc *sd, uint32_t flags)
1846204922Sweongyo{
1847203319Sweongyo	struct siba_softc *siba = sd->sd_bus;
1848203319Sweongyo	uint32_t reject, val;
1849203319Sweongyo	int i;
1850203319Sweongyo
1851204922Sweongyo	if (siba_read_4_sub(sd, SIBA_TGSLOW) & SIBA_TGSLOW_RESET)
1852203319Sweongyo		return;
1853203319Sweongyo
1854203319Sweongyo	reject = siba_tmslow_reject_bitmask(sd);
1855204922Sweongyo	siba_write_4_sub(sd, SIBA_TGSLOW, reject | SIBA_TGSLOW_CLOCK);
1856203319Sweongyo
1857203319Sweongyo	for (i = 0; i < 1000; i++) {
1858204922Sweongyo		val = siba_read_4_sub(sd, SIBA_TGSLOW);
1859203319Sweongyo		if (val & reject)
1860203319Sweongyo			break;
1861203319Sweongyo		DELAY(10);
1862203319Sweongyo	}
1863203319Sweongyo	if ((val & reject) == 0) {
1864203319Sweongyo		device_printf(siba->siba_dev, "timeout (bit %#x reg %#x)\n",
1865203319Sweongyo		    reject, SIBA_TGSLOW);
1866203319Sweongyo	}
1867203319Sweongyo	for (i = 0; i < 1000; i++) {
1868204922Sweongyo		val = siba_read_4_sub(sd, SIBA_TGSHIGH);
1869203319Sweongyo		if (!(val & SIBA_TGSHIGH_BUSY))
1870203319Sweongyo			break;
1871203319Sweongyo		DELAY(10);
1872203319Sweongyo	}
1873203319Sweongyo	if ((val & SIBA_TGSHIGH_BUSY) != 0) {
1874203319Sweongyo		device_printf(siba->siba_dev, "timeout (bit %#x reg %#x)\n",
1875203319Sweongyo		    SIBA_TGSHIGH_BUSY, SIBA_TGSHIGH);
1876203319Sweongyo	}
1877203319Sweongyo
1878204922Sweongyo	siba_write_4_sub(sd, SIBA_TGSLOW, SIBA_TGSLOW_FGC | SIBA_TGSLOW_CLOCK |
1879203319Sweongyo	    reject | SIBA_TGSLOW_RESET | flags);
1880204922Sweongyo	siba_read_4_sub(sd, SIBA_TGSLOW);
1881203319Sweongyo	DELAY(1);
1882204922Sweongyo	siba_write_4_sub(sd, SIBA_TGSLOW, reject | SIBA_TGSLOW_RESET | flags);
1883204922Sweongyo	siba_read_4_sub(sd, SIBA_TGSLOW);
1884203319Sweongyo	DELAY(1);
1885203319Sweongyo}
1886203319Sweongyo
1887203319Sweongyostatic void
1888203319Sweongyosiba_pcicore_setup(struct siba_pci *spc, struct siba_dev_softc *sd)
1889203319Sweongyo{
1890203319Sweongyo	struct siba_dev_softc *psd = spc->spc_dev;
1891203319Sweongyo	struct siba_softc *siba = psd->sd_bus;
1892203319Sweongyo	uint32_t tmp;
1893203319Sweongyo
1894203319Sweongyo	if (psd->sd_id.sd_device == SIBA_DEVID_PCI) {
1895203319Sweongyo		siba_pcicore_write_4(spc, SIBA_PCICORE_SBTOPCI2,
1896203319Sweongyo		    siba_pcicore_read_4(spc, SIBA_PCICORE_SBTOPCI2) |
1897203319Sweongyo		    SIBA_PCICORE_SBTOPCI_PREF | SIBA_PCICORE_SBTOPCI_BURST);
1898203319Sweongyo
1899203319Sweongyo		if (psd->sd_id.sd_rev < 5) {
1900204922Sweongyo			tmp = siba_read_4_sub(psd, SIBA_IMCFGLO);
1901203319Sweongyo			tmp &= ~SIBA_IMCFGLO_SERTO;
1902203319Sweongyo			tmp = (tmp | 2) & ~SIBA_IMCFGLO_REQTO;
1903203319Sweongyo			tmp |= 3 << 4 /* SIBA_IMCFGLO_REQTO_SHIFT */;
1904204922Sweongyo			siba_write_4_sub(psd, SIBA_IMCFGLO, tmp);
1905203319Sweongyo
1906203319Sweongyo			/* broadcast value */
1907203319Sweongyo			sd = (siba->siba_cc.scc_dev != NULL) ?
1908203319Sweongyo			    siba->siba_cc.scc_dev : siba->siba_pci.spc_dev;
1909203319Sweongyo			if (sd != NULL) {
1910204922Sweongyo				siba_write_4_sub(sd, SIBA_PCICORE_BCAST_ADDR,
1911203319Sweongyo				    0xfd8);
1912204922Sweongyo				siba_read_4_sub(sd, SIBA_PCICORE_BCAST_ADDR);
1913204922Sweongyo				siba_write_4_sub(sd,
1914204922Sweongyo				    SIBA_PCICORE_BCAST_DATA, 0);
1915204922Sweongyo				siba_read_4_sub(sd, SIBA_PCICORE_BCAST_DATA);
1916203319Sweongyo			}
1917203319Sweongyo		} else if (psd->sd_id.sd_rev >= 11) {
1918203319Sweongyo			tmp = siba_pcicore_read_4(spc, SIBA_PCICORE_SBTOPCI2);
1919203319Sweongyo			tmp |= SIBA_PCICORE_SBTOPCI_MRM;
1920203319Sweongyo			siba_pcicore_write_4(spc, SIBA_PCICORE_SBTOPCI2, tmp);
1921203319Sweongyo		}
1922203319Sweongyo	} else {
1923203319Sweongyo		KASSERT(psd->sd_id.sd_device == SIBA_DEVID_PCIE, ("only PCIE"));
1924203319Sweongyo		if ((psd->sd_id.sd_rev == 0) || (psd->sd_id.sd_rev == 1))
1925203319Sweongyo			siba_pcie_write(spc, 0x4,
1926203319Sweongyo			    siba_pcie_read(spc, 0x4) | 0x8);
1927203319Sweongyo		if (psd->sd_id.sd_rev == 0) {
1928203319Sweongyo			siba_pcie_mdio_write(spc, 0x1f, 2, 0x8128); /* Timer */
1929203319Sweongyo			siba_pcie_mdio_write(spc, 0x1f, 6, 0x0100); /* CDR */
1930203319Sweongyo			siba_pcie_mdio_write(spc, 0x1f, 7, 0x1466); /* CDR BW */
1931203319Sweongyo		} else if (psd->sd_id.sd_rev == 1)
1932203319Sweongyo			siba_pcie_write(spc, 0x100,
1933203319Sweongyo			    siba_pcie_read(spc, 0x100) | 0x40);
1934203319Sweongyo	}
1935203319Sweongyo	spc->spc_inited = 1;
1936203319Sweongyo}
1937203319Sweongyo
1938203319Sweongyovoid
1939204922Sweongyosiba_pcicore_intr(device_t dev)
1940203319Sweongyo{
1941204922Sweongyo	struct siba_dev_softc *sd = device_get_ivars(dev);
1942204922Sweongyo	struct siba_softc *siba = sd->sd_bus;
1943204922Sweongyo	struct siba_pci *spc = &siba->siba_pci;
1944203319Sweongyo	struct siba_dev_softc *psd = spc->spc_dev;
1945203319Sweongyo	uint32_t tmp;
1946203319Sweongyo
1947204922Sweongyo	if (siba->siba_type != SIBA_TYPE_PCI || !psd)
1948203319Sweongyo		return;
1949203319Sweongyo
1950204922Sweongyo	KASSERT(siba == psd->sd_bus, ("different pointers"));
1951204922Sweongyo
1952203319Sweongyo	/* enable interrupts */
1953203319Sweongyo	if (siba->siba_dev != NULL &&
1954204922Sweongyo	    (psd->sd_id.sd_rev >= 6 ||
1955204922Sweongyo	     psd->sd_id.sd_device == SIBA_DEVID_PCIE)) {
1956203319Sweongyo		tmp = pci_read_config(siba->siba_dev, SIBA_IRQMASK, 4);
1957203319Sweongyo		tmp |= (1 << sd->sd_coreidx) << 8;
1958203319Sweongyo		pci_write_config(siba->siba_dev, SIBA_IRQMASK, tmp, 4);
1959203319Sweongyo	} else {
1960204922Sweongyo		tmp = siba_read_4_sub(sd, SIBA_TPS);
1961203319Sweongyo		tmp &= SIBA_TPS_BPFLAG;
1962204922Sweongyo		siba_write_4_sub(psd, SIBA_INTR_MASK,
1963204922Sweongyo		    siba_read_4_sub(psd, SIBA_INTR_MASK) | (1 << tmp));
1964203319Sweongyo	}
1965203319Sweongyo
1966203319Sweongyo	/* setup PCIcore */
1967203319Sweongyo	if (spc->spc_inited == 0)
1968203319Sweongyo		siba_pcicore_setup(spc, sd);
1969203319Sweongyo}
1970203319Sweongyo
1971203319Sweongyostatic uint32_t
1972203319Sweongyosiba_pcicore_read_4(struct siba_pci *spc, uint16_t offset)
1973203319Sweongyo{
1974203319Sweongyo
1975204922Sweongyo	return (siba_read_4_sub(spc->spc_dev, offset));
1976203319Sweongyo}
1977203319Sweongyo
1978203319Sweongyostatic void
1979203319Sweongyosiba_pcicore_write_4(struct siba_pci *spc, uint16_t offset, uint32_t value)
1980203319Sweongyo{
1981203319Sweongyo
1982204922Sweongyo	siba_write_4_sub(spc->spc_dev, offset, value);
1983203319Sweongyo}
1984203319Sweongyo
1985203319Sweongyostatic uint32_t
1986203319Sweongyosiba_pcie_read(struct siba_pci *spc, uint32_t address)
1987203319Sweongyo{
1988203319Sweongyo
1989203319Sweongyo	siba_pcicore_write_4(spc, 0x130, address);
1990203319Sweongyo	return (siba_pcicore_read_4(spc, 0x134));
1991203319Sweongyo}
1992203319Sweongyo
1993203319Sweongyostatic void
1994203319Sweongyosiba_pcie_write(struct siba_pci *spc, uint32_t address, uint32_t data)
1995203319Sweongyo{
1996203319Sweongyo
1997203319Sweongyo	siba_pcicore_write_4(spc, 0x130, address);
1998203319Sweongyo	siba_pcicore_write_4(spc, 0x134, data);
1999203319Sweongyo}
2000203319Sweongyo
2001203319Sweongyostatic void
2002203319Sweongyosiba_pcie_mdio_write(struct siba_pci *spc, uint8_t device, uint8_t address,
2003203319Sweongyo    uint16_t data)
2004203319Sweongyo{
2005203319Sweongyo	int i;
2006203319Sweongyo
2007203319Sweongyo	siba_pcicore_write_4(spc, SIBA_PCICORE_MDIO_CTL, 0x80 | 0x2);
2008203319Sweongyo	siba_pcicore_write_4(spc, SIBA_PCICORE_MDIO_DATA,
2009203319Sweongyo	    (1 << 30) | (1 << 28) |
2010203319Sweongyo	    ((uint32_t)device << 22) | ((uint32_t)address << 18) |
2011203319Sweongyo	    (1 << 17) | data);
2012203319Sweongyo	DELAY(10);
2013203319Sweongyo	for (i = 0; i < 10; i++) {
2014203319Sweongyo		if (siba_pcicore_read_4(spc, SIBA_PCICORE_MDIO_CTL) & 0x100)
2015203319Sweongyo			break;
2016203319Sweongyo		DELAY(1000);
2017203319Sweongyo	}
2018203319Sweongyo	siba_pcicore_write_4(spc, SIBA_PCICORE_MDIO_CTL, 0);
2019203319Sweongyo}
2020203319Sweongyo
2021203319Sweongyouint32_t
2022204922Sweongyosiba_dma_translation(device_t dev)
2023203319Sweongyo{
2024205003Sthompsa#ifdef INVARIANTS
2025205003Sthompsa	struct siba_dev_softc *sd = device_get_ivars(dev);
2026205003Sthompsa	struct siba_softc *siba = sd->sd_bus;
2027203319Sweongyo
2028205003Sthompsa	KASSERT(siba->siba_type == SIBA_TYPE_PCI,
2029205003Sthompsa	    ("unsupported bustype %d\n", siba->siba_type));
2030205003Sthompsa#endif
2031203319Sweongyo	return (SIBA_PCI_DMA);
2032203319Sweongyo}
2033203319Sweongyo
2034203319Sweongyovoid
2035204922Sweongyosiba_barrier(device_t dev, int flags)
2036203319Sweongyo{
2037204922Sweongyo	struct siba_dev_softc *sd = device_get_ivars(dev);
2038203319Sweongyo	struct siba_softc *siba = sd->sd_bus;
2039203319Sweongyo
2040203319Sweongyo	SIBA_BARRIER(siba, flags);
2041203319Sweongyo}
2042203319Sweongyo
2043203319Sweongyostatic void
2044203319Sweongyosiba_cc_suspend(struct siba_cc *scc)
2045203319Sweongyo{
2046203319Sweongyo
2047203319Sweongyo	siba_cc_clock(scc, SIBA_CLOCK_SLOW);
2048203319Sweongyo}
2049203319Sweongyo
2050203319Sweongyostatic void
2051203319Sweongyosiba_cc_resume(struct siba_cc *scc)
2052203319Sweongyo{
2053203319Sweongyo
2054203319Sweongyo	siba_cc_power_init(scc);
2055203319Sweongyo	siba_cc_clock(scc, SIBA_CLOCK_FAST);
2056203319Sweongyo}
2057203319Sweongyo
2058203319Sweongyoint
2059203319Sweongyosiba_core_suspend(struct siba_softc *siba)
2060203319Sweongyo{
2061203319Sweongyo
2062203319Sweongyo	siba_cc_suspend(&siba->siba_cc);
2063203319Sweongyo	siba_pci_gpio(siba, SIBA_GPIO_CRYSTAL | SIBA_GPIO_PLL, 0);
2064203319Sweongyo	return (0);
2065203319Sweongyo}
2066203319Sweongyo
2067203319Sweongyoint
2068203319Sweongyosiba_core_resume(struct siba_softc *siba)
2069203319Sweongyo{
2070203319Sweongyo
2071203319Sweongyo	siba->siba_pci.spc_inited = 0;
2072203319Sweongyo	siba->siba_curdev = NULL;
2073203319Sweongyo
2074204922Sweongyo	siba_powerup_sub(siba, 0);
2075203319Sweongyo	/* XXX setup H/W for PCMCIA??? */
2076203319Sweongyo	siba_cc_resume(&siba->siba_cc);
2077204922Sweongyo	siba_powerdown_sub(siba);
2078203319Sweongyo
2079203319Sweongyo	return (0);
2080203319Sweongyo}
2081203944Sweongyo
2082203944Sweongyostatic void
2083203944Sweongyosiba_cc_regctl_setmask(struct siba_cc *cc, uint32_t offset, uint32_t mask,
2084203944Sweongyo    uint32_t set)
2085203944Sweongyo{
2086203944Sweongyo
2087203944Sweongyo	SIBA_CC_READ32(cc, SIBA_CC_REGCTL_ADDR);
2088203944Sweongyo	SIBA_CC_WRITE32(cc, SIBA_CC_REGCTL_ADDR, offset);
2089203944Sweongyo	SIBA_CC_READ32(cc, SIBA_CC_REGCTL_ADDR);
2090203944Sweongyo	SIBA_CC_WRITE32(cc, SIBA_CC_REGCTL_DATA,
2091203944Sweongyo	    (SIBA_CC_READ32(cc, SIBA_CC_REGCTL_DATA) & mask) | set);
2092203944Sweongyo	SIBA_CC_READ32(cc, SIBA_CC_REGCTL_DATA);
2093203944Sweongyo}
2094203944Sweongyo
2095203944Sweongyovoid
2096204922Sweongyosiba_cc_pmu_set_ldovolt(device_t dev, int id, uint32_t volt)
2097203944Sweongyo{
2098204922Sweongyo	struct siba_dev_softc *sd = device_get_ivars(dev);
2099204922Sweongyo	struct siba_softc *siba = sd->sd_bus;
2100204922Sweongyo	struct siba_cc *scc = &siba->siba_cc;
2101203944Sweongyo	uint32_t *p = NULL, info[5][3] = {
2102203944Sweongyo		{ 2, 25,  0xf },
2103203944Sweongyo		{ 3,  1,  0xf },
2104203944Sweongyo		{ 3,  9,  0xf },
2105203944Sweongyo		{ 3, 17, 0x3f },
2106203944Sweongyo		{ 0, 21, 0x3f }
2107203944Sweongyo	};
2108203944Sweongyo
2109203944Sweongyo	if (siba->siba_chipid == 0x4312) {
2110203944Sweongyo		if (id != SIBA_LDO_PAREF)
2111203944Sweongyo			return;
2112203944Sweongyo		p = info[4];
2113203944Sweongyo		siba_cc_regctl_setmask(scc, p[0], ~(p[2] << p[1]),
2114203944Sweongyo		    (volt & p[2]) << p[1]);
2115203944Sweongyo		return;
2116203944Sweongyo	}
2117203944Sweongyo	if (siba->siba_chipid == 0x4328 || siba->siba_chipid == 0x5354) {
2118203944Sweongyo		switch (id) {
2119203944Sweongyo		case SIBA_LDO_PAREF:
2120203944Sweongyo			p = info[3];
2121203944Sweongyo			break;
2122203944Sweongyo		case SIBA_LDO_VOLT1:
2123203944Sweongyo			p = info[0];
2124203944Sweongyo			break;
2125203944Sweongyo		case SIBA_LDO_VOLT2:
2126203944Sweongyo			p = info[1];
2127203944Sweongyo			break;
2128203944Sweongyo		case SIBA_LDO_VOLT3:
2129203944Sweongyo			p = info[2];
2130203944Sweongyo			break;
2131203944Sweongyo		default:
2132203944Sweongyo			KASSERT(0 == 1,
2133203944Sweongyo			    ("%s: unsupported voltage ID %#x", __func__, id));
2134203944Sweongyo			return;
2135203944Sweongyo		}
2136203944Sweongyo		siba_cc_regctl_setmask(scc, p[0], ~(p[2] << p[1]),
2137203944Sweongyo		    (volt & p[2]) << p[1]);
2138203944Sweongyo	}
2139203944Sweongyo}
2140203944Sweongyo
2141203944Sweongyovoid
2142204922Sweongyosiba_cc_pmu_set_ldoparef(device_t dev, uint8_t on)
2143203944Sweongyo{
2144204922Sweongyo	struct siba_dev_softc *sd = device_get_ivars(dev);
2145204922Sweongyo	struct siba_softc *siba = sd->sd_bus;
2146204922Sweongyo	struct siba_cc *scc = &siba->siba_cc;
2147203944Sweongyo	int ldo;
2148203944Sweongyo
2149203944Sweongyo	ldo = ((siba->siba_chipid == 0x4312) ? SIBA_CC_PMU_4312_PA_REF :
2150203944Sweongyo	    ((siba->siba_chipid == 0x4328) ? SIBA_CC_PMU_4328_PA_REF :
2151203944Sweongyo	    ((siba->siba_chipid == 0x5354) ? SIBA_CC_PMU_5354_PA_REF : -1)));
2152203944Sweongyo	if (ldo == -1)
2153203944Sweongyo		return;
2154203944Sweongyo
2155203944Sweongyo	if (on)
2156203944Sweongyo		SIBA_CC_SET32(scc, SIBA_CC_PMU_MINRES, 1 << ldo);
2157203944Sweongyo	else
2158203944Sweongyo		SIBA_CC_MASK32(scc, SIBA_CC_PMU_MINRES, ~(1 << ldo));
2159203944Sweongyo	SIBA_CC_READ32(scc, SIBA_CC_PMU_MINRES);
2160203944Sweongyo}
2161204922Sweongyo
2162204922Sweongyoint
2163204922Sweongyosiba_read_sprom(device_t dev, device_t child, int which, uintptr_t *result)
2164204922Sweongyo{
2165204922Sweongyo	struct siba_dev_softc *sd = device_get_ivars(child);
2166204922Sweongyo	struct siba_softc *siba = sd->sd_bus;
2167204922Sweongyo
2168204922Sweongyo	switch (which) {
2169204922Sweongyo	case SIBA_SPROMVAR_REV:
2170204922Sweongyo		*result = siba->siba_sprom.rev;
2171204922Sweongyo		break;
2172204922Sweongyo	case SIBA_SPROMVAR_MAC_80211BG:
2173204922Sweongyo		*((uint8_t **) result) = siba->siba_sprom.mac_80211bg;
2174204922Sweongyo		break;
2175204922Sweongyo	case SIBA_SPROMVAR_MAC_ETH:
2176204922Sweongyo		*((uint8_t **) result) = siba->siba_sprom.mac_eth;
2177204922Sweongyo		break;
2178204922Sweongyo	case SIBA_SPROMVAR_MAC_80211A:
2179204922Sweongyo		*((uint8_t **) result) = siba->siba_sprom.mac_80211a;
2180204922Sweongyo		break;
2181204922Sweongyo	case SIBA_SPROMVAR_MII_ETH0:
2182204922Sweongyo		*result = siba->siba_sprom.mii_eth0;
2183204922Sweongyo		break;
2184204922Sweongyo	case SIBA_SPROMVAR_MII_ETH1:
2185204922Sweongyo		*result = siba->siba_sprom.mii_eth1;
2186204922Sweongyo		break;
2187204922Sweongyo	case SIBA_SPROMVAR_MDIO_ETH0:
2188204922Sweongyo		*result = siba->siba_sprom.mdio_eth0;
2189204922Sweongyo		break;
2190204922Sweongyo	case SIBA_SPROMVAR_MDIO_ETH1:
2191204922Sweongyo		*result = siba->siba_sprom.mdio_eth1;
2192204922Sweongyo		break;
2193204922Sweongyo	case SIBA_SPROMVAR_BREV:
2194204922Sweongyo		*result = siba->siba_sprom.brev;
2195204922Sweongyo		break;
2196204922Sweongyo	case SIBA_SPROMVAR_CCODE:
2197204922Sweongyo		*result = siba->siba_sprom.ccode;
2198204922Sweongyo		break;
2199204922Sweongyo	case SIBA_SPROMVAR_ANT_A:
2200204922Sweongyo		*result = siba->siba_sprom.ant_a;
2201204922Sweongyo		break;
2202204922Sweongyo	case SIBA_SPROMVAR_ANT_BG:
2203204922Sweongyo		*result = siba->siba_sprom.ant_bg;
2204204922Sweongyo		break;
2205204922Sweongyo	case SIBA_SPROMVAR_PA0B0:
2206204922Sweongyo		*result = siba->siba_sprom.pa0b0;
2207204922Sweongyo		break;
2208204922Sweongyo	case SIBA_SPROMVAR_PA0B1:
2209204922Sweongyo		*result = siba->siba_sprom.pa0b1;
2210204922Sweongyo		break;
2211204922Sweongyo	case SIBA_SPROMVAR_PA0B2:
2212204922Sweongyo		*result = siba->siba_sprom.pa0b2;
2213204922Sweongyo		break;
2214204922Sweongyo	case SIBA_SPROMVAR_PA1B0:
2215204922Sweongyo		*result = siba->siba_sprom.pa1b0;
2216204922Sweongyo		break;
2217204922Sweongyo	case SIBA_SPROMVAR_PA1B1:
2218204922Sweongyo		*result = siba->siba_sprom.pa1b1;
2219204922Sweongyo		break;
2220204922Sweongyo	case SIBA_SPROMVAR_PA1B2:
2221204922Sweongyo		*result = siba->siba_sprom.pa1b2;
2222204922Sweongyo		break;
2223204922Sweongyo	case SIBA_SPROMVAR_PA1LOB0:
2224204922Sweongyo		*result = siba->siba_sprom.pa1lob0;
2225204922Sweongyo		break;
2226204922Sweongyo	case SIBA_SPROMVAR_PA1LOB1:
2227204922Sweongyo		*result = siba->siba_sprom.pa1lob1;
2228204922Sweongyo		break;
2229204922Sweongyo	case SIBA_SPROMVAR_PA1LOB2:
2230204922Sweongyo		*result = siba->siba_sprom.pa1lob2;
2231204922Sweongyo		break;
2232204922Sweongyo	case SIBA_SPROMVAR_PA1HIB0:
2233204922Sweongyo		*result = siba->siba_sprom.pa1hib0;
2234204922Sweongyo		break;
2235204922Sweongyo	case SIBA_SPROMVAR_PA1HIB1:
2236204922Sweongyo		*result = siba->siba_sprom.pa1hib1;
2237204922Sweongyo		break;
2238204922Sweongyo	case SIBA_SPROMVAR_PA1HIB2:
2239204922Sweongyo		*result = siba->siba_sprom.pa1hib2;
2240204922Sweongyo		break;
2241204922Sweongyo	case SIBA_SPROMVAR_GPIO0:
2242204922Sweongyo		*result = siba->siba_sprom.gpio0;
2243204922Sweongyo		break;
2244204922Sweongyo	case SIBA_SPROMVAR_GPIO1:
2245204922Sweongyo		*result = siba->siba_sprom.gpio1;
2246204922Sweongyo		break;
2247204922Sweongyo	case SIBA_SPROMVAR_GPIO2:
2248204922Sweongyo		*result = siba->siba_sprom.gpio2;
2249204922Sweongyo		break;
2250204922Sweongyo	case SIBA_SPROMVAR_GPIO3:
2251204922Sweongyo		*result = siba->siba_sprom.gpio3;
2252204922Sweongyo		break;
2253204922Sweongyo	case SIBA_SPROMVAR_MAXPWR_AL:
2254204922Sweongyo		*result = siba->siba_sprom.maxpwr_al;
2255204922Sweongyo		break;
2256204922Sweongyo	case SIBA_SPROMVAR_MAXPWR_A:
2257204922Sweongyo		*result = siba->siba_sprom.maxpwr_a;
2258204922Sweongyo		break;
2259204922Sweongyo	case SIBA_SPROMVAR_MAXPWR_AH:
2260204922Sweongyo		*result = siba->siba_sprom.maxpwr_ah;
2261204922Sweongyo		break;
2262204922Sweongyo	case SIBA_SPROMVAR_MAXPWR_BG:
2263204922Sweongyo		*result = siba->siba_sprom.maxpwr_bg;
2264204922Sweongyo		break;
2265204922Sweongyo	case SIBA_SPROMVAR_RXPO2G:
2266204922Sweongyo		*result = siba->siba_sprom.rxpo2g;
2267204922Sweongyo		break;
2268204922Sweongyo	case SIBA_SPROMVAR_RXPO5G:
2269204922Sweongyo		*result = siba->siba_sprom.rxpo5g;
2270204922Sweongyo		break;
2271204922Sweongyo	case SIBA_SPROMVAR_TSSI_A:
2272204922Sweongyo		*result = siba->siba_sprom.tssi_a;
2273204922Sweongyo		break;
2274204922Sweongyo	case SIBA_SPROMVAR_TSSI_BG:
2275204922Sweongyo		*result = siba->siba_sprom.tssi_bg;
2276204922Sweongyo		break;
2277204922Sweongyo	case SIBA_SPROMVAR_TRI2G:
2278204922Sweongyo		*result = siba->siba_sprom.tri2g;
2279204922Sweongyo		break;
2280204922Sweongyo	case SIBA_SPROMVAR_TRI5GL:
2281204922Sweongyo		*result = siba->siba_sprom.tri5gl;
2282204922Sweongyo		break;
2283204922Sweongyo	case SIBA_SPROMVAR_TRI5G:
2284204922Sweongyo		*result = siba->siba_sprom.tri5g;
2285204922Sweongyo		break;
2286204922Sweongyo	case SIBA_SPROMVAR_TRI5GH:
2287204922Sweongyo		*result = siba->siba_sprom.tri5gh;
2288204922Sweongyo		break;
2289204922Sweongyo	case SIBA_SPROMVAR_RSSISAV2G:
2290204922Sweongyo		*result = siba->siba_sprom.rssisav2g;
2291204922Sweongyo		break;
2292204922Sweongyo	case SIBA_SPROMVAR_RSSISMC2G:
2293204922Sweongyo		*result = siba->siba_sprom.rssismc2g;
2294204922Sweongyo		break;
2295204922Sweongyo	case SIBA_SPROMVAR_RSSISMF2G:
2296204922Sweongyo		*result = siba->siba_sprom.rssismf2g;
2297204922Sweongyo		break;
2298204922Sweongyo	case SIBA_SPROMVAR_BXA2G:
2299204922Sweongyo		*result = siba->siba_sprom.bxa2g;
2300204922Sweongyo		break;
2301204922Sweongyo	case SIBA_SPROMVAR_RSSISAV5G:
2302204922Sweongyo		*result = siba->siba_sprom.rssisav5g;
2303204922Sweongyo		break;
2304204922Sweongyo	case SIBA_SPROMVAR_RSSISMC5G:
2305204922Sweongyo		*result = siba->siba_sprom.rssismc5g;
2306204922Sweongyo		break;
2307204922Sweongyo	case SIBA_SPROMVAR_RSSISMF5G:
2308204922Sweongyo		*result = siba->siba_sprom.rssismf5g;
2309204922Sweongyo		break;
2310204922Sweongyo	case SIBA_SPROMVAR_BXA5G:
2311204922Sweongyo		*result = siba->siba_sprom.bxa5g;
2312204922Sweongyo		break;
2313204922Sweongyo	case SIBA_SPROMVAR_CCK2GPO:
2314204922Sweongyo		*result = siba->siba_sprom.cck2gpo;
2315204922Sweongyo		break;
2316204922Sweongyo	case SIBA_SPROMVAR_OFDM2GPO:
2317204922Sweongyo		*result = siba->siba_sprom.ofdm2gpo;
2318204922Sweongyo		break;
2319204922Sweongyo	case SIBA_SPROMVAR_OFDM5GLPO:
2320204922Sweongyo		*result = siba->siba_sprom.ofdm5glpo;
2321204922Sweongyo		break;
2322204922Sweongyo	case SIBA_SPROMVAR_OFDM5GPO:
2323204922Sweongyo		*result = siba->siba_sprom.ofdm5gpo;
2324204922Sweongyo		break;
2325204922Sweongyo	case SIBA_SPROMVAR_OFDM5GHPO:
2326204922Sweongyo		*result = siba->siba_sprom.ofdm5ghpo;
2327204922Sweongyo		break;
2328204922Sweongyo	case SIBA_SPROMVAR_BF_LO:
2329204922Sweongyo		*result = siba->siba_sprom.bf_lo;
2330204922Sweongyo		break;
2331204922Sweongyo	case SIBA_SPROMVAR_BF_HI:
2332204922Sweongyo		*result = siba->siba_sprom.bf_hi;
2333204922Sweongyo		break;
2334204922Sweongyo	case SIBA_SPROMVAR_BF2_LO:
2335204922Sweongyo		*result = siba->siba_sprom.bf2_lo;
2336204922Sweongyo		break;
2337204922Sweongyo	case SIBA_SPROMVAR_BF2_HI:
2338204922Sweongyo		*result = siba->siba_sprom.bf2_hi;
2339204922Sweongyo		break;
2340204922Sweongyo	default:
2341204922Sweongyo		return (ENOENT);
2342204922Sweongyo	}
2343204922Sweongyo	return (0);
2344204922Sweongyo}
2345204922Sweongyo
2346204922Sweongyoint
2347204922Sweongyosiba_write_sprom(device_t dev, device_t child, int which, uintptr_t value)
2348204922Sweongyo{
2349204922Sweongyo	struct siba_dev_softc *sd = device_get_ivars(child);
2350204922Sweongyo	struct siba_softc *siba = sd->sd_bus;
2351204922Sweongyo
2352204922Sweongyo	switch (which) {
2353204922Sweongyo	case SIBA_SPROMVAR_REV:
2354204922Sweongyo		siba->siba_sprom.rev = value;
2355204922Sweongyo		break;
2356204922Sweongyo	case SIBA_SPROMVAR_MII_ETH0:
2357204922Sweongyo		siba->siba_sprom.mii_eth0 = value;
2358204922Sweongyo		break;
2359204922Sweongyo	case SIBA_SPROMVAR_MII_ETH1:
2360204922Sweongyo		siba->siba_sprom.mii_eth1 = value;
2361204922Sweongyo		break;
2362204922Sweongyo	case SIBA_SPROMVAR_MDIO_ETH0:
2363204922Sweongyo		siba->siba_sprom.mdio_eth0 = value;
2364204922Sweongyo		break;
2365204922Sweongyo	case SIBA_SPROMVAR_MDIO_ETH1:
2366204922Sweongyo		siba->siba_sprom.mdio_eth1 = value;
2367204922Sweongyo		break;
2368204922Sweongyo	case SIBA_SPROMVAR_BREV:
2369204922Sweongyo		siba->siba_sprom.brev = value;
2370204922Sweongyo		break;
2371204922Sweongyo	case SIBA_SPROMVAR_CCODE:
2372204922Sweongyo		siba->siba_sprom.ccode = value;
2373204922Sweongyo		break;
2374204922Sweongyo	case SIBA_SPROMVAR_ANT_A:
2375204922Sweongyo		siba->siba_sprom.ant_a = value;
2376204922Sweongyo		break;
2377204922Sweongyo	case SIBA_SPROMVAR_ANT_BG:
2378204922Sweongyo		siba->siba_sprom.ant_bg = value;
2379204922Sweongyo		break;
2380204922Sweongyo	case SIBA_SPROMVAR_PA0B0:
2381204922Sweongyo		siba->siba_sprom.pa0b0 = value;
2382204922Sweongyo		break;
2383204922Sweongyo	case SIBA_SPROMVAR_PA0B1:
2384204922Sweongyo		siba->siba_sprom.pa0b1 = value;
2385204922Sweongyo		break;
2386204922Sweongyo	case SIBA_SPROMVAR_PA0B2:
2387204922Sweongyo		siba->siba_sprom.pa0b2 = value;
2388204922Sweongyo		break;
2389204922Sweongyo	case SIBA_SPROMVAR_PA1B0:
2390204922Sweongyo		siba->siba_sprom.pa1b0 = value;
2391204922Sweongyo		break;
2392204922Sweongyo	case SIBA_SPROMVAR_PA1B1:
2393204922Sweongyo		siba->siba_sprom.pa1b1 = value;
2394204922Sweongyo		break;
2395204922Sweongyo	case SIBA_SPROMVAR_PA1B2:
2396204922Sweongyo		siba->siba_sprom.pa1b2 = value;
2397204922Sweongyo		break;
2398204922Sweongyo	case SIBA_SPROMVAR_PA1LOB0:
2399204922Sweongyo		siba->siba_sprom.pa1lob0 = value;
2400204922Sweongyo		break;
2401204922Sweongyo	case SIBA_SPROMVAR_PA1LOB1:
2402204922Sweongyo		siba->siba_sprom.pa1lob1 = value;
2403204922Sweongyo		break;
2404204922Sweongyo	case SIBA_SPROMVAR_PA1LOB2:
2405204922Sweongyo		siba->siba_sprom.pa1lob2 = value;
2406204922Sweongyo		break;
2407204922Sweongyo	case SIBA_SPROMVAR_PA1HIB0:
2408204922Sweongyo		siba->siba_sprom.pa1hib0 = value;
2409204922Sweongyo		break;
2410204922Sweongyo	case SIBA_SPROMVAR_PA1HIB1:
2411204922Sweongyo		siba->siba_sprom.pa1hib1 = value;
2412204922Sweongyo		break;
2413204922Sweongyo	case SIBA_SPROMVAR_PA1HIB2:
2414204922Sweongyo		siba->siba_sprom.pa1hib2 = value;
2415204922Sweongyo		break;
2416204922Sweongyo	case SIBA_SPROMVAR_GPIO0:
2417204922Sweongyo		siba->siba_sprom.gpio0 = value;
2418204922Sweongyo		break;
2419204922Sweongyo	case SIBA_SPROMVAR_GPIO1:
2420204922Sweongyo		siba->siba_sprom.gpio1 = value;
2421204922Sweongyo		break;
2422204922Sweongyo	case SIBA_SPROMVAR_GPIO2:
2423204922Sweongyo		siba->siba_sprom.gpio2 = value;
2424204922Sweongyo		break;
2425204922Sweongyo	case SIBA_SPROMVAR_GPIO3:
2426204922Sweongyo		siba->siba_sprom.gpio3 = value;
2427204922Sweongyo		break;
2428204922Sweongyo	case SIBA_SPROMVAR_MAXPWR_AL:
2429204922Sweongyo		siba->siba_sprom.maxpwr_al = value;
2430204922Sweongyo		break;
2431204922Sweongyo	case SIBA_SPROMVAR_MAXPWR_A:
2432204922Sweongyo		siba->siba_sprom.maxpwr_a = value;
2433204922Sweongyo		break;
2434204922Sweongyo	case SIBA_SPROMVAR_MAXPWR_AH:
2435204922Sweongyo		siba->siba_sprom.maxpwr_ah = value;
2436204922Sweongyo		break;
2437204922Sweongyo	case SIBA_SPROMVAR_MAXPWR_BG:
2438204922Sweongyo		siba->siba_sprom.maxpwr_bg = value;
2439204922Sweongyo		break;
2440204922Sweongyo	case SIBA_SPROMVAR_RXPO2G:
2441204922Sweongyo		siba->siba_sprom.rxpo2g = value;
2442204922Sweongyo		break;
2443204922Sweongyo	case SIBA_SPROMVAR_RXPO5G:
2444204922Sweongyo		siba->siba_sprom.rxpo5g = value;
2445204922Sweongyo		break;
2446204922Sweongyo	case SIBA_SPROMVAR_TSSI_A:
2447204922Sweongyo		siba->siba_sprom.tssi_a = value;
2448204922Sweongyo		break;
2449204922Sweongyo	case SIBA_SPROMVAR_TSSI_BG:
2450204922Sweongyo		siba->siba_sprom.tssi_bg = value;
2451204922Sweongyo		break;
2452204922Sweongyo	case SIBA_SPROMVAR_TRI2G:
2453204922Sweongyo		siba->siba_sprom.tri2g = value;
2454204922Sweongyo		break;
2455204922Sweongyo	case SIBA_SPROMVAR_TRI5GL:
2456204922Sweongyo		siba->siba_sprom.tri5gl = value;
2457204922Sweongyo		break;
2458204922Sweongyo	case SIBA_SPROMVAR_TRI5G:
2459204922Sweongyo		siba->siba_sprom.tri5g = value;
2460204922Sweongyo		break;
2461204922Sweongyo	case SIBA_SPROMVAR_TRI5GH:
2462204922Sweongyo		siba->siba_sprom.tri5gh = value;
2463204922Sweongyo		break;
2464204922Sweongyo	case SIBA_SPROMVAR_RSSISAV2G:
2465204922Sweongyo		siba->siba_sprom.rssisav2g = value;
2466204922Sweongyo		break;
2467204922Sweongyo	case SIBA_SPROMVAR_RSSISMC2G:
2468204922Sweongyo		siba->siba_sprom.rssismc2g = value;
2469204922Sweongyo		break;
2470204922Sweongyo	case SIBA_SPROMVAR_RSSISMF2G:
2471204922Sweongyo		siba->siba_sprom.rssismf2g = value;
2472204922Sweongyo		break;
2473204922Sweongyo	case SIBA_SPROMVAR_BXA2G:
2474204922Sweongyo		siba->siba_sprom.bxa2g = value;
2475204922Sweongyo		break;
2476204922Sweongyo	case SIBA_SPROMVAR_RSSISAV5G:
2477204922Sweongyo		siba->siba_sprom.rssisav5g = value;
2478204922Sweongyo		break;
2479204922Sweongyo	case SIBA_SPROMVAR_RSSISMC5G:
2480204922Sweongyo		siba->siba_sprom.rssismc5g = value;
2481204922Sweongyo		break;
2482204922Sweongyo	case SIBA_SPROMVAR_RSSISMF5G:
2483204922Sweongyo		siba->siba_sprom.rssismf5g = value;
2484204922Sweongyo		break;
2485204922Sweongyo	case SIBA_SPROMVAR_BXA5G:
2486204922Sweongyo		siba->siba_sprom.bxa5g = value;
2487204922Sweongyo		break;
2488204922Sweongyo	case SIBA_SPROMVAR_CCK2GPO:
2489204922Sweongyo		siba->siba_sprom.cck2gpo = value;
2490204922Sweongyo		break;
2491204922Sweongyo	case SIBA_SPROMVAR_OFDM2GPO:
2492204922Sweongyo		siba->siba_sprom.ofdm2gpo = value;
2493204922Sweongyo		break;
2494204922Sweongyo	case SIBA_SPROMVAR_OFDM5GLPO:
2495204922Sweongyo		siba->siba_sprom.ofdm5glpo = value;
2496204922Sweongyo		break;
2497204922Sweongyo	case SIBA_SPROMVAR_OFDM5GPO:
2498204922Sweongyo		siba->siba_sprom.ofdm5gpo = value;
2499204922Sweongyo		break;
2500204922Sweongyo	case SIBA_SPROMVAR_OFDM5GHPO:
2501204922Sweongyo		siba->siba_sprom.ofdm5ghpo = value;
2502204922Sweongyo		break;
2503204922Sweongyo	case SIBA_SPROMVAR_BF_LO:
2504204922Sweongyo		siba->siba_sprom.bf_lo = value;
2505204922Sweongyo		break;
2506204922Sweongyo	case SIBA_SPROMVAR_BF_HI:
2507204922Sweongyo		siba->siba_sprom.bf_hi = value;
2508204922Sweongyo		break;
2509204922Sweongyo	case SIBA_SPROMVAR_BF2_LO:
2510204922Sweongyo		siba->siba_sprom.bf2_lo = value;
2511204922Sweongyo		break;
2512204922Sweongyo	case SIBA_SPROMVAR_BF2_HI:
2513204922Sweongyo		siba->siba_sprom.bf2_hi = value;
2514204922Sweongyo		break;
2515204922Sweongyo	default:
2516204922Sweongyo		return (ENOENT);
2517204922Sweongyo	}
2518204922Sweongyo	return (0);
2519204922Sweongyo}
2520204922Sweongyo
2521204922Sweongyo#define	SIBA_GPIOCTL			0x06c
2522204922Sweongyo
2523204922Sweongyouint32_t
2524204922Sweongyosiba_gpio_get(device_t dev)
2525204922Sweongyo{
2526204922Sweongyo	struct siba_dev_softc *sd = device_get_ivars(dev);
2527204922Sweongyo	struct siba_softc *siba = sd->sd_bus;
2528204922Sweongyo	struct siba_dev_softc *gpiodev, *pcidev = NULL;
2529204922Sweongyo
2530204922Sweongyo	pcidev = siba->siba_pci.spc_dev;
2531204922Sweongyo	gpiodev = siba->siba_cc.scc_dev ? siba->siba_cc.scc_dev : pcidev;
2532204922Sweongyo	if (!gpiodev)
2533204922Sweongyo		return (-1);
2534204922Sweongyo	return (siba_read_4_sub(gpiodev, SIBA_GPIOCTL));
2535204922Sweongyo}
2536204922Sweongyo
2537204922Sweongyovoid
2538204922Sweongyosiba_gpio_set(device_t dev, uint32_t value)
2539204922Sweongyo{
2540204922Sweongyo	struct siba_dev_softc *sd = device_get_ivars(dev);
2541204922Sweongyo	struct siba_softc *siba = sd->sd_bus;
2542204922Sweongyo	struct siba_dev_softc *gpiodev, *pcidev = NULL;
2543204922Sweongyo
2544204922Sweongyo	pcidev = siba->siba_pci.spc_dev;
2545204922Sweongyo	gpiodev = siba->siba_cc.scc_dev ? siba->siba_cc.scc_dev : pcidev;
2546204922Sweongyo	if (!gpiodev)
2547204922Sweongyo		return;
2548204922Sweongyo	siba_write_4_sub(gpiodev, SIBA_GPIOCTL, value);
2549204922Sweongyo}
2550204922Sweongyo
2551204922Sweongyovoid
2552204922Sweongyosiba_fix_imcfglobug(device_t dev)
2553204922Sweongyo{
2554204922Sweongyo	struct siba_dev_softc *sd = device_get_ivars(dev);
2555204922Sweongyo	struct siba_softc *siba = sd->sd_bus;
2556204922Sweongyo	uint32_t tmp;
2557204922Sweongyo
2558204922Sweongyo	if (siba->siba_pci.spc_dev == NULL)
2559204922Sweongyo		return;
2560204922Sweongyo	if (siba->siba_pci.spc_dev->sd_id.sd_device != SIBA_DEVID_PCI ||
2561204922Sweongyo	    siba->siba_pci.spc_dev->sd_id.sd_rev > 5)
2562204922Sweongyo		return;
2563204922Sweongyo
2564204922Sweongyo	tmp = siba_read_4_sub(sd, SIBA_IMCFGLO) &
2565204922Sweongyo	    ~(SIBA_IMCFGLO_REQTO | SIBA_IMCFGLO_SERTO);
2566204922Sweongyo	switch (siba->siba_type) {
2567204922Sweongyo	case SIBA_TYPE_PCI:
2568204922Sweongyo	case SIBA_TYPE_PCMCIA:
2569204922Sweongyo		tmp |= 0x32;
2570204922Sweongyo		break;
2571204922Sweongyo	case SIBA_TYPE_SSB:
2572204922Sweongyo		tmp |= 0x53;
2573204922Sweongyo		break;
2574204922Sweongyo	}
2575204922Sweongyo	siba_write_4_sub(sd, SIBA_IMCFGLO, tmp);
2576204922Sweongyo}
2577