From patchwork Thu Apr 4 13:11:44 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jerome Brunet X-Patchwork-Id: 161795 Delivered-To: patch@linaro.org Received: by 2002:a02:c6d8:0:0:0:0:0 with SMTP id r24csp1584864jan; Thu, 4 Apr 2019 06:12:02 -0700 (PDT) X-Google-Smtp-Source: APXvYqwLKrwIOwVKo+oonZClw4tkMdRtGYGulAXeLG2ZNrEyjr0gLztYVeWdHdl/EK0SCWoidCGr X-Received: by 2002:a63:170d:: with SMTP id x13mr5834562pgl.169.1554383522459; Thu, 04 Apr 2019 06:12:02 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1554383522; cv=none; d=google.com; s=arc-20160816; b=kOHVMfiUcWtCa/5xczUiThCqB6WsEpEOmE81sHRtBM4bsrohkiK1CeK0lPzZScSEUH 9WvzjTkPYZKiNsDoqY6nkhUPGRArbodfaaMtylCCb5OKT/umWRk/yoYak0HdZxtNUjlS OzbunVHh3PczFy/QIAeYaLJ/mlSudCa3dgB5pjvDti7PLWS1OGHhDUpG1MKsaxZZygU8 HUST9WrPgB97ljrb6Impn6FH7BJgaNJ4q++dYvttCzp0VaoCD7hMjqKMd1W+hR1Fi3wm 0ttSazwsXLCSK+bkbFUaYh9iZG0zu0m+AiAi34tErAmt7kDA3G5Yq26jl/JF4CUkp5dY vv3w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=W34/cfcT6NSknRmwI1jY9uNwLfZHBK33QyXRjlFTgPM=; b=QIrinn7qTdbHgYSlJO+YKw/+trpP2n+RMtTSPcdiGyxEqpxKjk6uDebbKAsybkwQJW vIpX1GgaYLb5rasuod0lte+6GZYOUOOJ6De4Zhcfm8HFjnb+Al74rrJ2/q7WU27Killw wsZPYY/p3arMchKz8ZSVbViJMUv5whVP/Ps3ZwZGrTBavqf2r9000GYefB2L5ZIFDh2j H2G/ZqTlwoRi/0dihSUewueiz0STdup73fImkPZobfGPd4otcDF1x14Rus7Z1b+lkVzi 2VPe8LOyo/UhiwVWftL5m+Q8VpSOXyxlAoj0lxhUO1mQJ6diC8helCHx2299z1WrQnnz nhHw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=nWoqbLTF; spf=pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=devicetree-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id l18si5386554pfi.117.2019.04.04.06.12.02; Thu, 04 Apr 2019 06:12:02 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=nWoqbLTF; spf=pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=devicetree-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729240AbfDDNMA (ORCPT + 7 others); Thu, 4 Apr 2019 09:12:00 -0400 Received: from mail-wr1-f65.google.com ([209.85.221.65]:42598 "EHLO mail-wr1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728997AbfDDNL7 (ORCPT ); Thu, 4 Apr 2019 09:11:59 -0400 Received: by mail-wr1-f65.google.com with SMTP id g3so3717347wrx.9 for ; Thu, 04 Apr 2019 06:11:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=W34/cfcT6NSknRmwI1jY9uNwLfZHBK33QyXRjlFTgPM=; b=nWoqbLTFHP0Hbvks+1VbStS8n6ieZIS3NcTMMJ6zh1JNh+jy8OPOkkCEkhqIgCwuRc WiVLdCukT2E0aUqL7LRInMoDNs/MfDicoT89ZtuDuGpmIp2u4CBR36EU0u1s5ZCCwX2C z4Y3sGzm4nHJDjllJngjY3DijgoPft4lnsxHEV4Ych7nQLIxEHl1sAz35qyehHLeXsWz 1kG4OapmBUCRl8sCztE2ab9Sr2kH13det5do8lsZ/ItYdzec+Mm3qLyz1M52yf32Za6I dAjuFfoih3r0H/YqG6Y0ksIHixXyRX2iK0TTJxJVYFLyJIBLVlos5NUnSWh604nNMfWB GMPw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=W34/cfcT6NSknRmwI1jY9uNwLfZHBK33QyXRjlFTgPM=; b=het/PW+K2HcLb4le2aeda031Re4D+Ebjq+ftNpvgj6inMBZUsDwO3MMzGrqmVtQQAb nQ4sfsNVDE9dFu4JefmlFHlz2bBHkAhg3D2UcVOHAGcUt2U2485oGsjycdWRZUH6Drng VRrkEVKrtluQ8XRsjC4GolWK0BMsdIUiWBXjThQWVdHuu6JEiHCPkM0lW1cPIKZA8LJk 1X0siL7r4ByrmffikCcCYqbWzoThvHbZZsEl5yy1eO4ud89P7A2J+iPu0WIDFSHvb6yU MM2/h+sdDTslZB+aUMsxsEQAsUPI36zJrfgQVO9Nt9jd1yav9o5AOBZqNdzqOUYep//t X3WA== X-Gm-Message-State: APjAAAWxVCOJdOnH52sUxMt+WH24zELblwzpbZlYvWVeG42WvyCNRY1/ pTgBVvwUsD078qIDAr4L1nqjcg== X-Received: by 2002:adf:fe4d:: with SMTP id m13mr4236000wrs.267.1554383517539; Thu, 04 Apr 2019 06:11:57 -0700 (PDT) Received: from boomer.local ([2a01:e34:eeb6:4690:106b:bae3:31ed:7561]) by smtp.googlemail.com with ESMTPSA id y133sm21984923wmd.2.2019.04.04.06.11.55 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 04 Apr 2019 06:11:56 -0700 (PDT) From: Jerome Brunet To: Andrew Lunn , Florian Fainelli , Heiner Kallweit , "David S. Miller" , Kevin Hilman Cc: Jerome Brunet , netdev@vger.kernel.org, linux-amlogic@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, Rob Herring Subject: [PATCH net-next v3 1/4] dt-bindings: net: phy: add g12a mdio mux documentation Date: Thu, 4 Apr 2019 15:11:44 +0200 Message-Id: <20190404131147.31156-2-jbrunet@baylibre.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190404131147.31156-1-jbrunet@baylibre.com> References: <20190404131147.31156-1-jbrunet@baylibre.com> MIME-Version: 1.0 Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org Add documentation for the device tree bindings of the MDIO mux of Amlogic g12a SoC family Reviewed-by: Rob Herring Signed-off-by: Jerome Brunet --- .../bindings/net/mdio-mux-meson-g12a.txt | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 Documentation/devicetree/bindings/net/mdio-mux-meson-g12a.txt -- 2.20.1 diff --git a/Documentation/devicetree/bindings/net/mdio-mux-meson-g12a.txt b/Documentation/devicetree/bindings/net/mdio-mux-meson-g12a.txt new file mode 100644 index 000000000000..3a96cbed9294 --- /dev/null +++ b/Documentation/devicetree/bindings/net/mdio-mux-meson-g12a.txt @@ -0,0 +1,48 @@ +Properties for the MDIO bus multiplexer/glue of Amlogic G12a SoC family. + +This is a special case of a MDIO bus multiplexer. It allows to choose between +the internal mdio bus leading to the embedded 10/100 PHY or the external +MDIO bus. + +Required properties in addition to the generic multiplexer properties: +- compatible : amlogic,g12a-mdio-mux +- reg: physical address and length of the multiplexer/glue registers +- clocks: list of clock phandle, one for each entry clock-names. +- clock-names: should contain the following: + * "pclk" : peripheral clock. + * "clkin0" : platform crytal + * "clkin1" : SoC 50MHz MPLL + +Example : + +mdio_mux: mdio-multiplexer@4c000 { + compatible = "amlogic,g12a-mdio-mux"; + reg = <0x0 0x4c000 0x0 0xa4>; + clocks = <&clkc CLKID_ETH_PHY>, + <&xtal>, + <&clkc CLKID_MPLL_5OM>; + clock-names = "pclk", "clkin0", "clkin1"; + mdio-parent-bus = <&mdio0>; + #address-cells = <1>; + #size-cells = <0>; + + ext_mdio: mdio@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + }; + + int_mdio: mdio@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + internal_ephy: ethernet-phy@8 { + compatible = "ethernet-phy-id0180.3301", + "ethernet-phy-ieee802.3-c22"; + interrupts = ; + reg = <8>; + max-speed = <100>; + }; + }; +}; From patchwork Thu Apr 4 13:11:45 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jerome Brunet X-Patchwork-Id: 161796 Delivered-To: patch@linaro.org Received: by 2002:a02:c6d8:0:0:0:0:0 with SMTP id r24csp1584909jan; Thu, 4 Apr 2019 06:12:04 -0700 (PDT) X-Google-Smtp-Source: APXvYqztl6Ze2jLwOE70qFN5lesNyYf0M8LALW42SIm8/MS4GV7euP4mwy8v33cuzspp8/vGcKBM X-Received: by 2002:a63:c505:: with SMTP id f5mr5868793pgd.87.1554383524336; Thu, 04 Apr 2019 06:12:04 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1554383524; cv=none; d=google.com; s=arc-20160816; b=C2ILNy6j7BJOMhuBU/7PnIbskg2pAdyRceK2EK0RL/3Sl1t0jwzVQY5e4l3trXelIP q+o+9Wz8y5xVxmfv0BygLbx1Mhq/lpXmGoH63yupdNQsc49o4EZbnUJNGIOZylnLjvTs Aho2xst+a+Zdd1T9XhaaZcRNmjMdUlF4LRLUU5DixaZUKhvMFu1OSVx0v5CIpZ2h+iBg CFjbyN5CXtYdsB07SwPOlgpxOFEwb7LYOUFFc2NRXhm7ZkG4hhQ1zUigr9RmBv6/8D/C XarCfXHj3kRZ4Z14vo3vMmN0u/LwZki/7RPoAcE1DzIIkIUqdLHcEmQ728bNQrO3aPnp H2zw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=GfMgILKFC+nvM8EVCQlsEbNCDhCmyCn75eSr2Ib1MkE=; b=DLcCfWY+rxocv7EvkZReioV7PWZvjQ/K+X8QR4OQMhwHQ4tlnXoZ2nN7nLWMY0GGao JWdfeFS491h88vZJgwwBJXzNXim5opXTvx1AZKXptVzWbA/9jUG4DC+Q02krUxUkBC0F QuW//jD/d5xvzEbtADEqrXjLu0cOTAVKWIPgYjFA9txu+fu4rLk1SfHHo0wiDc3LGr0w 7tbp7JUOmYaty8CFOgadVOnDEDDFCtMmMuuSmNQbaAvBdt9T4iURaKu95szh9fSB8ikz ccFpg+82yhWiZOHTuKcoY9aoH9l1F7zY3YydUKefCxhkpjyn+LkxYe+79lEnyuSgU73q r8Nw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=ePnizs3Y; spf=pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=devicetree-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id b9si16048066pgn.457.2019.04.04.06.12.04; Thu, 04 Apr 2019 06:12:04 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=ePnizs3Y; spf=pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=devicetree-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728962AbfDDNMD (ORCPT + 7 others); Thu, 4 Apr 2019 09:12:03 -0400 Received: from mail-wm1-f68.google.com ([209.85.128.68]:34379 "EHLO mail-wm1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729306AbfDDNMC (ORCPT ); Thu, 4 Apr 2019 09:12:02 -0400 Received: by mail-wm1-f68.google.com with SMTP id r186so7292142wmf.1 for ; Thu, 04 Apr 2019 06:12:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=GfMgILKFC+nvM8EVCQlsEbNCDhCmyCn75eSr2Ib1MkE=; b=ePnizs3Y9TotUxUTBYHmb38IKLAbcdCuy5Ku9JH9Vs2C4pZ7aTSMyc/XlCX68VHB0W 9CB4XB07HW+1wNZt2NdMqlJTXCcrBRatb0LEde//5WssCsaScNupIkF4rwIPTn7HZGcp QEoChnmTLDxkXBrmuxR0OVwwyoXEuRnb1/u+5WLeKPPN0GxUU/zXWE32wGiU5dFZOZsN UJ29i3NaALjkBXAoOJYFCW/qgQnHJdBjTkvkJAKiPdRzoNEVUFr7bO0CGBGjy3duubwB fnTubdMCVmJdVFPtPLak0YY3wUVjb3lc4WcmAIaAZE66+M6I78DvwFZ43h0jehIBe3Yp mqHg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=GfMgILKFC+nvM8EVCQlsEbNCDhCmyCn75eSr2Ib1MkE=; b=kXw95/zlvf8BvB+atu2oLZs9GcsD/t6t6wlMaWlnt/hQ8gtGZpf/VO0TaIHvRA/Jt7 AFlz+WDM58woAGFs0r2mgzfq8CxnksEb0jeWWAquURQl023+u5gmt9qxaZP44pjTJKRw hwv8a2YbjQL28dugooEv4eSbqIffnGjv1c3oBtsKoRdbflfhCPZJfE1zxhNSZO1ZyPkJ R0uZVQNs1BmjyO+MlU0bF977AJIgM+m6JTC3l6UNOGBmfDkodkf5IqH/VxeuJmqMTOiE 1/T7O7P+03SSjzxlYZql4ZMfyaN5a4sZZtJ89rQrOfTjFdeDQQwiFWlkghhv9JPc4iwy gn7w== X-Gm-Message-State: APjAAAU8C1t0gr+Bfm2XibTVzzjKBdJjiOGm0lx4UIBIUsA5YpgTNUtt mM3E+rOZiNCy7ZPGhkW7wKiWQw== X-Received: by 2002:a1c:b782:: with SMTP id h124mr4140567wmf.5.1554383519528; Thu, 04 Apr 2019 06:11:59 -0700 (PDT) Received: from boomer.local ([2a01:e34:eeb6:4690:106b:bae3:31ed:7561]) by smtp.googlemail.com with ESMTPSA id y133sm21984923wmd.2.2019.04.04.06.11.57 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 04 Apr 2019 06:11:58 -0700 (PDT) From: Jerome Brunet To: Andrew Lunn , Florian Fainelli , Heiner Kallweit , "David S. Miller" , Kevin Hilman Cc: Jerome Brunet , netdev@vger.kernel.org, linux-amlogic@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, Neil Armstrong Subject: [PATCH net-next v3 2/4] net: phy: add amlogic g12a mdio mux support Date: Thu, 4 Apr 2019 15:11:45 +0200 Message-Id: <20190404131147.31156-3-jbrunet@baylibre.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190404131147.31156-1-jbrunet@baylibre.com> References: <20190404131147.31156-1-jbrunet@baylibre.com> MIME-Version: 1.0 Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org Add support for the mdio mux and internal phy glue of the g12a SoC family Reviewed-by: Neil Armstrong # clk parts Signed-off-by: Jerome Brunet --- drivers/net/phy/Kconfig | 11 + drivers/net/phy/Makefile | 1 + drivers/net/phy/mdio-mux-meson-g12a.c | 380 ++++++++++++++++++++++++++ 3 files changed, 392 insertions(+) create mode 100644 drivers/net/phy/mdio-mux-meson-g12a.c -- 2.20.1 diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 520657945b82..1b04004e1f37 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -76,6 +76,17 @@ config MDIO_BUS_MUX_GPIO several child MDIO busses to a parent bus. Child bus selection is under the control of GPIO lines. +config MDIO_BUS_MUX_MESON_G12A + tristate "Amlogic G12a based MDIO bus multiplexer" + depends on ARCH_MESON || COMPILE_TEST + depends on OF_MDIO && HAS_IOMEM && COMMON_CLK + select MDIO_BUS_MUX + default m if ARCH_MESON + help + This module provides a driver for the MDIO multiplexer/glue of + the amlogic g12a SoC. The multiplexers connects either the external + or the internal MDIO bus to the parent bus. + config MDIO_BUS_MUX_MMIOREG tristate "MMIO device-controlled MDIO bus multiplexers" depends on OF_MDIO && HAS_IOMEM diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index ece5dae67174..27d7f9f3b0de 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -28,6 +28,7 @@ obj-$(CONFIG_MDIO_BITBANG) += mdio-bitbang.o obj-$(CONFIG_MDIO_BUS_MUX) += mdio-mux.o obj-$(CONFIG_MDIO_BUS_MUX_BCM_IPROC) += mdio-mux-bcm-iproc.o obj-$(CONFIG_MDIO_BUS_MUX_GPIO) += mdio-mux-gpio.o +obj-$(CONFIG_MDIO_BUS_MUX_MESON_G12A) += mdio-mux-meson-g12a.o obj-$(CONFIG_MDIO_BUS_MUX_MMIOREG) += mdio-mux-mmioreg.o obj-$(CONFIG_MDIO_BUS_MUX_MULTIPLEXER) += mdio-mux-multiplexer.o obj-$(CONFIG_MDIO_CAVIUM) += mdio-cavium.o diff --git a/drivers/net/phy/mdio-mux-meson-g12a.c b/drivers/net/phy/mdio-mux-meson-g12a.c new file mode 100644 index 000000000000..6fa29ea8e2a3 --- /dev/null +++ b/drivers/net/phy/mdio-mux-meson-g12a.c @@ -0,0 +1,380 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2019 Baylibre, SAS. + * Author: Jerome Brunet + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ETH_PLL_STS 0x40 +#define ETH_PLL_CTL0 0x44 +#define PLL_CTL0_LOCK_DIG BIT(30) +#define PLL_CTL0_RST BIT(29) +#define PLL_CTL0_EN BIT(28) +#define PLL_CTL0_SEL BIT(23) +#define PLL_CTL0_N GENMASK(14, 10) +#define PLL_CTL0_M GENMASK(8, 0) +#define PLL_LOCK_TIMEOUT 1000000 +#define PLL_MUX_NUM_PARENT 2 +#define ETH_PLL_CTL1 0x48 +#define ETH_PLL_CTL2 0x4c +#define ETH_PLL_CTL3 0x50 +#define ETH_PLL_CTL4 0x54 +#define ETH_PLL_CTL5 0x58 +#define ETH_PLL_CTL6 0x5c +#define ETH_PLL_CTL7 0x60 + +#define ETH_PHY_CNTL0 0x80 +#define EPHY_G12A_ID 0x33000180 +#define ETH_PHY_CNTL1 0x84 +#define PHY_CNTL1_ST_MODE GENMASK(2, 0) +#define PHY_CNTL1_ST_PHYADD GENMASK(7, 3) +#define EPHY_DFLT_ADD 8 +#define PHY_CNTL1_MII_MODE GENMASK(15, 14) +#define EPHY_MODE_RMII 0x1 +#define PHY_CNTL1_CLK_EN BIT(16) +#define PHY_CNTL1_CLKFREQ BIT(17) +#define PHY_CNTL1_PHY_ENB BIT(18) +#define ETH_PHY_CNTL2 0x88 +#define PHY_CNTL2_USE_INTERNAL BIT(5) +#define PHY_CNTL2_SMI_SRC_MAC BIT(6) +#define PHY_CNTL2_RX_CLK_EPHY BIT(9) + +#define MESON_G12A_MDIO_EXTERNAL_ID 0 +#define MESON_G12A_MDIO_INTERNAL_ID 1 + +struct g12a_mdio_mux { + bool pll_is_enabled; + void __iomem *regs; + void *mux_handle; + struct clk *pclk; + struct clk *pll; +}; + +struct g12a_ephy_pll { + void __iomem *base; + struct clk_hw hw; +}; + +#define g12a_ephy_pll_to_dev(_hw) \ + container_of(_hw, struct g12a_ephy_pll, hw) + +static unsigned long g12a_ephy_pll_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct g12a_ephy_pll *pll = g12a_ephy_pll_to_dev(hw); + u32 val, m, n; + + val = readl(pll->base + ETH_PLL_CTL0); + m = FIELD_GET(PLL_CTL0_M, val); + n = FIELD_GET(PLL_CTL0_N, val); + + return parent_rate * m / n; +} + +static int g12a_ephy_pll_enable(struct clk_hw *hw) +{ + struct g12a_ephy_pll *pll = g12a_ephy_pll_to_dev(hw); + u32 val = readl(pll->base + ETH_PLL_CTL0); + + /* Apply both enable an reset */ + val |= PLL_CTL0_RST | PLL_CTL0_EN; + writel(val, pll->base + ETH_PLL_CTL0); + + /* Clear the reset to let PLL lock */ + val &= ~PLL_CTL0_RST; + writel(val, pll->base + ETH_PLL_CTL0); + + /* Poll on the digital lock instead of the usual analog lock + * This is done because bit 31 is unreliable on some SoC. Bit + * 31 may indicate that the PLL is not lock eventhough the clock + * is actually running + */ + return readl_poll_timeout(pll->base + ETH_PLL_CTL0, val, + val & PLL_CTL0_LOCK_DIG, 0, PLL_LOCK_TIMEOUT); +} + +static void g12a_ephy_pll_disable(struct clk_hw *hw) +{ + struct g12a_ephy_pll *pll = g12a_ephy_pll_to_dev(hw); + u32 val; + + val = readl(pll->base + ETH_PLL_CTL0); + val &= ~PLL_CTL0_EN; + val |= PLL_CTL0_RST; + writel(val, pll->base + ETH_PLL_CTL0); +} + +static int g12a_ephy_pll_is_enabled(struct clk_hw *hw) +{ + struct g12a_ephy_pll *pll = g12a_ephy_pll_to_dev(hw); + unsigned int val; + + val = readl(pll->base + ETH_PLL_CTL0); + + return (val & PLL_CTL0_LOCK_DIG) ? 1 : 0; +} + +static void g12a_ephy_pll_init(struct clk_hw *hw) +{ + struct g12a_ephy_pll *pll = g12a_ephy_pll_to_dev(hw); + + /* Apply PLL HW settings */ + writel(0x29c0040a, pll->base + ETH_PLL_CTL0); + writel(0x927e0000, pll->base + ETH_PLL_CTL1); + writel(0xac5f49e5, pll->base + ETH_PLL_CTL2); + writel(0x00000000, pll->base + ETH_PLL_CTL3); + writel(0x00000000, pll->base + ETH_PLL_CTL4); + writel(0x20200000, pll->base + ETH_PLL_CTL5); + writel(0x0000c002, pll->base + ETH_PLL_CTL6); + writel(0x00000023, pll->base + ETH_PLL_CTL7); +} + +static const struct clk_ops g12a_ephy_pll_ops = { + .recalc_rate = g12a_ephy_pll_recalc_rate, + .is_enabled = g12a_ephy_pll_is_enabled, + .enable = g12a_ephy_pll_enable, + .disable = g12a_ephy_pll_disable, + .init = g12a_ephy_pll_init, +}; + +static int g12a_enable_internal_mdio(struct g12a_mdio_mux *priv) +{ + int ret; + + /* Enable the phy clock */ + if (!priv->pll_is_enabled) { + ret = clk_prepare_enable(priv->pll); + if (ret) + return ret; + } + + priv->pll_is_enabled = true; + + /* Initialize ephy control */ + writel(EPHY_G12A_ID, priv->regs + ETH_PHY_CNTL0); + writel(FIELD_PREP(PHY_CNTL1_ST_MODE, 3) | + FIELD_PREP(PHY_CNTL1_ST_PHYADD, EPHY_DFLT_ADD) | + FIELD_PREP(PHY_CNTL1_MII_MODE, EPHY_MODE_RMII) | + PHY_CNTL1_CLK_EN | + PHY_CNTL1_CLKFREQ | + PHY_CNTL1_PHY_ENB, + priv->regs + ETH_PHY_CNTL1); + writel(PHY_CNTL2_USE_INTERNAL | + PHY_CNTL2_SMI_SRC_MAC | + PHY_CNTL2_RX_CLK_EPHY, + priv->regs + ETH_PHY_CNTL2); + + return 0; +} + +static int g12a_enable_external_mdio(struct g12a_mdio_mux *priv) +{ + /* Reset the mdio bus mux */ + writel_relaxed(0x0, priv->regs + ETH_PHY_CNTL2); + + /* Disable the phy clock if enabled */ + if (priv->pll_is_enabled) { + clk_disable_unprepare(priv->pll); + priv->pll_is_enabled = false; + } + + return 0; +} + +static int g12a_mdio_switch_fn(int current_child, int desired_child, + void *data) +{ + struct g12a_mdio_mux *priv = dev_get_drvdata(data); + + if (current_child == desired_child) + return 0; + + switch (desired_child) { + case MESON_G12A_MDIO_EXTERNAL_ID: + return g12a_enable_external_mdio(priv); + case MESON_G12A_MDIO_INTERNAL_ID: + return g12a_enable_internal_mdio(priv); + default: + return -EINVAL; + } +} + +static const struct of_device_id g12a_mdio_mux_match[] = { + { .compatible = "amlogic,g12a-mdio-mux", }, + {}, +}; +MODULE_DEVICE_TABLE(of, g12a_mdio_mux_match); + +static int g12a_ephy_glue_clk_register(struct device *dev) +{ + struct g12a_mdio_mux *priv = dev_get_drvdata(dev); + const char *parent_names[PLL_MUX_NUM_PARENT]; + struct clk_init_data init; + struct g12a_ephy_pll *pll; + struct clk_mux *mux; + struct clk *clk; + char *name; + int i; + + /* get the mux parents */ + for (i = 0; i < PLL_MUX_NUM_PARENT; i++) { + char in_name[8]; + + snprintf(in_name, sizeof(in_name), "clkin%d", i); + clk = devm_clk_get(dev, in_name); + if (IS_ERR(clk)) { + if (PTR_ERR(clk) != -EPROBE_DEFER) + dev_err(dev, "Missing clock %s\n", in_name); + return PTR_ERR(clk); + } + + parent_names[i] = __clk_get_name(clk); + } + + /* create the input mux */ + mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL); + if (!mux) + return -ENOMEM; + + name = kasprintf(GFP_KERNEL, "%s#mux", dev_name(dev)); + if (!name) + return -ENOMEM; + + init.name = name; + init.ops = &clk_mux_ro_ops; + init.flags = 0; + init.parent_names = parent_names; + init.num_parents = PLL_MUX_NUM_PARENT; + + mux->reg = priv->regs + ETH_PLL_CTL0; + mux->shift = __ffs(PLL_CTL0_SEL); + mux->mask = PLL_CTL0_SEL >> mux->shift; + mux->hw.init = &init; + + clk = devm_clk_register(dev, &mux->hw); + kfree(name); + if (IS_ERR(clk)) { + dev_err(dev, "failed to register input mux\n"); + return PTR_ERR(clk); + } + + /* create the pll */ + pll = devm_kzalloc(dev, sizeof(*pll), GFP_KERNEL); + if (!pll) + return -ENOMEM; + + name = kasprintf(GFP_KERNEL, "%s#pll", dev_name(dev)); + if (!name) + return -ENOMEM; + + init.name = name; + init.ops = &g12a_ephy_pll_ops; + init.flags = 0; + parent_names[0] = __clk_get_name(clk); + init.parent_names = parent_names; + init.num_parents = 1; + + pll->base = priv->regs; + pll->hw.init = &init; + + clk = devm_clk_register(dev, &pll->hw); + kfree(name); + if (IS_ERR(clk)) { + dev_err(dev, "failed to register input mux\n"); + return PTR_ERR(clk); + } + + priv->pll = clk; + + return 0; +} + +static int g12a_mdio_mux_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct g12a_mdio_mux *priv; + struct resource *res; + int ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + platform_set_drvdata(pdev, priv); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + priv->regs = devm_ioremap_resource(dev, res); + if (IS_ERR(priv->regs)) + return PTR_ERR(priv->regs); + + priv->pclk = devm_clk_get(dev, "pclk"); + if (IS_ERR(priv->pclk)) { + ret = PTR_ERR(priv->pclk); + if (ret != -EPROBE_DEFER) + dev_err(dev, "failed to get peripheral clock\n"); + return ret; + } + + /* Make sure the device registers are clocked */ + ret = clk_prepare_enable(priv->pclk); + if (ret) { + dev_err(dev, "failed to enable peripheral clock"); + return ret; + } + + /* Register PLL in CCF */ + ret = g12a_ephy_glue_clk_register(dev); + if (ret) + goto err; + + ret = mdio_mux_init(dev, dev->of_node, g12a_mdio_switch_fn, + &priv->mux_handle, dev, NULL); + if (ret) { + if (ret != -EPROBE_DEFER) + dev_err(dev, "mdio multiplexer init failed: %d", ret); + goto err; + } + + return 0; + +err: + clk_disable_unprepare(priv->pclk); + return ret; +} + +static int g12a_mdio_mux_remove(struct platform_device *pdev) +{ + struct g12a_mdio_mux *priv = platform_get_drvdata(pdev); + + mdio_mux_uninit(priv->mux_handle); + + if (priv->pll_is_enabled) + clk_disable_unprepare(priv->pll); + + clk_disable_unprepare(priv->pclk); + + return 0; +} + +static struct platform_driver g12a_mdio_mux_driver = { + .probe = g12a_mdio_mux_probe, + .remove = g12a_mdio_mux_remove, + .driver = { + .name = "g12a-mdio_mux", + .of_match_table = g12a_mdio_mux_match, + }, +}; +module_platform_driver(g12a_mdio_mux_driver); + +MODULE_DESCRIPTION("Amlogic G12a MDIO multiplexer driver"); +MODULE_AUTHOR("Jerome Brunet "); +MODULE_LICENSE("GPL v2");