From owner-svn-src-all@freebsd.org Wed Mar 4 20:48:32 2020 Return-Path: Delivered-To: svn-src-all@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 77F85250BE7; Wed, 4 Mar 2020 20:48:32 +0000 (UTC) (envelope-from manu@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 48XmDv6TD3z4S5R; Wed, 4 Mar 2020 20:48:31 +0000 (UTC) (envelope-from manu@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 58BFC23E9C; Wed, 4 Mar 2020 20:48:31 +0000 (UTC) (envelope-from manu@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id 024KmVXs011993; Wed, 4 Mar 2020 20:48:31 GMT (envelope-from manu@FreeBSD.org) Received: (from manu@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id 024KmUrT011985; Wed, 4 Mar 2020 20:48:30 GMT (envelope-from manu@FreeBSD.org) Message-Id: <202003042048.024KmUrT011985@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: manu set sender to manu@FreeBSD.org using -f From: Emmanuel Vadot Date: Wed, 4 Mar 2020 20:48:30 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org Subject: svn commit: r358641 - in stable/12/sys: arm64/conf arm64/rockchip arm64/rockchip/clk conf X-SVN-Group: stable-12 X-SVN-Commit-Author: manu X-SVN-Commit-Paths: in stable/12/sys: arm64/conf arm64/rockchip arm64/rockchip/clk conf X-SVN-Commit-Revision: 358641 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 04 Mar 2020 20:48:32 -0000 Author: manu Date: Wed Mar 4 20:48:29 2020 New Revision: 358641 URL: https://svnweb.freebsd.org/changeset/base/358641 Log: MFC r354087, r354089, r354094, r354100, r354103, r354152 r354087: arm64: rk3399: Add clock and gate for usb3 clocks r354089: arm64: rockchip: Add RK3399 TypeC phy driver This is a driver for the USB3 PHY present in the RK3399. While the phy support DP (Display Port) the driver doesn't has we have no driver to test this with for now. All the lane and pll configuration is just magic values from rockchip. While the manual have some info on those registers it's really hard to understand how to calculate those values (if there is a way). r354094 by peterj: Fix use of uninitialised variable. The RK805 regs array was being allocated before it's required size was known, causing the driver to use memory it didn't own. That memory was subsequently allocated and used elsewhere causing later fatal data aborts in rk805_map(). Whilst I'm here, add a sanity check to catch unsupported PMICs (this shouldn't ever get hit because the probe should have failed). Reviewed by: manu Sponsored by: Google r354100 by gonzo: arm64: rk3399: Add clock and gate for SPI clocks r354103 by gonzo: arm64: rk3399: add SPI driver and include it in GENERIC config SPI driver for Rockchip's RK3399 SoC. Implements PIO mode, CS selection, SPI mode and frequency configuration. Reviewed by: manu Differential Revision: https://reviews.freebsd.org/D22148 r354152: arm64: rockchip: typec_phy: Rename timeout to retry Declare retry in the function scope. Rename it to retry as there is a timeout function which was causing to code to compile. Reported by: jhibbits X-MFC-WITH: r354089 Added: stable/12/sys/arm64/rockchip/rk_spi.c - copied unchanged from r354103, head/sys/arm64/rockchip/rk_spi.c stable/12/sys/arm64/rockchip/rk_typec_phy.c - copied, changed from r354089, head/sys/arm64/rockchip/rk_typec_phy.c Modified: stable/12/sys/arm64/conf/GENERIC stable/12/sys/arm64/rockchip/clk/rk3399_cru.c stable/12/sys/arm64/rockchip/rk805.c stable/12/sys/conf/files.arm64 Directory Properties: stable/12/ (props changed) Modified: stable/12/sys/arm64/conf/GENERIC ============================================================================== --- stable/12/sys/arm64/conf/GENERIC Wed Mar 4 20:43:29 2020 (r358640) +++ stable/12/sys/arm64/conf/GENERIC Wed Mar 4 20:48:29 2020 (r358641) @@ -180,6 +180,7 @@ device pl011 # USB support device aw_usbphy # Allwinner USB PHY device rk_usb2phy # Rockchip USB2PHY +device rk_typec_phy # Rockchip TypeC PHY device dwcotg # DWC OTG controller device ohci # OHCI USB interface device ehci # EHCI USB interface (USB 2.0) @@ -251,6 +252,7 @@ device mv_thermal # Marvell Thermal Sensor Controller # SPI device spibus device bcm2835_spi # Broadcom BCM283x SPI bus +device rk_spi # RockChip SPI controller # PWM device pwm Modified: stable/12/sys/arm64/rockchip/clk/rk3399_cru.c ============================================================================== --- stable/12/sys/arm64/rockchip/clk/rk3399_cru.c Wed Mar 4 20:43:29 2020 (r358640) +++ stable/12/sys/arm64/rockchip/clk/rk3399_cru.c Wed Mar 4 20:48:29 2020 (r358641) @@ -54,9 +54,18 @@ __FBSDID("$FreeBSD$"); #define SCLK_USB2PHY0_REF 123 #define SCLK_USB2PHY1_REF 124 +#define SCLK_USB3OTG0_REF 129 +#define SCLK_USB3OTG1_REF 130 +#define SCLK_USB3OTG0_SUSPEND 131 +#define SCLK_USB3OTG1_SUSPEND 132 #define ACLK_EMMC_CORE 241 #define ACLK_EMMC_NOC 242 #define ACLK_EMMC_GRF 243 +#define ACLK_USB3_NOC 245 +#define ACLK_USB3OTG0 246 +#define ACLK_USB3OTG1 247 +#define ACLK_USB3_RKSOC_AXI_PERF 248 +#define ACLK_USB3_GRF 249 #define PCLK_GPIO2 336 #define PCLK_GPIO3 337 #define PCLK_GPIO4 338 @@ -66,6 +75,11 @@ __FBSDID("$FreeBSD$"); #define PCLK_I2C5 344 #define PCLK_I2C6 345 #define PCLK_I2C7 346 +#define PCLK_SPI0 347 +#define PCLK_SPI1 348 +#define PCLK_SPI2 349 +#define PCLK_SPI4 350 +#define PCLK_SPI5 351 #define HCLK_HOST0 456 #define HCLK_HOST0_ARB 457 #define HCLK_HOST1 458 @@ -103,6 +117,12 @@ static struct rk_cru_gate rk3399_gates[] = { CRU_GATE(0, "hclk_perilp1_cpll_src", "cpll", 0x320, 1) CRU_GATE(0, "hclk_perilp1_gpll_src", "gpll", 0x320, 0) + /* CRU_CLKGATE_CON12 */ + CRU_GATE(SCLK_USB3OTG0_REF, "sclk_usb3otg0_ref", "xin24m", 0x330, 1) + CRU_GATE(SCLK_USB3OTG1_REF, "sclk_usb3otg1_ref", "xin24m", 0x330, 2) + CRU_GATE(SCLK_USB3OTG0_SUSPEND, "sclk_usb3otg0_suspend", "xin24m", 0x330, 3) + CRU_GATE(SCLK_USB3OTG1_SUSPEND, "sclk_usb3otg1_suspend", "xin24m", 0x330, 4) + /* CRU_CLKGATE_CON20 */ CRU_GATE(HCLK_HOST0, "hclk_host0", "hclk_perihp", 0x350, 5) CRU_GATE(HCLK_HOST0_ARB, "hclk_host0_arb", "hclk_perihp", 0x350, 6) @@ -117,6 +137,19 @@ static struct rk_cru_gate rk3399_gates[] = { CRU_GATE(PCLK_I2C2, "pclk_rki2c2", "pclk_perilp1", 0x358, 9) CRU_GATE(PCLK_I2C3, "pclk_rki2c3", "pclk_perilp1", 0x358, 10) + /* CRU_CLKGATE_CON23 */ + CRU_GATE(PCLK_SPI0, "pclk_spi0", "pclk_perilp1", 0x35C, 10) + CRU_GATE(PCLK_SPI1, "pclk_spi1", "pclk_perilp1", 0x35C, 11) + CRU_GATE(PCLK_SPI2, "pclk_spi2", "pclk_perilp1", 0x35C, 12) + CRU_GATE(PCLK_SPI4, "pclk_spi4", "pclk_perilp1", 0x35C, 13) + + /* CRU_CLKGATE_CON30 */ + CRU_GATE(ACLK_USB3_NOC, "aclk_usb3_noc", "aclk_usb3", 0x378, 0) + CRU_GATE(ACLK_USB3OTG0, "aclk_usb3otg0", "aclk_usb3", 0x378, 1) + CRU_GATE(ACLK_USB3OTG1, "aclk_usb3otg1", "aclk_usb3", 0x378, 2) + CRU_GATE(ACLK_USB3_RKSOC_AXI_PERF, "aclk_usb3_rksoc_axi_perf", "aclk_usb3", 0x378, 3) + CRU_GATE(ACLK_USB3_GRF, "aclk_usb3_grf", "aclk_usb3", 0x378, 4) + /* CRU_CLKGATE_CON31 */ CRU_GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_alive", 0x37c, 3) CRU_GATE(PCLK_GPIO3, "pclk_gpio3", "pclk_alive", 0x37c, 4) @@ -129,6 +162,9 @@ static struct rk_cru_gate rk3399_gates[] = { /* CRU_CLKGATE_CON33 */ CRU_GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_sd", 0x384, 8) + + /* CRU_CLKGATE_CON34 */ + CRU_GATE(PCLK_SPI4, "pclk_spi5", "pclk_perilp1", 0x388, 5) }; @@ -1066,6 +1102,32 @@ static struct rk_clk_composite_def pclk_perilp1 = { .flags = RK_CLK_COMPOSITE_HAVE_GATE, }; +/* USB3 clock */ + +#define ACLK_USB3 244 +static const char *aclk_usb3_parents[] = {"cpll", "gpll", "npll", "npll"}; +static struct rk_clk_composite_def aclk_usb3 = { + .clkdef = { + .id = ACLK_USB3, + .name = "aclk_usb3", + .parent_names = aclk_usb3_parents, + .parent_cnt = nitems(aclk_usb3_parents), + }, + /* CRU_CLKSET_CON39 */ + .muxdiv_offset = 0x19C, + .mux_shift = 6, + .mux_width = 2, + + .div_shift = 0, + .div_width = 5, + + /* CRU_CLKGATE_CON12 */ + .gate_offset = 0x330, + .gate_shift = 0, + + .flags = RK_CLK_COMPOSITE_HAVE_GATE, +}; + /* * i2c */ @@ -1210,7 +1272,236 @@ static struct rk_clk_composite_def i2c7 = { .flags = RK_CLK_COMPOSITE_HAVE_MUX | RK_CLK_COMPOSITE_HAVE_GATE, }; +/* USB3 */ + +#define SCLK_UPHY0_TCPDPHY_REF 125 +#define SCLK_UPHY0_TCPDCORE 126 + +/* Missing xin32k exported by rk808 */ +static const char *uphy0_tcpdphy_ref_parents[] = {"xin24m"}; + +static struct rk_clk_composite_def uphy0_tcpdphy_ref = { + .clkdef = { + .id = SCLK_UPHY0_TCPDPHY_REF, + .name = "uphy0_tcpdphy_ref", + .parent_names = uphy0_tcpdphy_ref_parents, + .parent_cnt = nitems(uphy0_tcpdphy_ref_parents), + }, + /* CRU_CLKSET_CON64 */ + .muxdiv_offset = 0x0200, + .mux_shift = 15, + .mux_width = 1, + + .div_shift = 8, + .div_width = 5, + + /* CRU_CLKGATE_CON13 */ + .gate_offset = 0x0334, + .gate_shift = 4, + + .flags = RK_CLK_COMPOSITE_HAVE_MUX | RK_CLK_COMPOSITE_HAVE_GATE, +}; + +/* Missing xin32k exported by rk808 */ +static const char *uphy0_tcpdcore_parents[] = {"xin24m", "xin24m", "cpll", "gpll"}; + +static struct rk_clk_composite_def uphy0_tcpdcore = { + .clkdef = { + .id = SCLK_UPHY0_TCPDCORE, + .name = "uphy0_tcpdcore", + .parent_names = uphy0_tcpdcore_parents, + .parent_cnt = nitems(uphy0_tcpdcore_parents), + }, + /* CRU_CLKSET_CON64 */ + .muxdiv_offset = 0x0200, + .mux_shift = 6, + .mux_width = 2, + + .div_shift = 0, + .div_width = 5, + + /* CRU_CLKGATE_CON13 */ + .gate_offset = 0x0334, + .gate_shift = 5, + + .flags = RK_CLK_COMPOSITE_HAVE_MUX | RK_CLK_COMPOSITE_HAVE_GATE, +}; + +#define SCLK_UPHY1_TCPDPHY_REF 127 +#define SCLK_UPHY1_TCPDCORE 128 + +/* Missing xin32k exported by rk808 */ +static const char *uphy1_tcpdphy_ref_parents[] = {"xin24m"}; + +static struct rk_clk_composite_def uphy1_tcpdphy_ref = { + .clkdef = { + .id = SCLK_UPHY1_TCPDPHY_REF, + .name = "uphy1_tcpdphy_ref", + .parent_names = uphy1_tcpdphy_ref_parents, + .parent_cnt = nitems(uphy1_tcpdphy_ref_parents), + }, + /* CRU_CLKSET_CON65 */ + .muxdiv_offset = 0x0204, + .mux_shift = 15, + .mux_width = 1, + + .div_shift = 8, + .div_width = 5, + + /* CRU_CLKGATE_CON13 */ + .gate_offset = 0x0334, + .gate_shift = 6, + + .flags = RK_CLK_COMPOSITE_HAVE_MUX | RK_CLK_COMPOSITE_HAVE_GATE, +}; + +/* Missing xin32k exported by rk808 */ +static const char *uphy1_tcpdcore_parents[] = {"xin24m", "xin24m", "cpll", "gpll"}; + +static struct rk_clk_composite_def uphy1_tcpdcore = { + .clkdef = { + .id = SCLK_UPHY1_TCPDCORE, + .name = "uphy1_tcpdcore", + .parent_names = uphy1_tcpdcore_parents, + .parent_cnt = nitems(uphy1_tcpdcore_parents), + }, + /* CRU_CLKSET_CON65 */ + .muxdiv_offset = 0x0204, + .mux_shift = 6, + .mux_width = 2, + + .div_shift = 0, + .div_width = 5, + + /* CRU_CLKGATE_CON13 */ + .gate_offset = 0x0334, + .gate_shift = 7, + + .flags = RK_CLK_COMPOSITE_HAVE_MUX | RK_CLK_COMPOSITE_HAVE_GATE, +}; + /* + * spi + */ +static const char *spi_parents[] = {"cpll", "gpll"}; + +#define SCLK_SPI0 71 +#define SCLK_SPI1 72 +#define SCLK_SPI2 73 +#define SCLK_SPI4 74 +#define SCLK_SPI5 75 + +static struct rk_clk_composite_def spi0 = { + .clkdef = { + .id = SCLK_SPI0, + .name = "clk_spi0", + .parent_names = spi_parents, + .parent_cnt = nitems(spi_parents), + }, + /* CRU_CLKSEL_CON59 */ + .muxdiv_offset = 0x01ec, + .mux_shift = 7, + .mux_width = 1, + + .div_shift = 0, + .div_width = 7, + + /* CRU_CLKGATE_CON9 */ + .gate_offset = 0x0324, + .gate_shift = 12, + + .flags = RK_CLK_COMPOSITE_HAVE_MUX | RK_CLK_COMPOSITE_HAVE_GATE, +}; + +static struct rk_clk_composite_def spi1 = { + .clkdef = { + .id = SCLK_SPI1, + .name = "clk_spi1", + .parent_names = spi_parents, + .parent_cnt = nitems(spi_parents), + }, + /* CRU_CLKSEL_CON59 */ + .muxdiv_offset = 0x01ec, + .mux_shift = 15, + .mux_width = 1, + + .div_shift = 8, + .div_width = 7, + + /* CRU_CLKGATE_CON9 */ + .gate_offset = 0x0324, + .gate_shift = 13, + + .flags = RK_CLK_COMPOSITE_HAVE_MUX | RK_CLK_COMPOSITE_HAVE_GATE, +}; + +static struct rk_clk_composite_def spi2 = { + .clkdef = { + .id = SCLK_SPI2, + .name = "clk_spi2", + .parent_names = spi_parents, + .parent_cnt = nitems(spi_parents), + }, + /* CRU_CLKSEL_CON60 */ + .muxdiv_offset = 0x01f0, + .mux_shift = 7, + .mux_width = 1, + + .div_shift = 0, + .div_width = 7, + + /* CRU_CLKGATE_CON9 */ + .gate_offset = 0x0324, + .gate_shift = 14, + + .flags = RK_CLK_COMPOSITE_HAVE_MUX | RK_CLK_COMPOSITE_HAVE_GATE, +}; + +static struct rk_clk_composite_def spi4 = { + .clkdef = { + .id = SCLK_SPI4, + .name = "clk_spi4", + .parent_names = spi_parents, + .parent_cnt = nitems(spi_parents), + }, + /* CRU_CLKSEL_CON60 */ + .muxdiv_offset = 0x01f0, + .mux_shift = 15, + .mux_width = 1, + + .div_shift = 8, + .div_width = 7, + + /* CRU_CLKGATE_CON9 */ + .gate_offset = 0x0324, + .gate_shift = 15, + + .flags = RK_CLK_COMPOSITE_HAVE_MUX | RK_CLK_COMPOSITE_HAVE_GATE, +}; + +static struct rk_clk_composite_def spi5 = { + .clkdef = { + .id = SCLK_SPI5, + .name = "clk_spi5", + .parent_names = spi_parents, + .parent_cnt = nitems(spi_parents), + }, + /* CRU_CLKSEL_CON58 */ + .muxdiv_offset = 0x01e8, + .mux_shift = 15, + .mux_width = 1, + + .div_shift = 8, + .div_width = 7, + + /* CRU_CLKGATE_CON13 */ + .gate_offset = 0x0334, + .gate_shift = 13, + + .flags = RK_CLK_COMPOSITE_HAVE_MUX | RK_CLK_COMPOSITE_HAVE_GATE, +}; + +/* * ARM CPU clocks (LITTLE and big) */ #define ARMCLKL 8 @@ -1593,6 +1884,10 @@ static struct rk_clk rk3399_clks[] = { }, { .type = RK_CLK_COMPOSITE, + .clk.composite = &aclk_usb3, + }, + { + .type = RK_CLK_COMPOSITE, .clk.composite = &i2c1, }, { @@ -1614,6 +1909,43 @@ static struct rk_clk rk3399_clks[] = { { .type = RK_CLK_COMPOSITE, .clk.composite = &i2c7, + }, + { + .type = RK_CLK_COMPOSITE, + .clk.composite = &uphy0_tcpdphy_ref, + }, + { + .type = RK_CLK_COMPOSITE, + .clk.composite = &uphy0_tcpdcore, + }, + { + .type = RK_CLK_COMPOSITE, + .clk.composite = &uphy1_tcpdphy_ref, + }, + { + .type = RK_CLK_COMPOSITE, + .clk.composite = &uphy1_tcpdcore, + }, + + { + .type = RK_CLK_COMPOSITE, + .clk.composite = &spi0, + }, + { + .type = RK_CLK_COMPOSITE, + .clk.composite = &spi1, + }, + { + .type = RK_CLK_COMPOSITE, + .clk.composite = &spi2, + }, + { + .type = RK_CLK_COMPOSITE, + .clk.composite = &spi4, + }, + { + .type = RK_CLK_COMPOSITE, + .clk.composite = &spi5, }, { Modified: stable/12/sys/arm64/rockchip/rk805.c ============================================================================== --- stable/12/sys/arm64/rockchip/rk805.c Wed Mar 4 20:43:29 2020 (r358640) +++ stable/12/sys/arm64/rockchip/rk805.c Wed Mar 4 20:48:29 2020 (r358641) @@ -468,9 +468,6 @@ rk805_attach(device_t dev) if (config_intrhook_establish(&sc->intr_hook) != 0) return (ENOMEM); - sc->regs = malloc(sizeof(struct rk805_reg_sc *) * sc->nregs, - M_RK805_REG, M_WAITOK | M_ZERO); - sc->type = ofw_bus_search_compatible(dev, compat_data)->ocd_data; switch (sc->type) { case RK805: @@ -481,7 +478,13 @@ rk805_attach(device_t dev) regdefs = rk808_regdefs; sc->nregs = nitems(rk808_regdefs); break; + default: + device_printf(dev, "Unknown type %d\n", sc->type); + return (ENXIO); } + + sc->regs = malloc(sizeof(struct rk805_reg_sc *) * sc->nregs, + M_RK805_REG, M_WAITOK | M_ZERO); rnode = ofw_bus_find_child(ofw_bus_get_node(dev), "regulators"); if (rnode > 0) { Copied: stable/12/sys/arm64/rockchip/rk_spi.c (from r354103, head/sys/arm64/rockchip/rk_spi.c) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ stable/12/sys/arm64/rockchip/rk_spi.c Wed Mar 4 20:48:29 2020 (r358641, copy of r354103, head/sys/arm64/rockchip/rk_spi.c) @@ -0,0 +1,483 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2019 Oleksandr Tymoshenko + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include + +#include "spibus_if.h" + +#define RK_SPI_CTRLR0 0x0000 +#define CTRLR0_OPM_MASTER (0 << 20) +#define CTRLR0_XFM_TR (0 << 18) +#define CTRLR0_FRF_MOTO (0 << 16) +#define CTRLR0_BHT_8BIT (1 << 13) +#define CTRLR0_EM_BIG (1 << 11) +#define CTRLR0_SSD_ONE (1 << 10) +#define CTRLR0_SCPOL (1 << 7) +#define CTRLR0_SCPH (1 << 6) +#define CTRLR0_DFS_8BIT (1 << 0) +#define RK_SPI_CTRLR1 0x0004 +#define RK_SPI_ENR 0x0008 +#define RK_SPI_SER 0x000c +#define RK_SPI_BAUDR 0x0010 +#define RK_SPI_TXFTLR 0x0014 +#define RK_SPI_RXFTLR 0x0018 +#define RK_SPI_TXFLR 0x001c +#define RK_SPI_RXFLR 0x0020 +#define RK_SPI_SR 0x0024 +#define SR_BUSY (1 << 0) +#define RK_SPI_IPR 0x0028 +#define RK_SPI_IMR 0x002c +#define IMR_RFFIM (1 << 4) +#define IMR_TFEIM (1 << 0) +#define RK_SPI_ISR 0x0030 +#define ISR_RFFIS (1 << 4) +#define ISR_TFEIS (1 << 0) +#define RK_SPI_RISR 0x0034 +#define RK_SPI_ICR 0x0038 +#define RK_SPI_DMACR 0x003c +#define RK_SPI_DMATDLR 0x0040 +#define RK_SPI_DMARDLR 0x0044 +#define RK_SPI_TXDR 0x0400 +#define RK_SPI_RXDR 0x0800 + +#define CS_MAX 1 + +static struct ofw_compat_data compat_data[] = { + { "rockchip,rk3399-spi", 1 }, + { NULL, 0 } +}; + +static struct resource_spec rk_spi_spec[] = { + { SYS_RES_MEMORY, 0, RF_ACTIVE }, + { SYS_RES_IRQ, 0, RF_ACTIVE | RF_SHAREABLE }, + { -1, 0 } +}; + +struct rk_spi_softc { + device_t dev; + device_t spibus; + struct resource *res[2]; + struct mtx mtx; + clk_t clk_apb; + clk_t clk_spi; + void * intrhand; + int transfer; + uint32_t fifo_size; + uint64_t max_freq; + + uint32_t intreg; + uint8_t *rxbuf; + uint32_t rxidx; + uint8_t *txbuf; + uint32_t txidx; + uint32_t txlen; + uint32_t rxlen; +}; + +#define RK_SPI_LOCK(sc) mtx_lock(&(sc)->mtx) +#define RK_SPI_UNLOCK(sc) mtx_unlock(&(sc)->mtx) +#define RK_SPI_READ_4(sc, reg) bus_read_4((sc)->res[0], (reg)) +#define RK_SPI_WRITE_4(sc, reg, val) bus_write_4((sc)->res[0], (reg), (val)) + +static int rk_spi_probe(device_t dev); +static int rk_spi_attach(device_t dev); +static int rk_spi_detach(device_t dev); +static void rk_spi_intr(void *arg); + +static void +rk_spi_enable_chip(struct rk_spi_softc *sc, int enable) +{ + + RK_SPI_WRITE_4(sc, RK_SPI_ENR, enable ? 1 : 0); +} + +static int +rk_spi_set_cs(struct rk_spi_softc *sc, uint32_t cs, bool active) +{ + uint32_t reg; + + if (cs & SPIBUS_CS_HIGH) { + device_printf(sc->dev, "SPIBUS_CS_HIGH is not supported\n"); + return (EINVAL); + } + + if (cs > CS_MAX) + return (EINVAL); + + reg = RK_SPI_READ_4(sc, RK_SPI_SER); + if (active) + reg |= (1 << cs); + else + reg &= ~(1 << cs); + RK_SPI_WRITE_4(sc, RK_SPI_SER, reg); + + return (0); +} + +static void +rk_spi_hw_setup(struct rk_spi_softc *sc, uint32_t mode, uint32_t freq) +{ + uint32_t cr0; + uint32_t div; + + cr0 = CTRLR0_OPM_MASTER | CTRLR0_XFM_TR | CTRLR0_FRF_MOTO | + CTRLR0_BHT_8BIT | CTRLR0_EM_BIG | CTRLR0_SSD_ONE | + CTRLR0_DFS_8BIT; + + if (mode & SPIBUS_MODE_CPHA) + cr0 |= CTRLR0_SCPH; + if (mode & SPIBUS_MODE_CPOL) + cr0 |= CTRLR0_SCPOL; + + /* minimum divider is 2 */ + if (sc->max_freq < freq*2) { + clk_set_freq(sc->clk_spi, 2 * freq, CLK_SET_ROUND_DOWN); + clk_get_freq(sc->clk_spi, &sc->max_freq); + } + + div = ((sc->max_freq + freq - 1) / freq); + div = (div + 1) & 0xfffe; + RK_SPI_WRITE_4(sc, RK_SPI_BAUDR, div); + + RK_SPI_WRITE_4(sc, RK_SPI_CTRLR0, cr0); +} + +static uint32_t +rk_spi_fifo_size(struct rk_spi_softc *sc) +{ + uint32_t txftlr, reg; + + for (txftlr = 2; txftlr < 32; txftlr++) { + RK_SPI_WRITE_4(sc, RK_SPI_TXFTLR, txftlr); + reg = RK_SPI_READ_4(sc, RK_SPI_TXFTLR); + if (reg != txftlr) + break; + } + RK_SPI_WRITE_4(sc, RK_SPI_TXFTLR, 0); + + if (txftlr == 31) + return 0; + + return txftlr; +} + +static void +rk_spi_empty_rxfifo(struct rk_spi_softc *sc) +{ + uint32_t rxlevel; + rxlevel = RK_SPI_READ_4(sc, RK_SPI_RXFLR); + while (sc->rxidx < sc->rxlen && + (rxlevel-- > 0)) { + sc->rxbuf[sc->rxidx++] = (uint8_t)RK_SPI_READ_4(sc, RK_SPI_RXDR); + } +} + +static void +rk_spi_fill_txfifo(struct rk_spi_softc *sc) +{ + uint32_t txlevel; + txlevel = RK_SPI_READ_4(sc, RK_SPI_TXFLR); + int cnt = 0; + + while (sc->txidx < sc->txlen && txlevel < sc->fifo_size) { + RK_SPI_WRITE_4(sc, RK_SPI_TXDR, sc->txbuf[sc->txidx++]); + txlevel++; + cnt++; + } + + if (sc->txidx != sc->txlen) + sc->intreg |= (IMR_TFEIM | IMR_RFFIM); +} + +static int +rk_spi_xfer_buf(struct rk_spi_softc *sc, void *rxbuf, void *txbuf, uint32_t len) +{ + int err; + + if (len == 0) + return (0); + + sc->rxbuf = rxbuf; + sc->rxlen = len; + sc->rxidx = 0; + sc->txbuf = txbuf; + sc->txlen = len; + sc->txidx = 0; + sc->intreg = 0; + rk_spi_fill_txfifo(sc); + + RK_SPI_WRITE_4(sc, RK_SPI_IMR, sc->intreg); + + err = 0; + while (err == 0 && sc->intreg != 0) + err = msleep(sc, &sc->mtx, 0, "rk_spi", 10 * hz); + + while (err == 0 && sc->rxidx != sc->txidx) { + /* read residual data from RX fifo */ + rk_spi_empty_rxfifo(sc); + } + + if (sc->rxidx != sc->rxlen || sc->txidx != sc->txlen) + err = EIO; + + return (err); +} + +static int +rk_spi_probe(device_t dev) +{ + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data) + return (ENXIO); + + device_set_desc(dev, "Rockchip SPI"); + return (BUS_PROBE_DEFAULT); +} + +static int +rk_spi_attach(device_t dev) +{ + struct rk_spi_softc *sc; + int error; + + sc = device_get_softc(dev); + sc->dev = dev; + + mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF); + + if (bus_alloc_resources(dev, rk_spi_spec, sc->res) != 0) { + device_printf(dev, "cannot allocate resources for device\n"); + error = ENXIO; + goto fail; + } + + if (bus_setup_intr(dev, sc->res[1], + INTR_TYPE_MISC | INTR_MPSAFE, NULL, rk_spi_intr, sc, + &sc->intrhand)) { + bus_release_resources(dev, rk_spi_spec, sc->res); + device_printf(dev, "cannot setup interrupt handler\n"); + return (ENXIO); + } + + /* Activate the module clock. */ + error = clk_get_by_ofw_name(dev, 0, "apb_pclk", &sc->clk_apb); + if (error != 0) { + device_printf(dev, "cannot get apb_pclk clock\n"); + goto fail; + } + error = clk_get_by_ofw_name(dev, 0, "spiclk", &sc->clk_spi); + if (error != 0) { + device_printf(dev, "cannot get spiclk clock\n"); + goto fail; + } + error = clk_enable(sc->clk_apb); + if (error != 0) { + device_printf(dev, "cannot enable ahb clock\n"); + goto fail; + } + error = clk_enable(sc->clk_spi); + if (error != 0) { + device_printf(dev, "cannot enable spiclk clock\n"); + goto fail; + } + clk_get_freq(sc->clk_spi, &sc->max_freq); + + sc->fifo_size = rk_spi_fifo_size(sc); + if (sc->fifo_size == 0) { + device_printf(dev, "failed to get fifo size\n"); + goto fail; + } + + sc->spibus = device_add_child(dev, "spibus", -1); + + RK_SPI_WRITE_4(sc, RK_SPI_IMR, 0); + RK_SPI_WRITE_4(sc, RK_SPI_TXFTLR, sc->fifo_size/2 - 1); + RK_SPI_WRITE_4(sc, RK_SPI_RXFTLR, sc->fifo_size/2 - 1); + + return (bus_generic_attach(dev)); + +fail: + rk_spi_detach(dev); + return (error); +} + +static int +rk_spi_detach(device_t dev) +{ + struct rk_spi_softc *sc; + + sc = device_get_softc(dev); + + bus_generic_detach(sc->dev); + if (sc->spibus != NULL) + device_delete_child(dev, sc->spibus); + + if (sc->clk_spi != NULL) + clk_release(sc->clk_spi); + if (sc->clk_apb) + clk_release(sc->clk_apb); + + if (sc->intrhand != NULL) + bus_teardown_intr(sc->dev, sc->res[1], sc->intrhand); + + bus_release_resources(dev, rk_spi_spec, sc->res); + mtx_destroy(&sc->mtx); + + return (0); +} + +static void +rk_spi_intr(void *arg) +{ + struct rk_spi_softc *sc; + uint32_t intreg, isr; + + sc = arg; + + RK_SPI_LOCK(sc); + intreg = RK_SPI_READ_4(sc, RK_SPI_IMR); + isr = RK_SPI_READ_4(sc, RK_SPI_ISR); + RK_SPI_WRITE_4(sc, RK_SPI_ICR, isr); + + if (isr & ISR_RFFIS) + rk_spi_empty_rxfifo(sc); + + if (isr & ISR_TFEIS) + rk_spi_fill_txfifo(sc); + + /* no bytes left, disable interrupt */ + if (sc->txidx == sc->txlen) { + sc->intreg = 0; + wakeup(sc); + } + + if (sc->intreg != intreg) { + (void)RK_SPI_WRITE_4(sc, RK_SPI_IMR, sc->intreg); + (void)RK_SPI_READ_4(sc, RK_SPI_IMR); + } + + RK_SPI_UNLOCK(sc); +} + +static phandle_t +rk_spi_get_node(device_t bus, device_t dev) +{ + + return ofw_bus_get_node(bus); +} + +static int +rk_spi_transfer(device_t dev, device_t child, struct spi_command *cmd) +{ + struct rk_spi_softc *sc; + uint32_t cs, mode, clock; + int err = 0; + + sc = device_get_softc(dev); + + spibus_get_cs(child, &cs); + spibus_get_clock(child, &clock); + spibus_get_mode(child, &mode); + + RK_SPI_LOCK(sc); + rk_spi_hw_setup(sc, mode, clock); + rk_spi_enable_chip(sc, 1); + err = rk_spi_set_cs(sc, cs, true); + if (err != 0) { + rk_spi_enable_chip(sc, 0); + RK_SPI_UNLOCK(sc); + return (err); + } + + /* Transfer command then data bytes. */ + err = 0; + if (cmd->tx_cmd_sz > 0) + err = rk_spi_xfer_buf(sc, cmd->rx_cmd, cmd->tx_cmd, + cmd->tx_cmd_sz); + if (cmd->tx_data_sz > 0 && err == 0) + err = rk_spi_xfer_buf(sc, cmd->rx_data, cmd->tx_data, + cmd->tx_data_sz); + + rk_spi_set_cs(sc, cs, false); + rk_spi_enable_chip(sc, 0); + RK_SPI_UNLOCK(sc); + + return (err); +} + +static device_method_t rk_spi_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, rk_spi_probe), + DEVMETHOD(device_attach, rk_spi_attach), + DEVMETHOD(device_detach, rk_spi_detach), + + /* spibus_if */ + DEVMETHOD(spibus_transfer, rk_spi_transfer), + + /* ofw_bus_if */ + DEVMETHOD(ofw_bus_get_node, rk_spi_get_node), + + DEVMETHOD_END +}; + +static driver_t rk_spi_driver = { + "spi", + rk_spi_methods, + sizeof(struct rk_spi_softc), +}; + +static devclass_t rk_spi_devclass; + +DRIVER_MODULE(rk_spi, simplebus, rk_spi_driver, rk_spi_devclass, 0, 0); +DRIVER_MODULE(ofw_spibus, rk_spi, ofw_spibus_driver, ofw_spibus_devclass, 0, 0); +MODULE_DEPEND(rk_spi, ofw_spibus, 1, 1, 1); +SIMPLEBUS_PNP_INFO(compat_data); Copied and modified: stable/12/sys/arm64/rockchip/rk_typec_phy.c (from r354089, head/sys/arm64/rockchip/rk_typec_phy.c) ============================================================================== --- head/sys/arm64/rockchip/rk_typec_phy.c Fri Oct 25 18:10:02 2019 (r354089, copy source) +++ stable/12/sys/arm64/rockchip/rk_typec_phy.c Wed Mar 4 20:48:29 2020 (r358641) @@ -191,7 +191,7 @@ rk_typec_phy_enable(struct phynode *phynode, bool enab device_t dev; intptr_t phy; uint32_t reg; - int err; + int err, retry; dev = phynode_get_device(phynode); phy = phynode_get_id(phynode); @@ -271,13 +271,13 @@ rk_typec_phy_enable(struct phynode *phynode, bool enab hwreset_deassert(sc->rst_uphy); - for (int timeout = 10000; timeout > 0; timeout--) { + for (retry = 10000; retry > 0; retry--) { reg = RK_TYPEC_PHY_READ(sc, PMA_CMN_CTRL1); if (reg & PMA_CMN_CTRL1_READY) break; DELAY(10); } - if (timeout == 0) { + if (retry == 0) { device_printf(sc->dev, "Timeout waiting for PMA\n"); return (ENXIO); } Modified: stable/12/sys/conf/files.arm64 ============================================================================== --- stable/12/sys/conf/files.arm64 Wed Mar 4 20:43:29 2020 (r358640) +++ stable/12/sys/conf/files.arm64 Wed Mar 4 20:48:29 2020 (r358641) @@ -284,7 +284,9 @@ arm64/rockchip/rk805.c optional fdt rk805 soc_rockch arm64/rockchip/rk_grf.c optional fdt soc_rockchip_rk3328 | fdt soc_rockchip_rk3399 arm64/rockchip/rk_pinctrl.c optional fdt rk_pinctrl soc_rockchip_rk3328 | fdt rk_pinctrl soc_rockchip_rk3399 arm64/rockchip/rk_gpio.c optional fdt rk_gpio soc_rockchip_rk3328 | fdt rk_gpio soc_rockchip_rk3399 +arm64/rockchip/rk_spi.c optional fdt rk_spi arm64/rockchip/rk_usb2phy.c optional fdt rk_usb2phy soc_rockchip_rk3328 | soc_rockchip_rk3399 +arm64/rockchip/rk_typec_phy.c optional fdt rk_typec_phy soc_rockchip_rk3399 arm64/rockchip/if_dwc_rk.c optional fdt dwc_rk soc_rockchip_rk3328 | fdt dwc_rk soc_rockchip_rk3399 dev/dwc/if_dwc.c optional fdt dwc_rk soc_rockchip_rk3328 | fdt dwc_rk soc_rockchip_rk3399 dev/dwc/if_dwc_if.m optional fdt dwc_rk soc_rockchip_rk3328 | fdt dwc_rk soc_rockchip_rk3399