From patchwork Fri Feb 9 03:34:50 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wenyou Yang X-Patchwork-Id: 871195 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3zd19Y25sdz9s7M for ; Fri, 9 Feb 2018 14:42:57 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id C2350C21EFB; Fri, 9 Feb 2018 03:42:00 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=RCVD_IN_DNSWL_BLOCKED autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 1BC7EC21F01; Fri, 9 Feb 2018 03:41:57 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 391A3C21E8A; Fri, 9 Feb 2018 03:41:50 +0000 (UTC) Received: from eusmtp01.atmel.com (eusmtp01.atmel.com [212.144.249.243]) by lists.denx.de (Postfix) with ESMTPS id 9306BC21F1A for ; Fri, 9 Feb 2018 03:41:46 +0000 (UTC) Received: from apsmtp01.atmel.com (10.168.254.31) by eusmtp01.atmel.com (10.145.145.31) with Microsoft SMTP Server id 14.3.235.1; Fri, 9 Feb 2018 04:41:39 +0100 Received: from shaarm01.corp.atmel.com (10.168.254.13) by apsmtp01.atmel.com (10.168.254.31) with Microsoft SMTP Server id 14.3.235.1; Fri, 9 Feb 2018 11:50:36 +0800 From: Wenyou Yang To: U-Boot Mailing List Date: Fri, 9 Feb 2018 11:34:50 +0800 Message-ID: <20180209033452.15448-2-wenyou.yang@microchip.com> X-Mailer: git-send-email 2.16.0.rc1 In-Reply-To: <20180209033452.15448-1-wenyou.yang@microchip.com> References: <20180209033452.15448-1-wenyou.yang@microchip.com> MIME-Version: 1.0 Cc: Tom Rini , Nicolas Ferre , Wenyou Yang Subject: [U-Boot] [PATCH 1/3] clk: at91: add USB Host clock driver X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 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" Add USB clock driver to configure the input clock and the divider in the PMC_USB register to generate a 48MHz and a 12MHz signal to the USB Host OHCI. Signed-off-by: Wenyou Yang --- arch/arm/mach-at91/include/mach/at91_pmc.h | 6 ++ drivers/clk/at91/Kconfig | 8 ++ drivers/clk/at91/Makefile | 1 + drivers/clk/at91/clk-usb.c | 146 +++++++++++++++++++++++++++++ 4 files changed, 161 insertions(+) create mode 100644 drivers/clk/at91/clk-usb.c diff --git a/arch/arm/mach-at91/include/mach/at91_pmc.h b/arch/arm/mach-at91/include/mach/at91_pmc.h index 08ad1bf2d0..fbda8d5f63 100644 --- a/arch/arm/mach-at91/include/mach/at91_pmc.h +++ b/arch/arm/mach-at91/include/mach/at91_pmc.h @@ -233,9 +233,15 @@ typedef struct at91_pmc { #define AT91_PMC_PDIV_1 (0 << 12) #define AT91_PMC_PDIV_2 (1 << 12) +#define AT91_PMC_USB_USBS_MASK 0x1 +#define AT91_PMC_USB_USBS_OFFSET 0 +#define AT91_PMC_USB_USBS_(x) (x & 0x1) #define AT91_PMC_USBS_USB_PLLA (0x0) /* USB Clock Input is PLLA */ #define AT91_PMC_USBS_USB_UPLL (0x1) /* USB Clock Input is UPLL */ #define AT91_PMC_USBS_USB_PLLB (0x1) /* USB Clock Input is PLLB, AT91SAM9N12 only */ +#define AT91_PMC_USB_DIV_MASK 0xf +#define AT91_PMC_USB_DIV_OFFSET 8 +#define AT91_PMC_USB_DIV_(x) ((x & 0xf) << 8) #define AT91_PMC_USB_DIV_2 (0x1 << 8) /* USB Clock divided by 2 */ #define AT91_PMC_USBDIV_8 (0x7 << 8) /* USB Clock divided by 8 */ #define AT91_PMC_USBDIV_10 (0x9 << 8) /* USB Clock divided by 10 */ diff --git a/drivers/clk/at91/Kconfig b/drivers/clk/at91/Kconfig index fd56f200b9..8d482a2752 100644 --- a/drivers/clk/at91/Kconfig +++ b/drivers/clk/at91/Kconfig @@ -27,6 +27,14 @@ config AT91_UTMI fast crystal oscillator to meet the frequency accuracy required by USB. +config AT91_USB_CLK + bool "Support USB OHCI Input Clock" + depends on CLK_AT91 + help + This option is used to enable the USB Input Clock, from + the device tree, configure the USBS bit (PLLA or UTMI PLL) + and USBDIV field of the PMC_USB register. + config AT91_H32MX bool "Support H32MX 32-bit Matrix Clock" depends on CLK_AT91 diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile index fbe3cb6581..8cac3f9e18 100644 --- a/drivers/clk/at91/Makefile +++ b/drivers/clk/at91/Makefile @@ -7,5 +7,6 @@ obj-y += clk-slow.o clk-main.o clk-plla.o clk-master.o obj-y += clk-system.o clk-peripheral.o obj-$(CONFIG_AT91_UTMI) += clk-utmi.o +obj-$(CONFIG_AT91_USB_CLK) += clk-usb.o obj-$(CONFIG_AT91_H32MX) += clk-h32mx.o obj-$(CONFIG_AT91_GENERIC_CLK) += clk-generated.o diff --git a/drivers/clk/at91/clk-usb.c b/drivers/clk/at91/clk-usb.c new file mode 100644 index 0000000000..36622c09dc --- /dev/null +++ b/drivers/clk/at91/clk-usb.c @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2018 Microhip / Atmel Corporation + * Wenyou.Yang + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include "pmc.h" + +DECLARE_GLOBAL_DATA_PTR; + +#define AT91_USB_CLK_SOURCE_MAX 2 +#define AT91_USB_CLK_MAX_DIV 15 + +struct at91_usb_clk_priv { + u32 num_clksource; +}; + +static ulong at91_usb_clk_get_rate(struct clk *clk) +{ + struct pmc_platdata *plat = dev_get_platdata(clk->dev); + struct at91_pmc *pmc = plat->reg_base; + struct clk source; + u32 tmp, usbdiv; + u8 source_index; + int ret; + + tmp = readl(&pmc->pcr); + source_index = (tmp >> AT91_PMC_USB_USBS_OFFSET) & + AT91_PMC_USB_USBS_MASK; + usbdiv = (tmp >> AT91_PMC_USB_DIV_OFFSET) & AT91_PMC_USB_DIV_MASK; + + ret = clk_get_by_index(clk->dev, source_index, &source); + if (ret) + return 0; + + return clk_get_rate(&source) / (usbdiv + 1); +} + +static ulong at91_usb_clk_set_rate(struct clk *clk, ulong rate) +{ + struct pmc_platdata *plat = dev_get_platdata(clk->dev); + struct at91_pmc *pmc = plat->reg_base; + struct at91_usb_clk_priv *priv = dev_get_priv(clk->dev); + struct clk source, best_source; + ulong tmp_rate, best_rate = rate, source_rate; + int tmp_diff, best_diff = -1; + u32 div, best_div = 0; + u8 best_source_index = 0; + u8 i; + u32 tmp; + int ret; + + for (i = 0; i < priv->num_clksource; i++) { + ret = clk_get_by_index(clk->dev, i, &source); + if (ret) + return ret; + + source_rate = clk_get_rate(&source); + if (IS_ERR_VALUE(source_rate)) + return source_rate; + + for (div = 1; div < AT91_USB_CLK_MAX_DIV + 2; div++) { + tmp_rate = DIV_ROUND_CLOSEST(source_rate, div); + tmp_diff = abs(rate - tmp_rate); + + if (best_diff < 0 || best_diff > tmp_diff) { + best_rate = tmp_rate; + best_diff = tmp_diff; + + best_div = div - 1; + best_source = source; + best_source_index = i; + } + + if (!best_diff || tmp_rate < rate) + break; + } + + if (!best_diff) + break; + } + + debug("AT91 USB: best sourc: %s, best_rate = %ld, best_div = %d\n", + best_source.dev->name, best_rate, best_div); + + ret = clk_enable(&best_source); + if (ret) + return ret; + + tmp = AT91_PMC_USB_USBS_(best_source_index) | + AT91_PMC_USB_DIV_(best_div); + writel(tmp, &pmc->usb); + + return 0; +} + +static struct clk_ops at91_usb_clk_ops = { + .get_rate = at91_usb_clk_get_rate, + .set_rate = at91_usb_clk_set_rate, +}; + +static int at91_usb_clk_ofdata_to_platdata(struct udevice *dev) +{ + struct at91_usb_clk_priv *priv = dev_get_priv(dev); + u32 cells[AT91_USB_CLK_SOURCE_MAX]; + u32 num_clksource; + + num_clksource = fdtdec_get_int_array_count(gd->fdt_blob, + dev_of_offset(dev), + "clocks", cells, + AT91_USB_CLK_SOURCE_MAX); + + if (!num_clksource) + return -1; + + priv->num_clksource = num_clksource; + + return 0; +} + +static int at91_usb_clk_probe(struct udevice *dev) +{ + return at91_pmc_core_probe(dev); +} + +static const struct udevice_id at91_usb_clk_match[] = { + { .compatible = "atmel,at91sam9x5-clk-usb" }, + {} +}; + +U_BOOT_DRIVER(at91_usb_clk) = { + .name = "at91-usb-clk", + .id = UCLASS_CLK, + .of_match = at91_usb_clk_match, + .probe = at91_usb_clk_probe, + .ofdata_to_platdata = at91_usb_clk_ofdata_to_platdata, + .priv_auto_alloc_size = sizeof(struct at91_usb_clk_priv), + .platdata_auto_alloc_size = sizeof(struct pmc_platdata), + .ops = &at91_usb_clk_ops, +}; From patchwork Fri Feb 9 03:34:51 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wenyou Yang X-Patchwork-Id: 871197 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3zd19r60YQz9rxj for ; Fri, 9 Feb 2018 14:43:12 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id 8EAB0C21D6A; Fri, 9 Feb 2018 03:42:20 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 43ED3C21EFD; Fri, 9 Feb 2018 03:42:16 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id E480AC21E45; Fri, 9 Feb 2018 03:42:02 +0000 (UTC) Received: from DVREDG01.corp.atmel.com (f5out.microchip.com [198.175.253.81]) by lists.denx.de (Postfix) with ESMTPS id 5A896C21DE8 for ; Fri, 9 Feb 2018 03:41:58 +0000 (UTC) Received: from apsmtp01.atmel.com (10.168.254.31) by DVREDG01.corp.atmel.com (10.10.204.148) with Microsoft SMTP Server (TLS) id 14.3.235.1; Thu, 8 Feb 2018 20:42:12 -0700 Received: from shaarm01.corp.atmel.com (10.168.254.13) by apsmtp01.atmel.com (10.168.254.31) with Microsoft SMTP Server id 14.3.235.1; Fri, 9 Feb 2018 11:50:45 +0800 From: Wenyou Yang To: U-Boot Mailing List Date: Fri, 9 Feb 2018 11:34:51 +0800 Message-ID: <20180209033452.15448-3-wenyou.yang@microchip.com> X-Mailer: git-send-email 2.16.0.rc1 In-Reply-To: <20180209033452.15448-1-wenyou.yang@microchip.com> References: <20180209033452.15448-1-wenyou.yang@microchip.com> MIME-Version: 1.0 Cc: Tom Rini , Nicolas Ferre , Wenyou Yang Subject: [U-Boot] [PATCH 2/3] clk: at91: add PLLADIV driver X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 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" As said in the SAMA5D2 datasheet, the PLLA clock must be divided by 2 by writing the PLLADIV2 bit in PMC_MCKR, if the ratio between PCK and MCK is 3 (MDIV = 3). This is the purpose of the driver. Signed-off-by: Wenyou Yang --- drivers/clk/at91/Makefile | 2 +- drivers/clk/at91/clk-plladiv.c | 88 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 drivers/clk/at91/clk-plladiv.c diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile index 8cac3f9e18..8c197ff949 100644 --- a/drivers/clk/at91/Makefile +++ b/drivers/clk/at91/Makefile @@ -3,7 +3,7 @@ # obj-y += pmc.o sckc.o -obj-y += clk-slow.o clk-main.o clk-plla.o clk-master.o +obj-y += clk-slow.o clk-main.o clk-plla.o clk-plladiv.o clk-master.o obj-y += clk-system.o clk-peripheral.o obj-$(CONFIG_AT91_UTMI) += clk-utmi.o diff --git a/drivers/clk/at91/clk-plladiv.c b/drivers/clk/at91/clk-plladiv.c new file mode 100644 index 0000000000..0599d2893b --- /dev/null +++ b/drivers/clk/at91/clk-plladiv.c @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2018 Microhip / Atmel Corporation + * Wenyou.Yang + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include "pmc.h" + +DECLARE_GLOBAL_DATA_PTR; + +static int at91_plladiv_clk_enable(struct clk *clk) +{ + return 0; +} + +static ulong at91_plladiv_clk_get_rate(struct clk *clk) +{ + struct pmc_platdata *plat = dev_get_platdata(clk->dev); + struct at91_pmc *pmc = plat->reg_base; + struct clk source; + ulong clk_rate; + int ret; + + ret = clk_get_by_index(clk->dev, 0, &source); + if (ret) + return -EINVAL; + + clk_rate = clk_get_rate(&source); + if (readl(&pmc->mckr) & AT91_PMC_MCKR_PLLADIV_2) + clk_rate /= 2; + + return clk_rate; +} + +static ulong at91_plladiv_clk_set_rate(struct clk *clk, ulong rate) +{ + struct pmc_platdata *plat = dev_get_platdata(clk->dev); + struct at91_pmc *pmc = plat->reg_base; + struct clk source; + ulong parent_rate; + int ret; + + ret = clk_get_by_index(clk->dev, 0, &source); + if (ret) + return -EINVAL; + + parent_rate = clk_get_rate(&source); + if ((parent_rate != rate) && ((parent_rate) / 2 != rate)) + return -EINVAL; + + if (parent_rate != rate) { + writel((readl(&pmc->mckr) | AT91_PMC_MCKR_PLLADIV_2), + &pmc->mckr); + } + + return 0; +} + +static struct clk_ops at91_plladiv_clk_ops = { + .enable = at91_plladiv_clk_enable, + .get_rate = at91_plladiv_clk_get_rate, + .set_rate = at91_plladiv_clk_set_rate, +}; + +static int at91_plladiv_clk_probe(struct udevice *dev) +{ + return at91_pmc_core_probe(dev); +} + +static const struct udevice_id at91_plladiv_clk_match[] = { + { .compatible = "atmel,at91sam9x5-clk-plldiv" }, + {} +}; + +U_BOOT_DRIVER(at91_plladiv_clk) = { + .name = "at91-plladiv-clk", + .id = UCLASS_CLK, + .of_match = at91_plladiv_clk_match, + .probe = at91_plladiv_clk_probe, + .platdata_auto_alloc_size = sizeof(struct pmc_platdata), + .ops = &at91_plladiv_clk_ops, +}; From patchwork Fri Feb 9 03:34:52 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wenyou Yang X-Patchwork-Id: 871196 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3zd19c6c07z9rxj for ; Fri, 9 Feb 2018 14:43:00 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id 991D9C21F05; Fri, 9 Feb 2018 03:42:37 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 7231DC21F05; Fri, 9 Feb 2018 03:42:17 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 5F59DC21EE9; Fri, 9 Feb 2018 03:42:06 +0000 (UTC) Received: from DVREDG02.corp.atmel.com (f5out.microchip.com [198.175.253.81]) by lists.denx.de (Postfix) with ESMTPS id 002D1C21E45 for ; Fri, 9 Feb 2018 03:42:01 +0000 (UTC) Received: from apsmtp01.atmel.com (10.168.254.31) by DVREDG02.corp.atmel.com (10.10.204.149) with Microsoft SMTP Server (TLS) id 14.3.235.1; Thu, 8 Feb 2018 20:42:41 -0700 Received: from shaarm01.corp.atmel.com (10.168.254.13) by apsmtp01.atmel.com (10.168.254.31) with Microsoft SMTP Server id 14.3.235.1; Fri, 9 Feb 2018 11:50:49 +0800 From: Wenyou Yang To: U-Boot Mailing List Date: Fri, 9 Feb 2018 11:34:52 +0800 Message-ID: <20180209033452.15448-4-wenyou.yang@microchip.com> X-Mailer: git-send-email 2.16.0.rc1 In-Reply-To: <20180209033452.15448-1-wenyou.yang@microchip.com> References: <20180209033452.15448-1-wenyou.yang@microchip.com> MIME-Version: 1.0 Cc: Tom Rini , Nicolas Ferre , Wenyou Yang Subject: [U-Boot] [PATCH 3/3] clk: at91: clk-system: add set/get_rate operations X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 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" To support set/get the clock rate, add set/get_rate operations. Signed-off-by: Wenyou Yang --- drivers/clk/at91/clk-system.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/drivers/clk/at91/clk-system.c b/drivers/clk/at91/clk-system.c index 24b271aa18..81fe47a9d7 100644 --- a/drivers/clk/at91/clk-system.c +++ b/drivers/clk/at91/clk-system.c @@ -44,6 +44,30 @@ static inline int is_pck(int id) return (id >= 8) && (id <= 15); } +static ulong system_clk_get_rate(struct clk *clk) +{ + struct clk clk_dev; + int ret; + + ret = clk_get_by_index(clk->dev, 0, &clk_dev); + if (ret) + return -EINVAL; + + return clk_get_rate(&clk_dev); +} + +static ulong system_clk_set_rate(struct clk *clk, ulong rate) +{ + struct clk clk_dev; + int ret; + + ret = clk_get_by_index(clk->dev, 0, &clk_dev); + if (ret) + return -EINVAL; + + return clk_set_rate(&clk_dev, rate); +} + static int system_clk_enable(struct clk *clk) { struct pmc_platdata *plat = dev_get_platdata(clk->dev); @@ -73,6 +97,8 @@ static int system_clk_enable(struct clk *clk) static struct clk_ops system_clk_ops = { .of_xlate = at91_clk_of_xlate, + .get_rate = system_clk_get_rate, + .set_rate = system_clk_set_rate, .enable = system_clk_enable, };