brintos

brintos / linux-shallow public Read only

0
0
Text · 5.9 KiB · 9f995e1 Raw
246 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Broadcom Northstar USB 3.0 PHY Driver4 *5 * Copyright (C) 2016 Rafał Miłecki <rafal@milecki.pl>6 * Copyright (C) 2016 Broadcom7 *8 * All magic values used for initialization (and related comments) were obtained9 * from Broadcom's SDK:10 * Copyright (c) Broadcom Corp, 201211 */12 13#include <linux/bcma/bcma.h>14#include <linux/delay.h>15#include <linux/err.h>16#include <linux/iopoll.h>17#include <linux/mdio.h>18#include <linux/module.h>19#include <linux/of.h>20#include <linux/of_address.h>21#include <linux/platform_device.h>22#include <linux/phy/phy.h>23#include <linux/property.h>24#include <linux/slab.h>25 26#define BCM_NS_USB3_PHY_BASE_ADDR_REG	0x1f27#define BCM_NS_USB3_PHY_PLL30_BLOCK	0x800028#define BCM_NS_USB3_PHY_TX_PMD_BLOCK	0x804029#define BCM_NS_USB3_PHY_PIPE_BLOCK	0x806030 31/* Registers of PLL30 block */32#define BCM_NS_USB3_PLL_CONTROL		0x0133#define BCM_NS_USB3_PLLA_CONTROL0	0x0a34#define BCM_NS_USB3_PLLA_CONTROL1	0x0b35 36/* Registers of TX PMD block */37#define BCM_NS_USB3_TX_PMD_CONTROL1	0x0138 39/* Registers of PIPE block */40#define BCM_NS_USB3_LFPS_CMP		0x0241#define BCM_NS_USB3_LFPS_DEGLITCH	0x0342 43enum bcm_ns_family {44	BCM_NS_UNKNOWN,45	BCM_NS_AX,46	BCM_NS_BX,47};48 49struct bcm_ns_usb3 {50	struct device *dev;51	enum bcm_ns_family family;52	void __iomem *dmp;53	struct mdio_device *mdiodev;54	struct phy *phy;55};56 57static const struct of_device_id bcm_ns_usb3_id_table[] = {58	{59		.compatible = "brcm,ns-ax-usb3-phy",60		.data = (int *)BCM_NS_AX,61	},62	{63		.compatible = "brcm,ns-bx-usb3-phy",64		.data = (int *)BCM_NS_BX,65	},66	{},67};68 69static int bcm_ns_usb3_mdio_phy_write(struct bcm_ns_usb3 *usb3, u16 reg,70				      u16 value);71 72static int bcm_ns_usb3_phy_init_ns_bx(struct bcm_ns_usb3 *usb3)73{74	int err;75 76	/* USB3 PLL Block */77	err = bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PHY_BASE_ADDR_REG,78					 BCM_NS_USB3_PHY_PLL30_BLOCK);79	if (err < 0)80		return err;81 82	/* Assert Ana_Pllseq start */83	bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PLL_CONTROL, 0x1000);84 85	/* Assert CML Divider ratio to 26 */86	bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PLLA_CONTROL0, 0x6400);87 88	/* Asserting PLL Reset */89	bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PLLA_CONTROL1, 0xc000);90 91	/* Deaaserting PLL Reset */92	bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PLLA_CONTROL1, 0x8000);93 94	/* Deasserting USB3 system reset */95	writel(0, usb3->dmp + BCMA_RESET_CTL);96 97	/* PLL frequency monitor enable */98	bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PLL_CONTROL, 0x9000);99 100	/* PIPE Block */101	bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PHY_BASE_ADDR_REG,102				   BCM_NS_USB3_PHY_PIPE_BLOCK);103 104	/* CMPMAX & CMPMINTH setting */105	bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_LFPS_CMP, 0xf30d);106 107	/* DEGLITCH MIN & MAX setting */108	bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_LFPS_DEGLITCH, 0x6302);109 110	/* TXPMD block */111	bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PHY_BASE_ADDR_REG,112				   BCM_NS_USB3_PHY_TX_PMD_BLOCK);113 114	/* Enabling SSC */115	bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_TX_PMD_CONTROL1, 0x1003);116 117	return 0;118}119 120static int bcm_ns_usb3_phy_init_ns_ax(struct bcm_ns_usb3 *usb3)121{122	int err;123 124	/* PLL30 block */125	err = bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PHY_BASE_ADDR_REG,126					 BCM_NS_USB3_PHY_PLL30_BLOCK);127	if (err < 0)128		return err;129 130	bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PLLA_CONTROL0, 0x6400);131 132	bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PHY_BASE_ADDR_REG, 0x80e0);133 134	bcm_ns_usb3_mdio_phy_write(usb3, 0x02, 0x009c);135 136	/* Enable SSC */137	bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PHY_BASE_ADDR_REG,138				   BCM_NS_USB3_PHY_TX_PMD_BLOCK);139 140	bcm_ns_usb3_mdio_phy_write(usb3, 0x02, 0x21d3);141 142	bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_TX_PMD_CONTROL1, 0x1003);143 144	/* Deasserting USB3 system reset */145	writel(0, usb3->dmp + BCMA_RESET_CTL);146 147	return 0;148}149 150static int bcm_ns_usb3_phy_init(struct phy *phy)151{152	struct bcm_ns_usb3 *usb3 = phy_get_drvdata(phy);153	int err;154 155	/* Perform USB3 system soft reset */156	writel(BCMA_RESET_CTL_RESET, usb3->dmp + BCMA_RESET_CTL);157 158	switch (usb3->family) {159	case BCM_NS_AX:160		err = bcm_ns_usb3_phy_init_ns_ax(usb3);161		break;162	case BCM_NS_BX:163		err = bcm_ns_usb3_phy_init_ns_bx(usb3);164		break;165	default:166		WARN_ON(1);167		err = -ENOTSUPP;168	}169 170	return err;171}172 173static const struct phy_ops ops = {174	.init		= bcm_ns_usb3_phy_init,175	.owner		= THIS_MODULE,176};177 178/**************************************************179 * MDIO driver code180 **************************************************/181 182static int bcm_ns_usb3_mdio_phy_write(struct bcm_ns_usb3 *usb3, u16 reg,183				      u16 value)184{185	struct mdio_device *mdiodev = usb3->mdiodev;186 187	return mdiodev_write(mdiodev, reg, value);188}189 190static int bcm_ns_usb3_mdio_probe(struct mdio_device *mdiodev)191{192	struct device *dev = &mdiodev->dev;193	struct phy_provider *phy_provider;194	struct device_node *syscon_np;195	struct bcm_ns_usb3 *usb3;196	struct resource res;197	int err;198 199	usb3 = devm_kzalloc(dev, sizeof(*usb3), GFP_KERNEL);200	if (!usb3)201		return -ENOMEM;202 203	usb3->dev = dev;204	usb3->mdiodev = mdiodev;205 206	usb3->family = (enum bcm_ns_family)device_get_match_data(dev);207 208	syscon_np = of_parse_phandle(dev->of_node, "usb3-dmp-syscon", 0);209	err = of_address_to_resource(syscon_np, 0, &res);210	of_node_put(syscon_np);211	if (err)212		return err;213 214	usb3->dmp = devm_ioremap_resource(dev, &res);215	if (IS_ERR(usb3->dmp))216		return PTR_ERR(usb3->dmp);217 218	usb3->phy = devm_phy_create(dev, NULL, &ops);219	if (IS_ERR(usb3->phy)) {220		dev_err(dev, "Failed to create PHY\n");221		return PTR_ERR(usb3->phy);222	}223 224	phy_set_drvdata(usb3->phy, usb3);225 226	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);227 228	return PTR_ERR_OR_ZERO(phy_provider);229}230 231static struct mdio_driver bcm_ns_usb3_mdio_driver = {232	.mdiodrv = {233		.driver = {234			.name = "bcm_ns_mdio_usb3",235			.of_match_table = bcm_ns_usb3_id_table,236		},237	},238	.probe = bcm_ns_usb3_mdio_probe,239};240 241mdio_module_driver(bcm_ns_usb3_mdio_driver);242 243MODULE_DESCRIPTION("Broadcom Northstar USB 3.0 PHY Driver");244MODULE_LICENSE("GPL v2");245MODULE_DEVICE_TABLE(of, bcm_ns_usb3_id_table);246