From patchwork Thu Aug 4 14:27:10 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sumit Garg X-Patchwork-Id: 595323 Delivered-To: patch@linaro.org Received: by 2002:a05:7000:b345:0:0:0:0 with SMTP id w5csp483047maz; Thu, 4 Aug 2022 07:28:28 -0700 (PDT) X-Google-Smtp-Source: AA6agR7XnlDm90yvGsMTWFMjHCncLTA556B6dN7fNzjRReW6Y9vpqSzpT5LRmlKQhJT/iUh3yGCg X-Received: by 2002:a05:6e02:1ca5:b0:2df:3283:b4a8 with SMTP id x5-20020a056e021ca500b002df3283b4a8mr1050436ill.131.1659623308820; Thu, 04 Aug 2022 07:28:28 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1659623308; cv=none; d=google.com; s=arc-20160816; b=CBJtnNh4+3DtsK1vtwJkJ20XhW5buVZBm5g0G/aWIS79GuorxFSAEpL1lCthlGqS7q e/sF6vuF9Q9QjASlxIcehs7SPPaUlv8BaSILxh53Z4cUii/T7t/zeIruurb4fwrb1rIZ PETgKhEbrJgIvt8Gqcy0dUvPpopqi4kN53FNmpiFW82vk66Q6PHuzyj/Wz48SbPm04wa qFB9R07XVkMbEi5/Jsch+JoJEDpDCthXD+YU00lkMHmn0fGw2Ytg0hQggZMbNU8urlIN J8S6P98eX0lwW2MNlpc8xrApt/H0X/jSeC/3vjOELxCeBT7qDnDAAD85+oGSYJhyawHV i4Vw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=jhaBD8HitCKIVcliq4ZFKlpSMUuxYXyRbYamv1K4ejg=; b=rZBvTOroBQZB3Bb84wh4luGdzbXfY/5N1hqZXL14fzugmllV2PVd6famd5XL6JHfA3 PfIfGkyHmIIiKszcNEXZsRxAfMJHy0kCVXuE55DZOzQ7EYS4QdXJDqyiQWaDWNB91D1D oEGBvVkznvsGQoTwwlwfzT08bI7zGL+6KT4hyIigbz238z1/eqQ8Hws+9BkBbNA2eET8 QCd3oHruimitabhXdsmPuGPZomQJQUzSbrB9PBn/02LLyS0r0q5Q0uKr8Go4hj6gAowq COjaeH4IPu6JVpwGF/LX8WMjCWgnPDljEyxtZ2h5ZNUYF8Zw8XfxJlDKxNROW5oH/62D yWyA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=CuXrwtJd; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from phobos.denx.de (phobos.denx.de. [2a01:238:438b:c500:173d:9f52:ddab:ee01]) by mx.google.com with ESMTPS id z10-20020a056e0203ca00b002df347e51fesi1250250ilr.93.2022.08.04.07.28.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 04 Aug 2022 07:28:28 -0700 (PDT) Received-SPF: pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=CuXrwtJd; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 11E5084567; Thu, 4 Aug 2022 16:28:08 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="CuXrwtJd"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 2F7138482A; Thu, 4 Aug 2022 16:28:06 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-pj1-x1034.google.com (mail-pj1-x1034.google.com [IPv6:2607:f8b0:4864:20::1034]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 040EF841CC for ; Thu, 4 Aug 2022 16:28:03 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sumit.garg@linaro.org Received: by mail-pj1-x1034.google.com with SMTP id t22so11835613pjy.1 for ; Thu, 04 Aug 2022 07:28:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=jhaBD8HitCKIVcliq4ZFKlpSMUuxYXyRbYamv1K4ejg=; b=CuXrwtJdW02NsqVrWl+Db/eesD5S40faHPne4O9GWady1DzOGO5ieI5DFwywwpzs68 qEfaYWHeu9izoIoE/gQoN8eeXHzkCS8ICRTiqhwugkTTtl4iTO0vDqzhp+AlZYDQ1vF9 4G/Gmfsi3czsJJLxyKT5goZENU63t1njzMI/NpiIVovkLT5vLbFMxGpuGeV+5Zefc1hF 4E8R5el+1Mj6h/XnbRmDal7HkVv6gRxaULhTwRqrHKS4U4FqywJJvb1/XhI8q8L6IJic gkxj2azUBN9vwV0VhCn5M+6YhLyBJPKwm4p/Dqq6ebDpukfNn9UWhvBt3KmdMnbX0KVf bsNA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=jhaBD8HitCKIVcliq4ZFKlpSMUuxYXyRbYamv1K4ejg=; b=gHHZcMKQHnc7G4ZfdzGzWoLvHTR9e0LStHPfsy2ARxjYPptOox1UBkdRU5PLlDXun9 QVYq4gq/rUaINP1XRIKK/RY5xnCRWTtgSfReE9+3fBDcAbpGk/P0YGOwrH6vJjbb8zlC p63DRkvIWKmRsB/M3qnMCKTXT5v73CAof7fPXP2iJWlWVfRBTP3pV5yLLAJZzyH3Gn8T c1fnoGIS/c3TbnHdwKd7syMPMYpTYUeyePeBcz9SZHQkL0VqpPyA2MVgwdg9C6voPTfd StP88tPCIxDXHgIVFagR4We55ND90RPTfny/9Q/WeuiTkRKvBKnLRZ3xSyG79td32Mix Rx+g== X-Gm-Message-State: ACgBeo2wXwOAKddkuYwCSZmB8SUr5hzsCkUW9FxEPmrJ+OJx27Emgi65 mO5wwlIRef0CQk1Db3S4LmcY7a5ZrgyvOg== X-Received: by 2002:a17:902:b692:b0:16f:87a0:ddbb with SMTP id c18-20020a170902b69200b0016f87a0ddbbmr1065200pls.35.1659623280894; Thu, 04 Aug 2022 07:28:00 -0700 (PDT) Received: from localhost.localdomain ([122.162.196.218]) by smtp.gmail.com with ESMTPSA id h185-20020a6253c2000000b0052cdb06c125sm1013549pfb.159.2022.08.04.07.27.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 04 Aug 2022 07:28:00 -0700 (PDT) From: Sumit Garg To: u-boot@lists.denx.de Cc: rfried.dev@gmail.com, jorge.ramirez.ortiz@gmail.com, sjg@chromium.org, trini@konsulko.com, stephan@gerhold.net, mario.six@gdsys.cc, dsankouski@gmail.com, robert.marko@sartura.hr, luka.kovacic@sartura.hr, luka.perkov@sartura.hr, jh80.chung@samsung.com, nicolas.dechesne@linaro.org, vinod.koul@linaro.org, mworsfold@impinj.com, lgillham@impinj.com, daniel.thompson@linaro.org, pbrobinson@gmail.com, Sumit Garg Subject: [PATCH 02/13] phy: Add support for drivers to enable USB on QCS404 SoC Date: Thu, 4 Aug 2022 19:57:10 +0530 Message-Id: <20220804142721.536556-3-sumit.garg@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220804142721.536556-1-sumit.garg@linaro.org> References: <20220804142721.536556-1-sumit.garg@linaro.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.6 at phobos.denx.de X-Virus-Status: Clean QCS404 SoC supports two types of PHY, one supports high speed mode or USB2 PHY and the other supports super speed mode or USB3 PHY. So add corresponding PHY drivers. Signed-off-by: Sumit Garg --- drivers/phy/qcom/Kconfig | 16 ++ drivers/phy/qcom/Makefile | 2 + drivers/phy/qcom/phy-qcom-usb-hs-28nm.c | 250 ++++++++++++++++++++++++ drivers/phy/qcom/phy-qcom-usb-ss.c | 154 +++++++++++++++ 4 files changed, 422 insertions(+) create mode 100644 drivers/phy/qcom/phy-qcom-usb-hs-28nm.c create mode 100644 drivers/phy/qcom/phy-qcom-usb-ss.c diff --git a/drivers/phy/qcom/Kconfig b/drivers/phy/qcom/Kconfig index f685a6455e..f4ca174805 100644 --- a/drivers/phy/qcom/Kconfig +++ b/drivers/phy/qcom/Kconfig @@ -11,3 +11,19 @@ config PHY_QCOM_IPQ4019_USB depends on PHY && ARCH_IPQ40XX help Support for the USB PHY-s on Qualcomm IPQ40xx SoC-s. + +config PHY_QCOM_USB_HS_28NM + tristate "Qualcomm 28nm High-Speed PHY" + depends on PHY && ARCH_SNAPDRAGON + help + Enable this to support the Qualcomm Synopsys DesignWare Core 28nm + High-Speed PHY driver. This driver supports the Hi-Speed PHY which + is usually paired with either the ChipIdea or Synopsys DWC3 USB + IPs on MSM SOCs. + +config PHY_QCOM_USB_SS + tristate "Qualcomm USB Super-Speed PHY driver" + depends on PHY && ARCH_SNAPDRAGON + help + Enable this to support the Super-Speed USB transceiver on various + Qualcomm chipsets. diff --git a/drivers/phy/qcom/Makefile b/drivers/phy/qcom/Makefile index 4a340e33c8..2113f178c0 100644 --- a/drivers/phy/qcom/Makefile +++ b/drivers/phy/qcom/Makefile @@ -1,2 +1,4 @@ obj-$(CONFIG_PHY_QCOM_IPQ4019_USB) += phy-qcom-ipq4019-usb.o obj-$(CONFIG_MSM8916_USB_PHY) += msm8916-usbh-phy.o +obj-$(CONFIG_PHY_QCOM_USB_HS_28NM) += phy-qcom-usb-hs-28nm.o +obj-$(CONFIG_PHY_QCOM_USB_SS) += phy-qcom-usb-ss.o diff --git a/drivers/phy/qcom/phy-qcom-usb-hs-28nm.c b/drivers/phy/qcom/phy-qcom-usb-hs-28nm.c new file mode 100644 index 0000000000..14c3d8394d --- /dev/null +++ b/drivers/phy/qcom/phy-qcom-usb-hs-28nm.c @@ -0,0 +1,250 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2022 Sumit Garg + * + * Based on Linux driver + */ + +#include +#include +#include +#include +#include +#include +#include + +/* PHY register and bit definitions */ +#define PHY_CTRL_COMMON0 0x078 +#define SIDDQ BIT(2) + +struct hsphy_init_seq { + int offset; + int val; + int delay; +}; + +struct hsphy_data { + const struct hsphy_init_seq *init_seq; + unsigned int init_seq_num; +}; + +struct hsphy_priv { + void __iomem *base; + struct clk_bulk clks; + struct reset_ctl phy_rst; + struct reset_ctl por_rst; + const struct hsphy_data *data; +}; + +static int hsphy_power_on(struct phy *phy) +{ + struct hsphy_priv *priv = dev_get_priv(phy->dev); + u32 val; + + val = readb(priv->base + PHY_CTRL_COMMON0); + val &= ~SIDDQ; + writeb(val, priv->base + PHY_CTRL_COMMON0); + + return 0; +} + +static int hsphy_power_off(struct phy *phy) +{ + struct hsphy_priv *priv = dev_get_priv(phy->dev); + u32 val; + + val = readb(priv->base + PHY_CTRL_COMMON0); + val |= SIDDQ; + writeb(val, priv->base + PHY_CTRL_COMMON0); + + return 0; +} + +static int hsphy_reset(struct hsphy_priv *priv) +{ + int ret; + + ret = reset_assert(&priv->phy_rst); + if (ret) + return ret; + + udelay(10); + + ret = reset_deassert(&priv->phy_rst); + if (ret) + return ret; + + udelay(80); + + return 0; +} + +static void hsphy_init_sequence(struct hsphy_priv *priv) +{ + const struct hsphy_data *data = priv->data; + const struct hsphy_init_seq *seq; + int i; + + /* Device match data is optional. */ + if (!data) + return; + + seq = data->init_seq; + + for (i = 0; i < data->init_seq_num; i++, seq++) { + writeb(seq->val, priv->base + seq->offset); + if (seq->delay) + udelay(seq->delay); + } +} + +static int hsphy_por_reset(struct hsphy_priv *priv) +{ + int ret; + u32 val; + + ret = reset_assert(&priv->por_rst); + if (ret) + return ret; + + /* + * The Femto PHY is POR reset in the following scenarios. + * + * 1. After overriding the parameter registers. + * 2. Low power mode exit from PHY retention. + * + * Ensure that SIDDQ is cleared before bringing the PHY + * out of reset. + */ + val = readb(priv->base + PHY_CTRL_COMMON0); + val &= ~SIDDQ; + writeb(val, priv->base + PHY_CTRL_COMMON0); + + /* + * As per databook, 10 usec delay is required between + * PHY POR assert and de-assert. + */ + udelay(10); + ret = reset_deassert(&priv->por_rst); + if (ret) + return ret; + + /* + * As per databook, it takes 75 usec for PHY to stabilize + * after the reset. + */ + udelay(80); + + return 0; +} + +static int hsphy_clk_init(struct udevice *dev, struct hsphy_priv *priv) +{ + int ret; + + ret = clk_get_bulk(dev, &priv->clks); + if (ret == -ENOSYS || ret == -ENOENT) + return 0; + if (ret) + return ret; + + ret = clk_enable_bulk(&priv->clks); + if (ret) { + clk_release_bulk(&priv->clks); + return ret; + } + + return 0; +} + +static int hsphy_init(struct phy *phy) +{ + struct hsphy_priv *priv = dev_get_priv(phy->dev); + int ret; + + ret = hsphy_clk_init(phy->dev, priv); + if (ret) + return ret; + + ret = hsphy_reset(priv); + if (ret) + return ret; + + hsphy_init_sequence(priv); + + hsphy_por_reset(priv); + if (ret) + return ret; + + return 0; +} + +static int hsphy_probe(struct udevice *dev) +{ + struct hsphy_priv *priv = dev_get_priv(dev); + int ret; + + priv->base = (void *)dev_read_addr(dev); + if ((ulong)priv->base == FDT_ADDR_T_NONE) + return -EINVAL; + + ret = reset_get_by_name(dev, "phy", &priv->phy_rst); + if (ret) + return ret; + + ret = reset_get_by_name(dev, "por", &priv->por_rst); + if (ret) + return ret; + + priv->data = (const struct hsphy_data *)dev_get_driver_data(dev); + + return 0; +} + +static struct phy_ops hsphy_ops = { + .power_on = hsphy_power_on, + .power_off = hsphy_power_off, + .init = hsphy_init, +}; + +/* + * The macro is used to define an initialization sequence. Each tuple + * is meant to program 'value' into phy register at 'offset' with 'delay' + * in us followed. + */ +#define HSPHY_INIT_CFG(o, v, d) { .offset = o, .val = v, .delay = d, } + +static const struct hsphy_init_seq init_seq_femtophy[] = { + HSPHY_INIT_CFG(0xc0, 0x01, 0), + HSPHY_INIT_CFG(0xe8, 0x0d, 0), + HSPHY_INIT_CFG(0x74, 0x12, 0), + HSPHY_INIT_CFG(0x98, 0x63, 0), + HSPHY_INIT_CFG(0x9c, 0x03, 0), + HSPHY_INIT_CFG(0xa0, 0x1d, 0), + HSPHY_INIT_CFG(0xa4, 0x03, 0), + HSPHY_INIT_CFG(0x8c, 0x23, 0), + HSPHY_INIT_CFG(0x78, 0x08, 0), + HSPHY_INIT_CFG(0x7c, 0xdc, 0), + HSPHY_INIT_CFG(0x90, 0xe0, 20), + HSPHY_INIT_CFG(0x74, 0x10, 0), + HSPHY_INIT_CFG(0x90, 0x60, 0), +}; + +static const struct hsphy_data data_femtophy = { + .init_seq = init_seq_femtophy, + .init_seq_num = ARRAY_SIZE(init_seq_femtophy), +}; + +static const struct udevice_id hsphy_ids[] = { + { .compatible = "qcom,usb-hs-28nm-femtophy", .data = (ulong)&data_femtophy }, + { } +}; + +U_BOOT_DRIVER(qcom_usb_hs_28nm) = { + .name = "qcom-usb-hs-28nm", + .id = UCLASS_PHY, + .of_match = hsphy_ids, + .ops = &hsphy_ops, + .probe = hsphy_probe, + .priv_auto = sizeof(struct hsphy_priv), +}; diff --git a/drivers/phy/qcom/phy-qcom-usb-ss.c b/drivers/phy/qcom/phy-qcom-usb-ss.c new file mode 100644 index 0000000000..4e816879c6 --- /dev/null +++ b/drivers/phy/qcom/phy-qcom-usb-ss.c @@ -0,0 +1,154 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2022 Sumit Garg + * + * Based on Linux driver + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define PHY_CTRL0 0x6C +#define PHY_CTRL1 0x70 +#define PHY_CTRL2 0x74 +#define PHY_CTRL4 0x7C + +/* PHY_CTRL bits */ +#define REF_PHY_EN BIT(0) +#define LANE0_PWR_ON BIT(2) +#define SWI_PCS_CLK_SEL BIT(4) +#define TST_PWR_DOWN BIT(4) +#define PHY_RESET BIT(7) + +struct ssphy_priv { + void __iomem *base; + struct clk_bulk clks; + struct reset_ctl com_rst; + struct reset_ctl phy_rst; +}; + +static inline void ssphy_updatel(void __iomem *addr, u32 mask, u32 val) +{ + writel((readl(addr) & ~mask) | val, addr); +} + +static int ssphy_do_reset(struct ssphy_priv *priv) +{ + int ret; + + ret = reset_assert(&priv->com_rst); + if (ret) + return ret; + + ret = reset_assert(&priv->phy_rst); + if (ret) + return ret; + + udelay(10); + + ret = reset_deassert(&priv->com_rst); + if (ret) + return ret; + + ret = reset_deassert(&priv->phy_rst); + if (ret) + return ret; + + return 0; +} + +static int ssphy_power_on(struct phy *phy) +{ + struct ssphy_priv *priv = dev_get_priv(phy->dev); + int ret; + + ret = ssphy_do_reset(priv); + if (ret) + return ret; + + writeb(SWI_PCS_CLK_SEL, priv->base + PHY_CTRL0); + ssphy_updatel(priv->base + PHY_CTRL4, LANE0_PWR_ON, LANE0_PWR_ON); + ssphy_updatel(priv->base + PHY_CTRL2, REF_PHY_EN, REF_PHY_EN); + ssphy_updatel(priv->base + PHY_CTRL4, TST_PWR_DOWN, 0); + + return 0; +} + +static int ssphy_power_off(struct phy *phy) +{ + struct ssphy_priv *priv = dev_get_priv(phy->dev); + + ssphy_updatel(priv->base + PHY_CTRL4, LANE0_PWR_ON, 0); + ssphy_updatel(priv->base + PHY_CTRL2, REF_PHY_EN, 0); + ssphy_updatel(priv->base + PHY_CTRL4, TST_PWR_DOWN, TST_PWR_DOWN); + + return 0; +} + +static int ssphy_clk_init(struct udevice *dev, struct ssphy_priv *priv) +{ + int ret; + + ret = clk_get_bulk(dev, &priv->clks); + if (ret == -ENOSYS || ret == -ENOENT) + return 0; + if (ret) + return ret; + + ret = clk_enable_bulk(&priv->clks); + if (ret) { + clk_release_bulk(&priv->clks); + return ret; + } + + return 0; +} + +static int ssphy_probe(struct udevice *dev) +{ + struct ssphy_priv *priv = dev_get_priv(dev); + int ret; + + priv->base = (void *)dev_read_addr(dev); + if ((ulong)priv->base == FDT_ADDR_T_NONE) + return -EINVAL; + + ret = ssphy_clk_init(dev, priv); + if (ret) + return ret; + + ret = reset_get_by_name(dev, "com", &priv->com_rst); + if (ret) + return ret; + + ret = reset_get_by_name(dev, "phy", &priv->phy_rst); + if (ret) + return ret; + + return 0; +} + +static struct phy_ops ssphy_ops = { + .power_on = ssphy_power_on, + .power_off = ssphy_power_off, +}; + +static const struct udevice_id ssphy_ids[] = { + { .compatible = "qcom,usb-ss-28nm-phy" }, + { } +}; + +U_BOOT_DRIVER(qcom_usb_ss) = { + .name = "qcom-usb-ss", + .id = UCLASS_PHY, + .of_match = ssphy_ids, + .ops = &ssphy_ops, + .probe = ssphy_probe, + .priv_auto = sizeof(struct ssphy_priv), +};