blob: 9a633baeb984a86df078072e50087692b5076865 [file] [log] [blame]
/*
* Copyright 2017, Data61, CSIRO (ABN 41 687 119 230)
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <platsupport/src.h>
#include "../../services.h"
/** PWRREG **/
#define PWRREG_PHY_CONTROL_OFFSET 0x708
#define PWRREG_PHY_CONTROL_PHY_EN BIT(0)
#define PWRREG_SWRST_OFFSET 0x400
#define PWRREG_SWRST BIT(0)
/** SYSREG **/
#define SYSREG_PHY_CONFIG_OFFSET 0x230
#define SYSREG_PHY_CONFIG_PHY_EN BIT(0)
struct src_priv {
void* sysreg_vaddr[1];
void* pwrreg_vaddr[5];
};
struct src_priv _src_priv;
static inline struct src_priv*
src_get_priv(src_dev_t* d) {
return (struct src_priv*)d->priv;
}
static inline volatile uint32_t*
sreg(struct src_priv* src, int offset)
{
void* reg = src->sysreg_vaddr[offset >> 12] + (offset & MASK(12));
return (volatile uint32_t*)reg;
}
static inline volatile uint32_t*
preg(struct src_priv* src, int offset)
{
void* reg_base;
reg_base = src->pwrreg_vaddr[offset >> 12];
if (reg_base) {
return (volatile uint32_t*)(reg_base + (offset & MASK(12)));
} else {
return NULL;
}
}
int
sysreg_usbphy_enable(src_dev_t* dev)
{
volatile uint32_t* a;
struct src_priv* priv = src_get_priv(dev);
a = sreg(priv, SYSREG_PHY_CONFIG_OFFSET);
if (a) {
*a |= SYSREG_PHY_CONFIG_PHY_EN;
}
a = preg(priv, PWRREG_PHY_CONTROL_OFFSET);
if (a) {
*a |= PWRREG_PHY_CONTROL_PHY_EN;
}
return 0;
}
int
sysreg_swrst_enable(src_dev_t* dev)
{
struct src_priv* priv = src_get_priv(dev);
volatile uint32_t* a;
a = preg(priv, PWRREG_SWRST_OFFSET);
if (a) {
LOG_INFO("Software reset triggered");
fflush(stdout);
*a = PWRREG_SWRST;
while (1);
}
return 0;
}
void
reset_controller_assert_reset(src_dev_t* dev, enum src_rst_id id)
{
switch (id) {
case SRCRST_SW_RST:
sysreg_swrst_enable(dev);
break;
case SRCRST_USBPHY_EN:
sysreg_usbphy_enable(dev);
break;
default:
LOG_ERROR("Invalid option: %d", id);
}
}
int
reset_controller_init(enum src_id id, ps_io_ops_t* ops, src_dev_t* dev)
{
struct src_priv* src_priv = &_src_priv;
int i;
/* Sanity check the provided ID */
if (id < 0 || id >= NSRC) {
return -1;
}
/* Map sysreg memory */
for (i = 0; i < EXYNOS_SYSREG_SIZE >> 12; i++) {
if (src_priv->sysreg_vaddr[i] == NULL) {
void *vaddr;
vaddr = ps_io_map(&ops->io_mapper,
EXYNOS_SYSREG_PADDR + i * BIT(12),
0x1000, 0, PS_MEM_NORMAL);
src_priv->sysreg_vaddr[i] = vaddr;
}
}
/* Map pmu memory */
for (i = 0; i < EXYNOS_PMU_SIZE >> 12; i++) {
if (src_priv->pwrreg_vaddr[i] == NULL) {
void *vaddr;
vaddr = ps_io_map(&ops->io_mapper,
EXYNOS_PMU_PADDR + i * BIT(12),
0x1000 , 0, PS_MEM_NORMAL);
src_priv->pwrreg_vaddr[i] = vaddr;
}
}
/* Assign private data */
dev->priv = src_priv;
return 0;
}