From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.1 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9608AC282D7 for ; Wed, 30 Jan 2019 11:22:18 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 52EBB20869 for ; Wed, 30 Jan 2019 11:22:18 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b="QY1oHMYz" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729164AbfA3LWR (ORCPT ); Wed, 30 Jan 2019 06:22:17 -0500 Received: from mail-eopbgr10071.outbound.protection.outlook.com ([40.107.1.71]:31648 "EHLO EUR02-HE1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726548AbfA3LWR (ORCPT ); Wed, 30 Jan 2019 06:22:17 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nxp.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=R4EqQPV6P39NiyEJggZ5PHMm9XtiwITWHF4ax5elY60=; b=QY1oHMYzwRA9gCWxImsJsMkIGtmsu1tRMlYR7oznfeU2aq7yUwoTgkLPSqYpULkweZtucKnowNxo31NSLy3G3PjTIkk/AkRX5VweVd8eaddawU6zGMPM6yxtRgzTUVIT4cBlyUL9Q+iiskHK6ZCW9KzY7uKDSo9hcwXmDthuuao= Received: from VI1PR0401MB2496.eurprd04.prod.outlook.com (10.168.65.10) by VI1PR0401MB2589.eurprd04.prod.outlook.com (10.168.65.142) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.1558.18; Wed, 30 Jan 2019 11:22:00 +0000 Received: from VI1PR0401MB2496.eurprd04.prod.outlook.com ([fe80::208f:755e:b057:2cfe]) by VI1PR0401MB2496.eurprd04.prod.outlook.com ([fe80::208f:755e:b057:2cfe%8]) with mapi id 15.20.1558.023; Wed, 30 Jan 2019 11:22:00 +0000 From: Pankaj Bansal To: Andrew Lunn , Florian Fainelli CC: "netdev@vger.kernel.org" , Pankaj Bansal Subject: [PATCH 1/1] netdev/phy: add MDIO bus multiplexer driven by a regmap Thread-Topic: [PATCH 1/1] netdev/phy: add MDIO bus multiplexer driven by a regmap Thread-Index: AQHUuI4EM0m6x4EuSkqn3uRApubbkA== Date: Wed, 30 Jan 2019 11:22:00 +0000 Message-ID: <20190130164644.3948-2-pankaj.bansal@nxp.com> References: <20190130164644.3948-1-pankaj.bansal@nxp.com> In-Reply-To: <20190130164644.3948-1-pankaj.bansal@nxp.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-clientproxiedby: BM1PR01CA0101.INDPRD01.PROD.OUTLOOK.COM (2603:1096:b00::17) To VI1PR0401MB2496.eurprd04.prod.outlook.com (2603:10a6:800:56::10) authentication-results: spf=none (sender IP is ) smtp.mailfrom=pankaj.bansal@nxp.com; x-ms-exchange-messagesentrepresentingtype: 1 x-mailer: git-send-email 2.17.1 x-originating-ip: [92.120.1.69] x-ms-publictraffictype: Email x-microsoft-exchange-diagnostics: 1;VI1PR0401MB2589;6:lgwLdE6VaPi42YGmOHyeployh9Y1CmU17bL1o7Yo39jOeR432nbN18kwjT2O8saJ6O1iouXhRp8ohJFn2ih9jKRfRq42tSCmV/CNMPi+0Whtp6mn8UdqAS1DtvnVnwHQjCMqSyw5QF2hHvHTkw0d+b+uA/mNTfwebWzyBOr5KVQG29Y8NgATaGhb1x4eyXKS/7SpBgeDs8pVYjGgLHUhE5Iks8x6pGyNSB5EtIbirk7aMvcU60sgOIK8CDJ4eABQpP42DtkxLjlX/32tbaIGuuceWiphEh9+QDqQ3Gx7Hac0xKMsKQxpzyt2cOTD54WuVyvwiT/KQBRpcjYj5QDQK0xXSJrFoDgnxjAnERa3X6hsIHHR1heLoCwarDVWil7Z8SS8hY3ALV1zABCzXydgI0kDDwPAvc20yJW+l+jtLECnjTJWReLCuzoGL30gt9cTfHp+6xfcuO+9B4yQzrLpXQ==;5:9AUCTWdcIgZmAEK1VsqHYmW+1cBIHNuBABSlZlrRMRoRwe1Tpz5Z/2vUPIa3p9hdWXQ7oVqLwlw5CL/ZTWdDUWXdrmjCf+n2ZbVvdpP9lZlLqvknmvvy1bbyB8ocPy1SF8lRZAF1Dy+FfsTYtpEOYd7qLnzH5ONp5a2gKiG9dsIb7uL+fIc1mof5omNjbNf9APAfoXDOxopSGp6X44+lZQ==;7:wLrEsegnuw/zk2fXfDY7jS8IT/uk2kjYxs+hPs8ty3RlUMQqbRQZbD//BvFNfoGwrRKpdMyC+CHHSBcylBkRF05gRLcJi+ug4LkTZgrjqXJ5/GenGr+fYe9z0J8IiNXSOsjToCl+enePqGKWFOoHrw== x-ms-office365-filtering-correlation-id: 45f6358a-3d40-443f-0c21-08d686a526f7 x-ms-office365-filtering-ht: Tenant x-microsoft-antispam: BCL:0;PCL:0;RULEID:(2390118)(7020095)(4652040)(8989299)(4534185)(4627221)(201703031133081)(201702281549075)(8990200)(5600110)(711020)(4605077)(4618075)(2017052603328)(7153060)(7193020);SRVR:VI1PR0401MB2589; x-ms-traffictypediagnostic: VI1PR0401MB2589: x-microsoft-antispam-prvs: x-forefront-prvs: 0933E9FD8D x-forefront-antispam-report: SFV:NSPM;SFS:(10009020)(39860400002)(136003)(376002)(366004)(396003)(346002)(199004)(189003)(4326008)(52116002)(50226002)(102836004)(71190400001)(76176011)(6512007)(81166006)(186003)(81156014)(476003)(39060400002)(2616005)(71200400001)(8936002)(44832011)(6486002)(8676002)(66066001)(68736007)(25786009)(6436002)(110136005)(478600001)(97736004)(2906002)(7736002)(256004)(36756003)(5024004)(446003)(14454004)(86362001)(1076003)(11346002)(305945005)(106356001)(54906003)(53936002)(6506007)(14444005)(386003)(6116002)(486006)(26005)(316002)(105586002)(99286004)(3846002);DIR:OUT;SFP:1101;SCL:1;SRVR:VI1PR0401MB2589;H:VI1PR0401MB2496.eurprd04.prod.outlook.com;FPR:;SPF:None;LANG:en;PTR:InfoNoRecords;A:1;MX:1; received-spf: None (protection.outlook.com: nxp.com does not designate permitted sender hosts) x-ms-exchange-senderadcheck: 1 x-microsoft-antispam-message-info: Em5assWyrzr4sfQJ+Mwnf7kdbl60HrN+gP8iwDoFmlo8HxCAP1A/6nUO2NIxy6lf0HsRNb//RLPgo/BYTa4QbEELjaNt9czs8wL7j++pJzZAMCdMRcCOnk8fBr1OTLi40stfXaJ4JyKy7n1YHPY3qgcm86MrqzSAUs/FU6m1FZ6keAtc2oERfE/idWBGcJdJpqChdNy0wVjNfA9cuOyUg6PktLkZWJmPASQNPopbHKsXMyssEAYzuJmUyWmRIWpBJ/lWsrMJ2pWhK1s1EIq2jJBPDmWg+k4gDNEmJhbif7yFlOOmMM/ZalDT6z5bLXrceQE9suh9L/8MwWclChkqt0KaMRAmcjlPPtSHNZP6zjzU7UPD0SUpsTl74JDEEx+eNOsAl1Ej8l1CML25pepFgs/QhiTwIMfUczXyyQgzkIk= Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 45f6358a-3d40-443f-0c21-08d686a526f7 X-MS-Exchange-CrossTenant-originalarrivaltime: 30 Jan 2019 11:21:59.1579 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 686ea1d3-bc2b-4c6f-a92c-d99c5c301635 X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI1PR0401MB2589 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Add support for an MDIO bus multiplexer controlled by a regmap device, like an FPGA. Tested on a NXP LX2160AQDS board which uses the "QIXIS" FPGA attached to the i2c bus. Signed-off-by: Pankaj Bansal --- drivers/net/phy/Makefile | 2 +- drivers/net/phy/mdio-mux-regmap.c | 170 ++++++++++++++++++++++++++++ include/linux/mdio-mux.h | 20 ++++ 3 files changed, 191 insertions(+), 1 deletion(-) diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index f41b14115fde..16145973a42f 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -25,7 +25,7 @@ obj-$(CONFIG_PHYLIB) +=3D libphy.o obj-$(CONFIG_MDIO_BCM_IPROC) +=3D mdio-bcm-iproc.o obj-$(CONFIG_MDIO_BCM_UNIMAC) +=3D mdio-bcm-unimac.o obj-$(CONFIG_MDIO_BITBANG) +=3D mdio-bitbang.o -obj-$(CONFIG_MDIO_BUS_MUX) +=3D mdio-mux.o +obj-$(CONFIG_MDIO_BUS_MUX) +=3D mdio-mux.o mdio-mux-regmap.o obj-$(CONFIG_MDIO_BUS_MUX_BCM_IPROC) +=3D mdio-mux-bcm-iproc.o obj-$(CONFIG_MDIO_BUS_MUX_GPIO) +=3D mdio-mux-gpio.o obj-$(CONFIG_MDIO_BUS_MUX_MMIOREG) +=3D mdio-mux-mmioreg.o diff --git a/drivers/net/phy/mdio-mux-regmap.c b/drivers/net/phy/mdio-mux-r= egmap.c new file mode 100644 index 000000000000..ca63a44da25f --- /dev/null +++ b/drivers/net/phy/mdio-mux-regmap.c @@ -0,0 +1,170 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/* Simple regmap based MDIO MUX driver + * + * Copyright 2018 NXP + * + * Based on mdio-mux-mmioreg.c by Timur Tabi + * + * Author: + * Pankaj Bansal + */ + +#include +#include +#include +#include +#include +#include +#include + +struct mdio_mux_regmap_state { + void *mux_handle; + struct device *dev; + struct regmap *regmap; + u32 mux_reg; + u32 mask; +}; + +/* MDIO multiplexing switch function + * + * This function is called by the mdio-mux layer when it thinks the mdio b= us + * multiplexer needs to switch. + * + * 'current_child' is the current value of the mux register (masked via + * s->mask). + * + * 'desired_child' is the value of the 'reg' property of the target child = MDIO + * node. + * + * The first time this function is called, current_child =3D=3D -1. + * + * If current_child =3D=3D desired_child, then the mux is already set to t= he + * correct bus. + */ +static int mdio_mux_regmap_switch_fn(int current_child, int desired_child, + void *data) +{ + struct mdio_mux_regmap_state *s =3D data; + bool change; + int ret; + + ret =3D regmap_update_bits_check(s->regmap, + s->mux_reg, + s->mask, + desired_child, + &change); + + if (ret) + return ret; + if (change) + dev_dbg(s->dev, "%s %d -> %d\n", __func__, current_child, + desired_child); + return ret; +} + +/** + * mdio_mux_regmap_init - control MDIO bus muxing using regmap constructs. + * @dev: device with which regmap construct is associated. + * @mux_node: mdio bus mux node that contains parent mdio bus phandle. + * This node also contains sub nodes, where each subnode denotes + * a child mdio bus. All the child mdio buses are muxed, i.e. at a + * time only one of the child mdio buses can be used. + * @data: to store the address of data allocated by this function + */ +int mdio_mux_regmap_init(struct device *dev, + struct device_node *mux_node, + void **data) +{ + struct device_node *child; + struct mdio_mux_regmap_state *s; + int ret; + u32 val; + + dev_dbg(dev, "probing node %pOF\n", mux_node); + + s =3D devm_kzalloc(dev, sizeof(*s), GFP_KERNEL); + if (!s) + return -ENOMEM; + + s->regmap =3D dev_get_regmap(dev, NULL); + if (IS_ERR(s->regmap)) { + dev_err(dev, "Failed to get parent regmap\n"); + return PTR_ERR(s->regmap); + } + + ret =3D of_property_read_u32(mux_node, "reg", &s->mux_reg); + if (ret) { + dev_err(dev, "missing or invalid reg property\n"); + return -ENODEV; + } + + /* Test Register read write */ + ret =3D regmap_read(s->regmap, s->mux_reg, &val); + if (ret) { + dev_err(dev, "error while reading reg\n"); + return ret; + } + + ret =3D regmap_write(s->regmap, s->mux_reg, val); + if (ret) { + dev_err(dev, "error while writing reg\n"); + return ret; + } + + ret =3D of_property_read_u32(mux_node, "mux-mask", &s->mask); + if (ret) { + dev_err(dev, "missing or invalid mux-mask property\n"); + return -ENODEV; + } + + /* Verify that the 'reg' property of each child MDIO bus does not + * set any bits outside of the 'mask'. + */ + for_each_available_child_of_node(mux_node, child) { + ret =3D of_property_read_u32(child, "reg", &val); + if (ret) { + dev_err(dev, "mdio-mux child node %pOF is missing a 'reg' property\n", = child); + of_node_put(child); + return -ENODEV; + } + if (val & ~s->mask) { + dev_err(dev, "mdio-mux child node %pOF has a 'reg' value with unmasked = bits\n", child); + of_node_put(child); + return -ENODEV; + } + } + + ret =3D mdio_mux_init(dev, mux_node, mdio_mux_regmap_switch_fn, + &s->mux_handle, s, NULL); + if (ret) { + if (ret !=3D -EPROBE_DEFER) + dev_err(dev, "failed to register mdio-mux bus %pOF\n", mux_node); + return ret; + } + + *data =3D s; + + return 0; +} +EXPORT_SYMBOL_GPL(mdio_mux_regmap_init); + +/** + * mdio_mux_regmap_uninit - relinquish the control of MDIO bus muxing usin= g + * regmap constructs. + * @data: address of data allocated by mdio_mux_regmap_init + */ +int mdio_mux_regmap_uninit(void *data) +{ + struct mdio_mux_regmap_state *s =3D data; + + mdio_mux_uninit(s->mux_handle); + + return 0; +} +EXPORT_SYMBOL_GPL(mdio_mux_regmap_uninit); + +MODULE_AUTHOR("Pankaj Bansal "); +MODULE_DESCRIPTION("regmap based MDIO MUX driver"); +MODULE_LICENSE("GPL v2"); + diff --git a/include/linux/mdio-mux.h b/include/linux/mdio-mux.h index a5d58f221939..231cfa3ba429 100644 --- a/include/linux/mdio-mux.h +++ b/include/linux/mdio-mux.h @@ -29,4 +29,24 @@ int mdio_mux_init(struct device *dev, =20 void mdio_mux_uninit(void *mux_handle); =20 +/** + * mdio_mux_regmap_init - control MDIO bus muxing using regmap constructs. + * @dev: device with which regmap construct is associated. + * @mux_node: mdio bus mux node that contains parent mdio bus phandle. + * This node also contains sub nodes, where each subnode denotes + * a child mdio bus. All the child mdio buses are muxed, i.e. at a + * time only one of the child mdio buses can be used. + * @data: to store the address of data allocated by this function + */ +int mdio_mux_regmap_init(struct device *dev, + struct device_node *mux_node, + void **data); + +/** + * mdio_mux_regmap_uninit - relinquish the control of MDIO bus muxing usin= g + * regmap constructs. + * @data: address of data allocated by mdio_mux_regmap_init + */ +int mdio_mux_regmap_uninit(void *data); + #endif /* __LINUX_MDIO_MUX_H */ --=20 2.17.1