mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-10 07:04:28 +00:00
Merge branch 'master-riic' of https://source.denx.de/u-boot/custodians/u-boot-sh
- New renesas I2C controller driver and new PMIC driver along with enablement of them.
This commit is contained in:
commit
574aac1c8c
19 changed files with 896 additions and 34 deletions
|
@ -223,20 +223,20 @@
|
|||
<GIC_SPI 212 IRQ_TYPE_EDGE_RISING>,
|
||||
<GIC_SPI 213 IRQ_TYPE_EDGE_RISING>;
|
||||
interrupt-names = "tgia0", "tgib0", "tgic0", "tgid0",
|
||||
"tgiv0", "tgie0", "tgif0",
|
||||
"tgia1", "tgib1", "tgiv1", "tgiu1",
|
||||
"tgia2", "tgib2", "tgiv2", "tgiu2",
|
||||
"tciv0", "tgie0", "tgif0",
|
||||
"tgia1", "tgib1", "tciv1", "tciu1",
|
||||
"tgia2", "tgib2", "tciv2", "tciu2",
|
||||
"tgia3", "tgib3", "tgic3", "tgid3",
|
||||
"tgiv3",
|
||||
"tciv3",
|
||||
"tgia4", "tgib4", "tgic4", "tgid4",
|
||||
"tgiv4",
|
||||
"tciv4",
|
||||
"tgiu5", "tgiv5", "tgiw5",
|
||||
"tgia6", "tgib6", "tgic6", "tgid6",
|
||||
"tgiv6",
|
||||
"tciv6",
|
||||
"tgia7", "tgib7", "tgic7", "tgid7",
|
||||
"tgiv7",
|
||||
"tciv7",
|
||||
"tgia8", "tgib8", "tgic8", "tgid8",
|
||||
"tgiv8", "tgiu8";
|
||||
"tciv8", "tciu8";
|
||||
clocks = <&cpg CPG_MOD R9A07G044_MTU_X_MCK_MTU3>;
|
||||
power-domains = <&cpg>;
|
||||
resets = <&cpg R9A07G044_MTU_X_PRESET_MTU3>;
|
||||
|
|
|
@ -6,6 +6,27 @@
|
|||
*/
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
/* Enable SCIF2 (SER0) on PMOD1 (CN7) */
|
||||
#define PMOD1_SER0 1
|
||||
|
||||
/*
|
||||
* To enable MTU3a PWM on PMOD0,
|
||||
* Disable PMOD1_SER0 by setting "#define PMOD1_SER0 0" above and
|
||||
* enable PMOD_MTU3 by setting "#define PMOD_MTU3 1" below.
|
||||
*/
|
||||
#define PMOD_MTU3 0
|
||||
|
||||
#if (PMOD_MTU3 && PMOD1_SER0)
|
||||
#error "Cannot set as PMOD_MTU3 and PMOD1_SER0 are mutually exclusive "
|
||||
#endif
|
||||
|
||||
#define MTU3_COUNTER_Z_PHASE_SIGNAL 0
|
||||
|
||||
#if (!PMOD_MTU3 && MTU3_COUNTER_Z_PHASE_SIGNAL)
|
||||
#error "Cannot set 1 to MTU3_COUNTER_Z_PHASE_SIGNAL as PMOD_MTU3=0"
|
||||
#endif
|
||||
|
||||
#include "r9a07g044l2.dtsi"
|
||||
#include "rzg2l-smarc-som.dtsi"
|
||||
#include "rzg2l-smarc-pinfunction.dtsi"
|
||||
|
|
|
@ -32,12 +32,6 @@
|
|||
stdout-path = "serial0:115200n8";
|
||||
};
|
||||
|
||||
audio_mclock: audio_mclock {
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <11289600>;
|
||||
};
|
||||
|
||||
snd_rzg2l: sound {
|
||||
compatible = "simple-audio-card";
|
||||
simple-audio-card,format = "i2s";
|
||||
|
@ -55,7 +49,7 @@
|
|||
};
|
||||
|
||||
codec_dai: simple-audio-card,codec {
|
||||
clocks = <&audio_mclock>;
|
||||
clocks = <&versa3 2>;
|
||||
sound-dai = <&wm8978>;
|
||||
};
|
||||
};
|
||||
|
@ -76,13 +70,19 @@
|
|||
gpios-states = <1>;
|
||||
states = <3300000 1>, <1800000 0>;
|
||||
};
|
||||
|
||||
x1: x1-clock {
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <24000000>;
|
||||
};
|
||||
};
|
||||
|
||||
&audio_clk1{
|
||||
&audio_clk1 {
|
||||
clock-frequency = <11289600>;
|
||||
};
|
||||
|
||||
&audio_clk2{
|
||||
&audio_clk2 {
|
||||
clock-frequency = <12288000>;
|
||||
};
|
||||
|
||||
|
|
|
@ -53,6 +53,26 @@
|
|||
<RZG2L_PORT_PINMUX(18, 1, 3)>; /* SCL */
|
||||
};
|
||||
|
||||
mtu3_pins: mtu3 {
|
||||
mtu3-ext-clk-input-pin {
|
||||
pinmux = <RZG2L_PORT_PINMUX(48, 0, 4)>, /* MTCLKA */
|
||||
<RZG2L_PORT_PINMUX(48, 1, 4)>; /* MTCLKB */
|
||||
};
|
||||
|
||||
mtu3-pwm {
|
||||
pinmux = <RZG2L_PORT_PINMUX(44, 0, 4)>, /* MTIOC3A */
|
||||
<RZG2L_PORT_PINMUX(44, 1, 4)>, /* MTIOC3B */
|
||||
<RZG2L_PORT_PINMUX(44, 2, 4)>, /* MTIOC3C */
|
||||
<RZG2L_PORT_PINMUX(44, 3, 4)>; /* MTIOC3D */
|
||||
};
|
||||
|
||||
#if MTU3_COUNTER_Z_PHASE_SIGNAL
|
||||
mtu3-zphase-clk {
|
||||
pinmux = <RZG2L_PORT_PINMUX(19, 0, 3)>; /* MTIOC1A */
|
||||
};
|
||||
#endif /* MTU3_COUNTER_Z_PHASE_SIGNAL */
|
||||
};
|
||||
|
||||
scif0_pins: scif0 {
|
||||
pinmux = <RZG2L_PORT_PINMUX(38, 0, 1)>, /* TxD */
|
||||
<RZG2L_PORT_PINMUX(38, 1, 1)>; /* RxD */
|
||||
|
|
|
@ -73,6 +73,13 @@
|
|||
gpios = <&pinctrl RZG2L_GPIO(39, 0) GPIO_ACTIVE_HIGH>;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
/* 32.768kHz crystal */
|
||||
x2: x2-clock {
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <32768>;
|
||||
};
|
||||
};
|
||||
|
||||
&adc {
|
||||
|
@ -100,7 +107,7 @@
|
|||
rxc-skew-psec = <2400>;
|
||||
txc-skew-psec = <2400>;
|
||||
rxdv-skew-psec = <0>;
|
||||
txdv-skew-psec = <0>;
|
||||
txen-skew-psec = <0>;
|
||||
rxd0-skew-psec = <0>;
|
||||
rxd1-skew-psec = <0>;
|
||||
rxd2-skew-psec = <0>;
|
||||
|
@ -128,7 +135,7 @@
|
|||
rxc-skew-psec = <2400>;
|
||||
txc-skew-psec = <2400>;
|
||||
rxdv-skew-psec = <0>;
|
||||
txdv-skew-psec = <0>;
|
||||
txen-skew-psec = <0>;
|
||||
rxd0-skew-psec = <0>;
|
||||
rxd1-skew-psec = <0>;
|
||||
rxd2-skew-psec = <0>;
|
||||
|
@ -148,6 +155,17 @@
|
|||
mali-supply = <®_1p1v>;
|
||||
};
|
||||
|
||||
&i2c3 {
|
||||
raa215300: pmic@12 {
|
||||
compatible = "renesas,raa215300";
|
||||
reg = <0x12>, <0x6f>;
|
||||
reg-names = "main", "rtc";
|
||||
|
||||
clocks = <&x2>;
|
||||
clock-names = "xin";
|
||||
};
|
||||
};
|
||||
|
||||
&ostm1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
|
|
@ -8,9 +8,6 @@
|
|||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/pinctrl/rzg2l-pinctrl.h>
|
||||
|
||||
/* comment the #define statement to disable SCIF2 (SER0) on PMOD1 (CN7) */
|
||||
#define PMOD1_SER0 1
|
||||
|
||||
/ {
|
||||
aliases {
|
||||
serial1 = &scif2;
|
||||
|
@ -113,8 +110,48 @@
|
|||
#sound-dai-cells = <0>;
|
||||
reg = <0x1a>;
|
||||
};
|
||||
|
||||
versa3: clock-generator@68 {
|
||||
compatible = "renesas,5p35023";
|
||||
reg = <0x68>;
|
||||
#clock-cells = <1>;
|
||||
clocks = <&x1>;
|
||||
|
||||
renesas,settings = [
|
||||
80 00 11 19 4c 02 23 7f 83 19 08 a9 5f 25 24 bf
|
||||
00 14 7a e1 00 00 00 00 01 55 59 bb 3f 30 90 b6
|
||||
80 b0 45 c4 95
|
||||
];
|
||||
|
||||
assigned-clocks = <&versa3 0>, <&versa3 1>,
|
||||
<&versa3 2>, <&versa3 3>,
|
||||
<&versa3 4>, <&versa3 5>;
|
||||
assigned-clock-rates = <24000000>, <11289600>,
|
||||
<11289600>, <12000000>,
|
||||
<25000000>, <12288000>;
|
||||
};
|
||||
};
|
||||
|
||||
#if PMOD_MTU3
|
||||
&mtu3 {
|
||||
pinctrl-0 = <&mtu3_pins>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
#if MTU3_COUNTER_Z_PHASE_SIGNAL
|
||||
/* SDHI cd pin is muxed with counter Z phase signal */
|
||||
&sdhi1 {
|
||||
status = "disabled";
|
||||
};
|
||||
#endif /* MTU3_COUNTER_Z_PHASE_SIGNAL */
|
||||
|
||||
&spi1 {
|
||||
status = "disabled";
|
||||
};
|
||||
#endif /* PMOD_MTU3 */
|
||||
|
||||
/*
|
||||
* To enable SCIF2 (SER0) on PMOD1 (CN7)
|
||||
* SW1 should be at position 2->3 so that SER0_CTS# line is activated
|
||||
|
|
|
@ -78,6 +78,7 @@ config RZG2L
|
|||
imply RENESAS_SDHI
|
||||
imply RZG2L_GPIO
|
||||
imply SCIF_CONSOLE
|
||||
imply SYS_I2C_RZ_RIIC
|
||||
imply SYS_MALLOC_F
|
||||
help
|
||||
Enable support for the Renesas RZ/G2L family of SoCs. Currently
|
||||
|
|
|
@ -56,11 +56,3 @@ int board_init(void)
|
|||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void reset_cpu(void)
|
||||
{
|
||||
/*
|
||||
* TODO: Implement reset support once TrustedFirmware supports
|
||||
* the appropriate call.
|
||||
*/
|
||||
}
|
||||
|
|
|
@ -23,8 +23,10 @@ CONFIG_SYS_MALLOC_BOOTPARAMS=y
|
|||
CONFIG_HUSH_PARSER=y
|
||||
CONFIG_CMD_CLK=y
|
||||
CONFIG_CMD_GPIO=y
|
||||
CONFIG_CMD_I2C=y
|
||||
CONFIG_CMD_MMC=y
|
||||
CONFIG_CMD_PART=y
|
||||
CONFIG_CMD_PMIC=y
|
||||
CONFIG_CMD_EXT2=y
|
||||
CONFIG_CMD_EXT4=y
|
||||
CONFIG_CMD_EXT4_WRITE=y
|
||||
|
@ -43,9 +45,14 @@ CONFIG_CLK=y
|
|||
CONFIG_CLK_RENESAS=y
|
||||
# CONFIG_CLK_RCAR_GEN3 is not set
|
||||
CONFIG_GPIO_HOG=y
|
||||
CONFIG_DM_I2C=y
|
||||
CONFIG_MMC_IO_VOLTAGE=y
|
||||
CONFIG_MMC_UHS_SUPPORT=y
|
||||
CONFIG_MMC_HS400_SUPPORT=y
|
||||
CONFIG_DM_PMIC=y
|
||||
CONFIG_PMIC_RAA215300=y
|
||||
CONFIG_DM_REGULATOR=y
|
||||
CONFIG_DM_REGULATOR_FIXED=y
|
||||
CONFIG_DM_REGULATOR_GPIO=y
|
||||
CONFIG_SYSRESET=y
|
||||
CONFIG_SYSRESET_RAA215300=y
|
||||
|
|
|
@ -23,10 +23,18 @@
|
|||
#include <linux/iopoll.h>
|
||||
#include <reset-uclass.h>
|
||||
#include <reset.h>
|
||||
#include <wait_bit.h>
|
||||
|
||||
#include "rzg2l-cpg.h"
|
||||
|
||||
/*
|
||||
* Monitor registers for both clock and reset signals are offset by 0x180 from
|
||||
* the corresponding control registers.
|
||||
*/
|
||||
#define CLK_MON_R(reg) (0x180 + (reg))
|
||||
#define RST_MON_R(reg) (0x180 + (reg))
|
||||
|
||||
#define CPG_TIMEOUT_MSEC 100
|
||||
|
||||
static ulong rzg2l_cpg_clk_get_rate_by_id(struct udevice *dev, unsigned int id);
|
||||
static ulong rzg2l_cpg_clk_get_rate_by_name(struct udevice *dev, const char *name);
|
||||
|
@ -83,9 +91,9 @@ static int rzg2l_cpg_clk_set(struct clk *clk, bool enable)
|
|||
value |= BIT(mod_clk->bit);
|
||||
writel(value, data->base + mod_clk->off);
|
||||
|
||||
if (enable && readl_poll_timeout(data->base + CLK_MON_R(mod_clk->off),
|
||||
value, (value & BIT(mod_clk->bit)),
|
||||
10)) {
|
||||
if (enable && wait_for_bit_32(data->base + CLK_MON_R(mod_clk->off),
|
||||
BIT(mod_clk->bit), enable,
|
||||
CPG_TIMEOUT_MSEC, false)) {
|
||||
dev_err(clk->dev, "Timeout\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
@ -420,7 +428,8 @@ static int rzg2l_cpg_rst_set(struct reset_ctl *reset_ctl, bool asserted)
|
|||
value |= BIT(rst->bit);
|
||||
writel(value, data->base + rst->off);
|
||||
|
||||
return 0;
|
||||
return wait_for_bit_32(data->base + RST_MON_R(rst->off), BIT(rst->bit),
|
||||
asserted, CPG_TIMEOUT_MSEC, false);
|
||||
}
|
||||
|
||||
static int rzg2l_cpg_rst_assert(struct reset_ctl *reset_ctl)
|
||||
|
|
|
@ -524,6 +524,13 @@ config SYS_I2C_ROCKCHIP
|
|||
have several I2C ports and all are provided, controlled by the
|
||||
device tree.
|
||||
|
||||
config SYS_I2C_RZ_RIIC
|
||||
bool "Renesas RZ/G2L RIIC driver"
|
||||
depends on RZG2L && DM_I2C
|
||||
help
|
||||
Support for the I2C controller (RIIC) on the Renesas RZ/G2L SoC
|
||||
family.
|
||||
|
||||
config SYS_I2C_SANDBOX
|
||||
bool "Sandbox I2C driver"
|
||||
depends on SANDBOX && DM_I2C
|
||||
|
|
|
@ -40,6 +40,7 @@ obj-$(CONFIG_SYS_I2C_QUP) += qup_i2c.o
|
|||
obj-$(CONFIG_SYS_I2C_RCAR_I2C) += rcar_i2c.o
|
||||
obj-$(CONFIG_SYS_I2C_RCAR_IIC) += rcar_iic.o
|
||||
obj-$(CONFIG_SYS_I2C_ROCKCHIP) += rk_i2c.o
|
||||
obj-$(CONFIG_SYS_I2C_RZ_RIIC) += rz_riic.o
|
||||
obj-$(CONFIG_SYS_I2C_S3C24X0) += s3c24x0_i2c.o exynos_hs_i2c.o
|
||||
obj-$(CONFIG_SYS_I2C_SANDBOX) += sandbox_i2c.o i2c-emul-uclass.o
|
||||
obj-$(CONFIG_SYS_I2C_SH) += sh_i2c.o
|
||||
|
|
624
drivers/i2c/rz_riic.c
Normal file
624
drivers/i2c/rz_riic.c
Normal file
|
@ -0,0 +1,624 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* RZ/G2L I2C (RIIC) driver
|
||||
*
|
||||
* Copyright (C) 2021-2023 Renesas Electronics Corp.
|
||||
*/
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <clk.h>
|
||||
#include <dm.h>
|
||||
#include <dm/device_compat.h>
|
||||
#include <errno.h>
|
||||
#include <i2c.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/delay.h>
|
||||
#include <reset.h>
|
||||
#include <wait_bit.h>
|
||||
|
||||
#define RIIC_ICCR1 0x00
|
||||
#define RIIC_ICCR2 0x04
|
||||
#define RIIC_ICMR1 0x08
|
||||
#define RIIC_ICMR2 0x0c
|
||||
#define RIIC_ICMR3 0x10
|
||||
#define RIIC_ICFER 0x14
|
||||
#define RIIC_ICSER 0x18
|
||||
#define RIIC_ICIER 0x1c
|
||||
#define RIIC_ICSR1 0x20
|
||||
#define RIIC_ICSR2 0x24
|
||||
#define RIIC_ICSAR0 0x28
|
||||
#define RIIC_ICBRL 0x34
|
||||
#define RIIC_ICBRH 0x38
|
||||
#define RIIC_ICDRT 0x3c
|
||||
#define RIIC_ICDRR 0x40
|
||||
|
||||
/* ICCR1 */
|
||||
#define ICCR1_ICE BIT(7)
|
||||
#define ICCR1_IICRST BIT(6)
|
||||
#define ICCR1_CLO BIT(5)
|
||||
#define ICCR1_SOWP BIT(4)
|
||||
#define ICCR1_SCLO BIT(3)
|
||||
#define ICCR1_SDAO BIT(2)
|
||||
#define ICCR1_SCLI BIT(1)
|
||||
#define ICCR1_SDAI BIT(0)
|
||||
|
||||
/* ICCR2 */
|
||||
#define ICCR2_BBSY BIT(7)
|
||||
#define ICCR2_MST BIT(6)
|
||||
#define ICCR2_TRS BIT(5)
|
||||
#define ICCR2_SP BIT(3)
|
||||
#define ICCR2_RS BIT(2)
|
||||
#define ICCR2_ST BIT(1)
|
||||
|
||||
/* ICMR1 */
|
||||
#define ICMR1_MTWP BIT(7)
|
||||
#define ICMR1_CKS_MASK GENMASK(6, 4)
|
||||
#define ICMR1_BCWP BIT(3)
|
||||
#define ICMR1_BC_MASK GENMASK(2, 0)
|
||||
|
||||
#define ICMR1_CKS(x) (((x) << 4) & ICMR1_CKS_MASK)
|
||||
#define ICMR1_BC(x) ((x) & ICMR1_BC_MASK)
|
||||
|
||||
/* ICMR2 */
|
||||
#define ICMR2_DLCS BIT(7)
|
||||
#define ICMR2_SDDL_MASK GENMASK(6, 4)
|
||||
#define ICMR2_TMOH BIT(2)
|
||||
#define ICMR2_TMOL BIT(1)
|
||||
#define ICMR2_TMOS BIT(0)
|
||||
|
||||
/* ICMR3 */
|
||||
#define ICMR3_SMBS BIT(7)
|
||||
#define ICMR3_WAIT BIT(6)
|
||||
#define ICMR3_RDRFS BIT(5)
|
||||
#define ICMR3_ACKWP BIT(4)
|
||||
#define ICMR3_ACKBT BIT(3)
|
||||
#define ICMR3_ACKBR BIT(2)
|
||||
#define ICMR3_NF_MASK GENMASK(1, 0)
|
||||
|
||||
/* ICFER */
|
||||
#define ICFER_FMPE BIT(7)
|
||||
#define ICFER_SCLE BIT(6)
|
||||
#define ICFER_NFE BIT(5)
|
||||
#define ICFER_NACKE BIT(4)
|
||||
#define ICFER_SALE BIT(3)
|
||||
#define ICFER_NALE BIT(2)
|
||||
#define ICFER_MALE BIT(1)
|
||||
#define ICFER_TMOE BIT(0)
|
||||
|
||||
/* ICSER */
|
||||
#define ICSER_HOAE BIT(7)
|
||||
#define ICSER_DIDE BIT(5)
|
||||
#define ICSER_GCAE BIT(3)
|
||||
#define ICSER_SAR2E BIT(2)
|
||||
#define ICSER_SAR1E BIT(1)
|
||||
#define ICSER_SAR0E BIT(0)
|
||||
|
||||
/* ICIER */
|
||||
#define ICIER_TIE BIT(7)
|
||||
#define ICIER_TEIE BIT(6)
|
||||
#define ICIER_RIE BIT(5)
|
||||
#define ICIER_NAKIE BIT(4)
|
||||
#define ICIER_SPIE BIT(3)
|
||||
#define ICIER_STIE BIT(2)
|
||||
#define ICIER_ALIE BIT(1)
|
||||
#define ICIER_TMOIE BIT(0)
|
||||
|
||||
/* ICSR1 */
|
||||
#define ICSR1_HOA BIT(7)
|
||||
#define ICSR1_DID BIT(5)
|
||||
#define ICSR1_GCA BIT(3)
|
||||
#define ICSR1_AAS2 BIT(2)
|
||||
#define ICSR1_AAS1 BIT(1)
|
||||
#define ICSR1_AAS0 BIT(0)
|
||||
|
||||
/* ICSR2 */
|
||||
#define ICSR2_TDRE BIT(7)
|
||||
#define ICSR2_TEND BIT(6)
|
||||
#define ICSR2_RDRF BIT(5)
|
||||
#define ICSR2_NACKF BIT(4)
|
||||
#define ICSR2_STOP BIT(3)
|
||||
#define ICSR2_START BIT(2)
|
||||
#define ICSR2_AL BIT(1)
|
||||
#define ICSR2_TMOF BIT(0)
|
||||
|
||||
/* ICBRH */
|
||||
#define ICBRH_RESERVED GENMASK(7, 5) /* The write value should always be 1 */
|
||||
#define ICBRH_BRH_MASK GENMASK(4, 0)
|
||||
|
||||
/* ICBRL */
|
||||
#define ICBRL_RESERVED GENMASK(7, 5) /* The write value should always be 1 */
|
||||
#define ICBRL_BRL_MASK GENMASK(4, 0)
|
||||
|
||||
#define RIIC_TIMEOUT_MSEC 100
|
||||
|
||||
#define RIIC_FLAG_DEFAULT_SCL_RISE_TIME BIT(0)
|
||||
#define RIIC_FLAG_DEFAULT_SCL_FALL_TIME BIT(1)
|
||||
|
||||
/*
|
||||
* If SDA is stuck in a low state, the I2C spec says up to 9 clock cycles on SCL
|
||||
* may be needed to unblock whichever other device on the bus is holding SDA low.
|
||||
*/
|
||||
#define I2C_DEBLOCK_MAX_CYCLES 9
|
||||
|
||||
struct riic_priv {
|
||||
void __iomem *base;
|
||||
struct clk clk;
|
||||
uint bus_speed;
|
||||
u32 scl_rise_ns;
|
||||
u32 scl_fall_ns;
|
||||
u32 flags;
|
||||
};
|
||||
|
||||
static int riic_check_busy(struct udevice *dev)
|
||||
{
|
||||
struct riic_priv *priv = dev_get_priv(dev);
|
||||
int ret;
|
||||
|
||||
ret = wait_for_bit_8(priv->base + RIIC_ICCR2, ICCR2_BBSY, 0,
|
||||
RIIC_TIMEOUT_MSEC, 0);
|
||||
if (ret == -ETIMEDOUT) {
|
||||
dev_dbg(dev, "bus is busy!\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int riic_wait_for_icsr2(struct udevice *dev, u8 bit)
|
||||
{
|
||||
struct riic_priv *priv = dev_get_priv(dev);
|
||||
ulong start = get_timer(0);
|
||||
u8 icsr2;
|
||||
|
||||
/* We can't use wait_for_bit_8() here as we need to check for NACK. */
|
||||
while (!((icsr2 = readb(priv->base + RIIC_ICSR2)) & bit)) {
|
||||
if (icsr2 & ICSR2_NACKF)
|
||||
return -EIO;
|
||||
if (get_timer(start) > RIIC_TIMEOUT_MSEC) {
|
||||
dev_dbg(dev, "timeout! (bit=%x, icsr2=%x, iccr2=%x)\n",
|
||||
bit, icsr2, readb(priv->base + RIIC_ICCR2));
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
udelay(1);
|
||||
schedule();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int riic_check_nack_receive(struct udevice *dev)
|
||||
{
|
||||
struct riic_priv *priv = dev_get_priv(dev);
|
||||
|
||||
if (readb(priv->base + RIIC_ICSR2) & ICSR2_NACKF) {
|
||||
dev_dbg(dev, "received nack!\n");
|
||||
/* received NACK */
|
||||
clrbits_8(priv->base + RIIC_ICSR2, ICSR2_NACKF);
|
||||
setbits_8(priv->base + RIIC_ICCR2, ICCR2_SP);
|
||||
readb(priv->base + RIIC_ICDRR); /* dummy read */
|
||||
return -EIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int riic_i2c_raw_write(struct udevice *dev, u8 *buf, size_t len)
|
||||
{
|
||||
struct riic_priv *priv = dev_get_priv(dev);
|
||||
size_t i;
|
||||
int ret;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
ret = riic_check_nack_receive(dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = riic_wait_for_icsr2(dev, ICSR2_TDRE);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
writeb(buf[i], priv->base + RIIC_ICDRT);
|
||||
}
|
||||
|
||||
return riic_check_nack_receive(dev);
|
||||
}
|
||||
|
||||
static int riic_send_start_cond(struct udevice *dev, int restart)
|
||||
{
|
||||
struct riic_priv *priv = dev_get_priv(dev);
|
||||
int ret;
|
||||
|
||||
if (restart)
|
||||
setbits_8(priv->base + RIIC_ICCR2, ICCR2_RS);
|
||||
else
|
||||
setbits_8(priv->base + RIIC_ICCR2, ICCR2_ST);
|
||||
|
||||
ret = riic_wait_for_icsr2(dev, ICSR2_START);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
clrbits_8(priv->base + RIIC_ICSR2, ICSR2_START);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int riic_receive_data(struct udevice *dev, struct i2c_msg *msg)
|
||||
{
|
||||
struct riic_priv *priv = dev_get_priv(dev);
|
||||
int ret, stop_ret, i;
|
||||
|
||||
ret = riic_wait_for_icsr2(dev, ICSR2_RDRF);
|
||||
if (ret < 0)
|
||||
goto send_stop;
|
||||
|
||||
ret = riic_check_nack_receive(dev);
|
||||
if (ret < 0)
|
||||
goto send_stop;
|
||||
|
||||
setbits_8(priv->base + RIIC_ICMR3, ICMR3_WAIT | ICMR3_ACKWP | ICMR3_RDRFS);
|
||||
|
||||
/* A dummy read must be performed to trigger data reception */
|
||||
readb(priv->base + RIIC_ICDRR);
|
||||
|
||||
for (i = 0; i < msg->len; i++) {
|
||||
ret = riic_wait_for_icsr2(dev, ICSR2_RDRF);
|
||||
if (ret < 0)
|
||||
goto send_stop;
|
||||
|
||||
if (i == (msg->len - 1)) {
|
||||
clrbits_8(priv->base + RIIC_ICSR2, ICSR2_STOP);
|
||||
setbits_8(priv->base + RIIC_ICCR2, ICCR2_SP);
|
||||
setbits_8(priv->base + RIIC_ICMR3, ICMR3_ACKBT);
|
||||
} else {
|
||||
clrbits_8(priv->base + RIIC_ICMR3, ICMR3_ACKBT);
|
||||
}
|
||||
|
||||
msg->buf[i] = readb(priv->base + RIIC_ICDRR);
|
||||
};
|
||||
|
||||
send_stop:
|
||||
if (ret) {
|
||||
/*
|
||||
* We got here due to an error condition, so we need to perform
|
||||
* a dummy read to issue the stop bit.
|
||||
*/
|
||||
clrbits_8(priv->base + RIIC_ICSR2, ICSR2_STOP);
|
||||
setbits_8(priv->base + RIIC_ICCR2, ICCR2_SP);
|
||||
readb(priv->base + RIIC_ICDRR);
|
||||
}
|
||||
stop_ret = riic_wait_for_icsr2(dev, ICSR2_STOP);
|
||||
clrbits_8(priv->base + RIIC_ICSR2, ICSR2_STOP | ICSR2_NACKF);
|
||||
clrbits_8(priv->base + RIIC_ICMR3, ICMR3_WAIT | ICMR3_ACKWP | ICMR3_RDRFS);
|
||||
return ret ? ret : stop_ret;
|
||||
}
|
||||
|
||||
static int riic_transmit_stop(struct udevice *dev)
|
||||
{
|
||||
struct riic_priv *priv = dev_get_priv(dev);
|
||||
int ret;
|
||||
|
||||
clrbits_8(priv->base + RIIC_ICSR2, ICSR2_STOP);
|
||||
setbits_8(priv->base + RIIC_ICCR2, ICCR2_SP);
|
||||
|
||||
ret = riic_wait_for_icsr2(dev, ICSR2_STOP);
|
||||
clrbits_8(priv->base + RIIC_ICSR2, ICSR2_STOP | ICSR2_NACKF);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int riic_transmit_data(struct udevice *dev, struct i2c_msg *msg)
|
||||
{
|
||||
int ret, stop_ret;
|
||||
|
||||
ret = riic_i2c_raw_write(dev, msg->buf, msg->len);
|
||||
if (ret < 0)
|
||||
goto send_stop;
|
||||
|
||||
ret = riic_wait_for_icsr2(dev, ICSR2_TEND);
|
||||
if (ret < 0)
|
||||
goto send_stop;
|
||||
|
||||
if (!ret && !(msg->flags & I2C_M_STOP))
|
||||
return 0;
|
||||
|
||||
send_stop:
|
||||
stop_ret = riic_transmit_stop(dev);
|
||||
return ret ? ret : stop_ret;
|
||||
}
|
||||
|
||||
static int riic_xfer_one(struct udevice *dev, struct i2c_msg *msg, int first_msg)
|
||||
{
|
||||
u8 addr_byte = ((msg->addr << 1) | (msg->flags & I2C_M_RD));
|
||||
int ret;
|
||||
|
||||
if (!(msg->flags & I2C_M_NOSTART)) {
|
||||
/*
|
||||
* Send a start for the first message and a restart for
|
||||
* subsequent messages.
|
||||
*/
|
||||
ret = riic_send_start_cond(dev, !first_msg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = riic_i2c_raw_write(dev, &addr_byte, 1);
|
||||
if (ret < 0) {
|
||||
/*
|
||||
* We're aborting the transfer while still in master transmit
|
||||
* mode.
|
||||
*/
|
||||
riic_transmit_stop(dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (msg->flags & I2C_M_RD)
|
||||
return riic_receive_data(dev, msg);
|
||||
|
||||
return riic_transmit_data(dev, msg);
|
||||
}
|
||||
|
||||
static int riic_xfer(struct udevice *dev, struct i2c_msg *msg, int nmsgs)
|
||||
{
|
||||
int ret, i;
|
||||
|
||||
ret = riic_check_busy(dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Ensure that the last message is terminated with a stop bit. */
|
||||
msg[nmsgs - 1].flags |= I2C_M_STOP;
|
||||
|
||||
for (i = 0; i < nmsgs; i++) {
|
||||
ret = riic_xfer_one(dev, &msg[i], !i);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int riic_deblock(struct udevice *dev)
|
||||
{
|
||||
struct riic_priv *priv = dev_get_priv(dev);
|
||||
int i = 0;
|
||||
|
||||
/*
|
||||
* Issue clock cycles on SCL to hopefully unblock whatever is holding
|
||||
* SDA low. These clock cycles may trigger error conditions such as
|
||||
* Arbitration Lost, so we clear the status bits in ICSR2 after each
|
||||
* cycle.
|
||||
*/
|
||||
while (!(readb(priv->base + RIIC_ICCR1) & ICCR1_SDAI)) {
|
||||
if (i++ == I2C_DEBLOCK_MAX_CYCLES)
|
||||
return -EIO;
|
||||
|
||||
setbits_8(priv->base + RIIC_ICCR1, ICCR1_CLO);
|
||||
if (wait_for_bit_8(priv->base + RIIC_ICCR1, ICCR1_CLO, 0,
|
||||
RIIC_TIMEOUT_MSEC, false))
|
||||
return -ETIMEDOUT;
|
||||
writeb(0, priv->base + RIIC_ICSR2);
|
||||
}
|
||||
|
||||
/*
|
||||
* We have released SDA, but the I2C module is now out of sync
|
||||
* with the bus state, so we need to reset its state machine.
|
||||
*/
|
||||
setbits_8(priv->base + RIIC_ICCR1, ICCR1_IICRST);
|
||||
clrbits_8(priv->base + RIIC_ICCR1, ICCR1_IICRST);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int riic_set_bus_speed(struct udevice *dev, uint bus_speed)
|
||||
{
|
||||
struct riic_priv *priv = dev_get_priv(dev);
|
||||
ulong refclk;
|
||||
uint total_ticks, cks, brl, brh;
|
||||
|
||||
if (bus_speed > I2C_SPEED_FAST_PLUS_RATE) {
|
||||
dev_err(dev, "unsupported bus speed (%dHz). %d max\n", bus_speed,
|
||||
I2C_SPEED_FAST_PLUS_RATE);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Assume the default register settings:
|
||||
* FER.SCLE = 1 (SCL sync circuit enabled, adds 2 or 3 cycles)
|
||||
* FER.NFE = 1 (noise circuit enabled)
|
||||
* MR3.NF = 0 (1 cycle of noise filtered out)
|
||||
*
|
||||
* Freq (CKS=000) = (I2CCLK + tr + tf)/ (BRH + 3 + 1) + (BRL + 3 + 1)
|
||||
* Freq (CKS!=000) = (I2CCLK + tr + tf)/ (BRH + 2 + 1) + (BRL + 2 + 1)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Determine reference clock rate. We must be able to get the desired
|
||||
* frequency with only 62 clock ticks max (31 high, 31 low).
|
||||
* Aim for a duty of 60% LOW, 40% HIGH.
|
||||
*/
|
||||
refclk = clk_get_rate(&priv->clk);
|
||||
total_ticks = DIV_ROUND_UP(refclk, bus_speed ?: 1);
|
||||
|
||||
for (cks = 0; cks < 7; cks++) {
|
||||
/*
|
||||
* 60% low time must be less than BRL + 2 + 1
|
||||
* BRL max register value is 0x1F.
|
||||
*/
|
||||
brl = ((total_ticks * 6) / 10);
|
||||
if (brl <= (0x1f + 3))
|
||||
break;
|
||||
|
||||
total_ticks /= 2;
|
||||
refclk /= 2;
|
||||
}
|
||||
|
||||
if (brl > (0x1f + 3)) {
|
||||
dev_err(dev, "invalid speed (%u). Too slow.\n", bus_speed);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
brh = total_ticks - brl;
|
||||
|
||||
/* Remove automatic clock ticks for sync circuit and NF */
|
||||
if (cks == 0) {
|
||||
brl -= 4;
|
||||
brh -= 4;
|
||||
} else {
|
||||
brl -= 3;
|
||||
brh -= 3;
|
||||
}
|
||||
|
||||
/*
|
||||
* If SCL rise and fall times weren't set in the device tree, set them
|
||||
* based on the desired bus speed and the maximum timings given in the
|
||||
* I2C specification.
|
||||
*/
|
||||
if (priv->flags & RIIC_FLAG_DEFAULT_SCL_RISE_TIME)
|
||||
priv->scl_rise_ns = bus_speed <= I2C_SPEED_STANDARD_RATE ? 1000 :
|
||||
bus_speed <= I2C_SPEED_FAST_RATE ? 300 : 120;
|
||||
if (priv->flags & RIIC_FLAG_DEFAULT_SCL_FALL_TIME)
|
||||
priv->scl_fall_ns = bus_speed <= I2C_SPEED_FAST_RATE ? 300 : 120;
|
||||
|
||||
/*
|
||||
* Remove clock ticks for rise and fall times. Convert ns to clock
|
||||
* ticks.
|
||||
*/
|
||||
brl -= priv->scl_fall_ns / (1000000000 / refclk);
|
||||
brh -= priv->scl_rise_ns / (1000000000 / refclk);
|
||||
|
||||
/* Adjust for min register values for when SCLE=1 and NFE=1 */
|
||||
if (brl < 1)
|
||||
brl = 1;
|
||||
if (brh < 1)
|
||||
brh = 1;
|
||||
|
||||
priv->bus_speed = refclk / total_ticks;
|
||||
dev_dbg(dev, "freq=%u, duty=%d, fall=%lu, rise=%lu, cks=%d, brl=%d, brh=%d\n",
|
||||
priv->bus_speed, ((brl + 3) * 100) / (brl + brh + 6),
|
||||
priv->scl_fall_ns / (1000000000 / refclk),
|
||||
priv->scl_rise_ns / (1000000000 / refclk), cks, brl, brh);
|
||||
|
||||
setbits_8(priv->base + RIIC_ICCR1, ICCR1_IICRST);
|
||||
writeb(ICMR1_CKS(cks), priv->base + RIIC_ICMR1);
|
||||
writeb(brh | ICBRH_RESERVED, priv->base + RIIC_ICBRH);
|
||||
writeb(brl | ICBRL_RESERVED, priv->base + RIIC_ICBRL);
|
||||
clrbits_8(priv->base + RIIC_ICCR1, ICCR1_IICRST);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int riic_get_bus_speed(struct udevice *dev)
|
||||
{
|
||||
struct riic_priv *priv = dev_get_priv(dev);
|
||||
|
||||
return priv->bus_speed;
|
||||
}
|
||||
|
||||
static const struct dm_i2c_ops riic_ops = {
|
||||
.xfer = riic_xfer,
|
||||
.deblock = riic_deblock,
|
||||
.set_bus_speed = riic_set_bus_speed,
|
||||
.get_bus_speed = riic_get_bus_speed,
|
||||
};
|
||||
|
||||
static int riic_init_setting(struct udevice *dev)
|
||||
{
|
||||
struct riic_priv *priv = dev_get_priv(dev);
|
||||
int ret;
|
||||
|
||||
clrbits_8(priv->base + RIIC_ICCR1, ICCR1_ICE);
|
||||
setbits_8(priv->base + RIIC_ICCR1, ICCR1_IICRST);
|
||||
setbits_8(priv->base + RIIC_ICCR1, ICCR1_ICE);
|
||||
|
||||
/*
|
||||
* Set a default bitrate. The rate may be overridden based on the device
|
||||
* tree as part of i2c_post_probe().
|
||||
*/
|
||||
ret = riic_set_bus_speed(dev, I2C_SPEED_STANDARD_RATE);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
clrbits_8(priv->base + RIIC_ICCR1, ICCR1_IICRST);
|
||||
|
||||
/* Make sure the bus is not stuck. */
|
||||
if (!(readb(priv->base + RIIC_ICCR1) & ICCR1_SDAI)) {
|
||||
dev_dbg(dev, "clearing SDA low state\n");
|
||||
ret = riic_deblock(dev);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to clear SDA low state!\n");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
err:
|
||||
clrbits_8(priv->base + RIIC_ICCR1, ICCR1_ICE | ICCR1_IICRST);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int riic_probe(struct udevice *dev)
|
||||
{
|
||||
struct riic_priv *priv = dev_get_priv(dev);
|
||||
struct reset_ctl rst;
|
||||
int ret;
|
||||
|
||||
priv->base = dev_read_addr_ptr(dev);
|
||||
|
||||
ret = dev_read_u32(dev, "i2c-scl-rising-time-ns", &priv->scl_rise_ns);
|
||||
if (ret)
|
||||
priv->flags |= RIIC_FLAG_DEFAULT_SCL_RISE_TIME;
|
||||
ret = dev_read_u32(dev, "i2c-scl-falling-time-ns", &priv->scl_fall_ns);
|
||||
if (ret)
|
||||
priv->flags |= RIIC_FLAG_DEFAULT_SCL_FALL_TIME;
|
||||
|
||||
ret = clk_get_by_index(dev, 0, &priv->clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to get clock\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_enable(&priv->clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to enable clock\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = reset_get_by_index(dev, 0, &rst);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to get reset line\n");
|
||||
goto err_get_reset;
|
||||
}
|
||||
|
||||
ret = reset_deassert(&rst);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to de-assert reset line\n");
|
||||
goto err_reset;
|
||||
}
|
||||
|
||||
ret = riic_init_setting(dev);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to init i2c bus interface\n");
|
||||
goto err_init;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_init:
|
||||
reset_assert(&rst);
|
||||
err_reset:
|
||||
reset_free(&rst);
|
||||
err_get_reset:
|
||||
clk_disable(&priv->clk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct udevice_id riic_ids[] = {
|
||||
{ .compatible = "renesas,riic-rz", },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(riic_i2c) = {
|
||||
.name = "riic-i2c",
|
||||
.id = UCLASS_I2C,
|
||||
.of_match = riic_ids,
|
||||
.probe = riic_probe,
|
||||
.priv_auto = sizeof(struct riic_priv),
|
||||
.ops = &riic_ops,
|
||||
};
|
|
@ -404,6 +404,15 @@ config PMIC_TPS65219
|
|||
help
|
||||
The TPS65219 is a PMIC containing a bunch of SMPS & LDOs.
|
||||
This driver binds the pmic children.
|
||||
|
||||
config PMIC_RAA215300
|
||||
bool "Renesas RAA215300 PMIC driver"
|
||||
depends on DM_PMIC
|
||||
help
|
||||
The Renesas RAA215300 PMIC driver includes RTC support, system reset
|
||||
support and several voltage regulators. For now, this driver simply
|
||||
allows register access and will bind the sysreset driver
|
||||
(CONFIG_SYSRESET_RAA215300) if it is enabled.
|
||||
endif
|
||||
|
||||
config PMIC_TPS65217
|
||||
|
|
|
@ -35,6 +35,7 @@ obj-$(CONFIG_PMIC_STPMIC1) += stpmic1.o
|
|||
obj-$(CONFIG_PMIC_TPS65217) += pmic_tps65217.o
|
||||
obj-$(CONFIG_PMIC_TPS65219) += tps65219.o
|
||||
obj-$(CONFIG_PMIC_TPS65941) += tps65941.o
|
||||
obj-$(CONFIG_PMIC_RAA215300) += raa215300.o
|
||||
obj-$(CONFIG_POWER_TPS65218) += pmic_tps65218.o
|
||||
|
||||
ifeq ($(CONFIG_$(SPL_)POWER_LEGACY),y)
|
||||
|
|
50
drivers/power/pmic/raa215300.c
Normal file
50
drivers/power/pmic/raa215300.c
Normal file
|
@ -0,0 +1,50 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2023 Renesas Electronics Corporation
|
||||
*/
|
||||
|
||||
#include <dm.h>
|
||||
#include <dm/device-internal.h>
|
||||
#include <dm/lists.h>
|
||||
#include <i2c.h>
|
||||
#include <power/pmic.h>
|
||||
|
||||
#define RAA215300_REG_COUNT 0x80
|
||||
|
||||
static int raa215300_reg_count(struct udevice *dev)
|
||||
{
|
||||
return RAA215300_REG_COUNT;
|
||||
}
|
||||
|
||||
static struct dm_pmic_ops raa215300_ops = {
|
||||
.reg_count = raa215300_reg_count,
|
||||
.read = dm_i2c_read,
|
||||
.write = dm_i2c_write,
|
||||
};
|
||||
|
||||
static const struct udevice_id raa215300_ids[] = {
|
||||
{ .compatible = "renesas,raa215300" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
static int raa215300_bind(struct udevice *dev)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_SYSRESET_RAA215300)) {
|
||||
struct driver *drv = lists_driver_lookup_name("raa215300_sysreset");
|
||||
if (!drv)
|
||||
return -ENOENT;
|
||||
|
||||
return device_bind(dev, drv, dev->name, NULL, dev_ofnode(dev),
|
||||
NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
U_BOOT_DRIVER(raa215300_pmic) = {
|
||||
.name = "raa215300_pmic",
|
||||
.id = UCLASS_PMIC,
|
||||
.of_match = raa215300_ids,
|
||||
.bind = raa215300_bind,
|
||||
.ops = &raa215300_ops,
|
||||
};
|
|
@ -229,6 +229,12 @@ config SYSRESET_MPC83XX
|
|||
help
|
||||
Reboot support for NXP MPC83xx SoCs.
|
||||
|
||||
config SYSRESET_RAA215300
|
||||
bool "Support sysreset via Renesas RAA215300 PMIC"
|
||||
depends on PMIC_RAA215300
|
||||
help
|
||||
Add support for the system reboot via the Renesas RAA215300 PMIC.
|
||||
|
||||
endif
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -27,4 +27,5 @@ obj-$(CONFIG_SYSRESET_WATCHDOG) += sysreset_watchdog.o
|
|||
obj-$(CONFIG_SYSRESET_RESETCTL) += sysreset_resetctl.o
|
||||
obj-$(CONFIG_$(SPL_TPL_)SYSRESET_AT91) += sysreset_at91.o
|
||||
obj-$(CONFIG_$(SPL_TPL_)SYSRESET_X86) += sysreset_x86.o
|
||||
obj-$(CONFIG_SYSRESET_RAA215300) += sysreset_raa215300.o
|
||||
obj-$(CONFIG_TARGET_XTFPGA) += sysreset_xtfpga.o
|
||||
|
|
58
drivers/sysreset/sysreset_raa215300.c
Normal file
58
drivers/sysreset/sysreset_raa215300.c
Normal file
|
@ -0,0 +1,58 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2023 Renesas Electronics Corporation
|
||||
*/
|
||||
|
||||
#include <dm.h>
|
||||
#include <power/pmic.h>
|
||||
#include <sysreset.h>
|
||||
|
||||
#define RAA215300_REG_SWRESET 0x6D
|
||||
#define RAA215300_COLD_RESET BIT(0)
|
||||
#define RAA215300_WARM_RESET BIT(1)
|
||||
|
||||
static int raa215300_sysreset_request(struct udevice *dev, enum sysreset_t type)
|
||||
{
|
||||
struct udevice *pmic = dev_get_parent(dev);
|
||||
int ret;
|
||||
u8 val;
|
||||
|
||||
/*
|
||||
* The RAA215300 documentation names the available reset types
|
||||
* differently to u-boot:
|
||||
*
|
||||
* - A "warm" reset via the RAA215300 PMIC will fully reset the SoC
|
||||
* (CPU & GPIOs), so this corresponds to SYSRESET_COLD.
|
||||
*
|
||||
* - A "cold" reset via the RAA215300 PMIC will cycle all power supply
|
||||
* rails, so this corresponds to SYSRESET_POWER.
|
||||
*/
|
||||
switch (type) {
|
||||
case SYSRESET_COLD:
|
||||
val = RAA215300_WARM_RESET;
|
||||
break;
|
||||
|
||||
case SYSRESET_POWER:
|
||||
val = RAA215300_COLD_RESET;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EPROTONOSUPPORT;
|
||||
}
|
||||
|
||||
ret = pmic_reg_write(pmic, RAA215300_REG_SWRESET, val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return -EINPROGRESS;
|
||||
}
|
||||
|
||||
static struct sysreset_ops raa215300_sysreset_ops = {
|
||||
.request = raa215300_sysreset_request,
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(raa215300_sysreset) = {
|
||||
.name = "raa215300_sysreset",
|
||||
.id = UCLASS_SYSRESET,
|
||||
.ops = &raa215300_sysreset_ops,
|
||||
};
|
Loading…
Reference in a new issue