blob: 9f7b4a6758374fe420fb295b50113c3229661fd2 [file] [log] [blame]
// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <fbl/auto_lock.h>
#include "src/devices/usb/drivers/dwc3/dwc3-regs.h"
#include "src/devices/usb/drivers/dwc3/dwc3.h"
namespace dwc3 {
void Dwc3::CmdStartNewConfig(const Endpoint& ep, uint32_t rsrc_id) {
fbl::AutoLock lock(&lock_);
auto* mmio = get_mmio();
const uint8_t ep_num = ep.ep_num;
DEPCMDPAR0::Get(ep_num).FromValue(0).WriteTo(mmio);
DEPCMDPAR1::Get(ep_num).FromValue(0).WriteTo(mmio);
DEPCMDPAR2::Get(ep_num).FromValue(0).WriteTo(mmio);
DEPCMD::Get(ep_num)
.FromValue(0)
.set_CMDTYP(DEPCMD::DEPSTARTCFG)
.set_COMMANDPARAM(rsrc_id)
.set_CMDACT(1)
.WriteTo(mmio);
}
void Dwc3::CmdEpSetConfig(const Endpoint& ep, bool modify) {
fbl::AutoLock lock(&lock_);
auto* mmio = get_mmio();
const uint8_t ep_num = ep.ep_num;
// fifo number is zero for OUT endpoints and EP0_IN
const uint32_t fifo_num = (ep.IsOutput() || (ep_num == kEp0In)) ? 0 : ep_num >> 1;
const uint32_t action =
modify ? DEPCFG_DEPCMDPAR0::ACTION_MODIFY : DEPCFG_DEPCMDPAR0::ACTION_INITIALIZE;
DEPCFG_DEPCMDPAR0::Get(ep_num)
.FromValue(0)
.set_FIFO_NUM(fifo_num)
.set_MAX_PACKET_SIZE(ep.max_packet_size)
.set_EP_TYPE(ep.type)
.set_ACTION(action)
.WriteTo(mmio);
DEPCFG_DEPCMDPAR1::Get(ep_num)
.FromValue(0)
.set_EP_NUMBER(ep_num)
.set_INTERVAL(ep.interval)
.set_XFER_NOT_READY_EN(1)
.set_XFER_COMPLETE_EN(1)
.set_INTR_NUM(0)
.WriteTo(mmio);
DEPCMDPAR2::Get(ep_num).FromValue(0).WriteTo(mmio);
DEPCMD::Get(ep_num).FromValue(0).set_CMDTYP(DEPCMD::DEPCFG).set_CMDACT(1).WriteTo(mmio);
}
void Dwc3::CmdEpTransferConfig(const Endpoint& ep) {
fbl::AutoLock lock(&lock_);
auto* mmio = get_mmio();
const uint8_t ep_num = ep.ep_num;
DEPCMDPAR0::Get(ep_num).FromValue(0).set_PARAMETER(1).WriteTo(mmio);
DEPCMDPAR1::Get(ep_num).FromValue(0).WriteTo(mmio);
DEPCMDPAR2::Get(ep_num).FromValue(0).WriteTo(mmio);
DEPCMD::Get(ep_num).FromValue(0).set_CMDTYP(DEPCMD::DEPXFERCFG).set_CMDACT(1).WriteTo(mmio);
}
void Dwc3::CmdEpStartTransfer(const Endpoint& ep, zx_paddr_t trb_phys) {
fbl::AutoLock lock(&lock_);
auto* mmio = get_mmio();
const uint8_t ep_num = ep.ep_num;
DEPCMDPAR0::Get(ep_num)
.FromValue(0)
.set_PARAMETER(static_cast<uint32_t>(trb_phys >> 32))
.WriteTo(mmio);
DEPCMDPAR1::Get(ep_num).FromValue(0).set_PARAMETER(static_cast<uint32_t>(trb_phys)).WriteTo(mmio);
DEPCMDPAR2::Get(ep_num).FromValue(0).WriteTo(mmio);
DEPCMD::Get(ep_num)
.FromValue(0)
.set_CMDTYP(DEPCMD::DEPSTRTXFER)
.set_CMDACT(1)
.set_CMDIOC(1)
.WriteTo(mmio);
while (DEPCMD::Get(ep_num).ReadFrom(mmio).CMDACT()) {
usleep(1000);
}
}
void Dwc3::CmdEpEndTransfer(const Endpoint& ep) {
fbl::AutoLock lock(&lock_);
auto* mmio = get_mmio();
const uint32_t ep_num = ep.ep_num;
const uint32_t rsrc_id = ep.rsrc_id;
DEPCMDPAR0::Get(ep_num).FromValue(0).WriteTo(mmio);
DEPCMDPAR1::Get(ep_num).FromValue(0).WriteTo(mmio);
DEPCMDPAR2::Get(ep_num).FromValue(0).WriteTo(mmio);
DEPCMD::Get(ep_num)
.FromValue(0)
.set_CMDTYP(DEPCMD::DEPENDXFER)
.set_COMMANDPARAM(rsrc_id)
.set_CMDACT(1)
.set_CMDIOC(1)
.set_HIPRI_FORCERM(1)
.WriteTo(mmio);
while (DEPCMD::Get(ep_num).ReadFrom(mmio).CMDACT()) {
usleep(1000);
}
}
void Dwc3::CmdEpSetStall(const Endpoint& ep) {
fbl::AutoLock lock(&lock_);
auto* mmio = get_mmio();
const uint32_t ep_num = ep.ep_num;
DEPCMDPAR0::Get(ep_num).FromValue(0).WriteTo(mmio);
DEPCMDPAR1::Get(ep_num).FromValue(0).WriteTo(mmio);
DEPCMDPAR2::Get(ep_num).FromValue(0).WriteTo(mmio);
DEPCMD::Get(ep_num)
.FromValue(0)
.set_CMDTYP(DEPCMD::DEPSSTALL)
.set_CMDACT(1)
.set_CMDIOC(1)
.WriteTo(mmio);
while (DEPCMD::Get(ep_num).ReadFrom(mmio).CMDACT()) {
usleep(1000);
}
}
void Dwc3::CmdEpClearStall(const Endpoint& ep) {
fbl::AutoLock lock(&lock_);
auto* mmio = get_mmio();
const uint32_t ep_num = ep.ep_num;
DEPCMDPAR0::Get(ep_num).FromValue(0).WriteTo(mmio);
DEPCMDPAR1::Get(ep_num).FromValue(0).WriteTo(mmio);
DEPCMDPAR2::Get(ep_num).FromValue(0).WriteTo(mmio);
DEPCMD::Get(ep_num)
.FromValue(0)
.set_CMDTYP(DEPCMD::DEPCSTALL)
.set_CMDACT(1)
.set_CMDIOC(1)
.WriteTo(mmio);
while (DEPCMD::Get(ep_num).ReadFrom(mmio).CMDACT()) {
usleep(1000);
}
}
} // namespace dwc3