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