genode/repos/os/src/drivers/platform/spec/odroid_x2/pmu.h

168 lines
3.9 KiB
C++

/*
* \brief Regulator driver for power management unit of Exynos4412 SoC
* \author Alexy Gallardo Segura <alexy@uclv.cu>
* \author Humberto Lopez Leon <humberto@uclv.cu>
* \author Reinier Millo Sanchez <rmillo@uclv.cu>
* \date 2015-07-08
*/
/*
* Copyright (C) 2015-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _DRIVERS__PLATFORM__SPEC__ODROID_X2__PMU_H_
#define _DRIVERS__PLATFORM__SPEC__ODROID_X2__PMU_H_
#include <base/log.h>
#include <regulator/consts.h>
#include <regulator/driver.h>
#include <drivers/defs/odroid_x2.h>
#include <os/attached_mmio.h>
using Genode::warning;
using namespace Regulator;
class Pmu : public Regulator::Driver,
private Genode::Attached_mmio
{
private:
template <unsigned OFFSET>
struct Control : Register <OFFSET, 32>
{
struct Enable : Register<OFFSET, 32>::template Bitfield<0, 1> { };
};
template <unsigned OFFSET>
struct Configuration : Register <OFFSET, 32>
{
struct Local_pwr_cfg : Register<OFFSET, 32>::template Bitfield<0, 3> { };
};
template <unsigned OFFSET>
struct Status : Register <OFFSET, 32>
{
struct Stat : Register<OFFSET, 32>::template Bitfield<0, 3> { };
};
template <unsigned OFFSET>
struct Sysclk_configuration : Register <OFFSET, 32>
{
struct Local_pwr_cfg : Register<OFFSET, 32>::template Bitfield<0, 1> { };
};
template <unsigned OFFSET>
struct Sysclk_status : Register <OFFSET, 32>
{
struct Stat : Register<OFFSET, 32>::template Bitfield<0, 1> { };
};
struct Hdmi_phy_control : Register<0x700, 32>
{
struct Enable : Bitfield<0, 1> { };
struct Div_ratio : Bitfield<16, 10> { };
};
typedef Control<0x0704> Usbdrd_phy_control;
typedef Control<0x0708> Usbhost_phy1_control;
typedef Control<0x70c> Usbhost_phy2_control;
void _enable(unsigned long id)
{
switch (id) {
case PWR_USB20:
write<Usbdrd_phy_control::Enable>(1);
write<Usbhost_phy1_control::Enable>(1);
write<Usbhost_phy2_control::Enable>(1);
break;
case PWR_HDMI: {
Hdmi_phy_control::access_t hpc = read<Hdmi_phy_control>();
Hdmi_phy_control::Div_ratio::set(hpc, 150);
Hdmi_phy_control::Enable::set(hpc, 1);
write<Hdmi_phy_control>(hpc);
break; }
default:
warning("Unsupported for ", names[id].name);
}
}
void _disable(unsigned long id)
{
switch (id) {
case PWR_USB20:
write<Usbdrd_phy_control::Enable>(0);
write<Usbhost_phy1_control::Enable>(0);
write<Usbhost_phy2_control::Enable>(0);
break;
case PWR_HDMI:
write<Hdmi_phy_control::Enable>(0);
break;
default:
warning("Unsupported for ", names[id].name);
}
}
public:
/**
* Constructor
*/
Pmu(Genode::Env &env)
: Genode::Attached_mmio(env, Odroid_x2::PMU_MMIO_BASE,
Odroid_x2::PMU_MMIO_SIZE)
{
write<Usbdrd_phy_control::Enable>(0);
write<Usbhost_phy1_control::Enable>(0);
write<Usbhost_phy2_control::Enable>(0);
write<Hdmi_phy_control::Enable>(0);
}
/********************************
** Regulator driver interface **
********************************/
void level(Regulator_id id, unsigned long /* level */) override
{
switch (id) {
default:
warning("Unsupported for ", names[id].name);
}
}
unsigned long level(Regulator_id id) override
{
switch (id) {
default:
warning("Unsupported for ", names[id].name);
}
return 0;
}
void state(Regulator_id id, bool enable) override
{
if (enable)
_enable(id);
else
_disable(id);
}
bool state(Regulator_id id) override
{
switch (id) {
case PWR_USB20:
return read<Usbdrd_phy_control::Enable>();
default:
warning("Unsupported for ", names[id].name);
}
return true;
}
};
#endif /* _DRIVERS__PLATFORM__SPEC__ODROID_X2__PMU_H_ */