2 * (c) 2011 Alexander Warg <warg@os.inf.tu-dresden.de>
3 * economic rights: Technische Universität Dresden (Germany)
5 * This file is part of TUD:OS and distributed under the terms of the
6 * GNU General Public License 2.
7 * Please see the COPYING-GPL-2 file for details.
13 #include "hw_device.h"
15 #include "vbus_factory.h"
21 #include <l4/vbus/vbus_gpio-ops.h>
29 class Gpio : public Device, public Dev_feature
32 int dispatch(l4_umword_t, l4_uint32_t func, L4::Ipc::Iostream &ios);
34 explicit Gpio(Hw::Device *d)
35 : _hwd(dynamic_cast<Hw::Gpio_chip*>(d)), _mask(0)
39 for (unsigned i = 0; i < Max_pins; ++i)
43 int add_filter(cxx::String const &tag, cxx::String const &)
50 int add_filter(cxx::String const &tag, unsigned long long val)
54 _mask |= (1UL << val);
58 int add_filter(cxx::String const &tag, unsigned long long s, unsigned long long e)
62 _mask |= ~(~0UL << (e - s + 1)) << s;
66 void modify_mask(l4_uint32_t enable, l4_uint32_t disable)
68 _mask = (_mask & ~disable) | enable;
71 char const *hid() const { return "GPIO"; }
72 void set_host(Device *d) { _host = d; }
73 Device *host() const { return _host; }
75 bool match_hw_feature(const Hw::Dev_feature*) const
79 enum { Max_pins = 32 };
86 int setup(L4::Ipc::Iostream &ios);
87 int config_pad(L4::Ipc::Iostream &ios);
88 int config_get(L4::Ipc::Iostream &ios);
89 int get(L4::Ipc::Iostream &ios);
90 int set(L4::Ipc::Iostream &ios);
91 int multi_setup(L4::Ipc::Iostream &ios);
92 int multi_config_pad(L4::Ipc::Iostream &ios);
93 int multi_get(L4::Ipc::Iostream &ios);
94 int multi_set(L4::Ipc::Iostream &ios);
95 int to_irq(L4::Ipc::Iostream &ios);
97 void check(unsigned pin)
102 if (!((1UL << pin) & _mask))
106 void check_mask(unsigned mask)
116 Gpio::setup(L4::Ipc::Iostream &ios)
120 ios >> pin >> mode >> value;
122 _hwd->setup(pin, mode, value);
127 Gpio::config_pad(L4::Ipc::Iostream &ios)
129 unsigned pin, func, value;
130 ios >> pin >> func >> value;
132 _hwd->config_pad(pin, _mask, func, value);
137 Gpio::config_get(L4::Ipc::Iostream &ios)
139 unsigned pin, func, value;
142 _hwd->config_get(pin, _mask, func, &value);
148 Gpio::get(L4::Ipc::Iostream &ios)
153 return _hwd->get(pin);
157 Gpio::set(L4::Ipc::Iostream &ios)
163 _hwd->set(pin, value);
168 Gpio::multi_setup(L4::Ipc::Iostream &ios)
170 unsigned mask, mode, outvalue;
171 ios >> mask >> mode >> outvalue;
173 _hwd->multi_setup(mask, mode, outvalue);
178 Gpio::multi_config_pad(L4::Ipc::Iostream &ios)
180 unsigned mask, func, value;
181 ios >> mask >> func >> value;
183 _hwd->multi_config_pad(mask, func, value);
188 Gpio::multi_get(L4::Ipc::Iostream &ios)
190 unsigned data = _hwd->multi_get();
191 ios << (unsigned)(data & _mask);
196 Gpio::multi_set(L4::Ipc::Iostream &ios)
201 _hwd->multi_set(mask, data);
206 Gpio::to_irq(L4::Ipc::Iostream &ios)
212 if (_irqs[pin] == -1)
214 // we have to allocate the IRQ...
215 // if it fails we mark the IRQ as unavailable (-L4_ENODEV)
216 _irqs[pin] = -L4_ENODEV;
218 int irqnum = _hwd->get_irq(pin);
222 if (System_bus *sb = dynamic_cast<System_bus *>(get_root()))
224 int virq = sb->sw_icu()->alloc_irq(Sw_icu::S_allow_set_mode,
225 Sw_icu::real_irq(irqnum));
238 Gpio::dispatch(l4_umword_t, l4_uint32_t func, L4::Ipc::Iostream &ios)
244 case L4VBUS_GPIO_OP_SETUP: return setup(ios);
245 case L4VBUS_GPIO_OP_CONFIG_PAD: return config_pad(ios);
246 case L4VBUS_GPIO_OP_CONFIG_GET: return config_get(ios);
247 case L4VBUS_GPIO_OP_GET: return get(ios);
248 case L4VBUS_GPIO_OP_SET: return set(ios);
249 case L4VBUS_GPIO_OP_MULTI_SETUP: return multi_setup(ios);
250 case L4VBUS_GPIO_OP_MULTI_CONFIG_PAD: return multi_config_pad(ios);
251 case L4VBUS_GPIO_OP_MULTI_GET: return multi_get(ios);
252 case L4VBUS_GPIO_OP_MULTI_SET: return multi_set(ios);
253 case L4VBUS_GPIO_OP_TO_IRQ: return to_irq(ios);
254 default: return -L4_ENOSYS;
264 static Dev_factory_t<Gpio, Hw::Gpio_device> __gpio_factory;
266 class Gpio_resource : public Resource
269 explicit Gpio_resource(::Gpio_resource *hr)
270 : Resource(hr->flags(), hr->start(), hr->end()), _hwr(hr) {}
272 ::Gpio_resource *_hwr;
275 class Root_gpio_rs : public Resource_space
278 explicit Root_gpio_rs(System_bus *bus) : _bus(bus)
281 bool request(Resource *parent, ::Device *pdev, Resource *child, ::Device *)
283 Vi::System_bus *vsb = dynamic_cast<Vi::System_bus *>(pdev);
287 ::Gpio_resource *r = dynamic_cast< ::Gpio_resource*>(child);
291 Hw::Gpio_device *gpio = r->provider();
293 Vi::Device *vbus = vsb;
295 for (Hw::Device *bus = system_bus(); bus != gpio; )
297 Hw::Device *d = gpio;
298 while (d->parent() != bus)
302 //printf("BUS: %p:%s\n", bus, bus->name());
304 Vi::Device *vd = vbus->find_by_name(bus->name());
308 vd = new Vi::Device();
312 vd->name(bus->name());
315 // printf("VDEV=%p:%s\n", vd, vd ? vd->name() : "");
319 Gpio *vgpio = dynamic_cast<Gpio *>(vbus);
323 d_printf(DBG_ERR, "ERROR: device: %s is not a GPIO device\n", vbus->name());
327 d_printf(DBG_DEBUG2, "Add GPIO resource to vbus: ");
328 if (dlevel(DBG_DEBUG2))
333 unsigned e = r->end() + 1;
334 unsigned s = r->start();
337 l4_uint32_t mask = ((1UL << (e - s)) - 1) << s;
338 vgpio->modify_mask(mask, 0);
344 bool alloc(Resource *parent, ::Device *, Resource *child, ::Device *, bool)
346 d_printf(DBG_DEBUG2, "Allocate virtual GPIO resource ...\n");
347 if (dlevel(DBG_DEBUG2))
357 Root_gpio_rs(Root_gpio_rs const &);
358 void operator = (Root_gpio_rs const &);
361 std::vector<Gpio *> _gpios;
364 static System_bus::Root_resource_factory_t<Resource::Gpio_res, Root_gpio_rs> __rf;