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