* [PATCH v1 0/3] Init support for RK3576 UFS controller
@ 2024-08-06 7:19 Shawn Lin
2024-08-06 7:19 ` [PATCH v1 1/3] scsi: ufs: core: Export ufshcd_dme_link_startup() helper Shawn Lin
` (2 more replies)
0 siblings, 3 replies; 7+ messages in thread
From: Shawn Lin @ 2024-08-06 7:19 UTC (permalink / raw)
To: Rob Herring, Martin K . Petersen
Cc: Heiko Stuebner, Alim Akhtar, Avri Altman, Bart Van Assche,
YiFeng Zhao, Liang Chen, linux-scsi, linux-rockchip, devicetree,
Shawn Lin
This patchset add initial support UFS controller for RK3576 SoC.
Patch 1 export ufshcd_dme_link_startup function for host drivers, and
patch 2&3 add ufs-rockchip driver.
Shawn Lin (3):
scsi: ufs: core: Export ufshcd_dme_link_startup() helper
dt-bindings: ufs: Document Rockchip UFS host controller
scsi: ufs: rockchip: init support for UFS
.../devicetree/bindings/ufs/rockchip,ufs.yaml | 78 ++++
drivers/ufs/core/ufshcd.c | 4 +-
drivers/ufs/host/Kconfig | 12 +
drivers/ufs/host/Makefile | 1 +
drivers/ufs/host/ufs-rockchip.c | 477 +++++++++++++++++++++
drivers/ufs/host/ufs-rockchip.h | 52 +++
include/ufs/ufshcd.h | 1 +
7 files changed, 624 insertions(+), 1 deletion(-)
create mode 100644 Documentation/devicetree/bindings/ufs/rockchip,ufs.yaml
create mode 100644 drivers/ufs/host/ufs-rockchip.c
create mode 100644 drivers/ufs/host/ufs-rockchip.h
--
2.7.4
^ permalink raw reply [flat|nested] 7+ messages in thread* [PATCH v1 1/3] scsi: ufs: core: Export ufshcd_dme_link_startup() helper 2024-08-06 7:19 [PATCH v1 0/3] Init support for RK3576 UFS controller Shawn Lin @ 2024-08-06 7:19 ` Shawn Lin 2024-08-06 7:19 ` [PATCH v1 2/3] dt-bindings: ufs: Document Rockchip UFS host controller Shawn Lin 2024-08-06 7:20 ` [PATCH v1 3/3] scsi: ufs: rockchip: init support for UFS Shawn Lin 2 siblings, 0 replies; 7+ messages in thread From: Shawn Lin @ 2024-08-06 7:19 UTC (permalink / raw) To: Rob Herring, Martin K . Petersen Cc: Heiko Stuebner, Alim Akhtar, Avri Altman, Bart Van Assche, YiFeng Zhao, Liang Chen, linux-scsi, linux-rockchip, devicetree, Shawn Lin Export it for host drivers. Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com> --- drivers/ufs/core/ufshcd.c | 4 +++- include/ufs/ufshcd.h | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c index 8f4abc5..e09f004 100644 --- a/drivers/ufs/core/ufshcd.c +++ b/drivers/ufs/core/ufshcd.c @@ -4019,7 +4019,7 @@ static void ufshcd_host_memory_configure(struct ufs_hba *hba) * * Return: 0 on success, non-zero value on failure. */ -static int ufshcd_dme_link_startup(struct ufs_hba *hba) +int ufshcd_dme_link_startup(struct ufs_hba *hba) { struct uic_command uic_cmd = { .command = UIC_CMD_DME_LINK_STARTUP, @@ -4032,6 +4032,8 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba) "dme-link-startup: error code %d\n", ret); return ret; } +EXPORT_SYMBOL_GPL(ufshcd_dme_link_startup); + /** * ufshcd_dme_reset - UIC command for DME_RESET * @hba: per adapter instance diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h index cac0cdb..8bc28c1 100644 --- a/include/ufs/ufshcd.h +++ b/include/ufs/ufshcd.h @@ -1432,6 +1432,7 @@ int ufshcd_read_string_desc(struct ufs_hba *hba, u8 desc_index, void ufshcd_hold(struct ufs_hba *hba); void ufshcd_release(struct ufs_hba *hba); +int ufshcd_dme_link_startup(struct ufs_hba *hba); void ufshcd_clkgate_delay_set(struct device *dev, unsigned long value); int ufshcd_get_vreg(struct device *dev, struct ufs_vreg *vreg); -- 2.7.4 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v1 2/3] dt-bindings: ufs: Document Rockchip UFS host controller 2024-08-06 7:19 [PATCH v1 0/3] Init support for RK3576 UFS controller Shawn Lin 2024-08-06 7:19 ` [PATCH v1 1/3] scsi: ufs: core: Export ufshcd_dme_link_startup() helper Shawn Lin @ 2024-08-06 7:19 ` Shawn Lin 2024-08-06 8:46 ` Krzysztof Kozlowski 2024-08-06 10:18 ` Rob Herring (Arm) 2024-08-06 7:20 ` [PATCH v1 3/3] scsi: ufs: rockchip: init support for UFS Shawn Lin 2 siblings, 2 replies; 7+ messages in thread From: Shawn Lin @ 2024-08-06 7:19 UTC (permalink / raw) To: Rob Herring, Martin K . Petersen Cc: Heiko Stuebner, Alim Akhtar, Avri Altman, Bart Van Assche, YiFeng Zhao, Liang Chen, linux-scsi, linux-rockchip, devicetree, Shawn Lin Document Rockchip UFS host controller for RK3576 SoC. Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com> --- .../devicetree/bindings/ufs/rockchip,ufs.yaml | 78 ++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 Documentation/devicetree/bindings/ufs/rockchip,ufs.yaml diff --git a/Documentation/devicetree/bindings/ufs/rockchip,ufs.yaml b/Documentation/devicetree/bindings/ufs/rockchip,ufs.yaml new file mode 100644 index 0000000..e2e492c --- /dev/null +++ b/Documentation/devicetree/bindings/ufs/rockchip,ufs.yaml @@ -0,0 +1,78 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/ufs/rockchip,ufs.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Rockchip UFS Host Controller + +maintainers: + - Shawn Lin <shawn.lin@rock-chips.com> + +allOf: + - $ref: ufs-common.yaml + +properties: + compatible: + const: rockchip,rk3576-ufs + + reg: + maxItems: 5 + + reg-names: + items: + - const: hci + - const: mphy + - const: hci_grf + - const: mphy_grf + - const: hci_apb + + clocks: + maxItems: 4 + + clock-names: + items: + - const: core + - const: pclk + - const: pclk_mphy + - const: ref_out + + power-domains: + maxItems: 1 + + resets: + maxItems: 4 + +required: + - compatible + - reg + - clocks + - clock-names + - power-domains + - resets + +unevaluatedProperties: false + +examples: + - | + #include <dt-bindings/clock/rockchip,rk3576-cru.h> + #include <dt-bindings/interrupt-controller/arm-gic.h> + #include <dt-bindings/power/rk3576-power.h> + + ufs: ufs@2a2d0000 { + compatible = "rockchip,rk3576-ufs"; + reg = <0x0 0x2a2d0000 0 0x10000>, + <0x0 0x2b040000 0 0x10000>, + <0x0 0x2601f000 0 0x1000>, + <0x0 0x2603c000 0 0x1000>, + <0x0 0x2a2e0000 0 0x10000>; + reg-names = "hci", "mphy", "hci_grf", "mphy_grf", "hci_apb"; + clocks = <&cru ACLK_UFS_SYS>, <&cru PCLK_USB_ROOT>, <&cru PCLK_MPHY>, + <&cru CLK_REF_UFS_CLKOUT>; + clock-names = "core", "pclk", "pclk_mphy", "ref_out"; + interrupts = <GIC_SPI 361 IRQ_TYPE_LEVEL_HIGH>; + power-domains = <&power RK3576_PD_USB>; + resets = <&cru SRST_A_UFS_BIU>, <&cru SRST_A_UFS_SYS>, <&cru SRST_A_UFS>, + <&cru SRST_P_UFS_GRF>; + reset-names = "biu", "sys", "ufs", "grf"; + }; -- 2.7.4 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v1 2/3] dt-bindings: ufs: Document Rockchip UFS host controller 2024-08-06 7:19 ` [PATCH v1 2/3] dt-bindings: ufs: Document Rockchip UFS host controller Shawn Lin @ 2024-08-06 8:46 ` Krzysztof Kozlowski 2024-08-06 10:18 ` Rob Herring (Arm) 1 sibling, 0 replies; 7+ messages in thread From: Krzysztof Kozlowski @ 2024-08-06 8:46 UTC (permalink / raw) To: Shawn Lin, Rob Herring, Martin K . Petersen Cc: Heiko Stuebner, Alim Akhtar, Avri Altman, Bart Van Assche, YiFeng Zhao, Liang Chen, linux-scsi, linux-rockchip, devicetree On 06/08/2024 09:19, Shawn Lin wrote: > Document Rockchip UFS host controller for RK3576 SoC. > <form letter> Please use scripts/get_maintainers.pl to get a list of necessary people and lists to CC (and consider --no-git-fallback argument). It might happen, that command when run on an older kernel, gives you outdated entries. Therefore please be sure you base your patches on recent Linux kernel. Tools like b4 or scripts/get_maintainer.pl provide you proper list of people, so fix your workflow. Tools might also fail if you work on some ancient tree (don't, instead use mainline) or work on fork of kernel (don't, instead use mainline). Just use b4 and everything should be fine, although remember about `b4 prep --auto-to-cc` if you added new patches to the patchset. </form letter> Limited review follows. > Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com> > --- > > .../devicetree/bindings/ufs/rockchip,ufs.yaml | 78 ++++++++++++++++++++++ > 1 file changed, 78 insertions(+) > create mode 100644 Documentation/devicetree/bindings/ufs/rockchip,ufs.yaml > > diff --git a/Documentation/devicetree/bindings/ufs/rockchip,ufs.yaml b/Documentation/devicetree/bindings/ufs/rockchip,ufs.yaml > new file mode 100644 > index 0000000..e2e492c > --- /dev/null > +++ b/Documentation/devicetree/bindings/ufs/rockchip,ufs.yaml Filename as compatible. > @@ -0,0 +1,78 @@ > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) > +%YAML 1.2 > +--- > +$id: http://devicetree.org/schemas/ufs/rockchip,ufs.yaml# > +$schema: http://devicetree.org/meta-schemas/core.yaml# > + > +title: Rockchip UFS Host Controller > + > +maintainers: > + - Shawn Lin <shawn.lin@rock-chips.com> > + > +allOf: > + - $ref: ufs-common.yaml > + > +properties: > + compatible: > + const: rockchip,rk3576-ufs > + > + reg: > + maxItems: 5 > + > + reg-names: > + items: > + - const: hci > + - const: mphy > + - const: hci_grf > + - const: mphy_grf > + - const: hci_apb > + > + clocks: > + maxItems: 4 > + > + clock-names: > + items: > + - const: core > + - const: pclk > + - const: pclk_mphy > + - const: ref_out > + > + power-domains: > + maxItems: 1 > + > + resets: > + maxItems: 4 List the items instead > + > +required: > + - compatible > + - reg reg-names are not required? Test your DTS (where is it btw?) without reg-names then. > + - clocks > + - clock-names > + - power-domains > + - resets > + > +unevaluatedProperties: false > + > +examples: > + - | > + #include <dt-bindings/clock/rockchip,rk3576-cru.h> > + #include <dt-bindings/interrupt-controller/arm-gic.h> > + #include <dt-bindings/power/rk3576-power.h> > + > + ufs: ufs@2a2d0000 { > + compatible = "rockchip,rk3576-ufs"; > + reg = <0x0 0x2a2d0000 0 0x10000>, Fix indentation. See writing schema. Use 4 spaces for example indentation . > + <0x0 0x2b040000 0 0x10000>, > + <0x0 0x2601f000 0 0x1000>, > + <0x0 0x2603c000 0 0x1000>, > + <0x0 0x2a2e0000 0 0x10000>; > + reg-names = "hci", "mphy", "hci_grf", "mphy_grf", "hci_apb"; > + clocks = <&cru ACLK_UFS_SYS>, <&cru PCLK_USB_ROOT>, <&cru PCLK_MPHY>, > + <&cru CLK_REF_UFS_CLKOUT>; > + clock-names = "core", "pclk", "pclk_mphy", "ref_out"; > + interrupts = <GIC_SPI 361 IRQ_TYPE_LEVEL_HIGH>; > + power-domains = <&power RK3576_PD_USB>; > + resets = <&cru SRST_A_UFS_BIU>, <&cru SRST_A_UFS_SYS>, <&cru SRST_A_UFS>, > + <&cru SRST_P_UFS_GRF>; > + reset-names = "biu", "sys", "ufs", "grf"; Crap. This was never tested! NAK Best regards, Krzysztof ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v1 2/3] dt-bindings: ufs: Document Rockchip UFS host controller 2024-08-06 7:19 ` [PATCH v1 2/3] dt-bindings: ufs: Document Rockchip UFS host controller Shawn Lin 2024-08-06 8:46 ` Krzysztof Kozlowski @ 2024-08-06 10:18 ` Rob Herring (Arm) 1 sibling, 0 replies; 7+ messages in thread From: Rob Herring (Arm) @ 2024-08-06 10:18 UTC (permalink / raw) To: Shawn Lin Cc: Alim Akhtar, Avri Altman, linux-rockchip, Martin K . Petersen, Bart Van Assche, Liang Chen, devicetree, Heiko Stuebner, Rob Herring, linux-scsi, YiFeng Zhao On Tue, 06 Aug 2024 15:19:59 +0800, Shawn Lin wrote: > Document Rockchip UFS host controller for RK3576 SoC. > > Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com> > --- > > .../devicetree/bindings/ufs/rockchip,ufs.yaml | 78 ++++++++++++++++++++++ > 1 file changed, 78 insertions(+) > create mode 100644 Documentation/devicetree/bindings/ufs/rockchip,ufs.yaml > My bot found errors running 'make dt_binding_check' on your patch: yamllint warnings/errors: ./Documentation/devicetree/bindings/ufs/rockchip,ufs.yaml:24:6: [warning] wrong indentation: expected 6 but found 5 (indentation) ./Documentation/devicetree/bindings/ufs/rockchip,ufs.yaml:65:1: [error] syntax error: found character '\t' that cannot start any token (syntax) dtschema/dtc warnings/errors: make[2]: *** Deleting file 'Documentation/devicetree/bindings/ufs/rockchip,ufs.example.dts' Documentation/devicetree/bindings/ufs/rockchip,ufs.yaml:65:1: found a tab character where an indentation space is expected make[2]: *** [Documentation/devicetree/bindings/Makefile:26: Documentation/devicetree/bindings/ufs/rockchip,ufs.example.dts] Error 1 make[2]: *** Waiting for unfinished jobs.... ./Documentation/devicetree/bindings/ufs/rockchip,ufs.yaml:65:1: found a tab character where an indentation space is expected /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/ufs/rockchip,ufs.yaml: ignoring, error parsing file make[1]: *** [/builds/robherring/dt-review-ci/linux/Makefile:1430: dt_binding_check] Error 2 make: *** [Makefile:240: __sub-make] Error 2 doc reference errors (make refcheckdocs): See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/1722928800-137042-3-git-send-email-shawn.lin@rock-chips.com The base for the series is generally the latest rc1. A different dependency should be noted in *this* patch. If you already ran 'make dt_binding_check' and didn't see the above error(s), then make sure 'yamllint' is installed and dt-schema is up to date: pip3 install dtschema --upgrade Please check and re-submit after running the above command yourself. Note that DT_SCHEMA_FILES can be set to your schema file to speed up checking your schema. However, it must be unset to test all examples with your schema. ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v1 3/3] scsi: ufs: rockchip: init support for UFS 2024-08-06 7:19 [PATCH v1 0/3] Init support for RK3576 UFS controller Shawn Lin 2024-08-06 7:19 ` [PATCH v1 1/3] scsi: ufs: core: Export ufshcd_dme_link_startup() helper Shawn Lin 2024-08-06 7:19 ` [PATCH v1 2/3] dt-bindings: ufs: Document Rockchip UFS host controller Shawn Lin @ 2024-08-06 7:20 ` Shawn Lin 2024-08-06 8:43 ` Krzysztof Kozlowski 2 siblings, 1 reply; 7+ messages in thread From: Shawn Lin @ 2024-08-06 7:20 UTC (permalink / raw) To: Rob Herring, Martin K . Petersen Cc: Heiko Stuebner, Alim Akhtar, Avri Altman, Bart Van Assche, YiFeng Zhao, Liang Chen, linux-scsi, linux-rockchip, devicetree, Shawn Lin RK3576 contains a UFS controller, add init support fot it. Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com> --- drivers/ufs/host/Kconfig | 12 + drivers/ufs/host/Makefile | 1 + drivers/ufs/host/ufs-rockchip.c | 477 ++++++++++++++++++++++++++++++++++++++++ drivers/ufs/host/ufs-rockchip.h | 52 +++++ 4 files changed, 542 insertions(+) create mode 100644 drivers/ufs/host/ufs-rockchip.c create mode 100644 drivers/ufs/host/ufs-rockchip.h diff --git a/drivers/ufs/host/Kconfig b/drivers/ufs/host/Kconfig index 580c8d0..fafaa33 100644 --- a/drivers/ufs/host/Kconfig +++ b/drivers/ufs/host/Kconfig @@ -142,3 +142,15 @@ config SCSI_UFS_SPRD Select this if you have UFS controller on Unisoc chipset. If unsure, say N. + +config SCSI_UFS_ROCKCHIP + tristate "Rockchip specific hooks to UFS controller platform driver" + depends on SCSI_UFSHCD_PLATFORM && (ARCH_ROCKCHIP || COMPILE_TEST) + help + This selects the Rockchip specific additions to UFSHCD platform driver. + UFS host on Rockchip needs some vendor specific configuration before + accessing the hardware which includes PHY configuration and vendor + specific registers. + + Select this if you have UFS controller on Rockchip chipset. + If unsure, say N. diff --git a/drivers/ufs/host/Makefile b/drivers/ufs/host/Makefile index 4573aea..2f97feb 100644 --- a/drivers/ufs/host/Makefile +++ b/drivers/ufs/host/Makefile @@ -10,5 +10,6 @@ obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o obj-$(CONFIG_SCSI_UFS_HISI) += ufs-hisi.o obj-$(CONFIG_SCSI_UFS_MEDIATEK) += ufs-mediatek.o obj-$(CONFIG_SCSI_UFS_RENESAS) += ufs-renesas.o +obj-$(CONFIG_SCSI_UFS_ROCKCHIP) += ufs-rockchip.o obj-$(CONFIG_SCSI_UFS_SPRD) += ufs-sprd.o obj-$(CONFIG_SCSI_UFS_TI_J721E) += ti-j721e-ufs.o diff --git a/drivers/ufs/host/ufs-rockchip.c b/drivers/ufs/host/ufs-rockchip.c new file mode 100644 index 0000000..3220d6f --- /dev/null +++ b/drivers/ufs/host/ufs-rockchip.c @@ -0,0 +1,477 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Rockchip UFS Host Controller driver + * + * Copyright (C) 2024 Rockchip Electronics Co.Ltd. + */ + +#include <linux/clk.h> +#include <linux/gpio.h> +#include <linux/mfd/syscon.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> +#include <linux/reset.h> + +#include <ufs/ufshcd.h> +#include <ufs/unipro.h> +#include "ufshcd-pltfrm.h" +#include "ufshcd-dwc.h" +#include "ufs-rockchip.h" + +static inline bool ufshcd_is_device_present(struct ufs_hba *hba) +{ + return ufshcd_readl(hba, REG_CONTROLLER_STATUS) & DEVICE_PRESENT; +} + +static int ufs_rockchip_hce_enable_notify(struct ufs_hba *hba, + enum ufs_notify_change_status status) +{ + int err = 0; + + if (status == PRE_CHANGE) { + int retry_outer = 3; + int retry_inner; +start: + if (ufshcd_is_hba_active(hba)) + /* change controller state to "reset state" */ + ufshcd_hba_stop(hba); + + /* UniPro link is disabled at this point */ + ufshcd_set_link_off(hba); + + /* start controller initialization sequence */ + ufshcd_writel(hba, CONTROLLER_ENABLE, REG_CONTROLLER_ENABLE); + + usleep_range(100, 200); + + /* wait for the host controller to complete initialization */ + retry_inner = 50; + while (!ufshcd_is_hba_active(hba)) { + if (retry_inner) { + retry_inner--; + } else { + dev_err(hba->dev, + "Controller enable failed\n"); + if (retry_outer) { + retry_outer--; + goto start; + } + return -EIO; + } + usleep_range(1000, 1100); + } + } else { /* POST_CHANGE */ + err = ufshcd_vops_phy_initialization(hba); + } + + return err; +} + +static void ufs_rockchip_set_pm_lvl(struct ufs_hba *hba) +{ + hba->rpm_lvl = UFS_PM_LVL_1; + hba->spm_lvl = UFS_PM_LVL_3; +} + +static const unsigned char rk3576_phy_value[15][4] = { + {0x03, 0x38, 0x50, 0x80}, + {0x03, 0x14, 0x58, 0x80}, + {0x03, 0x26, 0x58, 0x80}, + {0x03, 0x49, 0x58, 0x80}, + {0x03, 0x5A, 0x58, 0x80}, + {0xC3, 0x38, 0x50, 0xC0}, + {0xC3, 0x14, 0x58, 0xC0}, + {0xC3, 0x26, 0x58, 0xC0}, + {0xC3, 0x49, 0x58, 0xC0}, + {0xC3, 0x5A, 0x58, 0xC0}, + {0x43, 0x38, 0x50, 0xC0}, + {0x43, 0x14, 0x58, 0xC0}, + {0x43, 0x26, 0x58, 0xC0}, + {0x43, 0x49, 0x58, 0xC0}, + {0x43, 0x5A, 0x58, 0xC0} +}; + +static int ufs_rockchip_rk3576_phy_init(struct ufs_hba *hba) +{ + struct ufs_rockchip_host *host = ufshcd_get_variant(hba); + u32 try_case = host->phy_config_mode, value; + + if (try_case >= ARRAY_SIZE(rk3576_phy_value)) + try_case = 0; + + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(PA_LOCAL_TX_LCC_ENABLE, 0x0), 0x0); + /* enable the mphy DME_SET cfg */ + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x200, 0x0), 0x40); + for (int i = 0; i < 2; i++) { + /* Configuration M-TX */ + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0xaa, SEL_TX_LANE0 + i), 0x06); + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0xa9, SEL_TX_LANE0 + i), 0x02); + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0xad, SEL_TX_LANE0 + i), 0x44); + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0xac, SEL_TX_LANE0 + i), 0xe6); + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0xab, SEL_TX_LANE0 + i), 0x07); + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x94, SEL_TX_LANE0 + i), 0x93); + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x93, SEL_TX_LANE0 + i), 0xc9); + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x7f, SEL_TX_LANE0 + i), 0x00); + /* Configuration M-RX */ + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x12, SEL_RX_LANE0 + i), 0x06); + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x11, SEL_RX_LANE0 + i), 0x00); + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x1d, SEL_RX_LANE0 + i), 0x58); + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x1c, SEL_RX_LANE0 + i), 0x8c); + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x1b, SEL_RX_LANE0 + i), 0x02); + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x25, SEL_RX_LANE0 + i), 0xf6); + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x2f, SEL_RX_LANE0 + i), 0x69); + } + /* disable the mphy DME_SET cfg */ + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x200, 0x0), 0x00); + + ufs_sys_writel(host->mphy_base, 0x80, 0x08C); + ufs_sys_writel(host->mphy_base, 0xB5, 0x110); + ufs_sys_writel(host->mphy_base, 0xB5, 0x250); + + value = rk3576_phy_value[try_case][0]; + ufs_sys_writel(host->mphy_base, value, 0x134); + ufs_sys_writel(host->mphy_base, value, 0x274); + + value = rk3576_phy_value[try_case][1]; + ufs_sys_writel(host->mphy_base, value, 0x0E0); + ufs_sys_writel(host->mphy_base, value, 0x220); + + value = rk3576_phy_value[try_case][2]; + ufs_sys_writel(host->mphy_base, value, 0x164); + ufs_sys_writel(host->mphy_base, value, 0x2A4); + + value = rk3576_phy_value[try_case][3]; + ufs_sys_writel(host->mphy_base, value, 0x178); + ufs_sys_writel(host->mphy_base, value, 0x2B8); + + ufs_sys_writel(host->mphy_base, 0x18, 0x1B0); + ufs_sys_writel(host->mphy_base, 0x18, 0x2F0); + + ufs_sys_writel(host->mphy_base, 0x03, 0x128); + ufs_sys_writel(host->mphy_base, 0x03, 0x268); + + ufs_sys_writel(host->mphy_base, 0x20, 0x12C); + ufs_sys_writel(host->mphy_base, 0x20, 0x26C); + + ufs_sys_writel(host->mphy_base, 0xC0, 0x120); + ufs_sys_writel(host->mphy_base, 0xC0, 0x260); + + ufs_sys_writel(host->mphy_base, 0x03, 0x094); + + ufs_sys_writel(host->mphy_base, 0x03, 0x1B4); + ufs_sys_writel(host->mphy_base, 0x03, 0x2F4); + + ufs_sys_writel(host->mphy_base, 0xC0, 0x08C); + udelay(1); + ufs_sys_writel(host->mphy_base, 0x00, 0x08C); + + udelay(200); + /* start link up */ + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(MIB_T_DBG_CPORT_TX_ENDIAN, 0), 0x0); + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(MIB_T_DBG_CPORT_RX_ENDIAN, 0), 0x0); + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(N_DEVICEID, 0), 0x0); + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(N_DEVICEID_VALID, 0), 0x1); + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(T_PEERDEVICEID, 0), 0x1); + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(T_CONNECTIONSTATE, 0), 0x1); + + return 0; +} + +static int ufs_rockchip_common_init(struct ufs_hba *hba) +{ + struct device *dev = hba->dev; + struct platform_device *pdev = to_platform_device(dev); + struct ufs_rockchip_host *host; + int err = 0; + + host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL); + if (!host) + return -ENOMEM; + + /* system control register for hci */ + host->ufs_sys_ctrl = devm_platform_ioremap_resource_byname(pdev, "hci_grf"); + if (IS_ERR(host->ufs_sys_ctrl)) { + dev_err(dev, "cannot ioremap for hci system control register\n"); + return PTR_ERR(host->ufs_sys_ctrl); + } + + /* system control register for mphy */ + host->ufs_phy_ctrl = devm_platform_ioremap_resource_byname(pdev, "mphy_grf"); + if (IS_ERR(host->ufs_phy_ctrl)) { + dev_err(dev, "cannot ioremap for mphy system control register\n"); + return PTR_ERR(host->ufs_phy_ctrl); + } + + /* mphy base register */ + host->mphy_base = devm_platform_ioremap_resource_byname(pdev, "mphy"); + if (IS_ERR(host->mphy_base)) { + dev_err(dev, "cannot ioremap for mphy base register\n"); + return PTR_ERR(host->mphy_base); + } + + host->rst = devm_reset_control_array_get_exclusive(dev); + if (IS_ERR(host->rst)) { + dev_err(dev, "failed to get reset control\n"); + return PTR_ERR(host->rst); + } + + reset_control_assert(host->rst); + udelay(1); + reset_control_deassert(host->rst); + + host->ref_out_clk = devm_clk_get(dev, "ref_out"); + if (IS_ERR(host->ref_out_clk)) { + dev_err(dev, "ciu-drive not available\n"); + return PTR_ERR(host->ref_out_clk); + } + err = clk_prepare_enable(host->ref_out_clk); + if (err) { + dev_err(dev, "failed to enable ref out clock %d\n", err); + return err; + } + + host->rst_gpio = devm_gpiod_get(&pdev->dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(host->rst_gpio)) { + dev_err(&pdev->dev, "invalid reset-gpios property in node\n"); + err = PTR_ERR(host->rst_gpio); + goto out; + } + udelay(20); + gpiod_set_value_cansleep(host->rst_gpio, 1); + + host->clks[0].id = "core"; + host->clks[1].id = "pclk"; + host->clks[2].id = "pclk_mphy"; + err = devm_clk_bulk_get_optional(dev, UFS_MAX_CLKS, host->clks); + if (err) { + dev_err(dev, "failed to get clocks %d\n", err); + goto out; + } + + err = clk_bulk_prepare_enable(UFS_MAX_CLKS, host->clks); + if (err) { + dev_err(dev, "failed to enable clocks %d\n", err); + goto out; + } + + if (device_property_read_u32(dev, "ufs-phy-config-mode", + &host->phy_config_mode)) + host->phy_config_mode = 0; + + pm_runtime_set_active(&pdev->dev); + + host->hba = hba; + ufs_rockchip_set_pm_lvl(hba); + + ufshcd_set_variant(hba, host); + + return 0; +out: + clk_disable_unprepare(host->ref_out_clk); + return err; +} + +static int ufs_rockchip_rk3576_init(struct ufs_hba *hba) +{ + int ret = 0; + struct device *dev = hba->dev; + + hba->quirks = UFSHCI_QUIRK_BROKEN_HCE | UFSHCD_QUIRK_SKIP_DEF_UNIPRO_TIMEOUT_SETTING; + + /* Enable BKOPS when suspend */ + hba->caps |= UFSHCD_CAP_AUTO_BKOPS_SUSPEND; + /* Enable putting device into deep sleep */ + hba->caps |= UFSHCD_CAP_DEEPSLEEP; + /* Enable devfreq of UFS */ + hba->caps |= UFSHCD_CAP_CLK_SCALING; + /* Enable WriteBooster */ + hba->caps |= UFSHCD_CAP_WB_EN; + + ret = ufs_rockchip_common_init(hba); + if (ret) { + dev_err(dev, "ufs common init fail\n"); + return ret; + } + + return 0; +} + +static int ufs_rockchip_device_reset(struct ufs_hba *hba) +{ + struct ufs_rockchip_host *host = ufshcd_get_variant(hba); + + if (!host->rst_gpio) + return -EOPNOTSUPP; + + gpiod_set_value_cansleep(host->rst_gpio, 0); + udelay(20); + + gpiod_set_value_cansleep(host->rst_gpio, 1); + udelay(20); + + return 0; +} + +static const struct ufs_hba_variant_ops ufs_hba_rk3576_vops = { + .name = "rk3576", + .init = ufs_rockchip_rk3576_init, + .device_reset = ufs_rockchip_device_reset, + .hce_enable_notify = ufs_rockchip_hce_enable_notify, + .phy_initialization = ufs_rockchip_rk3576_phy_init, +}; + +static const struct of_device_id ufs_rockchip_of_match[] = { + { .compatible = "rockchip,rk3576-ufs", .data = &ufs_hba_rk3576_vops}, + {}, +}; +MODULE_DEVICE_TABLE(of, ufs_rockchip_of_match); + +static int ufs_rockchip_probe(struct platform_device *pdev) +{ + int err; + struct device *dev = &pdev->dev; + const struct ufs_hba_variant_ops *vops; + + vops = device_get_match_data(dev); + err = ufshcd_pltfrm_init(pdev, vops); + if (err) + dev_err(dev, "ufshcd_pltfrm_init() failed %d\n", err); + + return err; +} + +static void ufs_rockchip_remove(struct platform_device *pdev) +{ + struct ufs_hba *hba = platform_get_drvdata(pdev); + struct ufs_rockchip_host *host = ufshcd_get_variant(hba); + + pm_runtime_forbid(&pdev->dev); + pm_runtime_get_noresume(&pdev->dev); + ufshcd_remove(hba); + ufshcd_dealloc_host(hba); + clk_disable_unprepare(host->ref_out_clk); +} + +static int ufs_rockchip_restore_link(struct ufs_hba *hba, bool is_store) +{ + struct ufs_rockchip_host *host = ufshcd_get_variant(hba); + int err, retry = 3; + + if (is_store) { + host->ie = ufshcd_readl(hba, REG_INTERRUPT_ENABLE); + host->ahit = ufshcd_readl(hba, REG_AUTO_HIBERNATE_IDLE_TIMER); + return 0; + } + + /* Enable controller */ + err = ufshcd_hba_enable(hba); + if (err) + return err; + + /* Link startup and wait for DP */ + do { + err = ufshcd_dme_link_startup(hba); + if (!err && ufshcd_is_device_present(hba)) { + dev_dbg_ratelimited(hba->dev, "rockchip link startup successfully.\n"); + break; + } + } while (retry--); + + if (retry < 0) { + dev_err(hba->dev, "rockchip link startup failed.\n"); + return -ENXIO; + } + + /* Restore negotiated power mode */ + err = ufshcd_config_pwr_mode(hba, &(hba->pwr_info)); + if (err) + dev_err(hba->dev, "Failed to restore power mode, err = %d\n", err); + + /* Restore task and transfer list */ + ufshcd_writel(hba, 0xffffffff, REG_INTERRUPT_STATUS); + ufshcd_make_hba_operational(hba); + + /* Restore lost regs */ + ufshcd_writel(hba, host->ie, REG_INTERRUPT_ENABLE); + ufshcd_writel(hba, host->ahit, REG_AUTO_HIBERNATE_IDLE_TIMER); + ufshcd_writel(hba, 0x1, REG_UTP_TRANSFER_REQ_LIST_RUN_STOP); + ufshcd_writel(hba, 0x1, REG_UTP_TASK_REQ_LIST_RUN_STOP); + + return err; +} + +static int ufs_rockchip_runtime_suspend(struct device *dev) +{ + struct ufs_hba *hba = dev_get_drvdata(dev); + struct ufs_rockchip_host *host = ufshcd_get_variant(hba); + + clk_disable_unprepare(host->ref_out_clk); + return ufs_rockchip_restore_link(hba, true); +} + +static int ufs_rockchip_runtime_resume(struct device *dev) +{ + struct ufs_hba *hba = dev_get_drvdata(dev); + struct ufs_rockchip_host *host = ufshcd_get_variant(hba); + int err; + + err = clk_prepare_enable(host->ref_out_clk); + if (err) { + dev_err(hba->dev, "failed to enable ref out clock %d\n", err); + return err; + } + + reset_control_assert(host->rst); + udelay(1); + reset_control_deassert(host->rst); + + return ufs_rockchip_restore_link(hba, false); +} + +static int ufs_rockchip_suspend(struct device *dev) +{ + struct ufs_hba *hba = dev_get_drvdata(dev); + + if (pm_runtime_suspended(hba->dev)) + return 0; + + ufs_rockchip_restore_link(hba, true); + + return 0; +} + +static int ufs_rockchip_resume(struct device *dev) +{ + struct ufs_hba *hba = dev_get_drvdata(dev); + + if (pm_runtime_suspended(hba->dev)) + return 0; + + /* Reset device if possible */ + ufs_rockchip_device_reset(hba); + ufs_rockchip_restore_link(hba, false); + + return 0; +} + +static const struct dev_pm_ops ufs_rockchip_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(ufs_rockchip_suspend, ufs_rockchip_resume) + SET_RUNTIME_PM_OPS(ufs_rockchip_runtime_suspend, ufs_rockchip_runtime_resume, NULL) + .prepare = ufshcd_suspend_prepare, + .complete = ufshcd_resume_complete, +}; + +static struct platform_driver ufs_rockchip_pltform = { + .probe = ufs_rockchip_probe, + .remove = ufs_rockchip_remove, + .driver = { + .name = "ufshcd-rockchip", + .pm = &ufs_rockchip_pm_ops, + .of_match_table = of_match_ptr(ufs_rockchip_of_match), + }, +}; +module_platform_driver(ufs_rockchip_pltform); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Rockchip UFS Host Driver"); diff --git a/drivers/ufs/host/ufs-rockchip.h b/drivers/ufs/host/ufs-rockchip.h new file mode 100644 index 0000000..7f3c260 --- /dev/null +++ b/drivers/ufs/host/ufs-rockchip.h @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Rockchip UFS Host Controller driver + * + * Copyright (C) 2024 Rockchip Electronics Co.Ltd. + */ + +#ifndef _UFS_ROCKCHIP_H_ +#define _UFS_ROCKCHIP_H_ + +#define UFS_MAX_CLKS 3 + +#define SEL_TX_LANE0 0x0 +#define SEL_TX_LANE1 0x1 +#define SEL_TX_LANE2 0x2 +#define SEL_TX_LANE3 0x3 +#define SEL_RX_LANE0 0x4 +#define SEL_RX_LANE1 0x5 +#define SEL_RX_LANE2 0x6 +#define SEL_RX_LANE3 0x7 + +#define MIB_T_DBG_CPORT_TX_ENDIAN 0xc022 +#define MIB_T_DBG_CPORT_RX_ENDIAN 0xc023 + +struct ufs_rockchip_host { + struct ufs_hba *hba; + void __iomem *ufs_phy_ctrl; + void __iomem *ufs_sys_ctrl; + void __iomem *mphy_base; + struct gpio_desc *rst_gpio; + struct reset_control *rst; + struct clk *ref_out_clk; + struct clk_bulk_data clks[UFS_MAX_CLKS]; + uint64_t caps; + uint32_t phy_config_mode; + bool in_suspend; + u32 ie; + u32 ahit; +}; + +#define ufs_sys_writel(base, val, reg) \ + writel((val), (base) + (reg)) +#define ufs_sys_readl(base, reg) readl((base) + (reg)) +#define ufs_sys_set_bits(base, mask, reg) \ + ufs_sys_writel( \ + (base), ((mask) | (ufs_sys_readl((base), (reg)))), (reg)) +#define ufs_sys_ctrl_clr_bits(base, mask, reg) \ + ufs_sys_writel((base), \ + ((~(mask)) & (ufs_sys_readl((base), (reg)))), \ + (reg)) + +#endif /* _UFS_ROCKCHIP_H_ */ -- 2.7.4 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v1 3/3] scsi: ufs: rockchip: init support for UFS 2024-08-06 7:20 ` [PATCH v1 3/3] scsi: ufs: rockchip: init support for UFS Shawn Lin @ 2024-08-06 8:43 ` Krzysztof Kozlowski 0 siblings, 0 replies; 7+ messages in thread From: Krzysztof Kozlowski @ 2024-08-06 8:43 UTC (permalink / raw) To: Shawn Lin, Rob Herring, Martin K . Petersen Cc: Heiko Stuebner, Alim Akhtar, Avri Altman, Bart Van Assche, YiFeng Zhao, Liang Chen, linux-scsi, linux-rockchip, devicetree On 06/08/2024 09:20, Shawn Lin wrote: > RK3576 contains a UFS controller, add init support fot it. > > Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com> > > --- > + > +static int ufs_rockchip_common_init(struct ufs_hba *hba) > +{ > + struct device *dev = hba->dev; > + struct platform_device *pdev = to_platform_device(dev); > + struct ufs_rockchip_host *host; > + int err = 0; > + > + host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL); > + if (!host) > + return -ENOMEM; > + > + /* system control register for hci */ > + host->ufs_sys_ctrl = devm_platform_ioremap_resource_byname(pdev, "hci_grf"); > + if (IS_ERR(host->ufs_sys_ctrl)) { > + dev_err(dev, "cannot ioremap for hci system control register\n"); > + return PTR_ERR(host->ufs_sys_ctrl); > + } > + > + /* system control register for mphy */ > + host->ufs_phy_ctrl = devm_platform_ioremap_resource_byname(pdev, "mphy_grf"); > + if (IS_ERR(host->ufs_phy_ctrl)) { > + dev_err(dev, "cannot ioremap for mphy system control register\n"); > + return PTR_ERR(host->ufs_phy_ctrl); > + } > + > + /* mphy base register */ > + host->mphy_base = devm_platform_ioremap_resource_byname(pdev, "mphy"); > + if (IS_ERR(host->mphy_base)) { > + dev_err(dev, "cannot ioremap for mphy base register\n"); > + return PTR_ERR(host->mphy_base); > + } > + > + host->rst = devm_reset_control_array_get_exclusive(dev); > + if (IS_ERR(host->rst)) { > + dev_err(dev, "failed to get reset control\n"); > + return PTR_ERR(host->rst); return dev_err_probe, assuming this is a probe path? > + } > + > + reset_control_assert(host->rst); > + udelay(1); > + reset_control_deassert(host->rst); > + > + host->ref_out_clk = devm_clk_get(dev, "ref_out"); > + if (IS_ERR(host->ref_out_clk)) { > + dev_err(dev, "ciu-drive not available\n"); > + return PTR_ERR(host->ref_out_clk); Ditto > + } > + err = clk_prepare_enable(host->ref_out_clk); > + if (err) { > + dev_err(dev, "failed to enable ref out clock %d\n", err); > + return err; > + } > + > + host->rst_gpio = devm_gpiod_get(&pdev->dev, "reset", GPIOD_OUT_LOW); Hm? Test your DTS and bindings. > + if (IS_ERR(host->rst_gpio)) { > + dev_err(&pdev->dev, "invalid reset-gpios property in node\n"); Post your DTS so we can review it. Post also results of dtbs_check... > + err = PTR_ERR(host->rst_gpio); dev_err_probe > + goto out; > + } > + udelay(20); > + gpiod_set_value_cansleep(host->rst_gpio, 1); > + > + host->clks[0].id = "core"; > + host->clks[1].id = "pclk"; > + host->clks[2].id = "pclk_mphy"; > + err = devm_clk_bulk_get_optional(dev, UFS_MAX_CLKS, host->clks); > + if (err) { > + dev_err(dev, "failed to get clocks %d\n", err); > + goto out; > + } > + > + err = clk_bulk_prepare_enable(UFS_MAX_CLKS, host->clks); > + if (err) { > + dev_err(dev, "failed to enable clocks %d\n", err); > + goto out; > + } > + > + if (device_property_read_u32(dev, "ufs-phy-config-mode", No, stop adding undocumented properties. > + &host->phy_config_mode)) > + host->phy_config_mode = 0; > + > + pm_runtime_set_active(&pdev->dev); > + > + host->hba = hba; > + ufs_rockchip_set_pm_lvl(hba); > + > + ufshcd_set_variant(hba, host); > + > + return 0; > +out: > + clk_disable_unprepare(host->ref_out_clk); > + return err; > +} > + > +static int ufs_rockchip_rk3576_init(struct ufs_hba *hba) > +{ > + int ret = 0; > + struct device *dev = hba->dev; > + > + hba->quirks = UFSHCI_QUIRK_BROKEN_HCE | UFSHCD_QUIRK_SKIP_DEF_UNIPRO_TIMEOUT_SETTING; > + > + /* Enable BKOPS when suspend */ > + hba->caps |= UFSHCD_CAP_AUTO_BKOPS_SUSPEND; > + /* Enable putting device into deep sleep */ > + hba->caps |= UFSHCD_CAP_DEEPSLEEP; > + /* Enable devfreq of UFS */ > + hba->caps |= UFSHCD_CAP_CLK_SCALING; > + /* Enable WriteBooster */ > + hba->caps |= UFSHCD_CAP_WB_EN; > + > + ret = ufs_rockchip_common_init(hba); > + if (ret) { > + dev_err(dev, "ufs common init fail\n"); > + return ret; > + } > + > + return 0; > +} > + > +static int ufs_rockchip_device_reset(struct ufs_hba *hba) > +{ > + struct ufs_rockchip_host *host = ufshcd_get_variant(hba); > + > + if (!host->rst_gpio) > + return -EOPNOTSUPP; > + > + gpiod_set_value_cansleep(host->rst_gpio, 0); > + udelay(20); > + > + gpiod_set_value_cansleep(host->rst_gpio, 1); > + udelay(20); > + > + return 0; > +} > + > +static const struct ufs_hba_variant_ops ufs_hba_rk3576_vops = { > + .name = "rk3576", > + .init = ufs_rockchip_rk3576_init, > + .device_reset = ufs_rockchip_device_reset, > + .hce_enable_notify = ufs_rockchip_hce_enable_notify, > + .phy_initialization = ufs_rockchip_rk3576_phy_init, > +}; > + > +static const struct of_device_id ufs_rockchip_of_match[] = { > + { .compatible = "rockchip,rk3576-ufs", .data = &ufs_hba_rk3576_vops}, > + {}, > +}; > +MODULE_DEVICE_TABLE(of, ufs_rockchip_of_match); > + > +static int ufs_rockchip_probe(struct platform_device *pdev) > +{ > + int err; > + struct device *dev = &pdev->dev; > + const struct ufs_hba_variant_ops *vops; > + > + vops = device_get_match_data(dev); > + err = ufshcd_pltfrm_init(pdev, vops); > + if (err) > + dev_err(dev, "ufshcd_pltfrm_init() failed %d\n", err); > + > + return err; > +} > + > +static void ufs_rockchip_remove(struct platform_device *pdev) > +{ > + struct ufs_hba *hba = platform_get_drvdata(pdev); > + struct ufs_rockchip_host *host = ufshcd_get_variant(hba); > + > + pm_runtime_forbid(&pdev->dev); > + pm_runtime_get_noresume(&pdev->dev); > + ufshcd_remove(hba); > + ufshcd_dealloc_host(hba); > + clk_disable_unprepare(host->ref_out_clk); > +} > + > +static int ufs_rockchip_restore_link(struct ufs_hba *hba, bool is_store) > +{ > + struct ufs_rockchip_host *host = ufshcd_get_variant(hba); > + int err, retry = 3; > + > + if (is_store) { > + host->ie = ufshcd_readl(hba, REG_INTERRUPT_ENABLE); > + host->ahit = ufshcd_readl(hba, REG_AUTO_HIBERNATE_IDLE_TIMER); > + return 0; > + } > + > + /* Enable controller */ > + err = ufshcd_hba_enable(hba); > + if (err) > + return err; > + > + /* Link startup and wait for DP */ > + do { > + err = ufshcd_dme_link_startup(hba); > + if (!err && ufshcd_is_device_present(hba)) { > + dev_dbg_ratelimited(hba->dev, "rockchip link startup successfully.\n"); > + break; > + } > + } while (retry--); > + > + if (retry < 0) { > + dev_err(hba->dev, "rockchip link startup failed.\n"); > + return -ENXIO; > + } > + > + /* Restore negotiated power mode */ > + err = ufshcd_config_pwr_mode(hba, &(hba->pwr_info)); > + if (err) > + dev_err(hba->dev, "Failed to restore power mode, err = %d\n", err); > + > + /* Restore task and transfer list */ > + ufshcd_writel(hba, 0xffffffff, REG_INTERRUPT_STATUS); > + ufshcd_make_hba_operational(hba); > + > + /* Restore lost regs */ > + ufshcd_writel(hba, host->ie, REG_INTERRUPT_ENABLE); > + ufshcd_writel(hba, host->ahit, REG_AUTO_HIBERNATE_IDLE_TIMER); > + ufshcd_writel(hba, 0x1, REG_UTP_TRANSFER_REQ_LIST_RUN_STOP); > + ufshcd_writel(hba, 0x1, REG_UTP_TASK_REQ_LIST_RUN_STOP); > + > + return err; > +} > + > +static int ufs_rockchip_runtime_suspend(struct device *dev) > +{ > + struct ufs_hba *hba = dev_get_drvdata(dev); > + struct ufs_rockchip_host *host = ufshcd_get_variant(hba); > + > + clk_disable_unprepare(host->ref_out_clk); > + return ufs_rockchip_restore_link(hba, true); > +} > + > +static int ufs_rockchip_runtime_resume(struct device *dev) > +{ > + struct ufs_hba *hba = dev_get_drvdata(dev); > + struct ufs_rockchip_host *host = ufshcd_get_variant(hba); > + int err; > + > + err = clk_prepare_enable(host->ref_out_clk); > + if (err) { > + dev_err(hba->dev, "failed to enable ref out clock %d\n", err); > + return err; > + } > + > + reset_control_assert(host->rst); > + udelay(1); > + reset_control_deassert(host->rst); > + > + return ufs_rockchip_restore_link(hba, false); > +} > + > +static int ufs_rockchip_suspend(struct device *dev) > +{ > + struct ufs_hba *hba = dev_get_drvdata(dev); > + > + if (pm_runtime_suspended(hba->dev)) > + return 0; > + > + ufs_rockchip_restore_link(hba, true); > + > + return 0; > +} > + > +static int ufs_rockchip_resume(struct device *dev) > +{ > + struct ufs_hba *hba = dev_get_drvdata(dev); > + > + if (pm_runtime_suspended(hba->dev)) > + return 0; > + > + /* Reset device if possible */ > + ufs_rockchip_device_reset(hba); > + ufs_rockchip_restore_link(hba, false); > + > + return 0; > +} > + > +static const struct dev_pm_ops ufs_rockchip_pm_ops = { > + SET_SYSTEM_SLEEP_PM_OPS(ufs_rockchip_suspend, ufs_rockchip_resume) > + SET_RUNTIME_PM_OPS(ufs_rockchip_runtime_suspend, ufs_rockchip_runtime_resume, NULL) > + .prepare = ufshcd_suspend_prepare, > + .complete = ufshcd_resume_complete, > +}; > + > +static struct platform_driver ufs_rockchip_pltform = { > + .probe = ufs_rockchip_probe, > + .remove = ufs_rockchip_remove, > + .driver = { > + .name = "ufshcd-rockchip", > + .pm = &ufs_rockchip_pm_ops, > + .of_match_table = of_match_ptr(ufs_rockchip_of_match), Drop of_match_ptr, you have here warnings. Best regards, Krzysztof ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2024-08-06 17:25 UTC | newest] Thread overview: 7+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2024-08-06 7:19 [PATCH v1 0/3] Init support for RK3576 UFS controller Shawn Lin 2024-08-06 7:19 ` [PATCH v1 1/3] scsi: ufs: core: Export ufshcd_dme_link_startup() helper Shawn Lin 2024-08-06 7:19 ` [PATCH v1 2/3] dt-bindings: ufs: Document Rockchip UFS host controller Shawn Lin 2024-08-06 8:46 ` Krzysztof Kozlowski 2024-08-06 10:18 ` Rob Herring (Arm) 2024-08-06 7:20 ` [PATCH v1 3/3] scsi: ufs: rockchip: init support for UFS Shawn Lin 2024-08-06 8:43 ` Krzysztof Kozlowski
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).