1/*	$NetBSD: ixp425_pci_space.c,v 1.9 2011/07/01 20:32:51 dyoung Exp $ */
2
3/*
4 * Copyright (c) 2003
5 *	Ichiro FUKUHARA <ichiro@ichiro.org>.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY ICHIRO FUKUHARA ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL ICHIRO FUKUHARA OR THE VOICES IN HIS HEAD BE LIABLE FOR
21 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#include <sys/cdefs.h>
31__KERNEL_RCSID(0, "$NetBSD: ixp425_pci_space.c,v 1.9 2011/07/01 20:32:51 dyoung Exp $");
32
33/*
34 * bus_space PCI functions for ixp425
35 */
36
37#include <sys/param.h>
38#include <sys/systm.h>
39#include <sys/queue.h>
40
41#include <uvm/uvm.h>
42
43#include <sys/bus.h>
44
45#include <arm/xscale/ixp425reg.h>
46#include <arm/xscale/ixp425var.h>
47
48/*
49 * Macros to read/write registers
50*/
51#define CSR_READ_4(x)		*(volatile uint32_t *) \
52	(IXP425_PCI_CSR_BASE + (x))
53#define CSR_WRITE_4(x, v)	*(volatile uint32_t *) \
54	(IXP425_PCI_CSR_BASE + (x)) = (v)
55
56/* Proto types for all the bus_space structure functions */
57bs_protos(ixp425_pci);
58bs_protos(ixp425_pci_io);
59bs_protos(ixp425_pci_mem);
60bs_protos(bs_notimpl);
61
62/* special I/O functions */
63#if 1	/* XXX */
64u_int8_t  _pci_io_bs_r_1(void *, bus_space_handle_t, bus_size_t);
65u_int16_t _pci_io_bs_r_2(void *, bus_space_handle_t, bus_size_t);
66u_int32_t _pci_io_bs_r_4(void *, bus_space_handle_t, bus_size_t);
67
68void _pci_io_bs_w_1(void *, bus_space_handle_t, bus_size_t, u_int8_t);
69void _pci_io_bs_w_2(void *, bus_space_handle_t, bus_size_t, u_int16_t);
70void _pci_io_bs_w_4(void *, bus_space_handle_t, bus_size_t, u_int32_t);
71#endif
72
73struct bus_space ixp425_pci_bs_tag_template = {
74	/* cookie */
75	(void *) 0,
76
77	/* mapping/unmapping */
78	NULL,
79	NULL,
80	ixp425_pci_bs_subregion,
81
82	/* allocation/deallocation */
83	NULL,
84	NULL,
85
86	/* get kernel virtual address */
87	NULL,
88
89	/* mmap bus space for userland */
90	ixp425_pci_bs_mmap,
91
92	/* barrier */
93	ixp425_pci_bs_barrier,
94
95	/* read (single) */
96	bs_notimpl_bs_r_1,
97	bs_notimpl_bs_r_2,
98	bs_notimpl_bs_r_4,
99	bs_notimpl_bs_r_8,
100
101	/* read multiple */
102	bs_notimpl_bs_rm_1,
103	bs_notimpl_bs_rm_2,
104	bs_notimpl_bs_rm_4,
105	bs_notimpl_bs_rm_8,
106
107	/* read region */
108	bs_notimpl_bs_rr_1,
109	bs_notimpl_bs_rr_2,
110	bs_notimpl_bs_rr_4,
111	bs_notimpl_bs_rr_8,
112
113	/* write (single) */
114	bs_notimpl_bs_w_1,
115	bs_notimpl_bs_w_2,
116	bs_notimpl_bs_w_4,
117	bs_notimpl_bs_w_8,
118
119	/* write multiple */
120	bs_notimpl_bs_wm_1,
121	bs_notimpl_bs_wm_2,
122	bs_notimpl_bs_wm_4,
123	bs_notimpl_bs_wm_8,
124
125	/* write region */
126	bs_notimpl_bs_wr_1,
127	bs_notimpl_bs_wr_2,
128	bs_notimpl_bs_wr_4,
129	bs_notimpl_bs_wr_8,
130
131	/* set multiple */
132	bs_notimpl_bs_sm_1,
133	bs_notimpl_bs_sm_2,
134	bs_notimpl_bs_sm_4,
135	bs_notimpl_bs_sm_8,
136
137	/* set region */
138	bs_notimpl_bs_sr_1,
139	bs_notimpl_bs_sr_2,
140	bs_notimpl_bs_sr_4,
141	bs_notimpl_bs_sr_8,
142
143	/* copy */
144	bs_notimpl_bs_c_1,
145	bs_notimpl_bs_c_2,
146	bs_notimpl_bs_c_4,
147	bs_notimpl_bs_c_8,
148};
149
150void
151ixp425_io_bs_init(bus_space_tag_t bs, void *cookie)
152{
153	*bs = ixp425_pci_bs_tag_template;
154	bs->bs_cookie = cookie;
155
156	bs->bs_map = ixp425_pci_io_bs_map;
157	bs->bs_unmap = ixp425_pci_io_bs_unmap;
158	bs->bs_alloc = ixp425_pci_io_bs_alloc;
159	bs->bs_free = ixp425_pci_io_bs_free;
160	bs->bs_vaddr = ixp425_pci_io_bs_vaddr;
161
162	/*
163	 * IXP425 processor does not have PCI I/O windows
164	 */
165	/* read (single) */
166	bs->bs_r_1 = _pci_io_bs_r_1;
167	bs->bs_r_2 = _pci_io_bs_r_2;
168	bs->bs_r_4 = _pci_io_bs_r_4;
169
170	/* write (single) */
171	bs->bs_w_1 = _pci_io_bs_w_1;
172	bs->bs_w_2 = _pci_io_bs_w_2;
173	bs->bs_w_4 = _pci_io_bs_w_4;
174}
175
176void
177ixp425_mem_bs_init(bus_space_tag_t bs, void *cookie)
178{
179	*bs = ixp425_pci_bs_tag_template;
180	bs->bs_cookie = cookie;
181
182	bs->bs_map = ixp425_pci_mem_bs_map;
183	bs->bs_unmap = ixp425_pci_mem_bs_unmap;
184	bs->bs_alloc = ixp425_pci_mem_bs_alloc;
185	bs->bs_free = ixp425_pci_mem_bs_free;
186	bs->bs_vaddr = ixp425_pci_mem_bs_vaddr;
187
188	/* read (single) */
189	bs->bs_r_1 = ixp425_pci_mem_bs_r_1;
190	bs->bs_r_2 = ixp425_pci_mem_bs_r_2;
191	bs->bs_r_4 = ixp425_pci_mem_bs_r_4;
192
193	/* write (single) */
194	bs->bs_w_1 = ixp425_pci_mem_bs_w_1;
195	bs->bs_w_2 = ixp425_pci_mem_bs_w_2;
196	bs->bs_w_4 = ixp425_pci_mem_bs_w_4;
197}
198
199/* common routine */
200int
201ixp425_pci_bs_subregion(void *t, bus_space_handle_t bsh, bus_size_t offset,
202	bus_size_t size, bus_space_handle_t *nbshp)
203{
204	*nbshp = bsh + offset;
205	return (0);
206}
207
208void
209ixp425_pci_bs_barrier(void *t, bus_space_handle_t bsh, bus_size_t offset,
210    bus_size_t len, int flags)
211{
212	/* NULL */
213}
214
215paddr_t
216ixp425_pci_bs_mmap(void *t, bus_addr_t addr, off_t off, int prot, int flags)
217{
218	/* Not supported. */
219	return (-1);
220}
221
222/* io bs */
223int
224ixp425_pci_io_bs_map(void *t, bus_addr_t bpa, bus_size_t size,
225	int cacheable, bus_space_handle_t *bshp)
226{
227	*bshp = bpa;
228	return (0);
229}
230
231void
232ixp425_pci_io_bs_unmap(void *t, bus_space_handle_t bsh, bus_size_t size)
233{
234	/* Nothing to do. */
235}
236
237int
238ixp425_pci_io_bs_alloc(void *t, bus_addr_t rstart, bus_addr_t rend,
239	bus_size_t size, bus_size_t alignment, bus_size_t boundary, int cacheable,
240	bus_addr_t *bpap, bus_space_handle_t *bshp)
241{
242	panic("ixp425_pci_io_bs_alloc(): not implemented\n");
243}
244
245void
246ixp425_pci_io_bs_free(void *t, bus_space_handle_t bsh, bus_size_t size)
247{
248	panic("ixp425_pci_io_bs_free(): not implemented\n");
249}
250
251void *
252ixp425_pci_io_bs_vaddr(void *t, bus_space_handle_t bsh)
253{
254	/* Not supported. */
255	return (NULL);
256}
257
258/* special I/O functions */
259#if 1	/* _pci_io_bs_{rw}_{124} */
260u_int8_t
261_pci_io_bs_r_1(void *v, bus_space_handle_t ioh, bus_size_t off)
262{
263	u_int32_t data, n, be;
264	int s;
265
266	n = (ioh + off) % 4;
267	be = (0xf & ~(1U << n)) << NP_CBE_SHIFT;
268
269	PCI_CONF_LOCK(s);
270	CSR_WRITE_4(PCI_NP_AD, (ioh + off) & ~3);
271	CSR_WRITE_4(PCI_NP_CBE, be | COMMAND_NP_IO_READ);
272	data = CSR_READ_4(PCI_NP_RDATA);
273	if (CSR_READ_4(PCI_ISR) & ISR_PFE)
274		CSR_WRITE_4(PCI_ISR, ISR_PFE);
275	PCI_CONF_UNLOCK(s);
276
277	return data >> (8 * n);
278}
279
280u_int16_t
281_pci_io_bs_r_2(void *v, bus_space_handle_t ioh, bus_size_t off)
282{
283	u_int32_t data, n, be;
284	int s;
285
286	n = (ioh + off) % 4;
287	be = (0xf & ~((1U << n) | (1U << (n + 1)))) << NP_CBE_SHIFT;
288
289	PCI_CONF_LOCK(s);
290	CSR_WRITE_4(PCI_NP_AD, (ioh + off) & ~3);
291	CSR_WRITE_4(PCI_NP_CBE, be | COMMAND_NP_IO_READ);
292	data = CSR_READ_4(PCI_NP_RDATA);
293	if (CSR_READ_4(PCI_ISR) & ISR_PFE)
294		CSR_WRITE_4(PCI_ISR, ISR_PFE);
295	PCI_CONF_UNLOCK(s);
296
297	return data >> (8 * n);
298}
299
300u_int32_t
301_pci_io_bs_r_4(void *v, bus_space_handle_t ioh, bus_size_t off)
302{
303	u_int32_t data;
304	int s;
305
306	PCI_CONF_LOCK(s);
307	CSR_WRITE_4(PCI_NP_AD, (ioh + off) & ~3);
308	CSR_WRITE_4(PCI_NP_CBE, COMMAND_NP_IO_READ);
309	data = CSR_READ_4(PCI_NP_RDATA);
310	if (CSR_READ_4(PCI_ISR) & ISR_PFE)
311		CSR_WRITE_4(PCI_ISR, ISR_PFE);
312	PCI_CONF_UNLOCK(s);
313
314	return data;
315}
316
317void
318_pci_io_bs_w_1(void *v, bus_space_handle_t ioh, bus_size_t off,
319	u_int8_t val)
320{
321	u_int32_t data, n, be;
322	int s;
323
324	n = (ioh + off) % 4;
325	be = (0xf & ~(1U << n)) << NP_CBE_SHIFT;
326	data = val << (8 * n);
327
328	PCI_CONF_LOCK(s);
329	CSR_WRITE_4(PCI_NP_AD, (ioh + off) & ~3);
330	CSR_WRITE_4(PCI_NP_CBE, be | COMMAND_NP_IO_WRITE);
331	CSR_WRITE_4(PCI_NP_WDATA, data);
332	if (CSR_READ_4(PCI_ISR) & ISR_PFE)
333		CSR_WRITE_4(PCI_ISR, ISR_PFE);
334	PCI_CONF_UNLOCK(s);
335}
336
337void
338_pci_io_bs_w_2(void *v, bus_space_handle_t ioh, bus_size_t off,
339	u_int16_t val)
340{
341	u_int32_t data, n, be;
342	int s;
343
344	n = (ioh + off) % 4;
345	be = (0xf & ~((1U << n) | (1U << (n + 1)))) << NP_CBE_SHIFT;
346	data = val << (8 * n);
347
348	PCI_CONF_LOCK(s);
349	CSR_WRITE_4(PCI_NP_AD, (ioh + off) & ~3);
350	CSR_WRITE_4(PCI_NP_CBE, be | COMMAND_NP_IO_WRITE);
351	CSR_WRITE_4(PCI_NP_WDATA, data);
352	if (CSR_READ_4(PCI_ISR) & ISR_PFE)
353		CSR_WRITE_4(PCI_ISR, ISR_PFE);
354	PCI_CONF_UNLOCK(s);
355}
356
357void
358_pci_io_bs_w_4(void *v, bus_space_handle_t ioh, bus_size_t off,
359	u_int32_t val)
360{
361	int s;
362
363	PCI_CONF_LOCK(s);
364	CSR_WRITE_4(PCI_NP_AD, (ioh + off) & ~3);
365	CSR_WRITE_4(PCI_NP_CBE, COMMAND_NP_IO_WRITE);
366	CSR_WRITE_4(PCI_NP_WDATA, val);
367	if (CSR_READ_4(PCI_ISR) & ISR_PFE)
368		CSR_WRITE_4(PCI_ISR, ISR_PFE);
369	PCI_CONF_UNLOCK(s);
370}
371#endif	/* _pci_io_bs_{rw}_{124} */
372
373/* mem bs */
374int
375ixp425_pci_mem_bs_map(void *t, bus_addr_t bpa, bus_size_t size,
376	      int cacheable, bus_space_handle_t *bshp)
377{
378	const struct pmap_devmap	*pd;
379
380	paddr_t		startpa;
381	paddr_t		endpa;
382	paddr_t		pa;
383	paddr_t		offset;
384	vaddr_t		va;
385	pt_entry_t	*pte;
386
387	if ((pd = pmap_devmap_find_pa(bpa, size)) != NULL) {
388		/* Device was statically mapped. */
389		*bshp = pd->pd_va + (bpa - pd->pd_pa);
390		return 0;
391	}
392
393	endpa = round_page(bpa + size);
394	offset = bpa & PAGE_MASK;
395	startpa = trunc_page(bpa);
396
397	/* Get some VM.  */
398	va = uvm_km_alloc(kernel_map, endpa - startpa, 0,
399	    UVM_KMF_VAONLY | UVM_KMF_NOWAIT);
400	if (va == 0)
401		return ENOMEM;
402
403	/* Store the bus space handle */
404	*bshp = va + offset;
405
406	/* Now map the pages */
407	for (pa = startpa; pa < endpa; pa += PAGE_SIZE, va += PAGE_SIZE) {
408		pmap_kenter_pa(va, pa, VM_PROT_READ | VM_PROT_WRITE, 0);
409		pte = vtopte(va);
410		*pte &= ~L2_S_CACHE_MASK;
411		PTE_SYNC(pte);
412	}
413	pmap_update(pmap_kernel());
414
415	return(0);
416}
417
418void
419ixp425_pci_mem_bs_unmap(void *t, bus_space_handle_t bsh, bus_size_t size)
420{
421	vaddr_t	va;
422	vaddr_t	endva;
423
424	if (pmap_devmap_find_va(bsh, size) != NULL) {
425		/* Device was statically mapped; nothing to do. */
426		return;
427	}
428
429	endva = round_page(bsh + size);
430	va = trunc_page(bsh);
431
432	pmap_kremove(va, endva - va);
433	uvm_km_free(kernel_map, va, endva - va, UVM_KMF_VAONLY);
434}
435
436int
437ixp425_pci_mem_bs_alloc(void *t, bus_addr_t rstart, bus_addr_t rend,
438	bus_size_t size, bus_size_t alignment, bus_size_t boundary, int cacheable,
439	bus_addr_t *bpap, bus_space_handle_t *bshp)
440{
441	panic("ixp425_mem_bs_alloc(): not implemented\n");
442}
443
444void
445ixp425_pci_mem_bs_free(void *t, bus_space_handle_t bsh, bus_size_t size)
446{
447	panic("ixp425_mem_bs_free(): not implemented\n");
448}
449
450void *
451ixp425_pci_mem_bs_vaddr(void *t, bus_space_handle_t bsh)
452{
453	return ((void *)bsh);
454}
455/* End of ixp425_pci_space.c */
456