mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-23 23:42:32 +00:00
Arndale: save power by default (Fix #774)
* Use regulator interface in eMMC driver to enable its clock
This commit is contained in:
parent
cc0f4bc9d2
commit
a4eb4bfa07
@ -22,6 +22,7 @@ namespace Regulator {
|
||||
CLK_CPU,
|
||||
CLK_SATA,
|
||||
CLK_USB30,
|
||||
CLK_MMC0,
|
||||
PWR_SATA,
|
||||
PWR_USB30,
|
||||
MAX,
|
||||
@ -37,6 +38,7 @@ namespace Regulator {
|
||||
{ CLK_CPU, "clock-cpu" },
|
||||
{ CLK_SATA, "clock-sata" },
|
||||
{ CLK_USB30, "clock-usb3.0" },
|
||||
{ CLK_MMC0, "clock-mmc0" },
|
||||
{ PWR_SATA, "power-sata" },
|
||||
{ PWR_USB30, "power-usb3.0" },
|
||||
};
|
||||
|
@ -5,6 +5,7 @@
|
||||
# generic components
|
||||
set build_components {
|
||||
core init
|
||||
drivers/platform
|
||||
drivers/timer
|
||||
drivers/sd_card
|
||||
test/block
|
||||
@ -36,6 +37,10 @@ set config {
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</default-route>
|
||||
|
||||
<start name="platform_drv">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides><service name="Regulator"/></provides>
|
||||
</start>
|
||||
<start name="timer">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides><service name="Timer"/></provides>
|
||||
@ -61,6 +66,7 @@ install_config $config
|
||||
set boot_modules {
|
||||
core init
|
||||
timer
|
||||
platform_drv
|
||||
sd_card_drv
|
||||
test-block
|
||||
}
|
||||
|
@ -47,6 +47,7 @@ class Cmu : public Regulator::Driver,
|
||||
struct P : Register<OFF, 32>::template Bitfield < 8, 6> { };
|
||||
struct M : Register<OFF, 32>::template Bitfield <16, 10> { };
|
||||
struct Locked : Register<OFF, 32>::template Bitfield <29, 1> { };
|
||||
struct Enable : Register<OFF, 32>::template Bitfield <31, 1> { };
|
||||
};
|
||||
|
||||
|
||||
@ -121,6 +122,11 @@ class Cmu : public Regulator::Driver,
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/************************
|
||||
** CMU CORE registers **
|
||||
************************/
|
||||
|
||||
typedef Pll_lock<0x4000> Mpll_lock;
|
||||
typedef Pll_con0<0x4100> Mpll_con0;
|
||||
|
||||
@ -129,11 +135,25 @@ class Cmu : public Regulator::Driver,
|
||||
struct Mux_mpll_sel : Bitfield<8, 1> { enum { XXTI, MPLL_FOUT_RGT }; };
|
||||
};
|
||||
|
||||
struct Clk_gate_ip_acp : Register<0x8800, 32> { };
|
||||
struct Clk_gate_ip_isp0 : Register<0xc800, 32> { };
|
||||
struct Clk_gate_ip_isp1 : Register<0xc804, 32> { };
|
||||
struct Clk_gate_sclk_isp : Register<0xc900, 32> { };
|
||||
|
||||
|
||||
/***********************
|
||||
** CMU TOP registers **
|
||||
***********************/
|
||||
|
||||
typedef Pll_lock<0x10020> Cpll_lock;
|
||||
typedef Pll_lock<0x10030> Epll_lock;
|
||||
typedef Pll_lock<0x10040> Vpll_lock;
|
||||
typedef Pll_lock<0x10050> Gpll_lock;
|
||||
typedef Pll_con0<0x10120> Cpll_con0;
|
||||
typedef Pll_con0<0x10130> Epll_con0;
|
||||
typedef Pll_con0<0x10140> Vpll_con0;
|
||||
typedef Pll_con0<0x10150> Gpll_con0;
|
||||
|
||||
struct Clk_src_top2 : Register<0x10218, 32>
|
||||
{
|
||||
struct Mux_mpll_user_sel : Bitfield<20, 1> { enum { XXTI, MOUT_MPLL}; };
|
||||
@ -149,6 +169,7 @@ class Cmu : public Regulator::Driver,
|
||||
|
||||
struct Clk_src_mask_fsys : Register<0x10340, 32>
|
||||
{
|
||||
struct Mmc0_mask : Bitfield<0, 1> { enum { MASK, UNMASK }; };
|
||||
struct Sata_mask : Bitfield<24, 1> { enum { MASK, UNMASK }; };
|
||||
struct Usbdrd30_mask : Bitfield<28, 1> { enum { MASK, UNMASK }; };
|
||||
};
|
||||
@ -165,16 +186,35 @@ class Cmu : public Regulator::Driver,
|
||||
struct Div_usbdrd30 : Bitfield<24, 1> {};
|
||||
};
|
||||
|
||||
struct Clk_gate_ip_gscl : Register<0x10920, 32> { };
|
||||
struct Clk_gate_ip_disp1 : Register<0x10928, 32> { };
|
||||
struct Clk_gate_ip_mfc : Register<0x1092c, 32> { };
|
||||
struct Clk_gate_ip_g3d : Register<0x10930, 32> { };
|
||||
struct Clk_gate_ip_gen : Register<0x10934, 32> { };
|
||||
|
||||
struct Clk_gate_ip_fsys : Register<0x10944, 32>
|
||||
{
|
||||
struct Pdma0 : Bitfield<1, 1> { };
|
||||
struct Pdma1 : Bitfield<2, 1> { };
|
||||
struct Sata : Bitfield<6, 1> { };
|
||||
struct Usbdrd30 : Bitfield<19, 0> { };
|
||||
struct Clk_sdmmc0 : Bitfield<12, 1> { };
|
||||
struct Clk_usbhost20 : Bitfield<18, 1> { };
|
||||
struct Usbdrd30 : Bitfield<19, 1> { };
|
||||
struct Sata_phy_ctrl : Bitfield<24, 1> { };
|
||||
struct Sata_phy_i2c : Bitfield<25, 1> { };
|
||||
};
|
||||
|
||||
struct Clk_gate_ip_peric : Register<0x10950, 32>
|
||||
{
|
||||
struct Clk_uart2 : Bitfield<2, 1> { };
|
||||
struct Clk_pwm : Bitfield<24, 1> { };
|
||||
};
|
||||
|
||||
struct Clk_gate_block : Register<0x10980, 32>
|
||||
{
|
||||
struct Clk_gen : Bitfield<2, 1> { };
|
||||
};
|
||||
|
||||
|
||||
/*************************
|
||||
** CMU CDREX registers **
|
||||
@ -240,9 +280,9 @@ class Cmu : public Regulator::Driver,
|
||||
}
|
||||
|
||||
|
||||
/********************
|
||||
** SATA functions **
|
||||
********************/
|
||||
/**********************
|
||||
** Device functions **
|
||||
**********************/
|
||||
|
||||
void _sata_enable()
|
||||
{
|
||||
@ -262,36 +302,13 @@ class Cmu : public Regulator::Driver,
|
||||
write<Clk_src_mask_fsys::Sata_mask>(1);
|
||||
}
|
||||
|
||||
void _sata_disable()
|
||||
{
|
||||
/* disable I2C for SATA */
|
||||
write<Clk_gate_ip_fsys::Sata_phy_i2c>(0);
|
||||
|
||||
/* disable SATA and SATA Phy */
|
||||
write<Clk_gate_ip_fsys::Sata>(0);
|
||||
write<Clk_gate_ip_fsys::Sata_phy_ctrl>(0);
|
||||
write<Clk_src_mask_fsys::Sata_mask>(0);
|
||||
}
|
||||
|
||||
bool _sata_enabled()
|
||||
{
|
||||
return read<Clk_gate_ip_fsys::Sata>() &&
|
||||
read<Clk_gate_ip_fsys::Sata_phy_ctrl>() &&
|
||||
read<Clk_src_mask_fsys::Sata_mask>();
|
||||
}
|
||||
|
||||
|
||||
/***********************
|
||||
** USB 3.0 functions **
|
||||
***********************/
|
||||
|
||||
void _usb30_enable()
|
||||
{
|
||||
/**
|
||||
* set USBDRD30 clock to 66 MHz
|
||||
* assuming 800 MHz from sclk_mpll_user, formula: sclk / (divider + 1)
|
||||
*/
|
||||
write<Clk_div_fsys0::Usbdrd30_ratio>(11); /* */
|
||||
write<Clk_div_fsys0::Usbdrd30_ratio>(11);
|
||||
while (read<Clk_div_stat_fsys0::Div_usbdrd30>()) ;
|
||||
|
||||
/* enable USBDRD30 clock */
|
||||
@ -299,16 +316,44 @@ class Cmu : public Regulator::Driver,
|
||||
write<Clk_src_mask_fsys::Usbdrd30_mask>(1);
|
||||
}
|
||||
|
||||
void _usb30_disable()
|
||||
void _enable(Regulator_id id)
|
||||
{
|
||||
write<Clk_gate_ip_fsys::Usbdrd30>(0);
|
||||
write<Clk_src_mask_fsys::Usbdrd30_mask>(0);
|
||||
switch (id) {
|
||||
case CLK_SATA:
|
||||
_sata_enable();
|
||||
break;
|
||||
case CLK_USB30:
|
||||
_usb30_enable();
|
||||
break;
|
||||
case CLK_MMC0:
|
||||
write<Clk_gate_ip_fsys::Clk_sdmmc0>(1);
|
||||
write<Clk_src_mask_fsys::Mmc0_mask>(1);
|
||||
break;
|
||||
default:
|
||||
PWRN("Unsupported for %s", names[id].name);
|
||||
}
|
||||
}
|
||||
|
||||
bool _usb30_enabled()
|
||||
void _disable(Regulator_id id)
|
||||
{
|
||||
return read<Clk_gate_ip_fsys::Usbdrd30>() &&
|
||||
read<Clk_src_mask_fsys::Usbdrd30_mask>();
|
||||
switch (id) {
|
||||
case CLK_SATA:
|
||||
write<Clk_gate_ip_fsys::Sata_phy_i2c>(0);
|
||||
write<Clk_gate_ip_fsys::Sata>(0);
|
||||
write<Clk_gate_ip_fsys::Sata_phy_ctrl>(0);
|
||||
write<Clk_src_mask_fsys::Sata_mask>(0);
|
||||
break;
|
||||
case CLK_USB30:
|
||||
write<Clk_gate_ip_fsys::Usbdrd30>(0);
|
||||
write<Clk_src_mask_fsys::Usbdrd30_mask>(0);
|
||||
break;
|
||||
case CLK_MMC0:
|
||||
write<Clk_gate_ip_fsys::Clk_sdmmc0>(0);
|
||||
write<Clk_src_mask_fsys::Mmc0_mask>(0);
|
||||
break;
|
||||
default:
|
||||
PWRN("Unsupported for %s", names[id].name);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
@ -321,13 +366,31 @@ class Cmu : public Regulator::Driver,
|
||||
Genode::Board_base::CMU_MMIO_SIZE),
|
||||
_cpu_freq(CPU_FREQ_1600)
|
||||
{
|
||||
_sata_disable();
|
||||
_usb30_disable();
|
||||
/**
|
||||
* Close certain clock gates by default (~ 0.7 Watt reduction)
|
||||
*/
|
||||
write<Clk_gate_ip_acp>(0);
|
||||
write<Clk_gate_ip_isp0>(0);
|
||||
write<Clk_gate_ip_isp1>(0);
|
||||
write<Clk_gate_sclk_isp>(0);
|
||||
write<Clk_gate_ip_gscl>(0);
|
||||
write<Clk_gate_ip_disp1>(0);
|
||||
write<Clk_gate_ip_mfc>(0);
|
||||
write<Clk_gate_ip_g3d>(0);
|
||||
write<Clk_gate_ip_gen>(0);
|
||||
write<Clk_gate_ip_fsys>(0);
|
||||
write<Clk_gate_ip_peric>(Clk_gate_ip_peric::Clk_uart2::bits(1) |
|
||||
Clk_gate_ip_peric::Clk_pwm::bits(1));
|
||||
write<Clk_gate_block>(Clk_gate_block::Clk_gen::bits(1));
|
||||
|
||||
|
||||
/**
|
||||
* Set default CPU frequency
|
||||
*/
|
||||
_cpu_clk_freq(_cpu_freq);
|
||||
|
||||
/**
|
||||
* Hard wiring of reference clocks
|
||||
* Hard wiring of certain reference clocks
|
||||
*/
|
||||
write<Pll_div2_sel::Mpll_fout_sel>(Pll_div2_sel::Mpll_fout_sel::MPLL_FOUT_HALF);
|
||||
write<Clk_src_core1::Mux_mpll_sel>(Clk_src_core1::Mux_mpll_sel::MPLL_FOUT_RGT);
|
||||
@ -372,31 +435,25 @@ class Cmu : public Regulator::Driver,
|
||||
|
||||
void set_state(Regulator_id id, bool enable)
|
||||
{
|
||||
switch (id) {
|
||||
case CLK_SATA:
|
||||
if (enable)
|
||||
_sata_enable();
|
||||
else
|
||||
_sata_disable();
|
||||
break;
|
||||
case CLK_USB30:
|
||||
if (enable)
|
||||
_usb30_enable();
|
||||
else
|
||||
_usb30_disable();
|
||||
break;
|
||||
default:
|
||||
PWRN("Unsupported for %s", names[id].name);
|
||||
}
|
||||
if (enable)
|
||||
_enable(id);
|
||||
else
|
||||
_disable(id);
|
||||
}
|
||||
|
||||
bool state(Regulator_id id)
|
||||
{
|
||||
switch (id) {
|
||||
case CLK_SATA:
|
||||
return _sata_enabled();
|
||||
return read<Clk_gate_ip_fsys::Sata>() &&
|
||||
read<Clk_gate_ip_fsys::Sata_phy_ctrl>() &&
|
||||
read<Clk_src_mask_fsys::Sata_mask>();
|
||||
case CLK_USB30:
|
||||
return _usb30_enabled();
|
||||
return read<Clk_gate_ip_fsys::Usbdrd30>() &&
|
||||
read<Clk_src_mask_fsys::Usbdrd30_mask>();
|
||||
case CLK_MMC0:
|
||||
return read<Clk_gate_ip_fsys::Clk_sdmmc0>() &&
|
||||
read<Clk_src_mask_fsys::Mmc0_mask>();
|
||||
default:
|
||||
PWRN("Unsupported for %s", names[id].name);
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ struct Driver_factory : Regulator::Driver_factory
|
||||
case Regulator::CLK_CPU:
|
||||
case Regulator::CLK_SATA:
|
||||
case Regulator::CLK_USB30:
|
||||
case Regulator::CLK_MMC0:
|
||||
return _cmu;
|
||||
case Regulator::PWR_SATA:
|
||||
case Regulator::PWR_USB30:
|
||||
|
@ -27,16 +27,77 @@ class Pmu : public Regulator::Driver,
|
||||
{
|
||||
private:
|
||||
|
||||
template <unsigned OFF>
|
||||
struct Control : Register <OFF, 32>
|
||||
template <unsigned OFFSET>
|
||||
struct Control : Register <OFFSET, 32>
|
||||
{
|
||||
struct Enable : Register<OFF, 32>::template Bitfield<0, 1> { };
|
||||
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> { };
|
||||
};
|
||||
|
||||
typedef Control<0x700> Hdmi_phy_control;
|
||||
typedef Control<0x704> Usbdrd_phy_control;
|
||||
typedef Control<0x708> Usbhost_phy_control;
|
||||
typedef Control<0x70c> Efnand_phy_control;
|
||||
typedef Control<0x718> Adc_phy_control;
|
||||
typedef Control<0x71c> Mtcadc_phy_control;
|
||||
typedef Control<0x720> Dptx_phy_control;
|
||||
typedef Control<0x724> Sata_phy_control;
|
||||
|
||||
typedef Sysclk_configuration<0x2a40> Vpll_sysclk_configuration;
|
||||
typedef Sysclk_status<0x2a44> Vpll_sysclk_status;
|
||||
typedef Sysclk_configuration<0x2a60> Epll_sysclk_configuration;
|
||||
typedef Sysclk_status<0x2a64> Epll_sysclk_status;
|
||||
typedef Sysclk_configuration<0x2aa0> Cpll_sysclk_configuration;
|
||||
typedef Sysclk_status<0x2aa4> Cpll_sysclk_status;
|
||||
typedef Sysclk_configuration<0x2ac0> Gpll_sysclk_configuration;
|
||||
typedef Sysclk_status<0x2ac4> Gpll_sysclk_status;
|
||||
|
||||
typedef Configuration<0x4000> Gscl_configuration;
|
||||
typedef Status<0x4004> Gscl_status;
|
||||
typedef Configuration<0x4020> Isp_configuration;
|
||||
typedef Status<0x4024> Isp_status;
|
||||
typedef Configuration<0x4040> Mfc_configuration;
|
||||
typedef Status<0x4044> Mfc_status;
|
||||
typedef Configuration<0x4060> G3d_configuration;
|
||||
typedef Status<0x4064> G3d_status;
|
||||
typedef Configuration<0x40A0> Disp1_configuration;
|
||||
typedef Status<0x40A4> Disp1_status;
|
||||
typedef Configuration<0x40C0> Mau_configuration;
|
||||
typedef Status<0x40C4> Mau_status;
|
||||
|
||||
|
||||
template <typename C, typename S>
|
||||
void _disable_domain()
|
||||
{
|
||||
if (read<typename S::Stat>() == 0)
|
||||
return;
|
||||
write<typename C::Local_pwr_cfg>(0);
|
||||
while (read<typename S::Stat>() != 0) ;
|
||||
}
|
||||
|
||||
|
||||
/***********************
|
||||
** USB 3.0 functions **
|
||||
@ -67,7 +128,29 @@ class Pmu : public Regulator::Driver,
|
||||
* Constructor
|
||||
*/
|
||||
Pmu() : Genode::Attached_mmio(Genode::Board_base::PMU_MMIO_BASE,
|
||||
Genode::Board_base::PMU_MMIO_SIZE) { }
|
||||
Genode::Board_base::PMU_MMIO_SIZE)
|
||||
{
|
||||
write<Hdmi_phy_control ::Enable>(0);
|
||||
write<Usbdrd_phy_control ::Enable>(0);
|
||||
write<Usbhost_phy_control::Enable>(0);
|
||||
write<Efnand_phy_control ::Enable>(0);
|
||||
write<Adc_phy_control ::Enable>(0);
|
||||
write<Mtcadc_phy_control ::Enable>(0);
|
||||
write<Dptx_phy_control ::Enable>(0);
|
||||
write<Sata_phy_control ::Enable>(0);
|
||||
|
||||
_disable_domain<Gscl_configuration, Gscl_status>();
|
||||
_disable_domain<Isp_configuration, Isp_status>();
|
||||
_disable_domain<Mfc_configuration, Mfc_status>();
|
||||
_disable_domain<G3d_configuration, G3d_status>();
|
||||
_disable_domain<Disp1_configuration, Disp1_status>();
|
||||
_disable_domain<Mau_configuration, Mau_status>();
|
||||
|
||||
_disable_domain<Vpll_sysclk_configuration, Vpll_sysclk_status>();
|
||||
_disable_domain<Epll_sysclk_configuration, Epll_sysclk_status>();
|
||||
_disable_domain<Cpll_sysclk_configuration, Cpll_sysclk_status>();
|
||||
_disable_domain<Gpll_sysclk_configuration, Gpll_sysclk_status>();
|
||||
}
|
||||
|
||||
|
||||
/********************************
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <base/sleep.h>
|
||||
#include <base/printf.h>
|
||||
#include <cap_session/connection.h>
|
||||
#include <regulator_session/connection.h>
|
||||
|
||||
/* local includes */
|
||||
#include <driver.h>
|
||||
@ -48,7 +49,8 @@ int main(int argc, char **argv)
|
||||
enum { STACK_SIZE = 8192 };
|
||||
static Cap_connection cap;
|
||||
static Rpc_entrypoint ep(&cap, STACK_SIZE, "block_ep");
|
||||
|
||||
static Regulator::Connection mmc0_regulator(Regulator::CLK_MMC0);
|
||||
mmc0_regulator.set_state(true);
|
||||
static Block::Root block_root(&ep, env()->heap(), driver_factory);
|
||||
env()->parent()->announce(ep.manage(&block_root));
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user