diff options
-rw-r--r-- | arch/arm/dts/r9a07g044.dtsi | 16 | ||||
-rw-r--r-- | arch/arm/dts/r9a07g044l2-smarc.dts | 21 | ||||
-rw-r--r-- | arch/arm/dts/rz-smarc-common.dtsi | 18 | ||||
-rw-r--r-- | arch/arm/dts/rzg2l-smarc-pinfunction.dtsi | 20 | ||||
-rw-r--r-- | arch/arm/dts/rzg2l-smarc-som.dtsi | 22 | ||||
-rw-r--r-- | arch/arm/dts/rzg2l-smarc.dtsi | 43 | ||||
-rw-r--r-- | arch/arm/mach-rmobile/Kconfig | 1 | ||||
-rw-r--r-- | board/renesas/rzg2l/rzg2l.c | 8 | ||||
-rw-r--r-- | configs/renesas_rzg2l_smarc_defconfig | 7 | ||||
-rw-r--r-- | drivers/clk/renesas/rzg2l-cpg.c | 17 | ||||
-rw-r--r-- | drivers/i2c/Kconfig | 7 | ||||
-rw-r--r-- | drivers/i2c/Makefile | 1 | ||||
-rw-r--r-- | drivers/i2c/rz_riic.c | 624 | ||||
-rw-r--r-- | drivers/power/pmic/Kconfig | 9 | ||||
-rw-r--r-- | drivers/power/pmic/Makefile | 1 | ||||
-rw-r--r-- | drivers/power/pmic/raa215300.c | 50 | ||||
-rw-r--r-- | drivers/sysreset/Kconfig | 6 | ||||
-rw-r--r-- | drivers/sysreset/Makefile | 1 | ||||
-rw-r--r-- | drivers/sysreset/sysreset_raa215300.c | 58 |
19 files changed, 896 insertions, 34 deletions
diff --git a/arch/arm/dts/r9a07g044.dtsi b/arch/arm/dts/r9a07g044.dtsi index 232910e074..66f68fc2b2 100644 --- a/arch/arm/dts/r9a07g044.dtsi +++ b/arch/arm/dts/r9a07g044.dtsi @@ -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>; diff --git a/arch/arm/dts/r9a07g044l2-smarc.dts b/arch/arm/dts/r9a07g044l2-smarc.dts index bc2af6c92c..568d49cfe4 100644 --- a/arch/arm/dts/r9a07g044l2-smarc.dts +++ b/arch/arm/dts/r9a07g044l2-smarc.dts @@ -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" diff --git a/arch/arm/dts/rz-smarc-common.dtsi b/arch/arm/dts/rz-smarc-common.dtsi index 3962d47b3e..b7a3e6caa3 100644 --- a/arch/arm/dts/rz-smarc-common.dtsi +++ b/arch/arm/dts/rz-smarc-common.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>; }; diff --git a/arch/arm/dts/rzg2l-smarc-pinfunction.dtsi b/arch/arm/dts/rzg2l-smarc-pinfunction.dtsi index 9085d8c76c..18c526c7a4 100644 --- a/arch/arm/dts/rzg2l-smarc-pinfunction.dtsi +++ b/arch/arm/dts/rzg2l-smarc-pinfunction.dtsi @@ -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 */ diff --git a/arch/arm/dts/rzg2l-smarc-som.dtsi b/arch/arm/dts/rzg2l-smarc-som.dtsi index fbbb4f0344..547859c388 100644 --- a/arch/arm/dts/rzg2l-smarc-som.dtsi +++ b/arch/arm/dts/rzg2l-smarc-som.dtsi @@ -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"; }; diff --git a/arch/arm/dts/rzg2l-smarc.dtsi b/arch/arm/dts/rzg2l-smarc.dtsi index 2a158a954b..37807f1bda 100644 --- a/arch/arm/dts/rzg2l-smarc.dtsi +++ b/arch/arm/dts/rzg2l-smarc.dtsi @@ -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,7 +110,47 @@ #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) diff --git a/arch/arm/mach-rmobile/Kconfig b/arch/arm/mach-rmobile/Kconfig index 2bb96749fc..38ede6e0b5 100644 --- a/arch/arm/mach-rmobile/Kconfig +++ b/arch/arm/mach-rmobile/Kconfig @@ -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 diff --git a/board/renesas/rzg2l/rzg2l.c b/board/renesas/rzg2l/rzg2l.c index 73201a8c69..0f6d6e7f51 100644 --- a/board/renesas/rzg2l/rzg2l.c +++ b/board/renesas/rzg2l/rzg2l.c @@ -56,11 +56,3 @@ int board_init(void) { return 0; } - -void reset_cpu(void) -{ - /* - * TODO: Implement reset support once TrustedFirmware supports - * the appropriate call. - */ -} diff --git a/configs/renesas_rzg2l_smarc_defconfig b/configs/renesas_rzg2l_smarc_defconfig index e928697262..7f22795b1a 100644 --- a/configs/renesas_rzg2l_smarc_defconfig +++ b/configs/renesas_rzg2l_smarc_defconfig @@ -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 diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c index e54508c35c..dba009997a 100644 --- a/drivers/clk/renesas/rzg2l-cpg.c +++ b/drivers/clk/renesas/rzg2l-cpg.c @@ -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) diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig index 4f42200f39..d2a3a13493 100644 --- a/drivers/i2c/Kconfig +++ b/drivers/i2c/Kconfig @@ -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 diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index a96a8c7e95..692f63bafd 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -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 diff --git a/drivers/i2c/rz_riic.c b/drivers/i2c/rz_riic.c new file mode 100644 index 0000000000..5f3f8d1b24 --- /dev/null +++ b/drivers/i2c/rz_riic.c @@ -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, +}; diff --git a/drivers/power/pmic/Kconfig b/drivers/power/pmic/Kconfig index 454a6e0cf8..9b61b18e11 100644 --- a/drivers/power/pmic/Kconfig +++ b/drivers/power/pmic/Kconfig @@ -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 diff --git a/drivers/power/pmic/Makefile b/drivers/power/pmic/Makefile index 55ee614364..a2d59deeed 100644 --- a/drivers/power/pmic/Makefile +++ b/drivers/power/pmic/Makefile @@ -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) diff --git a/drivers/power/pmic/raa215300.c b/drivers/power/pmic/raa215300.c new file mode 100644 index 0000000000..a581a1f6dc --- /dev/null +++ b/drivers/power/pmic/raa215300.c @@ -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, +}; diff --git a/drivers/sysreset/Kconfig b/drivers/sysreset/Kconfig index 0e52f99628..49c0787b26 100644 --- a/drivers/sysreset/Kconfig +++ b/drivers/sysreset/Kconfig @@ -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 diff --git a/drivers/sysreset/Makefile b/drivers/sysreset/Makefile index c9f1c625ae..e0e732205d 100644 --- a/drivers/sysreset/Makefile +++ b/drivers/sysreset/Makefile @@ -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 diff --git a/drivers/sysreset/sysreset_raa215300.c b/drivers/sysreset/sysreset_raa215300.c new file mode 100644 index 0000000000..32dfcb0aec --- /dev/null +++ b/drivers/sysreset/sysreset_raa215300.c @@ -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, +}; |