From 6418f3408283ee17bf8aefcd7346e78b8cc18940 Mon Sep 17 00:00:00 2001 From: Mark Date: Thu, 24 Mar 2016 17:03:20 +0100 Subject: [PATCH] zynq: add gpio, i2c and vdma drivers --- include/gpio_session/zynq/capability.h | 22 ++ include/gpio_session/zynq/client.h | 32 +++ include/gpio_session/zynq/connection.h | 30 ++ include/gpio_session/zynq/gpio_session.h | 54 ++++ include/i2c_session/capability.h | 25 ++ include/i2c_session/client.h | 43 +++ include/i2c_session/connection.h | 34 +++ include/i2c_session/i2c_session.h | 69 +++++ include/vdma_session/capability.h | 22 ++ include/vdma_session/client.h | 42 +++ include/vdma_session/connection.h | 30 ++ include/vdma_session/vdma_session.h | 54 ++++ src/drivers/gpio/spec/zynq/driver.h | 76 ++++++ src/drivers/gpio/spec/zynq/gpio.h | 98 +++++++ src/drivers/gpio/spec/zynq/main.cc | 132 +++++++++ src/drivers/gpio/spec/zynq/target.mk | 12 + src/drivers/i2c/spec/zynq/driver.h | 100 +++++++ src/drivers/i2c/spec/zynq/i2c.h | 333 +++++++++++++++++++++++ src/drivers/i2c/spec/zynq/main.cc | 102 +++++++ src/drivers/i2c/spec/zynq/target.mk | 12 + src/drivers/vdma/spec/zynq/driver.h | 105 +++++++ src/drivers/vdma/spec/zynq/main.cc | 147 ++++++++++ src/drivers/vdma/spec/zynq/target.mk | 12 + src/drivers/vdma/spec/zynq/vdma.h | 148 ++++++++++ 24 files changed, 1734 insertions(+) create mode 100644 include/gpio_session/zynq/capability.h create mode 100644 include/gpio_session/zynq/client.h create mode 100644 include/gpio_session/zynq/connection.h create mode 100644 include/gpio_session/zynq/gpio_session.h create mode 100644 include/i2c_session/capability.h create mode 100644 include/i2c_session/client.h create mode 100644 include/i2c_session/connection.h create mode 100644 include/i2c_session/i2c_session.h create mode 100644 include/vdma_session/capability.h create mode 100644 include/vdma_session/client.h create mode 100644 include/vdma_session/connection.h create mode 100644 include/vdma_session/vdma_session.h create mode 100644 src/drivers/gpio/spec/zynq/driver.h create mode 100644 src/drivers/gpio/spec/zynq/gpio.h create mode 100644 src/drivers/gpio/spec/zynq/main.cc create mode 100644 src/drivers/gpio/spec/zynq/target.mk create mode 100644 src/drivers/i2c/spec/zynq/driver.h create mode 100644 src/drivers/i2c/spec/zynq/i2c.h create mode 100644 src/drivers/i2c/spec/zynq/main.cc create mode 100644 src/drivers/i2c/spec/zynq/target.mk create mode 100644 src/drivers/vdma/spec/zynq/driver.h create mode 100644 src/drivers/vdma/spec/zynq/main.cc create mode 100644 src/drivers/vdma/spec/zynq/target.mk create mode 100644 src/drivers/vdma/spec/zynq/vdma.h diff --git a/include/gpio_session/zynq/capability.h b/include/gpio_session/zynq/capability.h new file mode 100644 index 0000000..7a84932 --- /dev/null +++ b/include/gpio_session/zynq/capability.h @@ -0,0 +1,22 @@ +/* + * \brief Zynq Gpio session capability type + * \author Mark Albers + * \date 2015-04-02 + */ + +/* + * Copyright (C) 2015 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _INCLUDE__GPIO_SESSION__CAPABILITY_H_ +#define _INCLUDE__GPIO_SESSION__CAPABILITY_H_ + +#include +#include + +namespace Gpio { typedef Genode::Capability Session_capability; } + +#endif /* _INCLUDE__GPIO_SESSION__CAPABILITY_H_ */ diff --git a/include/gpio_session/zynq/client.h b/include/gpio_session/zynq/client.h new file mode 100644 index 0000000..65c7951 --- /dev/null +++ b/include/gpio_session/zynq/client.h @@ -0,0 +1,32 @@ +/* + * \brief Client-side Zynq Gpio session interface + * \author Mark Albers + * \date 2015-04-02 + */ + +/* + * Copyright (C) 2015 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _INCLUDE__GPIO_SESSION_H__CLIENT_H_ +#define _INCLUDE__GPIO_SESSION_H__CLIENT_H_ + +#include +#include + +namespace Gpio { + + struct Session_client : Genode::Rpc_client + { + explicit Session_client(Session_capability session) + : Genode::Rpc_client(session) { } + + bool write(Genode::uint32_t data, bool isChannel2 = false) { return call(data, isChannel2); } + Genode::uint32_t read(bool isChannel2 = false) { return call(isChannel2); } + }; +} + +#endif /* _INCLUDE__GPIO_SESSION_H__CLIENT_H_ */ diff --git a/include/gpio_session/zynq/connection.h b/include/gpio_session/zynq/connection.h new file mode 100644 index 0000000..2252df7 --- /dev/null +++ b/include/gpio_session/zynq/connection.h @@ -0,0 +1,30 @@ +/* + * \brief Connection to Zynq Gpio session + * \author Mark Albers + * \date 2015-04-02 + */ + +/* + * Copyright (C) 2015 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _INCLUDE__GPIO_SESSION__CONNECTION_H_ +#define _INCLUDE__GPIO_SESSION__CONNECTION_H_ + +#include +#include + +namespace Gpio { + + struct Connection : Genode::Connection, Session_client + { + Connection(unsigned gpio_number) + : Genode::Connection(session("ram_quota=8K, gpio=%zd", gpio_number)), + Session_client(cap()) { } + }; +} + +#endif /* _INCLUDE__GPIO_SESSION__CONNECTION_H_ */ diff --git a/include/gpio_session/zynq/gpio_session.h b/include/gpio_session/zynq/gpio_session.h new file mode 100644 index 0000000..9b0de9f --- /dev/null +++ b/include/gpio_session/zynq/gpio_session.h @@ -0,0 +1,54 @@ +/* + * \brief Zynq Gpio session interface + * \author Mark Albers + * \date 2015-04-02 + */ + +/* + * Copyright (C) 2015 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _INCLUDE__GPIO_SESSION__GPIO_SESSION_H_ +#define _INCLUDE__GPIO_SESSION__GPIO_SESSION_H_ + +#include +#include + +namespace Gpio { + + struct Session : Genode::Session + { + static const char *service_name() { return "Gpio"; } + + virtual ~Session() { } + + /** + * Write + * + * \param data + */ + virtual bool write(Genode::uint32_t data, bool isChannel2) = 0; + + /** + * Read + * + * \return data + */ + virtual Genode::uint32_t read(bool isChannel2) = 0; + + + /******************* + ** RPC interface ** + *******************/ + + GENODE_RPC(Rpc_write, bool, write, Genode::uint32_t, bool); + GENODE_RPC(Rpc_read, Genode::uint32_t, read, bool); + + GENODE_RPC_INTERFACE(Rpc_write, Rpc_read); + }; +} + +#endif /* _INCLUDE__GPIO_SESSION__GPIO_SESSION_H_ */ diff --git a/include/i2c_session/capability.h b/include/i2c_session/capability.h new file mode 100644 index 0000000..564ed49 --- /dev/null +++ b/include/i2c_session/capability.h @@ -0,0 +1,25 @@ +/* + * \brief I2C bus driver session capability type + * \author Mark Albers + * \date 2015-04-13 + * \author Alexander Tarasikov + * \date 2012-09-18 + */ + +/* + * Copyright (C) 2012 Ksys Labs LLC + * Copyright (C) 2012-2015 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _INCLUDE__I2C_SESSION__CAPABILITY_H_ +#define _INCLUDE__I2C_SESSION__CAPABILITY_H_ + +#include +#include + +namespace I2C { typedef Genode::Capability Session_capability; } + +#endif /* _INCLUDE__I2C_SESSION__CAPABILITY_H_ */ diff --git a/include/i2c_session/client.h b/include/i2c_session/client.h new file mode 100644 index 0000000..d60c2ce --- /dev/null +++ b/include/i2c_session/client.h @@ -0,0 +1,43 @@ +/* + * \brief Client-side i2c interface + * \author Mark Albers + * \date 2015-04-13 + * \author Alexander Tarasikov + * \date 2012-09-18 + */ + +/* + * Copyright (C) 2012 Ksys Labs LLC + * Copyright (C) 2012-2015 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _INCLUDE__I2C_SESSION__CLIENT_H_ +#define _INCLUDE__I2C_SESSION__CLIENT_H_ + +#include +#include + +namespace I2C { + + struct Session_client : Genode::Rpc_client + { + explicit Session_client(Session_capability session) + : Genode::Rpc_client(session) { } + + bool read_byte_16bit_reg(Genode::uint8_t adr, Genode::uint16_t reg, Genode::uint8_t *data) + { + return call(adr, reg, data); + } + + bool write_16bit_reg(Genode::uint8_t adr, Genode::uint16_t reg, + Genode::uint8_t data) + { + return call(adr, reg, data); + } + }; +} + +#endif /* _INCLUDE__I2C_SESSION__CLIENT_H_ */ diff --git a/include/i2c_session/connection.h b/include/i2c_session/connection.h new file mode 100644 index 0000000..07ad211 --- /dev/null +++ b/include/i2c_session/connection.h @@ -0,0 +1,34 @@ +/* + * \brief Connection to i2c service + * \author Mark Albers + * \author Alexander Tarasikov + * \date 2012-09-18 + */ + +/* + * Copyright (C) 2012 Ksys Labs LLC + * Copyright (C) 2012 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _INCLUDE__I2C_SESSION__CONNECTION_H_ +#define _INCLUDE__I2C_SESSION__CONNECTION_H_ + +#include +#include + +namespace I2C { + + class Connection : public Genode::Connection, + public Session_client + { + public: + Connection(unsigned int bus_num) : + Genode::Connection(session("ram_quota=4K, bus=%zd", bus_num)), + Session_client(cap()) { } + }; +} + +#endif /* _INCLUDE__I2C_SESSION__CONNECTION_H_ */ diff --git a/include/i2c_session/i2c_session.h b/include/i2c_session/i2c_session.h new file mode 100644 index 0000000..34441a1 --- /dev/null +++ b/include/i2c_session/i2c_session.h @@ -0,0 +1,69 @@ +/* + * \brief I2C session interface + * \author Mark Albers + * \date 2015-04-13 + * \author Alexander Tarasikov + * \date 2012-09-18 + */ + +/* + * Copyright (C) 2012 Ksys Labs LLC + * Copyright (C) 2012-2015 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _INCLUDE__I2C_SESSION__I2C_SESSION_H_ +#define _INCLUDE__I2C_SESSION__I2C_SESSION_H_ + +#include +#include + +namespace I2C { + + struct Session : Genode::Session + { + static const char *service_name() { return "I2C"; } + + virtual ~Session() { } + + /** + * Read a single byte from a 16 bit register of the device + * + * \param adr the address of the device on the bus + * \param reg the register to read + * \param data the read value + * + */ + virtual bool read_byte_16bit_reg(Genode::uint8_t adr, Genode::uint16_t reg, Genode::uint8_t *data) = 0; + + /** + * Write a single data byte to a 16 bit register + * + * \param adr the address of the device on the bus + * \param reg the register to write + * \param data the value to write + * + */ + virtual bool write_16bit_reg(Genode::uint8_t adr, Genode::uint16_t reg, + Genode::uint8_t data) = 0; + + + /********************* + ** RPC declaration ** + *********************/ + + GENODE_RPC(Rpc_read_byte_16bit_reg, bool, read_byte_16bit_reg, + Genode::uint8_t, Genode::uint16_t, Genode::uint8_t*); + GENODE_RPC(Rpc_write_16bit_reg, bool, write_16bit_reg, + Genode::uint8_t, Genode::uint16_t, Genode::uint8_t); + + GENODE_RPC_INTERFACE( + Rpc_read_byte_16bit_reg, + Rpc_write_16bit_reg + ); + }; +} + +#endif /* _INCLUDE__I2C_SESSION__I2C_SESSION_H_ */ diff --git a/include/vdma_session/capability.h b/include/vdma_session/capability.h new file mode 100644 index 0000000..17610b8 --- /dev/null +++ b/include/vdma_session/capability.h @@ -0,0 +1,22 @@ +/* + * \brief Zynq VDMA session capability type + * \author Mark Albers + * \date 2015-04-13 + */ + +/* + * Copyright (C) 2015 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _INCLUDE__VDMA_SESSION__CAPABILITY_H_ +#define _INCLUDE__VDMA_SESSION__CAPABILITY_H_ + +#include +#include + +namespace Vdma { typedef Genode::Capability Session_capability; } + +#endif /* _INCLUDE__VDMA_SESSION__CAPABILITY_H_ */ diff --git a/include/vdma_session/client.h b/include/vdma_session/client.h new file mode 100644 index 0000000..d94cdfd --- /dev/null +++ b/include/vdma_session/client.h @@ -0,0 +1,42 @@ +/* + * \brief Client-side Zynq VDMA session interface + * \author Mark Albers + * \date 2015-04-13 + */ + +/* + * Copyright (C) 2015 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _INCLUDE__VDMA_SESSION_H__CLIENT_H_ +#define _INCLUDE__VDMA_SESSION_H__CLIENT_H_ + +#include +#include + +#define S2MM false +#define MM2S true + +namespace Vdma { + + struct Session_client : Genode::Rpc_client + { + explicit Session_client(Session_capability session) + : Genode::Rpc_client(session) { } + + bool setConfig(Genode::uint32_t data, bool isMM2S) { return call(data, isMM2S); } + + bool setStride(Genode::uint16_t data, bool isMM2S) { return call(data, isMM2S); } + + bool setWidth(Genode::uint16_t data, bool isMM2S) { return call(data, isMM2S); } + + bool setHeight(Genode::uint16_t data, bool isMM2S) { return call(data, isMM2S); } + + bool setAddr(Genode::uint32_t data, bool isMM2S) { return call(data, isMM2S); } + }; +} + +#endif /* _INCLUDE__VDMA_SESSION_H__CLIENT_H_ */ diff --git a/include/vdma_session/connection.h b/include/vdma_session/connection.h new file mode 100644 index 0000000..e37df5c --- /dev/null +++ b/include/vdma_session/connection.h @@ -0,0 +1,30 @@ +/* + * \brief Connection to Zynq VDMA session + * \author Mark Albers + * \date 2015-04-13 + */ + +/* + * Copyright (C) 2015 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _INCLUDE__VDMA_SESSION__CONNECTION_H_ +#define _INCLUDE__VDMA_SESSION__CONNECTION_H_ + +#include +#include + +namespace Vdma { + + struct Connection : Genode::Connection, Session_client + { + Connection(unsigned vdma_number) + : Genode::Connection(session("ram_quota=8K, vdma=%zd", vdma_number)), + Session_client(cap()) { } + }; +} + +#endif /* _INCLUDE__VDMA_SESSION__CONNECTION_H_ */ diff --git a/include/vdma_session/vdma_session.h b/include/vdma_session/vdma_session.h new file mode 100644 index 0000000..280b4c0 --- /dev/null +++ b/include/vdma_session/vdma_session.h @@ -0,0 +1,54 @@ +/* + * \brief Zynq VDMA session interface + * \author Mark Albers + * \date 2015-04-13 + */ + +/* + * Copyright (C) 2015 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _INCLUDE__VDMA_SESSION__VDMA_SESSION_H_ +#define _INCLUDE__VDMA_SESSION__VDMA_SESSION_H_ + +#include +#include + +namespace Vdma { + + struct Session : Genode::Session + { + static const char *service_name() { return "Vdma"; } + + virtual ~Session() { } + + virtual bool setConfig(Genode::uint32_t data, bool isMM2S) = 0; + + virtual bool setStride(Genode::uint16_t data, bool isMM2S) = 0; + + virtual bool setWidth(Genode::uint16_t data, bool isMM2S) = 0; + + virtual bool setHeight(Genode::uint16_t data, bool isMM2S) = 0; + + virtual bool setAddr(Genode::uint32_t data, bool isMM2S) = 0; + + + /******************* + ** RPC interface ** + *******************/ + + GENODE_RPC(Rpc_setConfig, bool, setConfig, Genode::uint32_t, bool); + GENODE_RPC(Rpc_setStride, bool, setStride, Genode::uint16_t, bool); + GENODE_RPC(Rpc_setWidth, bool, setWidth, Genode::uint16_t, bool); + GENODE_RPC(Rpc_setHeight, bool, setHeight, Genode::uint16_t, bool); + GENODE_RPC(Rpc_setAddr, bool, setAddr, Genode::uint32_t, bool); + + GENODE_RPC_INTERFACE(Rpc_setConfig, Rpc_setStride, Rpc_setWidth, + Rpc_setHeight, Rpc_setAddr); + }; +} + +#endif /* _INCLUDE__VDMA_SESSION__VDMA_SESSION_H_ */ diff --git a/src/drivers/gpio/spec/zynq/driver.h b/src/drivers/gpio/spec/zynq/driver.h new file mode 100644 index 0000000..b0872a5 --- /dev/null +++ b/src/drivers/gpio/spec/zynq/driver.h @@ -0,0 +1,76 @@ +/* + * \brief Gpio Driver for Zynq + * \author Mark Albers + * \date 2015-03-12 + */ + +/* + * Copyright (C) 2015 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _DRIVER_H_ +#define _DRIVER_H_ + +#include +#include +#include +#include +#include +#include +#include "gpio.h" + +namespace Gpio { + using namespace Genode; + class Driver; +} + +class Gpio::Driver +{ + private: + + std::vector _gpio_bank; + + Driver(std::vector addr) + { + for (unsigned i = 0; i < addr.size(); i++) + { + _gpio_bank.push_back(new Zynq_Gpio(addr[i], Genode::Board_base::GPIO_MMIO_SIZE)); + } + } + + ~Driver() + { + for (std::vector::iterator it = _gpio_bank.begin() ; it != _gpio_bank.end(); ++it) + { + delete (*it); + } + _gpio_bank.clear(); + } + + public: + + static Driver& factory(std::vector addr); + + Genode::uint8_t read(unsigned gpio, bool isChannel2) + { + Zynq_Gpio *gpio_reg = _gpio_bank[gpio]; + return gpio_reg->gpio_read(isChannel2); + } + + bool write(unsigned gpio, Genode::uint8_t data, bool isChannel2) + { + Zynq_Gpio *gpio_reg = _gpio_bank[gpio]; + return gpio_reg->gpio_write(data, isChannel2); + } +}; + +Gpio::Driver& Gpio::Driver::factory(std::vector addr) +{ + static Gpio::Driver driver(addr); + return driver; +} + +#endif /* _DRIVER_H_ */ diff --git a/src/drivers/gpio/spec/zynq/gpio.h b/src/drivers/gpio/spec/zynq/gpio.h new file mode 100644 index 0000000..704dcb0 --- /dev/null +++ b/src/drivers/gpio/spec/zynq/gpio.h @@ -0,0 +1,98 @@ +/* + * \brief Gpio Driver for Zynq + * \author Mark Albers + * \date 2015-04-02 + */ + +/* + * Copyright (C) 2015 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _GPIO_H_ +#define _GPIO_H_ + +#include +#include + +namespace Gpio { + using namespace Genode; + class Zynq_Gpio; +} + +struct Gpio::Zynq_Gpio : Attached_io_mem_dataspace, Mmio +{ + Zynq_Gpio(Genode::addr_t const mmio_base, Genode::size_t const mmio_size) : + Genode::Attached_io_mem_dataspace(mmio_base, mmio_size), + Genode::Mmio((Genode::addr_t)local_addr()) + { } + + ~Zynq_Gpio() + { } + + /* + * Registers + */ + + struct GPIO_DATA : Register<0x00, 32> {}; + + struct GPIO_TRI : Register<0x04, 32> {}; + + struct GPIO2_DATA : Register<0x08, 32> {}; + + struct GPIO2_TRI : Register<0x0C, 32> {}; + + struct GIER : Register<0x011C, 32> + { + struct Global_Interrupt_Enable : Bitfield<31,1> {}; + }; + + struct IP_IER : Register<0x0128, 32> + { + struct Channel_1_Interrupt_Enable : Bitfield<0,1> {}; + struct Channel_2_Interrupt_Enable : Bitfield<1,1> {}; + }; + + struct IP_ISR : Register<0x120, 32> + { + struct Channel_1_Interrupt_Status : Bitfield<0,1> {}; + struct Channel_2_Interrupt_Status : Bitfield<1,1> {}; + }; + + + /* + * Functions + */ + Genode::uint8_t gpio_read(bool isChannel2) + { + if (isChannel2) + { + write(0xffffffff); + return read(); + } + else + { + write(0xffffffff); + return read(); + } + } + + bool gpio_write(Genode::uint8_t data, bool isChannel2) + { + if (isChannel2) + { + write(0); + write(data); + } + else + { + write(0); + write(data); + } + return true; + } +}; + +#endif // _GPIO_H_ diff --git a/src/drivers/gpio/spec/zynq/main.cc b/src/drivers/gpio/spec/zynq/main.cc new file mode 100644 index 0000000..b238dbd --- /dev/null +++ b/src/drivers/gpio/spec/zynq/main.cc @@ -0,0 +1,132 @@ +/* + * \brief Gpio Driver for Zynq + * \author Mark Albers + * \date 2015-03-30 + */ + +/* + * Copyright (C) 2015 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "driver.h" + +namespace Gpio { + using namespace Genode; + class Session_component; + class Root; +}; + +class Gpio::Session_component : public Genode::Rpc_object +{ + private: + + Driver &_driver; + unsigned _number; + + public: + + Session_component(Driver &driver, unsigned gpio_number) : _driver(driver), _number(gpio_number) {} + + virtual Genode::uint32_t read(bool isChannel2) + { + return _driver.read(_number, isChannel2); + } + + virtual bool write(Genode::uint32_t data, bool isChannel2) + { + return _driver.write(_number, data, isChannel2); + } +}; + +class Gpio::Root : public Genode::Root_component +{ + private: + + Driver &_driver; + + protected: + + Session_component *_create_session(const char *args) + { + unsigned number = Genode::Arg_string::find_arg(args, "gpio").ulong_value(0); + Genode::size_t ram_quota = Genode::Arg_string::find_arg(args, "ram_quota").ulong_value(0); + + if (ram_quota < sizeof(Session_component)) { + PWRN("Insufficient dontated ram_quota (%zd bytes), require %zd bytes", + ram_quota, sizeof(Session_component)); + throw Genode::Root::Quota_exceeded(); + } + + return new (md_alloc()) Session_component(_driver, number); + } + + public: + + Root(Genode::Rpc_entrypoint *session_ep, + Genode::Allocator *md_alloc, Driver &driver) + : Genode::Root_component(session_ep, md_alloc), + _driver(driver) { } +}; + +int main(int, char **) +{ + using namespace Gpio; + + PINF("Zynq Gpio driver"); + + /* + * Read config + */ + std::vector addr; + + try { + Genode::Xml_node gpio_node = Genode::config()->xml_node().sub_node("gpio"); + + for (unsigned i = 0; ;i++, gpio_node = gpio_node.next("gpio")) + { + addr.push_back(0); + gpio_node.attribute("addr").value(&addr[i]); + PINF("Gpio with mio address 0x%x added.", (unsigned int)addr[i]); + + if (gpio_node.is_last("gpio")) break; + } + } + catch (Genode::Xml_node::Nonexistent_sub_node) { + PWRN("No Gpio config"); + } + + /* + * Create Driver + */ + Driver &driver = Driver::factory(addr); + addr.clear(); + + /* + * Initialize server entry point + */ + enum { STACK_SIZE = 4096 }; + static Cap_connection cap; + Sliced_heap sliced_heap(env()->ram_session(), env()->rm_session()); + static Rpc_entrypoint ep(&cap, STACK_SIZE, "gpio_ep"); + static Gpio::Root gpio_root(&ep, &sliced_heap, driver); + + /* + * Announce service + */ + env()->parent()->announce(ep.manage(&gpio_root)); + + Genode::sleep_forever(); + return 0; +} diff --git a/src/drivers/gpio/spec/zynq/target.mk b/src/drivers/gpio/spec/zynq/target.mk new file mode 100644 index 0000000..46501bd --- /dev/null +++ b/src/drivers/gpio/spec/zynq/target.mk @@ -0,0 +1,12 @@ +# \brief Gpio specific for zynq systems +# \author Mark Albers +# \date 2015-03-30 + +TARGET = zynq_gpio_drv + +SRC_CC = main.cc +LIBS = base config libc libm stdcxx +INC_DIR += $(PRG_DIR) + +vpath main.cc $(PRG_DIR) + diff --git a/src/drivers/i2c/spec/zynq/driver.h b/src/drivers/i2c/spec/zynq/driver.h new file mode 100644 index 0000000..e1bd30d --- /dev/null +++ b/src/drivers/i2c/spec/zynq/driver.h @@ -0,0 +1,100 @@ +/* + * \brief I2C Driver for Zynq + * \author Mark Albers + * \date 2015-03-12 + */ + +/* + * Copyright (C) 2015 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _DRIVER_H_ +#define _DRIVER_H_ + +#include +#include +#include + +#include + +#include "i2c.h" + +namespace I2C { + using namespace Genode; + class Driver; +} + +class I2C::Driver +{ + private: + class I2C_bank + { + private: + Zynq_I2C _i2c; + + public: + + I2C_bank(Genode::addr_t base, Genode::size_t size) : _i2c(base, size) { } + + Zynq_I2C* regs() { return &_i2c; } + }; + + static I2C_bank _i2c_bank[2]; + + Driver() {} + ~Driver() {} + + public: + static Driver& factory(); + + bool read_byte_16bit_reg(unsigned bus, Genode::uint8_t adr, Genode::uint16_t reg, Genode::uint8_t *data) + { + Zynq_I2C *i2c_reg = _i2c_bank[bus].regs(); + Genode::uint8_t buf[2]; + buf[0]=reg >> 8; + buf[1]=reg; + if (i2c_reg->i2c_write(adr, buf, 2) != 0) + { + PERR("Zynq i2c: read failed"); + return false; + } + if (i2c_reg->i2c_read_byte(adr, data) != 0) + { + PERR("Zynq i2c: read failed"); + return false; + } + return true; + } + + bool write_16bit_reg(unsigned bus, Genode::uint8_t adr, Genode::uint16_t reg, + Genode::uint8_t data) + { + Zynq_I2C *i2c_reg = _i2c_bank[bus].regs(); + Genode::uint8_t buf[3]; + buf[0]=reg >> 8; + buf[1]=reg; + buf[2]=data; + if (i2c_reg->i2c_write(adr, buf, 3) != 0) + { + PERR("Zynq i2c: write failed"); + return false; + } + return true; + } +}; + +I2C::Driver::I2C_bank I2C::Driver::_i2c_bank[2] = { + {Genode::Board_base::I2C0_MMIO_BASE, Genode::Board_base::I2C_MMIO_SIZE}, + {Genode::Board_base::I2C1_MMIO_BASE, Genode::Board_base::I2C_MMIO_SIZE}, +}; + +I2C::Driver& I2C::Driver::factory() +{ + static I2C::Driver driver; + return driver; +} + +#endif /* _DRIVER_H_ */ diff --git a/src/drivers/i2c/spec/zynq/i2c.h b/src/drivers/i2c/spec/zynq/i2c.h new file mode 100644 index 0000000..4bbd420 --- /dev/null +++ b/src/drivers/i2c/spec/zynq/i2c.h @@ -0,0 +1,333 @@ +/* + * \brief I2C Driver for Zynq + * \author Mark Albers + * \date 2015-03-12 + */ + +/* + * Copyright (C) 2015 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _I2C_H_ +#define _I2C_H_ + +#include +#include + +/* Transfer direction */ +#define SENDING 0 +#define RECEIVING 1 + +/* Interrupt masks */ +#define INTERRUPT_ARB_LOST_MASK 0x00000200 +#define INTERRUPT_RX_UNF_MASK 0x00000080 +#define INTERRUPT_TX_OVR_MASK 0x00000040 +#define INTERRUPT_RX_OVR_MASK 0x00000020 +#define INTERRUPT_SLV_RDY_MASK 0x00000010 +#define INTERRUPT_TO_MASK 0x00000008 +#define INTERRUPT_NACK_MASK 0x00000004 +#define INTERRUPT_DATA_MASK 0x00000002 +#define INTERRUPT_COMP_MASK 0x00000001 +#define ALL_INTERRUPTS_MASK 0x000002FF + +/* Maximal transfer size */ +#define I2C_MAX_TRANSFER_SIZE 252 + +/* FIFO size */ +#define I2C_FIFO_DEPTH 16 + +/* Number of bytes at data intr */ +#define I2C_DATA_INTR_DEPTH 14 + +namespace I2C { + using namespace Genode; + class Zynq_I2C; +} + +struct I2C::Zynq_I2C : Attached_io_mem_dataspace, Mmio +{ + Zynq_I2C(Genode::addr_t const mmio_base, Genode::size_t const mmio_size) : + Genode::Attached_io_mem_dataspace(mmio_base, mmio_size), + Genode::Mmio((Genode::addr_t)local_addr()) + { + + } + + ~Zynq_I2C() + { + + } + + /* + * Registers + */ + + struct Control : Register<0x0, 16> + { + struct divisor_a : Bitfield<14,2> {}; + struct divisor_b : Bitfield<8,6> {}; + struct CLR_FIFO : Bitfield<6,1> {}; + struct SLVMON : Bitfield<5,1> {}; + struct HOLD : Bitfield<4,1> {}; + struct ACK_EN : Bitfield<3,1> {}; + struct NEA : Bitfield<2,1> {}; + struct MS : Bitfield<1,1> {}; + struct RW : Bitfield<0,1> {}; + }; + + struct Status : Register<0x4, 16> + { + struct BA : Bitfield<8,1> {}; + struct RXOVF : Bitfield<7,1> {}; + struct TXDV : Bitfield<6,1> {}; + struct RXDV : Bitfield<5,1> {}; + struct RXRW : Bitfield<3,1> {}; + }; + + struct I2C_address : Register<0x8, 16> + { + struct ADD : Bitfield<0,10> {}; + }; + + struct I2C_data : Register<0xC, 16> + { + struct DATA : Bitfield<0,8> {}; + }; + + struct Interrupt_status : Register<0x10, 16> + { + struct ARB_LOST : Bitfield<9,1> {}; + struct RX_UNF : Bitfield<7,1> {}; + struct TX_OVF : Bitfield<6,1> {}; + struct RX_OVF : Bitfield<5,1> {}; + struct SLV_RDY : Bitfield<4,1> {}; + struct TO : Bitfield<3,1> {}; + struct NACK : Bitfield<2,1> {}; + struct DATA : Bitfield<1,1> {}; + struct COMP : Bitfield<0,1> {}; + }; + + struct Transfer_size : Register<0x14, 8> + { + struct SIZE : Bitfield<0,8> {}; + }; + + struct Slave_mon_pause : Register<0x18, 8> + { + struct PAUSE : Bitfield<0,4> {}; + }; + + struct Time_out : Register<0x1C, 8> + { + struct TO : Bitfield<0,8> {}; + }; + + struct Interrupt_mask : Register<0x20, 16> + { + struct ARB_LOST : Bitfield<9,1> {}; + struct RX_UNF : Bitfield<7,1> {}; + struct TX_OVF : Bitfield<6,1> {}; + struct RX_OVF : Bitfield<5,1> {}; + struct SLV_RDY : Bitfield<4,1> {}; + struct TO : Bitfield<3,1> {}; + struct NACK : Bitfield<2,1> {}; + struct DATA : Bitfield<1,1> {}; + struct COMP : Bitfield<0,1> {}; + }; + + struct Interrupt_enable : Register<0x24, 16> + { + struct ARB_LOST : Bitfield<9,1> {}; + struct RX_UNF : Bitfield<7,1> {}; + struct TX_OVF : Bitfield<6,1> {}; + struct RX_OVF : Bitfield<5,1> {}; + struct SLV_RDY : Bitfield<4,1> {}; + struct TO : Bitfield<3,1> {}; + struct NACK : Bitfield<2,1> {}; + struct DATA : Bitfield<1,1> {}; + struct COMP : Bitfield<0,1> {}; + }; + + struct Interrupt_disable : Register<0x28, 16> + { + struct ARB_LOST : Bitfield<9,1> {}; + struct RX_UNF : Bitfield<7,1> {}; + struct TX_OVF : Bitfield<6,1> {}; + struct RX_OVF : Bitfield<5,1> {}; + struct SLV_RDY : Bitfield<4,1> {}; + struct TO : Bitfield<3,1> {}; + struct NACK : Bitfield<2,1> {}; + struct DATA : Bitfield<1,1> {}; + struct COMP : Bitfield<0,1> {}; + }; + + + Timer::Connection _timer; + int sendByteCount; + uint8_t *sendBufferPtr; + + void init(int direction) + { + write( Control::divisor_a::bits(2) | + Control::divisor_b::bits(16) | + Control::ACK_EN::bits(1) | + Control::CLR_FIFO::bits(1) | + Control::NEA::bits(1) | + Control::MS::bits(1)); + write(direction); + } + + void transmitFifoFill() + { + uint8_t availBytes; + int loopCnt; + int numBytesToSend; + + /* + * Determine number of bytes to write to FIFO. + */ + availBytes = I2C_FIFO_DEPTH - read(); + numBytesToSend = sendByteCount > availBytes ? availBytes : sendByteCount; + + /* + * Fill FIFO with amount determined above. + */ + for (loopCnt = 0; loopCnt < numBytesToSend; loopCnt++) + { + write(*sendBufferPtr); + sendBufferPtr++; + sendByteCount--; + } + } + + int i2c_write(uint8_t slaveAddr, uint8_t *msgPtr, int byteCount) + { + uint32_t intrs, intrStatusReg; + + sendByteCount = byteCount; + sendBufferPtr = msgPtr; + + /* + * Set HOLD bit if byteCount is bigger than FIFO. + */ + if (byteCount > I2C_FIFO_DEPTH) write(1); + + /* + * Init sending master. + */ + init(SENDING); + + /* + * intrs keeps all the error-related interrupts. + */ + intrs = INTERRUPT_ARB_LOST_MASK | INTERRUPT_TX_OVR_MASK | INTERRUPT_NACK_MASK; + + /* + * Clear the interrupt status register before use it to monitor. + */ + write(read()); + + /* + * Transmit first FIFO full of data. + */ + transmitFifoFill(); + write(slaveAddr); + intrStatusReg = read(); + + /* + * Continue sending as long as there is more data and there are no errors. + */ + while ((sendByteCount > 0) && ((intrStatusReg & intrs) == 0)) + { + /* + * Wait until transmit FIFO is empty. + */ + if (read() != 0) + { + intrStatusReg = read(); + continue; + } + + /* + * Send more data out through transmit FIFO. + */ + transmitFifoFill(); + } + + /* + * Check for completion of transfer. + */ + while ((intrStatusReg & INTERRUPT_COMP_MASK) != INTERRUPT_COMP_MASK) + { + + intrStatusReg = read(); + /* + * If there is an error, tell the caller. + */ + if ((intrStatusReg & intrs) != 0) + { + return 1; + } + } + + write(0); + + return 0; + } + + int i2c_read_byte(uint8_t slaveAddr, uint8_t *msgPtr) + { + uint32_t intrs, intrStatusReg; + + /* + * Init receiving master. + */ + init(RECEIVING); + + /* + * Clear the interrupt status register before use it to monitor. + */ + write(read()); + + /* + * Set up the transfer size register so the slave knows how much + * to send to us. + */ + write(1); + + /* + * Set slave address. + */ + write(slaveAddr); + + /* + * intrs keeps all the error-related interrupts. + */ + intrs = INTERRUPT_ARB_LOST_MASK | INTERRUPT_RX_OVR_MASK | + INTERRUPT_RX_UNF_MASK | INTERRUPT_NACK_MASK; + + /* + * Poll the interrupt status register to find the errors. + */ + intrStatusReg = read(); + + while (read() != 1) + { + if (intrStatusReg & intrs) return 1; + } + + if (intrStatusReg & intrs) return 1; + + *msgPtr = read(); + + while (read() != 1) {} + + return 0; + } + +}; + +#endif // _I2C_H_ diff --git a/src/drivers/i2c/spec/zynq/main.cc b/src/drivers/i2c/spec/zynq/main.cc new file mode 100644 index 0000000..652c8a1 --- /dev/null +++ b/src/drivers/i2c/spec/zynq/main.cc @@ -0,0 +1,102 @@ +/* + * \brief I2C Driver for Zynq + * \author Mark Albers + * \date 2015-03-12 + */ + +/* + * Copyright (C) 2015 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "driver.h" + +namespace I2C { + using namespace Genode; + class Session_component; + class Root; +}; + +class I2C::Session_component : public Genode::Rpc_object +{ + private: + Driver &_driver; + unsigned int _bus; + Genode::Signal_context_capability _sigh; + + public: + + Session_component(Driver &driver, unsigned int bus_num) : _driver(driver), _bus(bus_num) {} + + virtual bool read_byte_16bit_reg(Genode::uint8_t adr, Genode::uint16_t reg, Genode::uint8_t *data) + { + return _driver.read_byte_16bit_reg(_bus, adr, reg, data); + } + + virtual bool write_16bit_reg(Genode::uint8_t adr, Genode::uint16_t reg, + Genode::uint8_t data) + { + return _driver.write_16bit_reg(_bus, adr, reg, data); + } +}; + +class I2C::Root : public Genode::Root_component +{ + private: + + Driver &_driver; + + protected: + + Session_component *_create_session(const char *args) + { + unsigned int bus = Genode::Arg_string::find_arg(args, "bus").ulong_value(0); + return new (md_alloc()) Session_component(_driver, bus); + } + + public: + + Root(Genode::Rpc_entrypoint *session_ep, + Genode::Allocator *md_alloc, Driver &driver) + : Genode::Root_component(session_ep, md_alloc), + _driver(driver) { } +}; + +int main(int, char **) +{ + using namespace I2C; + + PINF("Zynq I2C driver"); + + Driver &driver = Driver::factory(); + + /* + * Initialize server entry point + */ + enum { STACK_SIZE = 4096 }; + static Cap_connection cap; + Sliced_heap sliced_heap(env()->ram_session(), env()->rm_session()); + static Rpc_entrypoint ep(&cap, STACK_SIZE, "i2c_ep"); + static I2C::Root i2c_root(&ep, &sliced_heap, driver); + + /* + * Announce service + */ + env()->parent()->announce(ep.manage(&i2c_root)); + + Genode::sleep_forever(); + return 0; +} + diff --git a/src/drivers/i2c/spec/zynq/target.mk b/src/drivers/i2c/spec/zynq/target.mk new file mode 100644 index 0000000..c029ed3 --- /dev/null +++ b/src/drivers/i2c/spec/zynq/target.mk @@ -0,0 +1,12 @@ +# \brief I2C specific for zynq systems +# \author Mark Albers +# \date 2015-03-12 + +TARGET = zynq_i2c_drv + +SRC_CC = main.cc +LIBS = base config +INC_DIR += $(PRG_DIR) + +vpath main.cc $(PRG_DIR) + diff --git a/src/drivers/vdma/spec/zynq/driver.h b/src/drivers/vdma/spec/zynq/driver.h new file mode 100644 index 0000000..fae6967 --- /dev/null +++ b/src/drivers/vdma/spec/zynq/driver.h @@ -0,0 +1,105 @@ +/* + * \brief VDMA Driver for Zynq + * \author Mark Albers + * \date 2015-04-13 + */ + +/* + * Copyright (C) 2015 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _DRIVER_H_ +#define _DRIVER_H_ + +#include +#include +#include +#include +#include +#include +#include "vdma.h" + +namespace Vdma { + using namespace Genode; + class Driver; +} + +class Vdma::Driver +{ + private: + + std::vector _vdma_bank; + + Driver(std::vector addr) + { + for (unsigned i = 0; i < addr.size(); i++) + { + _vdma_bank.push_back(new Zynq_Vdma(addr[i], Board_base::VDMA_MMIO_SIZE)); + } + } + + ~Driver() + { + for (std::vector::iterator it = _vdma_bank.begin() ; it != _vdma_bank.end(); ++it) + { + delete (*it); + } + _vdma_bank.clear(); + } + + public: + + static Driver& factory(std::vector addr); + + bool setConfig(unsigned vdma, Genode::uint32_t data, bool isMM2S) + { + Zynq_Vdma *vdma_reg = _vdma_bank[vdma]; + if (isMM2S) vdma_reg->write(data); + else vdma_reg->write(data); + return true; + } + + bool setStride(unsigned vdma, Genode::uint16_t data, bool isMM2S) + { + Zynq_Vdma *vdma_reg = _vdma_bank[vdma]; + if (isMM2S) vdma_reg->write(data); + else vdma_reg->write(data); + return true; + } + + bool setWidth(unsigned vdma, Genode::uint16_t data, bool isMM2S) + { + Zynq_Vdma *vdma_reg = _vdma_bank[vdma]; + if (isMM2S) vdma_reg->write(data); + else vdma_reg->write(data); + return true; + } + + bool setHeight(unsigned vdma, Genode::uint16_t data, bool isMM2S) + { + Zynq_Vdma *vdma_reg = _vdma_bank[vdma]; + if (isMM2S) vdma_reg->write(data); + else vdma_reg->write(data); + return true; + } + + + bool setAddr(unsigned vdma, Genode::uint32_t data, bool isMM2S) + { + Zynq_Vdma *vdma_reg = _vdma_bank[vdma]; + if (isMM2S) vdma_reg->write(data); + else vdma_reg->write(data); + return true; + } +}; + +Vdma::Driver& Vdma::Driver::factory(std::vector addr) +{ + static Vdma::Driver driver(addr); + return driver; +} + +#endif /* _DRIVER_H_ */ diff --git a/src/drivers/vdma/spec/zynq/main.cc b/src/drivers/vdma/spec/zynq/main.cc new file mode 100644 index 0000000..c5b3138 --- /dev/null +++ b/src/drivers/vdma/spec/zynq/main.cc @@ -0,0 +1,147 @@ +/* + * \brief VDMA Driver for Zynq + * \author Mark Albers + * \date 2015-04-13 + */ + +/* + * Copyright (C) 2015 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "driver.h" + +namespace Vdma { + using namespace Genode; + class Session_component; + class Root; +}; + +class Vdma::Session_component : public Genode::Rpc_object +{ + private: + + Driver &_driver; + unsigned _number; + + public: + + Session_component(Driver &driver, unsigned vdma_number) : _driver(driver), _number(vdma_number) {} + + virtual bool setConfig(Genode::uint32_t data, bool isMM2S) + { + return _driver.setConfig(_number, data, isMM2S); + } + + virtual bool setStride(Genode::uint16_t data, bool isMM2S) + { + return _driver.setStride(_number, data, isMM2S); + } + + virtual bool setWidth(Genode::uint16_t data, bool isMM2S) + { + return _driver.setWidth(_number, data, isMM2S); + } + + virtual bool setHeight(Genode::uint16_t data, bool isMM2S) + { + return _driver.setHeight(_number, data, isMM2S); + } + + virtual bool setAddr(Genode::uint32_t data, bool isMM2S) + { + return _driver.setAddr(_number, data, isMM2S); + } +}; + +class Vdma::Root : public Genode::Root_component +{ + private: + + Driver &_driver; + + protected: + + Session_component *_create_session(const char *args) + { + unsigned number = Genode::Arg_string::find_arg(args, "vdma").ulong_value(0); + Genode::size_t ram_quota = Genode::Arg_string::find_arg(args, "ram_quota").ulong_value(0); + + if (ram_quota < sizeof(Session_component)) { + PWRN("Insufficient dontated ram_quota (%zd bytes), require %zd bytes", + ram_quota, sizeof(Session_component)); + throw Genode::Root::Quota_exceeded(); + } + + return new (md_alloc()) Session_component(_driver, number); + } + + public: + + Root(Genode::Rpc_entrypoint *session_ep, + Genode::Allocator *md_alloc, Driver &driver) + : Genode::Root_component(session_ep, md_alloc), + _driver(driver) { } +}; + +int main(int, char **) +{ + using namespace Vdma; + + PINF("Zynq VDMA driver"); + + /* + * Read config + */ + std::vector addr; + + try { + Genode::Xml_node vdma_node = Genode::config()->xml_node().sub_node("vdma"); + + for (unsigned i = 0; ;i++, vdma_node = vdma_node.next("vdma")) + { + addr.push_back(0); + vdma_node.attribute("addr").value(&addr[i]); + PINF("VDMA with mio address 0x%x added.", (unsigned int)addr[i]); + + if (vdma_node.is_last("vdma")) break; + } + } + catch (Genode::Xml_node::Nonexistent_sub_node) { + PWRN("No VDMA config"); + } + + /* + * Create Driver + */ + Driver &driver = Driver::factory(addr); + addr.clear(); + + /* + * Initialize server entry point + */ + enum { STACK_SIZE = 4096 }; + static Cap_connection cap; + Sliced_heap sliced_heap(env()->ram_session(), env()->rm_session()); + static Rpc_entrypoint ep(&cap, STACK_SIZE, "vdma_ep"); + static Vdma::Root vdma_root(&ep, &sliced_heap, driver); + + /* + * Announce service + */ + env()->parent()->announce(ep.manage(&vdma_root)); + + Genode::sleep_forever(); + return 0; +} diff --git a/src/drivers/vdma/spec/zynq/target.mk b/src/drivers/vdma/spec/zynq/target.mk new file mode 100644 index 0000000..72c35da --- /dev/null +++ b/src/drivers/vdma/spec/zynq/target.mk @@ -0,0 +1,12 @@ +# \brief VDMA specific for zynq systems +# \author Mark Albers +# \date 2015-04-13 + +TARGET = zynq_vdma_drv + +SRC_CC = main.cc +LIBS = base config libc libm stdcxx +INC_DIR += $(PRG_DIR) + +vpath main.cc $(PRG_DIR) + diff --git a/src/drivers/vdma/spec/zynq/vdma.h b/src/drivers/vdma/spec/zynq/vdma.h new file mode 100644 index 0000000..c6a34ef --- /dev/null +++ b/src/drivers/vdma/spec/zynq/vdma.h @@ -0,0 +1,148 @@ +/* + * \brief VDMA Driver for Zynq + * \author Mark Albers + * \date 2015-04-13 + */ + +/* + * Copyright (C) 2015 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _VDMA_H_ +#define _VDMA_H_ + +#include +#include + +namespace Vdma { + using namespace Genode; + class Zynq_Vdma; +} + +struct Vdma::Zynq_Vdma : Attached_io_mem_dataspace, Mmio +{ + Zynq_Vdma(Genode::addr_t const mmio_base, Genode::size_t const mmio_size) : + Genode::Attached_io_mem_dataspace(mmio_base, mmio_size), + Genode::Mmio((Genode::addr_t)local_addr()) + { } + + ~Zynq_Vdma() + { } + + /* + * Registers + */ + + struct MM2S_VDMACR : Register<0x00, 32> + { + struct Repeat_En : Bitfield<15,1> {}; + struct Err_IrqEn : Bitfield<14,1> {}; + struct RdPntrNum : Bitfield<8,4> {}; + struct GenlockSrc : Bitfield<7,1> {}; + struct GenlockEn : Bitfield<3,1> {}; + struct Reset : Bitfield<2,1> {}; + struct Circular_Park : Bitfield<1,1> {}; + struct RS : Bitfield<0,1> {}; + }; + + struct MM2S_VDMASR : Register<0x04, 32> + { + struct Err_Irq : Bitfield<14,1> {}; + struct SOFEarlyErr : Bitfield<7,1> {}; + struct VDMADecErr : Bitfield<6,1> {}; + struct VDMASlvErr : Bitfield<5,1> {}; + struct VDMAIntErr : Bitfield<4,1> {}; + struct Halted : Bitfield<0,1> {}; + }; + + struct MM2S_REG_INDEX : Register<0x14, 32> + { + struct MM2S_Reg_Index : Bitfield<0,1> {}; + }; + + struct PARK_PTR_REG : Register<0x28, 32> + { + struct WrFrmStore : Bitfield<24,5> {}; + struct RdFrmStore : Bitfield<16,5> {}; + struct WrFrmPtrRef : Bitfield<8,5> {}; + struct RdFrmPtrRef : Bitfield<0,5> {}; + }; + + struct VDMA_VERSION : Register<0x2c, 32> + { + struct Major_Version : Bitfield<28,4> {}; + struct Minor_Version : Bitfield<20,8> {}; + struct Revision : Bitfield<16,4> {}; + struct Xilinx_Internal : Bitfield<0,16> {}; + }; + + struct S2MM_VDMACR : Register<0x30, 32> + { + struct Repeat_En : Bitfield<15,1> {}; + struct Err_IrqEn : Bitfield<14,1> {}; + struct WrPntrNum : Bitfield<8,4> {}; + struct GenlockSrc : Bitfield<7,1> {}; + struct GenlockEn : Bitfield<3,1> {}; + struct Reset : Bitfield<2,1> {}; + }; + + struct S2MM_VDMASR : Register<0x34, 32> + { + struct EOLLateErr : Bitfield<15,1> {}; + struct Err_Irq : Bitfield<14,1> {}; + struct SOFLateErr : Bitfield<11,1> {}; + struct EOLEarlyErr : Bitfield<8,1> {}; + struct SOFEarlyErr : Bitfield<7,1> {}; + struct VDMADecErr : Bitfield<6,1> {}; + struct DMASlvErr : Bitfield<5,1> {}; + struct DMAIntErr : Bitfield<4,1> {}; + struct Halted : Bitfield<0,1> {}; + }; + + struct S2MM_REG_INDEX : Register<0x44, 32> + { + struct S2MM_Reg_Index : Bitfield<0,1> {}; + }; + + struct MM2S_VSIZE : Register<0x50, 32> + { + struct Vertical_Size : Bitfield<0,13> {}; + }; + + struct MM2S_HSIZE : Register<0x54, 32> + { + struct Horizontal_Size : Bitfield<0,16> {}; + }; + + struct MM2S_FRMDLY_STRIDE : Register<0x58, 32> + { + struct Frame_Delay : Bitfield<24,5> {}; + struct Stride : Bitfield<0,16> {}; + }; + + struct MM2S_START_ADDRESS : Register<0x5c, 32> {}; + + struct S2MM_VSIZE : Register<0xa0, 32> + { + struct Vertical_Size : Bitfield<0,13> {}; + }; + + struct S2MM_HSIZE : Register<0xa4, 32> + { + struct Horizontal_Size : Bitfield<0,16> {}; + }; + + struct S2MM_FRMDLY_STRIDE : Register<0xa8, 32> + { + struct Frame_Delay : Bitfield<24,5> {}; + struct Stride : Bitfield<0,16> {}; + }; + + struct S2MM_START_ADDRESS : Register<0xac, 32> {}; + +}; + +#endif // _VDMA_H_