ahci: remove Exynos5 support

Exynos5 support has ceased on Genode

issue #3636
This commit is contained in:
Sebastian Sumpf 2020-02-05 17:21:59 +01:00 committed by Norman Feske
parent de24035066
commit 73f2c7043c
2 changed files with 0 additions and 405 deletions

View File

@ -1,400 +0,0 @@
/*
* \brief Driver for Exynos-5250 soc
* \author Martin Stein
* \author Sebastian Sumpf
* \date 2015-05-04
*/
/*
* Copyright (C) 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.
*/
#include <drivers/defs/exynos5.h>
#include <irq_session/connection.h>
#include <regulator/consts.h>
#include <regulator_session/connection.h>
#include <ahci.h>
using namespace Genode;
/**
* I2C master interface
*/
struct I2c_interface : Attached_mmio
{
enum { TX_DELAY_US = 1 };
/********************************
** MMIO structure description **
********************************/
struct Start_msg : Genode::Register<8>
{
struct Addr : Bitfield<1, 7> { };
};
struct Con : Register<0x0, 8>
{
struct Tx_prescaler : Bitfield<0, 4> { };
struct Irq_pending : Bitfield<4, 1> { };
struct Irq_en : Bitfield<5, 1> { };
struct Clk_sel : Bitfield<6, 1> { };
struct Ack_en : Bitfield<7, 1> { };
};
struct Stat : Register<0x4, 8>
{
struct Last_bit : Bitfield<0, 1> { };
struct Arbitr : Bitfield<3, 1> { };
struct Txrx_en : Bitfield<4, 1> { };
struct Busy : Bitfield<5, 1> { };
struct Mode : Bitfield<6, 2> { };
};
struct Add : Register<0x8, 8>
{
struct Slave_addr : Bitfield<0, 8> { };
};
struct Ds : Register<0xc, 8> { };
struct Lc : Register<0x10, 8>
{
struct Sda_out_delay : Bitfield<0, 2> { };
struct Filter_en : Bitfield<2, 1> { };
};
Mmio::Delayer &delayer;
/* single-word message that starts a multi-word message transfer */
Start_msg::access_t const start_msg;
/**
* Constructor
*
* \param base physical MMIO base
* \param slave_addr ID of the targeted slave
*/
I2c_interface(Genode::Env &env,
addr_t base, unsigned slave_addr, Mmio::Delayer &delayer)
: Attached_mmio(env, base, 0x10000), delayer(delayer),
start_msg(Start_msg::Addr::bits(slave_addr))
{ }
/**
* Wether acknowledgment for last transaction can be received
*/
bool ack_received()
{
for (unsigned i = 0; i < 3; i++) {
if (read<Con::Irq_pending>() && !read<Stat::Last_bit>()) return 1;
delayer.usleep(TX_DELAY_US);
}
Genode::error("I2C ack not received");
return 0;
}
/**
* Wether arbitration errors occured during the last transaction
*/
bool arbitration_error()
{
if (read<Stat::Arbitr>()) {
Genode::error("I2C arbitration failed");
return 1;
}
return 0;
}
/**
* Let I2C master send a message to I2C slave
*
* \param msg message base
* \param msg_size message size
*
* \retval 0 call was successful
* \retval <0 call failed, error code
*/
int send(uint8_t * msg, size_t msg_size)
{
/* initiate message transfer */
try {
wait_for(delayer, Stat::Busy::Equal(0));
} catch (Polling_timeout) {
Genode::error("I2C busy");
return -1;
}
Stat::access_t stat = read<Stat>();
Stat::Txrx_en::set(stat, 1);
Stat::Mode::set(stat, 3);
write<Stat>(stat);
write<Ds>(start_msg);
delayer.usleep(1000);
write<Con::Tx_prescaler>(11);
write<Stat::Busy>(1);
/* transmit message payload */
for (unsigned i = 0; i < msg_size; i++) {
if (!ack_received()) return -1;
write<Ds>(msg[i]);
delayer.usleep(TX_DELAY_US);
write<Con::Irq_pending>(0);
if (arbitration_error()) return -1;
}
/* end message transfer */
if (!ack_received()) return -1;
write<Stat::Busy>(0);
write<Con::Irq_en>(0);
write<Con::Irq_pending>(0); /* FIXME fixup */
if (arbitration_error()) return -1;
try {
wait_for(delayer, Stat::Busy::Equal(0));
} catch (Polling_timeout) {
Genode::error("I2C end transfer failed");
return -1;
}
return 0;
}
};
/**
* I2C control interface of SATA PHY-layer controller
*/
struct I2c_sataphy : I2c_interface
{
enum { SLAVE_ADDR = 0x38 };
/**
* Constructor
*/
I2c_sataphy(Genode::Env &env, Mmio::Delayer &delayer)
: I2c_interface(env, 0x121d0000, SLAVE_ADDR, delayer)
{ }
/**
* Enable the 40-pin interface of the SATA PHY controller
*
* \retval 0 call was successful
* \retval <0 call failed, error code
*/
int enable_40_pins()
{
/*
* I2C message
*
* first byte: set address
* second byte: set data
*/
static uint8_t msg[] = { 0x3a, 0x0b };
enum { MSG_SIZE = sizeof(msg)/sizeof(msg[0]) };
/* send messaage */
if (send(msg, MSG_SIZE)) return -1;
if (verbose) Genode::log("SATA PHY 40-pin interface enabled");
return 0;
}
/**
* Get I2C interface ready for transmissions
*/
void init()
{
write<Add::Slave_addr>(SLAVE_ADDR);
Con::access_t con = read<Con>();
Con::Irq_en::set(con, 1);
Con::Ack_en::set(con, 1);
Con::Clk_sel::set(con, 1);
Con::Tx_prescaler::set(con, 9);
write<Con>(con);
Lc::access_t lc = 0;
Lc::Sda_out_delay::set(lc, 3);
Lc::Filter_en::set(lc, 1);
write<Lc>(lc);
}
};
/**
* Classical control interface of SATA PHY-layer controller
*/
struct Sata_phy_ctrl : Attached_mmio
{
Mmio::Delayer &delayer;
I2c_sataphy i2c_sataphy;
/********************************
** MMIO structure description **
********************************/
struct Reset : Register<0x4, 32>
{
struct Global : Bitfield<1, 1> { };
struct Non_link : Bitfield<0, 8> { };
struct Link : Bitfield<16, 4> { };
};
struct Mode0 : Register<0x10, 32>
{
struct P0_phy_spdmode : Bitfield<0, 2> { };
};
struct Ctrl0 : Register<0x14, 32>
{
struct P0_phy_calibrated : Bitfield<8, 1> { };
struct P0_phy_calibrated_sel : Bitfield<9, 1> { };
};
struct Phctrlm : Register<0xe0, 32>
{
struct High_speed : Bitfield<0, 1> { };
struct Ref_rate : Bitfield<1, 1> { };
};
struct Phstatm : Register<0xf0, 32>
{
struct Pll_locked : Bitfield<0, 1> { };
};
/**
* Constructor
*/
Sata_phy_ctrl(Genode::Env &env, Mmio::Delayer &delayer)
:
Attached_mmio(env, 0x12170000, 0x10000), delayer(delayer),
i2c_sataphy(env, delayer)
{
i2c_sataphy.init();
}
/**
* Initialize parts of SATA PHY that are controlled classically
*
* \retval 0 call was successful
* \retval <0 call failed, error code
*/
int init()
{
/* reset */
write<Reset>(0);
write<Reset::Non_link>(~0);
write<Reset::Link>(~0);
write<Reset::Global>(~0);
/* set up SATA phy generation 3 (6 Gb/s) */
Phctrlm::access_t phctrlm = read<Phctrlm>();
Phctrlm::Ref_rate::set(phctrlm, 0);
Phctrlm::High_speed::set(phctrlm, 1);
write<Phctrlm>(phctrlm);
Ctrl0::access_t ctrl0 = read<Ctrl0>();
Ctrl0::P0_phy_calibrated::set(ctrl0, 1);
Ctrl0::P0_phy_calibrated_sel::set(ctrl0, 1);
write<Ctrl0>(ctrl0);
write<Mode0::P0_phy_spdmode>(2);
if (i2c_sataphy.enable_40_pins()) return -1;
/* Release reset */
write<Reset::Global>(0);
write<Reset::Global>(1);
/*
* FIXME Linux reads this bit once only and continues
* directly, also with zero. So if we get an error
* at this point we should study the Linux behavior
* in more depth.
*/
try {
wait_for(delayer, Phstatm::Pll_locked::Equal(1));
} catch (Polling_timeout) {
Genode::error("PLL lock failed");
return -1;
}
if (verbose)
Genode::log("SATA PHY initialized");
return 0;
}
};
struct Exynos5_hba : Platform::Hba
{
Genode::Env &env;
Irq_connection irq { env, Exynos5::SATA_IRQ };
Regulator::Connection clock_src { env, Regulator::CLK_SATA };
Regulator::Connection power_src { env, Regulator::PWR_SATA };
Exynos5_hba(Genode::Env &env, Mmio::Delayer &delayer)
: env(env)
{
clock_src.state(true);
power_src.state(true);
Sata_phy_ctrl phy(env, delayer);
if (phy.init())
throw Service_denied();
/* additionally perform some generic initializations */
::Hba hba(env, *this, delayer);
::Hba::Cap::access_t cap = hba.read< ::Hba::Cap>();
::Hba::Cap2::access_t cap2 = hba.read< ::Hba::Cap2>();
/* reset */
hba.write< ::Hba::Ghc::Hr>(1);
try {
hba.wait_for(::Hba::Attempts(1000), ::Hba::Microseconds(1000),
hba.delayer(), ::Hba::Ghc::Hr::Equal(0));
} catch (::Hba::Polling_timeout) {
Genode::error("HBA reset failed");
throw Service_denied();
}
hba.write< ::Hba::Cap>(cap);
hba.write< ::Hba::Cap2>(cap2);
/* for exynos set port 0 as implemented, usally set by BIOS */
hba.write< ::Hba::Pi>(0x1);
}
/*******************
** Hba interface **
*******************/
Genode::addr_t base() const override { return 0x122f0000; }
Genode::size_t size() const override { return 0x10000; }
void sigh_irq(Signal_context_capability sigh) override
{
irq.sigh(sigh);
ack_irq();
}
void ack_irq() override { irq.ack_irq(); }
Ram_dataspace_capability
alloc_dma_buffer(size_t size) override
{
return env.ram().alloc(size, UNCACHED);
}
void free_dma_buffer(Ram_dataspace_capability ds) override
{
env.ram().free(ds);
}
};
Platform::Hba &Platform::init(Genode::Env &env, Mmio::Delayer &delayer)
{
static Exynos5_hba h(env, delayer);
return h;
}

View File

@ -1,5 +0,0 @@
TARGET = exynos5_ahci_drv
REQUIRES = arm_v7
INC_DIR = $(call select_from_repositories,include/spec/exynos5)
include $(REP_DIR)/src/drivers/ahci/target.inc