mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-14 17:07:38 +00:00
db4256f60d
The CPUWD reset reason is used for kmp204x. And the qrio cpu reset request is configured to operate in core reset mode. But for the evaluation of the qrio's reset reason register the CPUWD figures as a unit reset source rather than a core reset source. This patch defines the CPUWD reset as a core reset source when evaluating the reset reason register. Signed-off-by: Rainer Boschung <rainer.boschung@ch.abb.com> CC: Priyanka Jain <priyanka.jain@nxp.com>
279 lines
5.8 KiB
C
279 lines
5.8 KiB
C
// SPDX-License-Identifier: GPL-2.0+
|
|
/*
|
|
* (C) Copyright 2013 Keymile AG
|
|
* Valentin Longchamp <valentin.longchamp@keymile.com>
|
|
*/
|
|
|
|
#include <common.h>
|
|
|
|
#include "common.h"
|
|
#include "qrio.h"
|
|
|
|
/* QRIO GPIO register offsets */
|
|
#define DIRECT_OFF 0x18
|
|
#define GPRT_OFF 0x1c
|
|
|
|
int qrio_get_gpio(u8 port_off, u8 gpio_nr)
|
|
{
|
|
u32 gprt;
|
|
|
|
void __iomem *qrio_base = (void *)CONFIG_SYS_QRIO_BASE;
|
|
|
|
gprt = in_be32(qrio_base + port_off + GPRT_OFF);
|
|
|
|
return (gprt >> gpio_nr) & 1U;
|
|
}
|
|
|
|
void qrio_set_gpio(u8 port_off, u8 gpio_nr, bool value)
|
|
{
|
|
u32 gprt, mask;
|
|
|
|
void __iomem *qrio_base = (void *)CONFIG_SYS_QRIO_BASE;
|
|
|
|
mask = 1U << gpio_nr;
|
|
|
|
gprt = in_be32(qrio_base + port_off + GPRT_OFF);
|
|
if (value)
|
|
gprt |= mask;
|
|
else
|
|
gprt &= ~mask;
|
|
|
|
out_be32(qrio_base + port_off + GPRT_OFF, gprt);
|
|
}
|
|
|
|
void qrio_gpio_direction_output(u8 port_off, u8 gpio_nr, bool value)
|
|
{
|
|
u32 direct, mask;
|
|
|
|
void __iomem *qrio_base = (void *)CONFIG_SYS_QRIO_BASE;
|
|
|
|
mask = 1U << gpio_nr;
|
|
|
|
direct = in_be32(qrio_base + port_off + DIRECT_OFF);
|
|
direct |= mask;
|
|
out_be32(qrio_base + port_off + DIRECT_OFF, direct);
|
|
|
|
qrio_set_gpio(port_off, gpio_nr, value);
|
|
}
|
|
|
|
void qrio_gpio_direction_input(u8 port_off, u8 gpio_nr)
|
|
{
|
|
u32 direct, mask;
|
|
|
|
void __iomem *qrio_base = (void *)CONFIG_SYS_QRIO_BASE;
|
|
|
|
mask = 1U << gpio_nr;
|
|
|
|
direct = in_be32(qrio_base + port_off + DIRECT_OFF);
|
|
direct &= ~mask;
|
|
out_be32(qrio_base + port_off + DIRECT_OFF, direct);
|
|
}
|
|
|
|
void qrio_set_opendrain_gpio(u8 port_off, u8 gpio_nr, u8 val)
|
|
{
|
|
u32 direct, mask;
|
|
|
|
void __iomem *qrio_base = (void *)CONFIG_SYS_QRIO_BASE;
|
|
|
|
mask = 1U << gpio_nr;
|
|
|
|
direct = in_be32(qrio_base + port_off + DIRECT_OFF);
|
|
if (val == 0)
|
|
/* set to output -> GPIO drives low */
|
|
direct |= mask;
|
|
else
|
|
/* set to input -> GPIO floating */
|
|
direct &= ~mask;
|
|
|
|
out_be32(qrio_base + port_off + DIRECT_OFF, direct);
|
|
}
|
|
|
|
#define WDMASK_OFF 0x16
|
|
|
|
void qrio_wdmask(u8 bit, bool wden)
|
|
{
|
|
u16 wdmask;
|
|
void __iomem *qrio_base = (void *)CONFIG_SYS_QRIO_BASE;
|
|
|
|
wdmask = in_be16(qrio_base + WDMASK_OFF);
|
|
|
|
if (wden)
|
|
wdmask |= (1 << bit);
|
|
else
|
|
wdmask &= ~(1 << bit);
|
|
|
|
out_be16(qrio_base + WDMASK_OFF, wdmask);
|
|
}
|
|
|
|
#define PRST_OFF 0x1a
|
|
|
|
void qrio_prst(u8 bit, bool en, bool wden)
|
|
{
|
|
u16 prst;
|
|
void __iomem *qrio_base = (void *)CONFIG_SYS_QRIO_BASE;
|
|
|
|
qrio_wdmask(bit, wden);
|
|
|
|
prst = in_be16(qrio_base + PRST_OFF);
|
|
|
|
if (en)
|
|
prst &= ~(1 << bit);
|
|
else
|
|
prst |= (1 << bit);
|
|
|
|
out_be16(qrio_base + PRST_OFF, prst);
|
|
}
|
|
|
|
#define PRSTCFG_OFF 0x1c
|
|
|
|
void qrio_prstcfg(u8 bit, u8 mode)
|
|
{
|
|
u32 prstcfg;
|
|
u8 i;
|
|
void __iomem *qrio_base = (void *)CONFIG_SYS_QRIO_BASE;
|
|
|
|
prstcfg = in_be32(qrio_base + PRSTCFG_OFF);
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
if (mode & (1 << i))
|
|
set_bit(2 * bit + i, &prstcfg);
|
|
else
|
|
clear_bit(2 * bit + i, &prstcfg);
|
|
}
|
|
|
|
out_be32(qrio_base + PRSTCFG_OFF, prstcfg);
|
|
}
|
|
|
|
#define CTRLH_OFF 0x02
|
|
#define CTRLH_WRL_BOOT 0x01
|
|
#define CTRLH_WRL_UNITRUN 0x02
|
|
|
|
void qrio_set_leds(void)
|
|
{
|
|
u8 ctrlh;
|
|
void __iomem *qrio_base = (void *)CONFIG_SYS_QRIO_BASE;
|
|
|
|
/* set UNIT LED to RED and BOOT LED to ON */
|
|
ctrlh = in_8(qrio_base + CTRLH_OFF);
|
|
ctrlh |= (CTRLH_WRL_BOOT | CTRLH_WRL_UNITRUN);
|
|
out_8(qrio_base + CTRLH_OFF, ctrlh);
|
|
}
|
|
|
|
#define CTRLL_OFF 0x03
|
|
#define CTRLL_WRB_BUFENA 0x20
|
|
|
|
void qrio_enable_app_buffer(void)
|
|
{
|
|
u8 ctrll;
|
|
void __iomem *qrio_base = (void *)CONFIG_SYS_QRIO_BASE;
|
|
|
|
/* enable application buffer */
|
|
ctrll = in_8(qrio_base + CTRLL_OFF);
|
|
ctrll |= (CTRLL_WRB_BUFENA);
|
|
out_8(qrio_base + CTRLL_OFF, ctrll);
|
|
}
|
|
|
|
#define REASON1_OFF 0x12
|
|
#define REASON1_CPUWD 0x01
|
|
|
|
void qrio_cpuwd_flag(bool flag)
|
|
{
|
|
u8 reason1;
|
|
void __iomem *qrio_base = (void *)CONFIG_SYS_QRIO_BASE;
|
|
|
|
reason1 = in_8(qrio_base + REASON1_OFF);
|
|
if (flag)
|
|
reason1 |= REASON1_CPUWD;
|
|
else
|
|
reason1 &= ~REASON1_CPUWD;
|
|
out_8(qrio_base + REASON1_OFF, reason1);
|
|
}
|
|
|
|
#define REASON0_OFF 0x13
|
|
#define REASON0_SWURST 0x80
|
|
#define REASON0_CPURST 0x40
|
|
#define REASON0_BPRST 0x20
|
|
#define REASON0_COPRST 0x10
|
|
#define REASON0_SWCRST 0x08
|
|
#define REASON0_WDRST 0x04
|
|
#define REASON0_KBRST 0x02
|
|
#define REASON0_POWUP 0x01
|
|
#define UNIT_RESET\
|
|
(REASON0_POWUP | REASON0_COPRST | REASON0_KBRST |\
|
|
REASON0_BPRST | REASON0_SWURST | REASON0_WDRST)
|
|
#define CORE_RESET ((REASON1_CPUWD << 8) | REASON0_SWCRST)
|
|
|
|
bool qrio_reason_unitrst(void)
|
|
{
|
|
u16 reason;
|
|
void __iomem *qrio_base = (void *)CONFIG_SYS_QRIO_BASE;
|
|
|
|
reason = in_be16(qrio_base + REASON1_OFF);
|
|
|
|
return (reason & UNIT_RESET) > 0;
|
|
}
|
|
|
|
#define RSTCFG_OFF 0x11
|
|
|
|
void qrio_uprstreq(u8 mode)
|
|
{
|
|
u32 rstcfg;
|
|
void __iomem *qrio_base = (void *)CONFIG_SYS_QRIO_BASE;
|
|
|
|
rstcfg = in_8(qrio_base + RSTCFG_OFF);
|
|
|
|
if (mode & UPREQ_CORE_RST)
|
|
rstcfg |= UPREQ_CORE_RST;
|
|
else
|
|
rstcfg &= ~UPREQ_CORE_RST;
|
|
|
|
out_8(qrio_base + RSTCFG_OFF, rstcfg);
|
|
}
|
|
|
|
/* I2C deblocking uses the algorithm defined in board/keymile/common/common.c
|
|
* 2 dedicated QRIO GPIOs externally pull the SCL and SDA lines
|
|
* For I2C only the low state is activly driven and high state is pulled-up
|
|
* by a resistor. Therefore the deblock GPIOs are used
|
|
* -> as an active output to drive a low state
|
|
* -> as an open-drain input to have a pulled-up high state
|
|
*/
|
|
|
|
/* By default deblock GPIOs are floating */
|
|
void i2c_deblock_gpio_cfg(void)
|
|
{
|
|
/* set I2C bus 1 deblocking GPIOs input, but 0 value for open drain */
|
|
qrio_gpio_direction_input(KM_I2C_DEBLOCK_PORT,
|
|
KM_I2C_DEBLOCK_SCL);
|
|
qrio_gpio_direction_input(KM_I2C_DEBLOCK_PORT,
|
|
KM_I2C_DEBLOCK_SDA);
|
|
|
|
qrio_set_gpio(KM_I2C_DEBLOCK_PORT,
|
|
KM_I2C_DEBLOCK_SCL, 0);
|
|
qrio_set_gpio(KM_I2C_DEBLOCK_PORT,
|
|
KM_I2C_DEBLOCK_SDA, 0);
|
|
}
|
|
|
|
void set_sda(int state)
|
|
{
|
|
qrio_set_opendrain_gpio(KM_I2C_DEBLOCK_PORT,
|
|
KM_I2C_DEBLOCK_SDA, state);
|
|
}
|
|
|
|
void set_scl(int state)
|
|
{
|
|
qrio_set_opendrain_gpio(KM_I2C_DEBLOCK_PORT,
|
|
KM_I2C_DEBLOCK_SCL, state);
|
|
}
|
|
|
|
int get_sda(void)
|
|
{
|
|
return qrio_get_gpio(KM_I2C_DEBLOCK_PORT,
|
|
KM_I2C_DEBLOCK_SDA);
|
|
}
|
|
|
|
int get_scl(void)
|
|
{
|
|
return qrio_get_gpio(KM_I2C_DEBLOCK_PORT,
|
|
KM_I2C_DEBLOCK_SCL);
|
|
}
|
|
|