xref: /openbmc/linux/drivers/ssb/embedded.c (revision 7dd65feb)
1 /*
2  * Sonics Silicon Backplane
3  * Embedded systems support code
4  *
5  * Copyright 2005-2008, Broadcom Corporation
6  * Copyright 2006-2008, Michael Buesch <mb@bu3sch.de>
7  *
8  * Licensed under the GNU/GPL. See COPYING for details.
9  */
10 
11 #include <linux/ssb/ssb.h>
12 #include <linux/ssb/ssb_embedded.h>
13 #include <linux/ssb/ssb_driver_pci.h>
14 #include <linux/ssb/ssb_driver_gige.h>
15 #include <linux/pci.h>
16 
17 #include "ssb_private.h"
18 
19 
20 int ssb_watchdog_timer_set(struct ssb_bus *bus, u32 ticks)
21 {
22 	if (ssb_chipco_available(&bus->chipco)) {
23 		ssb_chipco_watchdog_timer_set(&bus->chipco, ticks);
24 		return 0;
25 	}
26 	if (ssb_extif_available(&bus->extif)) {
27 		ssb_extif_watchdog_timer_set(&bus->extif, ticks);
28 		return 0;
29 	}
30 	return -ENODEV;
31 }
32 EXPORT_SYMBOL(ssb_watchdog_timer_set);
33 
34 u32 ssb_gpio_in(struct ssb_bus *bus, u32 mask)
35 {
36 	unsigned long flags;
37 	u32 res = 0;
38 
39 	spin_lock_irqsave(&bus->gpio_lock, flags);
40 	if (ssb_chipco_available(&bus->chipco))
41 		res = ssb_chipco_gpio_in(&bus->chipco, mask);
42 	else if (ssb_extif_available(&bus->extif))
43 		res = ssb_extif_gpio_in(&bus->extif, mask);
44 	else
45 		SSB_WARN_ON(1);
46 	spin_unlock_irqrestore(&bus->gpio_lock, flags);
47 
48 	return res;
49 }
50 EXPORT_SYMBOL(ssb_gpio_in);
51 
52 u32 ssb_gpio_out(struct ssb_bus *bus, u32 mask, u32 value)
53 {
54 	unsigned long flags;
55 	u32 res = 0;
56 
57 	spin_lock_irqsave(&bus->gpio_lock, flags);
58 	if (ssb_chipco_available(&bus->chipco))
59 		res = ssb_chipco_gpio_out(&bus->chipco, mask, value);
60 	else if (ssb_extif_available(&bus->extif))
61 		res = ssb_extif_gpio_out(&bus->extif, mask, value);
62 	else
63 		SSB_WARN_ON(1);
64 	spin_unlock_irqrestore(&bus->gpio_lock, flags);
65 
66 	return res;
67 }
68 EXPORT_SYMBOL(ssb_gpio_out);
69 
70 u32 ssb_gpio_outen(struct ssb_bus *bus, u32 mask, u32 value)
71 {
72 	unsigned long flags;
73 	u32 res = 0;
74 
75 	spin_lock_irqsave(&bus->gpio_lock, flags);
76 	if (ssb_chipco_available(&bus->chipco))
77 		res = ssb_chipco_gpio_outen(&bus->chipco, mask, value);
78 	else if (ssb_extif_available(&bus->extif))
79 		res = ssb_extif_gpio_outen(&bus->extif, mask, value);
80 	else
81 		SSB_WARN_ON(1);
82 	spin_unlock_irqrestore(&bus->gpio_lock, flags);
83 
84 	return res;
85 }
86 EXPORT_SYMBOL(ssb_gpio_outen);
87 
88 u32 ssb_gpio_control(struct ssb_bus *bus, u32 mask, u32 value)
89 {
90 	unsigned long flags;
91 	u32 res = 0;
92 
93 	spin_lock_irqsave(&bus->gpio_lock, flags);
94 	if (ssb_chipco_available(&bus->chipco))
95 		res = ssb_chipco_gpio_control(&bus->chipco, mask, value);
96 	spin_unlock_irqrestore(&bus->gpio_lock, flags);
97 
98 	return res;
99 }
100 EXPORT_SYMBOL(ssb_gpio_control);
101 
102 u32 ssb_gpio_intmask(struct ssb_bus *bus, u32 mask, u32 value)
103 {
104 	unsigned long flags;
105 	u32 res = 0;
106 
107 	spin_lock_irqsave(&bus->gpio_lock, flags);
108 	if (ssb_chipco_available(&bus->chipco))
109 		res = ssb_chipco_gpio_intmask(&bus->chipco, mask, value);
110 	else if (ssb_extif_available(&bus->extif))
111 		res = ssb_extif_gpio_intmask(&bus->extif, mask, value);
112 	else
113 		SSB_WARN_ON(1);
114 	spin_unlock_irqrestore(&bus->gpio_lock, flags);
115 
116 	return res;
117 }
118 EXPORT_SYMBOL(ssb_gpio_intmask);
119 
120 u32 ssb_gpio_polarity(struct ssb_bus *bus, u32 mask, u32 value)
121 {
122 	unsigned long flags;
123 	u32 res = 0;
124 
125 	spin_lock_irqsave(&bus->gpio_lock, flags);
126 	if (ssb_chipco_available(&bus->chipco))
127 		res = ssb_chipco_gpio_polarity(&bus->chipco, mask, value);
128 	else if (ssb_extif_available(&bus->extif))
129 		res = ssb_extif_gpio_polarity(&bus->extif, mask, value);
130 	else
131 		SSB_WARN_ON(1);
132 	spin_unlock_irqrestore(&bus->gpio_lock, flags);
133 
134 	return res;
135 }
136 EXPORT_SYMBOL(ssb_gpio_polarity);
137 
138 #ifdef CONFIG_SSB_DRIVER_GIGE
139 static int gige_pci_init_callback(struct ssb_bus *bus, unsigned long data)
140 {
141 	struct pci_dev *pdev = (struct pci_dev *)data;
142 	struct ssb_device *dev;
143 	unsigned int i;
144 	int res;
145 
146 	for (i = 0; i < bus->nr_devices; i++) {
147 		dev = &(bus->devices[i]);
148 		if (dev->id.coreid != SSB_DEV_ETHERNET_GBIT)
149 			continue;
150 		if (!dev->dev ||
151 		    !dev->dev->driver ||
152 		    !device_is_registered(dev->dev))
153 			continue;
154 		res = ssb_gige_pcibios_plat_dev_init(dev, pdev);
155 		if (res >= 0)
156 			return res;
157 	}
158 
159 	return -ENODEV;
160 }
161 #endif /* CONFIG_SSB_DRIVER_GIGE */
162 
163 int ssb_pcibios_plat_dev_init(struct pci_dev *dev)
164 {
165 	int err;
166 
167 	err = ssb_pcicore_plat_dev_init(dev);
168 	if (!err)
169 		return 0;
170 #ifdef CONFIG_SSB_DRIVER_GIGE
171 	err = ssb_for_each_bus_call((unsigned long)dev, gige_pci_init_callback);
172 	if (err >= 0)
173 		return err;
174 #endif
175 	/* This is not a PCI device on any SSB device. */
176 
177 	return -ENODEV;
178 }
179 
180 #ifdef CONFIG_SSB_DRIVER_GIGE
181 static int gige_map_irq_callback(struct ssb_bus *bus, unsigned long data)
182 {
183 	const struct pci_dev *pdev = (const struct pci_dev *)data;
184 	struct ssb_device *dev;
185 	unsigned int i;
186 	int res;
187 
188 	for (i = 0; i < bus->nr_devices; i++) {
189 		dev = &(bus->devices[i]);
190 		if (dev->id.coreid != SSB_DEV_ETHERNET_GBIT)
191 			continue;
192 		if (!dev->dev ||
193 		    !dev->dev->driver ||
194 		    !device_is_registered(dev->dev))
195 			continue;
196 		res = ssb_gige_map_irq(dev, pdev);
197 		if (res >= 0)
198 			return res;
199 	}
200 
201 	return -ENODEV;
202 }
203 #endif /* CONFIG_SSB_DRIVER_GIGE */
204 
205 int ssb_pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
206 {
207 	int res;
208 
209 	/* Check if this PCI device is a device on a SSB bus or device
210 	 * and return the IRQ number for it. */
211 
212 	res = ssb_pcicore_pcibios_map_irq(dev, slot, pin);
213 	if (res >= 0)
214 		return res;
215 #ifdef CONFIG_SSB_DRIVER_GIGE
216 	res = ssb_for_each_bus_call((unsigned long)dev, gige_map_irq_callback);
217 	if (res >= 0)
218 		return res;
219 #endif
220 	/* This is not a PCI device on any SSB device. */
221 
222 	return -ENODEV;
223 }
224