From owner-svn-src-stable-12@freebsd.org Thu Nov 28 17:45:58 2019 Return-Path: Delivered-To: svn-src-stable-12@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 BC2A01B0BF7; Thu, 28 Nov 2019 17:45:58 +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 47P4n25KYKz3Lxf; Thu, 28 Nov 2019 17:45:58 +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 9B0EC153B; Thu, 28 Nov 2019 17:45:58 +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 xASHjwrW068057; Thu, 28 Nov 2019 17:45:58 GMT (envelope-from manu@FreeBSD.org) Received: (from manu@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id xASHjvcx068051; Thu, 28 Nov 2019 17:45:57 GMT (envelope-from manu@FreeBSD.org) Message-Id: <201911281745.xASHjvcx068051@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: manu set sender to manu@FreeBSD.org using -f From: Emmanuel Vadot Date: Thu, 28 Nov 2019 17:45:57 +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: r355177 - in stable/12/sys: arm64/conf arm64/rockchip arm64/rockchip/clk conf dev/iicbus 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 dev/iicbus X-SVN-Commit-Revision: 355177 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-12@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: SVN commit messages for only the 12-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 28 Nov 2019 17:45:58 -0000 Author: manu Date: Thu Nov 28 17:45:57 2019 New Revision: 355177 URL: https://svnweb.freebsd.org/changeset/base/355177 Log: MFC r352853, r352903-r352904, r352936-r352937 r352853: arm64: rockchip: Add usb2phy driver This driver is for the usb phy present on rockchip SoC. It only support RK3399 and host mode for now. The driver expose the usb clock needed by the usb controller. r352903: arm64: rockchip: correct reset value If bit is 0 the reset is not asserted. Also register our self as a reset provider, this was commented in r352850 Reported by: mmel r352904: arm64: rockchip: rk_clk_pll: Check mode on recalc If the pll is in slow or deep slow mode return the correct frequency. r352936: arm64: rockchip: rk805: Switch to iicdev_{readfrom,writeto} This simpify the code a bit. r352937: syr827: Switch to iicdev_{readfrom,writeto} Also use IIC_INTRWAIT as we need this to work with the rockchip i2c driver. Added: stable/12/sys/arm64/rockchip/rk_usb2phy.c - copied unchanged from r352853, head/sys/arm64/rockchip/rk_usb2phy.c Modified: stable/12/sys/arm64/conf/GENERIC stable/12/sys/arm64/rockchip/clk/rk_clk_pll.c stable/12/sys/arm64/rockchip/clk/rk_cru.c stable/12/sys/arm64/rockchip/rk805.c stable/12/sys/conf/files.arm64 stable/12/sys/dev/iicbus/syr827.c Directory Properties: stable/12/ (props changed) Modified: stable/12/sys/arm64/conf/GENERIC ============================================================================== --- stable/12/sys/arm64/conf/GENERIC Thu Nov 28 17:42:11 2019 (r355176) +++ stable/12/sys/arm64/conf/GENERIC Thu Nov 28 17:45:57 2019 (r355177) @@ -178,6 +178,7 @@ device pl011 # USB support device aw_ehci # Allwinner EHCI USB interface (USB 2.0) device aw_usbphy # Allwinner USB PHY +device rk_usb2phy # Rockchip USB2PHY device dwcotg # DWC OTG controller device ohci # OHCI USB interface device ehci # EHCI USB interface (USB 2.0) Modified: stable/12/sys/arm64/rockchip/clk/rk_clk_pll.c ============================================================================== --- stable/12/sys/arm64/rockchip/clk/rk_clk_pll.c Thu Nov 28 17:42:11 2019 (r355176) +++ stable/12/sys/arm64/rockchip/clk/rk_clk_pll.c Thu Nov 28 17:45:57 2019 (r355177) @@ -367,7 +367,7 @@ rk3399_clk_pll_recalc(struct clknode *clk, uint64_t *f uint32_t postdiv1, postdiv2, fracdiv; uint32_t con1, con2, con3, con4; uint64_t foutvco; - + uint32_t mode; sc = clknode_get_softc(clk); DEVICE_LOCK(clk); @@ -376,6 +376,21 @@ rk3399_clk_pll_recalc(struct clknode *clk, uint64_t *f READ4(clk, sc->base_offset + 8, &con3); READ4(clk, sc->base_offset + 0xC, &con4); DEVICE_UNLOCK(clk); + + /* + * if we are in slow mode the output freq + * is the parent one, the 24Mhz external oscillator + * if we are in deep mode the output freq is 32.768khz + */ + mode = (con4 & RK3399_CLK_PLL_MODE_MASK) >> RK3399_CLK_PLL_MODE_SHIFT; + if (mode == RK3399_CLK_PLL_MODE_SLOW) { + dprintf("pll in slow mode, con4=%x\n", con4); + return (0); + } else if (mode == RK3399_CLK_PLL_MODE_DEEPSLOW) { + dprintf("pll in deep slow, con4=%x\n", con4); + *freq = 32768; + return (0); + } dprintf("con0: %x\n", con1); dprintf("con1: %x\n", con2); Modified: stable/12/sys/arm64/rockchip/clk/rk_cru.c ============================================================================== --- stable/12/sys/arm64/rockchip/clk/rk_cru.c Thu Nov 28 17:42:11 2019 (r355176) +++ stable/12/sys/arm64/rockchip/clk/rk_cru.c Thu Nov 28 17:45:57 2019 (r355177) @@ -153,7 +153,7 @@ rk_cru_reset_is_asserted(device_t dev, intptr_t id, bo val = CCU_READ4(sc, reg); mtx_unlock(&sc->mtx); - *reset = true; + *reset = false; if (val & (1 << bit)) *reset = true; @@ -263,9 +263,8 @@ rk_cru_attach(device_t dev) clk_set_assigned(dev, node); - /* If we have resets, register our self as a reset provider */ - /* if (sc->resets) */ - /* hwreset_register_ofw_provider(dev); */ + /* register our self as a reset provider */ + hwreset_register_ofw_provider(dev); return (0); } Modified: stable/12/sys/arm64/rockchip/rk805.c ============================================================================== --- stable/12/sys/arm64/rockchip/rk805.c Thu Nov 28 17:42:11 2019 (r355176) +++ stable/12/sys/arm64/rockchip/rk805.c Thu Nov 28 17:45:57 2019 (r355177) @@ -227,24 +227,16 @@ static struct rk805_regdef rk808_regdefs[] = { static int rk805_read(device_t dev, uint8_t reg, uint8_t *data, uint8_t size) { + int err; - return (iicdev_readfrom(dev, reg, data, size, IIC_INTRWAIT)); + err = iicdev_readfrom(dev, reg, data, size, IIC_INTRWAIT); + return (err); } static int rk805_write(device_t dev, uint8_t reg, uint8_t data) { - struct iic_msg msg; - uint8_t buf[2]; - - buf[0] = reg; - buf[1] = data; - msg.slave = iicbus_get_addr(dev); - msg.flags = IIC_M_WR; - msg.buf = buf; - msg.len = sizeof(buf); - - return (iicbus_transfer_excl(dev, &msg, 1, IIC_INTRWAIT)); + return (iicdev_writeto(dev, reg, &data, 1, IIC_INTRWAIT)); } static int Copied: stable/12/sys/arm64/rockchip/rk_usb2phy.c (from r352853, head/sys/arm64/rockchip/rk_usb2phy.c) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ stable/12/sys/arm64/rockchip/rk_usb2phy.c Thu Nov 28 17:45:57 2019 (r355177, copy of r352853, head/sys/arm64/rockchip/rk_usb2phy.c) @@ -0,0 +1,374 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2019 Emmanuel Vadot + * + * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. + */ + +/* + * Rockchip USB2PHY + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "clkdev_if.h" +#include "syscon_if.h" + +#define RK3399_GRF_USB20_PHY0_CON0 0x0 +#define RK3399_GRF_USB20_PHY0_CON1 0x4 +#define RK3399_GRF_USB20_PHY0_CON2 0x8 +#define RK3399_GRF_USB20_PHY0_CON3 0xC + +struct rk_usb2phy_reg { + uint32_t offset; + uint32_t enable_mask; + uint32_t disable_mask; +}; + +struct rk_usb2phy_regs { + struct rk_usb2phy_reg clk_ctl; +}; + +struct rk_usb2phy_regs rk3399_regs = { + .clk_ctl = { + /* bit 4 put pll in suspend */ + .enable_mask = 0x100000, + .disable_mask = 0x100010, + } +}; + +static struct ofw_compat_data compat_data[] = { + { "rockchip,rk3399-usb2phy", (uintptr_t)&rk3399_regs }, + { NULL, 0 } +}; + +struct rk_usb2phy_softc { + device_t dev; + struct syscon *grf; + regulator_t phy_supply; + clk_t clk; +}; + +/* Phy class and methods. */ +static int rk_usb2phy_enable(struct phynode *phynode, bool enable); +static phynode_method_t rk_usb2phy_phynode_methods[] = { + PHYNODEMETHOD(phynode_enable, rk_usb2phy_enable), + + PHYNODEMETHOD_END +}; + +DEFINE_CLASS_1(rk_usb2phy_phynode, rk_usb2phy_phynode_class, + rk_usb2phy_phynode_methods, + sizeof(struct phynode_usb_sc), phynode_usb_class); + +enum RK3399_USBPHY { + RK3399_USBPHY_HOST = 0, + RK3399_USBPHY_OTG, +}; + +static int +rk_usb2phy_enable(struct phynode *phynode, bool enable) +{ + struct rk_usb2phy_softc *sc; + device_t dev; + intptr_t phy; + int error; + + dev = phynode_get_device(phynode); + phy = phynode_get_id(phynode); + sc = device_get_softc(dev); + + if (phy != RK3399_USBPHY_HOST) + return (ERANGE); + + if (sc->phy_supply) { + if (enable) + error = regulator_enable(sc->phy_supply); + else + error = regulator_disable(sc->phy_supply); + if (error != 0) { + device_printf(dev, "Cannot %sable the regulator\n", + enable ? "En" : "Dis"); + goto fail; + } + } + + return (0); +fail: + return (ENXIO); +} + +/* Clock class and method */ +struct rk_usb2phy_clk_sc { + device_t clkdev; + struct syscon *grf; + struct rk_usb2phy_regs *regs; +}; + +static int +rk_usb2phy_clk_init(struct clknode *clk, device_t dev) +{ + + clknode_init_parent_idx(clk, 0); + return (0); +} + +static int +rk_usb2phy_clk_set_gate(struct clknode *clk, bool enable) +{ + struct rk_usb2phy_clk_sc *sc; + + sc = clknode_get_softc(clk); + + if (enable) + SYSCON_WRITE_4(sc->grf, sc->regs->clk_ctl.offset, + sc->regs->clk_ctl.enable_mask); + else + SYSCON_WRITE_4(sc->grf, sc->regs->clk_ctl.offset, + sc->regs->clk_ctl.disable_mask); + return (0); +} + +static int +rk_usb2phy_clk_recalc(struct clknode *clk, uint64_t *freq) +{ + + *freq = 480000000; + + return (0); +} + +static clknode_method_t rk_usb2phy_clk_clknode_methods[] = { + /* Device interface */ + + CLKNODEMETHOD(clknode_init, rk_usb2phy_clk_init), + CLKNODEMETHOD(clknode_set_gate, rk_usb2phy_clk_set_gate), + CLKNODEMETHOD(clknode_recalc_freq, rk_usb2phy_clk_recalc), + CLKNODEMETHOD_END +}; + +DEFINE_CLASS_1(rk_usb2phy_clk_clknode, rk_usb2phy_clk_clknode_class, + rk_usb2phy_clk_clknode_methods, sizeof(struct rk_usb2phy_clk_sc), + clknode_class); + +static int +rk_usb2phy_clk_ofw_map(struct clkdom *clkdom, uint32_t ncells, + phandle_t *cells, struct clknode **clk) +{ + + if (ncells != 0) + return (ERANGE); + + *clk = clknode_find_by_id(clkdom, 0); + + if (*clk == NULL) + return (ENXIO); + return (0); +} + +static int +rk_usb2phy_export_clock(struct rk_usb2phy_softc *devsc) +{ + struct clknode_init_def def; + struct rk_usb2phy_clk_sc *sc; + const char **clknames; + struct clkdom *clkdom; + struct clknode *clk; + clk_t clk_parent; + phandle_t node; + phandle_t regs[2]; + int i, nclocks, ncells, error; + + node = ofw_bus_get_node(devsc->dev); + + error = ofw_bus_parse_xref_list_get_length(node, "clocks", + "#clock-cells", &ncells); + if (error != 0 || ncells != 1) { + device_printf(devsc->dev, "couldn't find parent clock\n"); + return (ENXIO); + } + + nclocks = ofw_bus_string_list_to_array(node, "clock-output-names", + &clknames); + if (nclocks != 1) + return (ENXIO); + + clkdom = clkdom_create(devsc->dev); + clkdom_set_ofw_mapper(clkdom, rk_usb2phy_clk_ofw_map); + + memset(&def, 0, sizeof(def)); + def.id = 0; + def.name = clknames[0]; + def.parent_names = malloc(sizeof(char *) * ncells, M_OFWPROP, M_WAITOK); + for (i = 0; i < ncells; i++) { + error = clk_get_by_ofw_index(devsc->dev, 0, i, &clk_parent); + if (error != 0) { + device_printf(devsc->dev, "cannot get clock %d\n", error); + return (ENXIO); + } + def.parent_names[i] = clk_get_name(clk_parent); + clk_release(clk_parent); + } + def.parent_cnt = ncells; + + clk = clknode_create(clkdom, &rk_usb2phy_clk_clknode_class, &def); + if (clk == NULL) { + device_printf(devsc->dev, "cannot create clknode\n"); + return (ENXIO); + } + + sc = clknode_get_softc(clk); + sc->clkdev = device_get_parent(devsc->dev); + sc->grf = devsc->grf; + sc->regs = (struct rk_usb2phy_regs *)ofw_bus_search_compatible(devsc->dev, compat_data)->ocd_data; + OF_getencprop(node, "reg", regs, sizeof(regs)); + sc->regs->clk_ctl.offset = regs[0]; + clknode_register(clkdom, clk); + + if (clkdom_finit(clkdom) != 0) { + device_printf(devsc->dev, "cannot finalize clkdom initialization\n"); + return (ENXIO); + } + + if (bootverbose) + clkdom_dump(clkdom); + + return (0); +} + +static int +rk_usb2phy_probe(device_t dev) +{ + + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) + return (ENXIO); + + device_set_desc(dev, "Rockchip RK3399 USB2PHY"); + return (BUS_PROBE_DEFAULT); +} + +static int +rk_usb2phy_attach(device_t dev) +{ + struct rk_usb2phy_softc *sc; + struct phynode_init_def phy_init; + struct phynode *phynode; + phandle_t node, host; + int err; + + sc = device_get_softc(dev); + sc->dev = dev; + node = ofw_bus_get_node(dev); + + if (syscon_get_handle_default(dev, &sc->grf) != 0) { + device_printf(dev, "Cannot get syscon handle\n"); + return (ENXIO); + } + + if (clk_get_by_ofw_name(dev, 0, "phyclk", &sc->clk) != 0) { + device_printf(dev, "Cannot get clock\n"); + return (ENXIO); + } + err = clk_enable(sc->clk); + if (err != 0) { + device_printf(dev, "Could not enable clock %s\n", + clk_get_name(sc->clk)); + return (ENXIO); + } + + err = rk_usb2phy_export_clock(sc); + if (err != 0) + return (err); + + /* Only host is supported right now */ + + host = ofw_bus_find_child(node, "host-port"); + if (host == 0) { + device_printf(dev, "Cannot find host-port child node\n"); + return (ENXIO); + } + + if (!ofw_bus_node_status_okay(host)) { + device_printf(dev, "host-port isn't okay\n"); + return (0); + } + + regulator_get_by_ofw_property(dev, host, "phy-supply", &sc->phy_supply); + phy_init.id = RK3399_USBPHY_HOST; + phy_init.ofw_node = host; + phynode = phynode_create(dev, &rk_usb2phy_phynode_class, &phy_init); + if (phynode == NULL) { + device_printf(dev, "failed to create host USB2PHY\n"); + return (ENXIO); + } + if (phynode_register(phynode) == NULL) { + device_printf(dev, "failed to register host USB2PHY\n"); + return (ENXIO); + } + + OF_device_register_xref(OF_xref_from_node(host), dev); + + return (0); +} + +static device_method_t rk_usb2phy_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, rk_usb2phy_probe), + DEVMETHOD(device_attach, rk_usb2phy_attach), + + DEVMETHOD_END +}; + +static driver_t rk_usb2phy_driver = { + "rk_usb2phy", + rk_usb2phy_methods, + sizeof(struct rk_usb2phy_softc) +}; + +static devclass_t rk_usb2phy_devclass; +EARLY_DRIVER_MODULE(rk_usb2phy, simplebus, rk_usb2phy_driver, + rk_usb2phy_devclass, 0, 0, BUS_PASS_SUPPORTDEV + BUS_PASS_ORDER_MIDDLE); +MODULE_VERSION(rk_usb2phy, 1); Modified: stable/12/sys/conf/files.arm64 ============================================================================== --- stable/12/sys/conf/files.arm64 Thu Nov 28 17:42:11 2019 (r355176) +++ stable/12/sys/conf/files.arm64 Thu Nov 28 17:45:57 2019 (r355177) @@ -278,6 +278,7 @@ 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_usb2phy.c optional fdt rk_usb2phy soc_rockchip_rk3328 | 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 Modified: stable/12/sys/dev/iicbus/syr827.c ============================================================================== --- stable/12/sys/dev/iicbus/syr827.c Thu Nov 28 17:42:11 2019 (r355176) +++ stable/12/sys/dev/iicbus/syr827.c Thu Nov 28 17:45:57 2019 (r355177) @@ -90,42 +90,13 @@ struct syr827_softc { static int syr827_read(device_t dev, uint8_t reg, uint8_t *data, uint8_t size) { - struct syr827_softc *sc; - struct iic_msg msg[2]; - - sc = device_get_softc(dev); - - msg[0].slave = sc->addr; - msg[0].flags = IIC_M_WR; - msg[0].len = 1; - msg[0].buf = ® - - msg[1].slave = sc->addr; - msg[1].flags = IIC_M_RD; - msg[1].len = size; - msg[1].buf = data; - - return (iicbus_transfer(dev, msg, 2)); + return (iicdev_readfrom(dev, reg, data, size, IIC_INTRWAIT)); } static int syr827_write(device_t dev, uint8_t reg, uint8_t val) { - struct syr827_softc *sc; - struct iic_msg msg; - uint8_t buffer[2]; - - sc = device_get_softc(dev); - - buffer[0] = reg; - buffer[1] = val; - - msg.slave = sc->addr; - msg.flags = IIC_M_WR; - msg.len = 2; - msg.buf = buffer; - - return (iicbus_transfer(dev, &msg, 1)); + return (iicdev_writeto(dev, reg, &val, 1, IIC_INTRWAIT)); } static int