source: mainline/kernel/arch/sparc64/src/drivers/pci.c@ 0d107f31

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 0d107f31 was e2cc9a0, checked in by Jakub Jermar <jakub@…>, 19 years ago

Add support for interrupt mapping in the Sabre PCI controller.
Add support for PCI and EBUS interrupt mapping via the OpenFirmware device tree.
Unfortunatelly, the code is not capable enough to earn single ns16550 interrupt.
I suspect something needs to be enabled in the EBUS registers.

  • Property mode set to 100644
File size: 4.1 KB
Line 
1/*
2 * Copyright (C) 2006 Jakub Jermar
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup sparc64
30 * @{
31 */
32/**
33 * @file
34 * @brief PCI driver.
35 */
36
37#include <arch/drivers/pci.h>
38#include <genarch/ofw/ofw_tree.h>
39#include <arch/trap/interrupt.h>
40#include <arch/mm/page.h>
41#include <mm/slab.h>
42#include <arch/types.h>
43#include <typedefs.h>
44#include <debug.h>
45#include <print.h>
46#include <func.h>
47#include <arch/asm.h>
48
49#define PCI_SABRE_REGS_REG 0
50
51#define PCI_SABRE_IMAP_BASE 0x200
52#define PCI_SABRE_ICLR_BASE 0x300
53
54static pci_t *pci_sabre_init(ofw_tree_node_t *node);
55static void pci_sabre_enable_interrupt(pci_t *pci, int inr);
56static void pci_sabre_clear_interrupt(pci_t *pci, int inr);
57
58/** PCI operations for Sabre model. */
59static pci_operations_t pci_sabre_ops = {
60 .enable_interrupt = pci_sabre_enable_interrupt,
61 .clear_interrupt = pci_sabre_clear_interrupt
62};
63
64/** Initialize PCI controller (model Sabre). */
65pci_t *pci_sabre_init(ofw_tree_node_t *node)
66{
67 pci_t *pci;
68 ofw_tree_property_t *prop;
69
70 /*
71 * Get registers.
72 */
73 prop = ofw_tree_getprop(node, "reg");
74 if (!prop || !prop->value)
75 return NULL;
76
77 ofw_upa_reg_t *reg = prop->value;
78 count_t regs = prop->size / sizeof(ofw_upa_reg_t);
79
80 if (regs < PCI_SABRE_REGS_REG + 1)
81 return NULL;
82
83 uintptr_t paddr;
84 if (!ofw_upa_apply_ranges(node->parent, &reg[PCI_SABRE_REGS_REG], &paddr))
85 return NULL;
86
87 pci = (pci_t *) malloc(sizeof(pci_t), FRAME_ATOMIC);
88 if (!pci)
89 return NULL;
90
91 pci->model = PCI_SABRE;
92 pci->op = &pci_sabre_ops;
93 pci->reg = (uint64_t *) hw_map(paddr, reg[PCI_SABRE_REGS_REG].size);
94
95 return pci;
96}
97
98void pci_sabre_enable_interrupt(pci_t *pci, int inr)
99{
100 pci->reg[PCI_SABRE_ICLR_BASE + (inr & INO_MASK)] = 0;
101 pci->reg[PCI_SABRE_IMAP_BASE + (inr & INO_MASK)] |= IMAP_V_MASK;
102}
103
104void pci_sabre_clear_interrupt(pci_t *pci, int inr)
105{
106 pci->reg[PCI_SABRE_ICLR_BASE + (inr & INO_MASK)] = 0;
107}
108
109/** Initialize PCI controller. */
110pci_t *pci_init(ofw_tree_node_t *node)
111{
112 ofw_tree_property_t *prop;
113
114 /*
115 * First, verify this is a PCI node.
116 */
117 ASSERT(strcmp(ofw_tree_node_name(node), "pci") == 0);
118
119 /*
120 * Determine PCI controller model.
121 */
122 prop = ofw_tree_getprop(node, "model");
123 if (!prop || !prop->value)
124 return NULL;
125
126 if (strcmp(prop->value, "SUNW,sabre") == 0) {
127 /*
128 * PCI controller Sabre.
129 * This model is found on UltraSPARC IIi based machines.
130 */
131 return pci_sabre_init(node);
132 } else {
133 /*
134 * Unsupported model.
135 */
136 printf("Unsupported PCI controller model (%s).\n", prop->value);
137 }
138
139 return NULL;
140}
141
142void pci_enable_interrupt(pci_t *pci, int inr)
143{
144 ASSERT(pci->model);
145 ASSERT(pci->op && pci->op->enable_interrupt);
146 pci->op->enable_interrupt(pci, inr);
147}
148
149void pci_clear_interrupt(pci_t *pci, int inr)
150{
151 ASSERT(pci->model);
152 ASSERT(pci->op && pci->op->clear_interrupt);
153 pci->op->clear_interrupt(pci, inr);
154}
155
156/** @}
157 */
Note: See TracBrowser for help on using the repository browser.