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.
12 #include "hw_device.h"
14 #include "vbus_factory.h"
18 #include <l4/vbus/vbus_gpio-ops.h>
26 class Gpio : public Device, public Dev_feature
29 int dispatch(l4_umword_t, l4_uint32_t func, L4::Ipc::Iostream &ios);
31 explicit Gpio(Hw::Device *d)
32 : _hwd(dynamic_cast<Hw::Gpio_chip*>(d)), _mask(0)
36 for (unsigned i = 0; i < Max_pins; ++i)
40 int add_filter(cxx::String const &tag, cxx::String const &)
47 int add_filter(cxx::String const &tag, unsigned long long val)
51 _mask |= (1UL << val);
55 int add_filter(cxx::String const &tag, unsigned long long s, unsigned long long e)
59 _mask |= ~(~0UL << (e - s + 1)) << s;
63 char const *hid() const { return "GPIO"; }
64 void set_host(Device *d) { _host = d; }
65 Device *host() const { return _host; }
67 bool match_hw_feature(const Hw::Dev_feature*) const
71 enum { Max_pins = 32 };
78 int setup(L4::Ipc::Iostream &ios);
79 int config_pad(L4::Ipc::Iostream &ios);
80 int config_get(L4::Ipc::Iostream &ios);
81 int get(L4::Ipc::Iostream &ios);
82 int set(L4::Ipc::Iostream &ios);
83 int multi_setup(L4::Ipc::Iostream &ios);
84 int multi_config_pad(L4::Ipc::Iostream &ios);
85 int multi_get(L4::Ipc::Iostream &ios);
86 int multi_set(L4::Ipc::Iostream &ios);
87 int to_irq(L4::Ipc::Iostream &ios);
89 void check(unsigned pin)
94 if (!((1UL << pin) & _mask))
98 void check_mask(unsigned mask)
108 Gpio::setup(L4::Ipc::Iostream &ios)
112 ios >> pin >> mode >> value;
114 _hwd->setup(pin, mode, value);
119 Gpio::config_pad(L4::Ipc::Iostream &ios)
121 unsigned pin, func, value;
122 ios >> pin >> func >> value;
124 _hwd->config_pad(pin, _mask, func, value);
129 Gpio::config_get(L4::Ipc::Iostream &ios)
131 unsigned pin, func, value;
134 _hwd->config_get(pin, _mask, func, &value);
140 Gpio::get(L4::Ipc::Iostream &ios)
145 return _hwd->get(pin);
149 Gpio::set(L4::Ipc::Iostream &ios)
155 _hwd->set(pin, value);
160 Gpio::multi_setup(L4::Ipc::Iostream &ios)
162 unsigned mask, mode, outvalue;
163 ios >> mask >> mode >> outvalue;
165 _hwd->multi_setup(mask, mode, outvalue);
170 Gpio::multi_config_pad(L4::Ipc::Iostream &ios)
172 unsigned mask, func, value;
173 ios >> mask >> func >> value;
175 _hwd->multi_config_pad(mask, func, value);
180 Gpio::multi_get(L4::Ipc::Iostream &ios)
182 unsigned data = _hwd->multi_get();
183 ios << (unsigned)(data & _mask);
188 Gpio::multi_set(L4::Ipc::Iostream &ios)
193 _hwd->multi_set(mask, data);
198 Gpio::to_irq(L4::Ipc::Iostream &ios)
204 if (_irqs[pin] == -1)
206 // we have to allocate the IRQ...
207 // if it fails we mark the IRQ as unavailable (-L4_ENODEV)
208 _irqs[pin] = -L4_ENODEV;
210 int irqnum = _hwd->get_irq(pin);
214 if (System_bus *sb = dynamic_cast<System_bus *>(get_root()))
216 int virq = sb->sw_icu()->alloc_irq(Sw_icu::S_allow_set_mode,
217 Sw_icu::real_irq(irqnum));
230 Gpio::dispatch(l4_umword_t, l4_uint32_t func, L4::Ipc::Iostream &ios)
236 case L4VBUS_GPIO_OP_SETUP: return setup(ios);
237 case L4VBUS_GPIO_OP_CONFIG_PAD: return config_pad(ios);
238 case L4VBUS_GPIO_OP_CONFIG_GET: return config_get(ios);
239 case L4VBUS_GPIO_OP_GET: return get(ios);
240 case L4VBUS_GPIO_OP_SET: return set(ios);
241 case L4VBUS_GPIO_OP_MULTI_SETUP: return multi_setup(ios);
242 case L4VBUS_GPIO_OP_MULTI_CONFIG_PAD: return multi_config_pad(ios);
243 case L4VBUS_GPIO_OP_MULTI_GET: return multi_get(ios);
244 case L4VBUS_GPIO_OP_MULTI_SET: return multi_set(ios);
245 case L4VBUS_GPIO_OP_TO_IRQ: return to_irq(ios);
246 default: return -L4_ENOSYS;
256 static Dev_factory_t<Gpio, Hw::Gpio_device> __gpio_factory;