From patchwork Mon Aug 18 14:28:28 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kishon Vijay Abraham I X-Patchwork-Id: 35520 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-yk0-f197.google.com (mail-yk0-f197.google.com [209.85.160.197]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 644FE20676 for ; Mon, 18 Aug 2014 15:10:32 +0000 (UTC) Received: by mail-yk0-f197.google.com with SMTP id 142sf17816203ykq.4 for ; Mon, 18 Aug 2014 08:10:32 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:from:to:date:message-id:in-reply-to :references:mime-version:subject:precedence:list-id:list-unsubscribe :list-archive:list-post:list-help:list-subscribe:sender:errors-to :x-original-sender:x-original-authentication-results:mailing-list :content-type:content-transfer-encoding; bh=f3Qv9dSA6B1jGMxL2vI6Eqrmq7uEaXtX1S0tkDujClU=; b=AkB+W971/4HpR5SPWXf4UaNibyK1QgErrkDyPnubyAa5Nqc/Fse215j2dzrfYm6a/t HSorTM1FCSxrlJzdo28fS9bJQvjVm8KXZ8rFy4naxuB1ELp8aTe0barZdXu7b4pVXHKZ 1e2WZM8UjeINWO1TsrpMnhNj2qpYcDAwGo7+w4fD4btGyFedDC02h4th1Mobvp9s40A4 F8o9qqYvyqGPsD11eHkUXzZTCkjI3LoYzy9btoXnQgzOzFU/mDEHeabFklFTrGp6ekzf KM5fpYPGPGxEa5H5r5Gyna9u21qlZg8JBSbqD/gN/byD2Xxm7kpHMrvA/NGdIgN0ZYQH SFeA== X-Gm-Message-State: ALoCoQm7wBXChMr+B5U0NMWSFEdxhPksc9ASd/YMIOKFpGsS1YmeAOWZ0IB6aKbeClQoHDWLp+65 X-Received: by 10.52.186.103 with SMTP id fj7mr3741493vdc.8.1408374632196; Mon, 18 Aug 2014 08:10:32 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.50.141 with SMTP id s13ls2308341qga.6.gmail; Mon, 18 Aug 2014 08:10:32 -0700 (PDT) X-Received: by 10.221.36.3 with SMTP id sy3mr480866vcb.67.1408374632058; Mon, 18 Aug 2014 08:10:32 -0700 (PDT) Received: from mail-vc0-f179.google.com (mail-vc0-f179.google.com [209.85.220.179]) by mx.google.com with ESMTPS id xk3si3145602vdb.7.2014.08.18.08.10.31 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 18 Aug 2014 08:10:31 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.179 as permitted sender) client-ip=209.85.220.179; Received: by mail-vc0-f179.google.com with SMTP id hq11so5949511vcb.10 for ; Mon, 18 Aug 2014 08:10:31 -0700 (PDT) X-Received: by 10.52.129.200 with SMTP id ny8mr11894653vdb.27.1408374631735; Mon, 18 Aug 2014 08:10:31 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.221.37.5 with SMTP id tc5csp160348vcb; Mon, 18 Aug 2014 08:10:30 -0700 (PDT) X-Received: by 10.180.102.130 with SMTP id fo2mr68015834wib.29.1408374630217; Mon, 18 Aug 2014 08:10:30 -0700 (PDT) Received: from theia.denx.de (theia.denx.de. [85.214.87.163]) by mx.google.com with ESMTP id dm8si16996583wib.37.2014.08.18.08.10.29 for ; Mon, 18 Aug 2014 08:10:30 -0700 (PDT) Received-SPF: none (google.com: u-boot-bounces@lists.denx.de does not designate permitted sender hosts) client-ip=85.214.87.163; Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 8298FA73F6; Mon, 18 Aug 2014 17:09:16 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id bdO1VZVTgsNY; Mon, 18 Aug 2014 17:09:16 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id BC8964B617; Mon, 18 Aug 2014 17:07:58 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 812CC4A04A for ; Mon, 18 Aug 2014 16:29:21 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id js03NXrgi+4x for ; Mon, 18 Aug 2014 16:29:08 +0200 (CEST) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from bear.ext.ti.com (bear.ext.ti.com [192.94.94.41]) by theia.denx.de (Postfix) with ESMTPS id 072104A04E for ; Mon, 18 Aug 2014 16:28:57 +0200 (CEST) Received: from dlelxv90.itg.ti.com ([172.17.2.17]) by bear.ext.ti.com (8.13.7/8.13.7) with ESMTP id s7IEStZM012903 for ; Mon, 18 Aug 2014 09:28:56 -0500 Received: from DFLE72.ent.ti.com (dfle72.ent.ti.com [128.247.5.109]) by dlelxv90.itg.ti.com (8.14.3/8.13.8) with ESMTP id s7IEStNq006435 for ; Mon, 18 Aug 2014 09:28:55 -0500 Received: from dlep32.itg.ti.com (157.170.170.100) by DFLE72.ent.ti.com (128.247.5.109) with Microsoft SMTP Server id 14.3.174.1; Mon, 18 Aug 2014 09:28:55 -0500 Received: from a0393678lt.apr.dhcp.ti.com (ileax41-snat.itg.ti.com [10.172.224.153]) by dlep32.itg.ti.com (8.14.3/8.13.8) with ESMTP id s7IESbM7003614; Mon, 18 Aug 2014 09:28:53 -0500 From: Kishon Vijay Abraham I To: , , , , , , Date: Mon, 18 Aug 2014 19:58:28 +0530 Message-ID: <1408372115-4570-7-git-send-email-kishon@ti.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1408372115-4570-1-git-send-email-kishon@ti.com> References: <1408372115-4570-1-git-send-email-kishon@ti.com> MIME-Version: 1.0 X-Mailman-Approved-At: Mon, 18 Aug 2014 17:07:53 +0200 Subject: [U-Boot] [UBOOT RFC PATCH 06/13] usb: dwc3: TI PHY: PHY driver for dwc3 in TI platforms X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.11 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: , List-Help: , List-Subscribe: , Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: kishon@ti.com X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.179 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 Added a single driver for both USB2 PHY programming and USB3 PHY programming. Signed-off-by: Kishon Vijay Abraham I --- drivers/usb/dwc3/Makefile | 1 + drivers/usb/dwc3/ti_usb_phy.c | 269 ++++++++++++++++++++++++++++++++++++++++++ include/ti-usb-phy-uboot.h | 22 ++++ 3 files changed, 292 insertions(+) create mode 100644 drivers/usb/dwc3/ti_usb_phy.c create mode 100644 include/ti-usb-phy-uboot.h diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile index 5533546..6b55b9f 100644 --- a/drivers/usb/dwc3/Makefile +++ b/drivers/usb/dwc3/Makefile @@ -7,3 +7,4 @@ dwc3-y := core.o dwc3-$(CONFIG_USB_DWC3_GADGET) += gadget.o ep0.o obj-$(CONFIG_USB_DWC3_OMAP) += dwc3-omap.o +obj-$(CONFIG_USB_DWC3_PHY_OMAP) += ti_usb_phy.o diff --git a/drivers/usb/dwc3/ti_usb_phy.c b/drivers/usb/dwc3/ti_usb_phy.c new file mode 100644 index 0000000..05052c3 --- /dev/null +++ b/drivers/usb/dwc3/ti_usb_phy.c @@ -0,0 +1,269 @@ +/** + * ti_usb_phy.c - USB3 and USB3 PHY programming for dwc3 + * + * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com + * + * Author: Kishon Vijay Abraham I + * + * Taken from Linux Kernel v3.16 (drivers/phy/phy-ti-pipe3.c and + * drivers/phy/phy-omap-usb2.c) and ported to uboot. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include "linux-compat.h" +#include +#include +#include +#include + +#define PLL_STATUS 0x00000004 +#define PLL_GO 0x00000008 +#define PLL_CONFIGURATION1 0x0000000C +#define PLL_CONFIGURATION2 0x00000010 +#define PLL_CONFIGURATION3 0x00000014 +#define PLL_CONFIGURATION4 0x00000020 + +#define PLL_REGM_MASK 0x001FFE00 +#define PLL_REGM_SHIFT 0x9 +#define PLL_REGM_F_MASK 0x0003FFFF +#define PLL_REGM_F_SHIFT 0x0 +#define PLL_REGN_MASK 0x000001FE +#define PLL_REGN_SHIFT 0x1 +#define PLL_SELFREQDCO_MASK 0x0000000E +#define PLL_SELFREQDCO_SHIFT 0x1 +#define PLL_SD_MASK 0x0003FC00 +#define PLL_SD_SHIFT 10 +#define SET_PLL_GO 0x1 +#define PLL_LDOPWDN BIT(15) +#define PLL_TICOPWDN BIT(16) +#define PLL_LOCK 0x2 +#define PLL_IDLE 0x1 + +#define OMAP_CTRL_DEV_PHY_PD BIT(0) +#define OMAP_CTRL_USB3_PHY_PWRCTL_CLK_CMD_MASK 0x003FC000 +#define OMAP_CTRL_USB3_PHY_PWRCTL_CLK_CMD_SHIFT 0xE + +#define OMAP_CTRL_USB3_PHY_PWRCTL_CLK_FREQ_MASK 0xFFC00000 +#define OMAP_CTRL_USB3_PHY_PWRCTL_CLK_FREQ_SHIFT 0x16 + +#define OMAP_CTRL_USB3_PHY_TX_RX_POWERON 0x3 +#define OMAP_CTRL_USB3_PHY_TX_RX_POWEROFF 0x0 + +static LIST_HEAD(ti_usb_phy_list); +typedef unsigned int u32; + +struct usb3_dpll_params { + u16 m; + u8 n; + u8 freq:3; + u8 sd; + u32 mf; +}; + +struct usb3_dpll_map { + unsigned long rate; + struct usb3_dpll_params params; + struct usb3_dpll_map *dpll_map; +}; + +struct ti_usb_phy { + void __iomem *pll_ctrl_base; + void __iomem *usb2_phy_power; + void __iomem *usb3_phy_power; + struct usb3_dpll_map *dpll_map; + struct list_head list; + int index; +}; + +static struct usb3_dpll_map dpll_map_usb[] = { + {12000000, {1250, 5, 4, 20, 0} }, /* 12 MHz */ + {16800000, {3125, 20, 4, 20, 0} }, /* 16.8 MHz */ + {19200000, {1172, 8, 4, 20, 65537} }, /* 19.2 MHz */ + {20000000, {1000, 7, 4, 10, 0} }, /* 20 MHz */ + {26000000, {1250, 12, 4, 20, 0} }, /* 26 MHz */ + {38400000, {3125, 47, 4, 20, 92843} }, /* 38.4 MHz */ + { }, /* Terminator */ +}; + +static inline unsigned int ti_usb3_readl(void __iomem *base, u32 offset) +{ + return readl(base + offset); +} + +static inline void ti_usb3_writel(void __iomem *base, u32 offset, u32 value) +{ + writel(value, base + offset); +} + +static struct usb3_dpll_params *ti_usb3_get_dpll_params(struct ti_usb_phy *phy) +{ + unsigned long rate; + struct usb3_dpll_map *dpll_map = phy->dpll_map; + + rate = get_sys_clk_freq(); + + for (; dpll_map->rate; dpll_map++) { + if (rate == dpll_map->rate) + return &dpll_map->params; + } + + dev_err(phy->dev, "No DPLL configuration for %lu Hz SYS CLK\n", rate); + + return NULL; +} + +static int ti_usb3_dpll_wait_lock(struct ti_usb_phy *phy) +{ + u32 val; + do { + val = ti_usb3_readl(phy->pll_ctrl_base, PLL_STATUS); + if (val & PLL_LOCK) + break; + } while (1); + + return 0; +} + +static int ti_usb3_dpll_program(struct ti_usb_phy *phy) +{ + u32 val; + struct usb3_dpll_params *dpll_params; + + if (!phy->pll_ctrl_base) + return -EINVAL; + + dpll_params = ti_usb3_get_dpll_params(phy); + if (!dpll_params) + return -EINVAL; + + val = ti_usb3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1); + val &= ~PLL_REGN_MASK; + val |= dpll_params->n << PLL_REGN_SHIFT; + ti_usb3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val); + + val = ti_usb3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2); + val &= ~PLL_SELFREQDCO_MASK; + val |= dpll_params->freq << PLL_SELFREQDCO_SHIFT; + ti_usb3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val); + + val = ti_usb3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1); + val &= ~PLL_REGM_MASK; + val |= dpll_params->m << PLL_REGM_SHIFT; + ti_usb3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val); + + val = ti_usb3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION4); + val &= ~PLL_REGM_F_MASK; + val |= dpll_params->mf << PLL_REGM_F_SHIFT; + ti_usb3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION4, val); + + val = ti_usb3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION3); + val &= ~PLL_SD_MASK; + val |= dpll_params->sd << PLL_SD_SHIFT; + ti_usb3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION3, val); + + ti_usb3_writel(phy->pll_ctrl_base, PLL_GO, SET_PLL_GO); + + return ti_usb3_dpll_wait_lock(phy); +} + +void ti_usb2_phy_power(struct ti_usb_phy *phy, int on) +{ + u32 val; + + val = readl(phy->usb2_phy_power); + if (on) + val &= ~OMAP_CTRL_DEV_PHY_PD; + else + val |= OMAP_CTRL_DEV_PHY_PD; + writel(val, phy->usb2_phy_power); +} + +void ti_usb3_phy_power(struct ti_usb_phy *phy, int on) +{ + u32 val; + u32 rate; + rate = get_sys_clk_freq(); + rate = rate/1000000; + + if (!phy->usb3_phy_power) + return; + + val = readl(phy->usb3_phy_power); + if (on) { + val &= ~(OMAP_CTRL_USB3_PHY_PWRCTL_CLK_CMD_MASK | + OMAP_CTRL_USB3_PHY_PWRCTL_CLK_FREQ_MASK); + val |= (OMAP_CTRL_USB3_PHY_TX_RX_POWERON) << + OMAP_CTRL_USB3_PHY_PWRCTL_CLK_CMD_SHIFT; + val |= rate << + OMAP_CTRL_USB3_PHY_PWRCTL_CLK_FREQ_SHIFT; + } else { + val &= ~OMAP_CTRL_USB3_PHY_PWRCTL_CLK_CMD_MASK; + val |= OMAP_CTRL_USB3_PHY_TX_RX_POWEROFF << + OMAP_CTRL_USB3_PHY_PWRCTL_CLK_CMD_SHIFT; + } + writel(val, phy->usb3_phy_power); +} + +/** + * ti_usb_phy_uboot_init - usb phy uboot initialization code + * @dev: struct ti_usb_phy_device containing initialization data + * + * Entry point for ti usb phy driver. This driver handles initialization + * of both usb2 phy and usb3 phy. Pointer to ti_usb_phy_device should be + * passed containing base address and other initialization data. + * Returns '0' on success and a negative value on failure. + * + * Generally called from board_usb_init() implemented in board file. + */ +int ti_usb_phy_uboot_init(struct ti_usb_phy_device *dev) +{ + struct ti_usb_phy *phy; + + phy = devm_kzalloc(NULL, sizeof(*phy), GFP_KERNEL); + if (!phy) { + dev_err(NULL, "unable to alloc mem for TI USB3 PHY\n"); + return -ENOMEM; + } + + phy->dpll_map = dpll_map_usb; + phy->index = dev->index; + phy->pll_ctrl_base = dev->pll_ctrl_base; + phy->usb2_phy_power = dev->usb2_phy_power; + phy->usb3_phy_power = dev->usb3_phy_power; + + ti_usb3_dpll_program(phy); + ti_usb2_phy_power(phy, 1); + ti_usb3_phy_power(phy, 1); + mdelay(150); + list_add_tail(&phy->list, &ti_usb_phy_list); + + return 0; +} + +/** + * ti_usb_phy_uboot_exit - usb phy uboot cleanup code + * @index: index of this controller + * + * Performs cleanup of memory allocated in ti_usb_phy_uboot_init. + * index of _this_ controller should be passed and should match with + * the index passed in ti_usb_phy_device during init. + * + * Generally called from board file. + */ +void ti_usb_phy_uboot_exit(int index) +{ + struct ti_usb_phy *phy = NULL; + + list_for_each_entry(phy, &ti_usb_phy_list, list) { + if (phy->index != index) + continue; + + ti_usb2_phy_power(phy, 0); + ti_usb3_phy_power(phy, 0); + list_del(&phy->list); + kfree(phy); + break; + } +} diff --git a/include/ti-usb-phy-uboot.h b/include/ti-usb-phy-uboot.h new file mode 100644 index 0000000..93f7101 --- /dev/null +++ b/include/ti-usb-phy-uboot.h @@ -0,0 +1,22 @@ +/* include/ti_usb_phy_uboot.h + * + * Copyright (c) 2014 Texas Instruments Incorporated - http://www.ti.com + * + * USB2 and USB3 PHY uboot init + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __TI_USB_PHY_UBOOT_H_ +#define __TI_USB_PHY_UBOOT_H_ + +struct ti_usb_phy_device { + void *pll_ctrl_base; + void *usb2_phy_power; + void *usb3_phy_power; + int index; +}; + +int ti_usb_phy_uboot_init(struct ti_usb_phy_device *dev); +void ti_usb_phy_uboot_exit(int index); +#endif /* __TI_USB_PHY_UBOOT_H_ */