sb_scd.c revision 203509
11573Srgrimes/*-
21573Srgrimes * Copyright (c) 2009 Neelkanth Natu
31573Srgrimes * All rights reserved.
41573Srgrimes *
51573Srgrimes * Redistribution and use in source and binary forms, with or without
61573Srgrimes * modification, are permitted provided that the following conditions
71573Srgrimes * are met:
81573Srgrimes * 1. Redistributions of source code must retain the above copyright
91573Srgrimes *    notice, this list of conditions and the following disclaimer.
101573Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111573Srgrimes *    notice, this list of conditions and the following disclaimer in the
121573Srgrimes *    documentation and/or other materials provided with the distribution.
131573Srgrimes *
141573Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
151573Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
161573Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
171573Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
181573Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
191573Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
201573Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
211573Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
221573Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
231573Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
241573Srgrimes * SUCH DAMAGE.
251573Srgrimes */
261573Srgrimes
271573Srgrimes#include <sys/cdefs.h>
281573Srgrimes__FBSDID("$FreeBSD: head/sys/mips/sibyte/sb_scd.c 203509 2010-02-05 03:20:47Z neel $");
291573Srgrimes
301573Srgrimes#include <sys/param.h>
311573Srgrimes#include <sys/kernel.h>
321573Srgrimes#include <sys/systm.h>
331573Srgrimes#include <sys/module.h>
341573Srgrimes#include <sys/bus.h>
351573Srgrimes
361573Srgrimes#include <machine/resource.h>
371573Srgrimes#include <machine/intr_machdep.h>
381573Srgrimes
391573Srgrimes#include "sb_scd.h"
401573Srgrimes
411573Srgrimesextern void	sb_store64(uint32_t addr, uint64_t val);
421573Srgrimesextern uint64_t	sb_load64(uint32_t addr);
431573Srgrimes
441573Srgrimes/*
4535125Sjb * System Control and Debug (SCD) unit on the Sibyte ZBbus.
4635125Sjb */
4735125Sjb
4835125Sjb/*
4935125Sjb * Extract the value starting at bit position 'b' for 'n' bits from 'x'.
5035125Sjb */
5135125Sjb#define	GET_VAL_64(x, b, n)	(((x) >> (b)) & ((1ULL << (n)) - 1))
5235125Sjb
5335125Sjb#define	SYSREV_ADDR		MIPS_PHYS_TO_KSEG1(0x10020000)
541573Srgrimes#define	SYSREV_NUM_PROCESSORS(x) GET_VAL_64((x), 24, 4)
551573Srgrimes
561573Srgrimes#define	SYSCFG_ADDR		MIPS_PHYS_TO_KSEG1(0x10020008)
571573Srgrimes#define SYSCFG_PLLDIV(x)	GET_VAL_64((x), 7, 5)
581573Srgrimes
591573Srgrimes#define	INTSRC_MASK_ADDR(cpu)	\
601573Srgrimes	(MIPS_PHYS_TO_KSEG1(0x10020028) | ((cpu) << 13))
611573Srgrimes
621573Srgrimes#define	INTSRC_MAP_ADDR(cpu, intsrc)	\
631573Srgrimes	(MIPS_PHYS_TO_KSEG1(0x10020200) | ((cpu) << 13)) + (intsrc * 8)
641573Srgrimes
651573Srgrimes#define	MAILBOX_SET_ADDR(cpu)	\
661573Srgrimes	(MIPS_PHYS_TO_KSEG1(0x100200C8) | ((cpu) << 13))
671573Srgrimes
681573Srgrimes#define	MAILBOX_CLEAR_ADDR(cpu)	\
691573Srgrimes	(MIPS_PHYS_TO_KSEG1(0x100200D0) | ((cpu) << 13))
70
71static uint64_t
72sb_read_syscfg(void)
73{
74
75	return (sb_load64(SYSCFG_ADDR));
76}
77
78static void
79sb_write_syscfg(uint64_t val)
80{
81
82	sb_store64(SYSCFG_ADDR, val);
83}
84
85uint64_t
86sb_cpu_speed(void)
87{
88	int plldiv;
89	const uint64_t MHZ = 1000000;
90
91	plldiv = SYSCFG_PLLDIV(sb_read_syscfg());
92	if (plldiv == 0) {
93		printf("PLL_DIV is 0 - assuming 6 (300MHz).\n");
94		plldiv = 6;
95	}
96
97	return (plldiv * 50 * MHZ);
98}
99
100void
101sb_system_reset(void)
102{
103	uint64_t syscfg;
104
105	const uint64_t SYSTEM_RESET = 1ULL << 60;
106	const uint64_t EXT_RESET = 1ULL << 59;
107	const uint64_t SOFT_RESET = 1ULL << 58;
108
109	syscfg = sb_read_syscfg();
110	syscfg &= ~SOFT_RESET;
111	syscfg |= SYSTEM_RESET | EXT_RESET;
112	sb_write_syscfg(syscfg);
113}
114
115void
116sb_disable_intsrc(int cpu, int src)
117{
118	uint32_t regaddr;
119	uint64_t val;
120
121	regaddr = INTSRC_MASK_ADDR(cpu);
122
123	val = sb_load64(regaddr);
124	val |= 1ULL << src;
125	sb_store64(regaddr, val);
126}
127
128void
129sb_enable_intsrc(int cpu, int src)
130{
131	uint32_t regaddr;
132	uint64_t val;
133
134	regaddr = INTSRC_MASK_ADDR(cpu);
135
136	val = sb_load64(regaddr);
137	val &= ~(1ULL << src);
138	sb_store64(regaddr, val);
139}
140
141void
142sb_write_intsrc_mask(int cpu, uint64_t val)
143{
144	uint32_t regaddr;
145
146	regaddr = INTSRC_MASK_ADDR(cpu);
147	sb_store64(regaddr, val);
148}
149
150uint64_t
151sb_read_intsrc_mask(int cpu)
152{
153	uint32_t regaddr;
154	uint64_t val;
155
156	regaddr = INTSRC_MASK_ADDR(cpu);
157	val = sb_load64(regaddr);
158
159	return (val);
160}
161
162void
163sb_write_intmap(int cpu, int intsrc, int intrnum)
164{
165	uint32_t regaddr;
166
167	regaddr = INTSRC_MAP_ADDR(cpu, intsrc);
168	sb_store64(regaddr, intrnum);
169}
170
171int
172sb_read_intmap(int cpu, int intsrc)
173{
174	uint32_t regaddr;
175
176	regaddr = INTSRC_MAP_ADDR(cpu, intsrc);
177	return (sb_load64(regaddr) & 0x7);
178}
179
180int
181sb_route_intsrc(int intsrc)
182{
183	int intrnum;
184
185	KASSERT(intsrc >= 0 && intsrc < NUM_INTSRC,
186		("Invalid interrupt source number (%d)", intsrc));
187
188	/*
189	 * Interrupt 5 is used by sources internal to the CPU (e.g. timer).
190	 * Use a deterministic mapping for the remaining sources.
191	 */
192	intrnum = intsrc % 5;
193
194	return (intrnum);
195}
196
197#define	SCD_PHYSADDR	0x10000000
198#define	SCD_SIZE	0x00060000
199
200static int
201scd_probe(device_t dev)
202{
203
204	device_set_desc(dev, "Broadcom/Sibyte System Control and Debug");
205	return (0);
206}
207
208static int
209scd_attach(device_t dev)
210{
211	int rid;
212	struct resource *res;
213
214	if (bootverbose)
215		device_printf(dev, "attached.\n");
216
217	rid = 0;
218	res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, SCD_PHYSADDR,
219				 SCD_PHYSADDR + SCD_SIZE - 1, SCD_SIZE, 0);
220	if (res == NULL)
221		panic("Cannot allocate resource for system control and debug.");
222
223	return (0);
224}
225
226static device_method_t scd_methods[] ={
227	/* Device interface */
228	DEVMETHOD(device_probe,		scd_probe),
229	DEVMETHOD(device_attach,	scd_attach),
230	DEVMETHOD(device_detach,	bus_generic_detach),
231	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
232	DEVMETHOD(device_suspend,	bus_generic_suspend),
233	DEVMETHOD(device_resume,	bus_generic_resume),
234
235	{ 0, 0 }
236};
237
238static driver_t scd_driver = {
239	"scd",
240	scd_methods
241};
242
243static devclass_t scd_devclass;
244
245DRIVER_MODULE(scd, zbbus, scd_driver, scd_devclass, 0, 0);
246