brintos

brintos / linux-shallow public Read only

0
0
Text · 7.7 KiB · 5b71deb Raw
291 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (C) 2011 Marvell International Ltd. All rights reserved.4 * Copyright (C) 2018,2019 Lubomir Rintel <lkundrak@v3.sk>5 */6 7#include <linux/delay.h>8#include <linux/io.h>9#include <linux/mod_devicetable.h>10#include <linux/module.h>11#include <linux/phy/phy.h>12#include <linux/platform_device.h>13#include <linux/soc/mmp/cputype.h>14 15#define USB2_PLL_REG0		0x416#define USB2_PLL_REG1		0x817#define USB2_TX_REG0		0x1018#define USB2_TX_REG1		0x1419#define USB2_TX_REG2		0x1820#define USB2_RX_REG0		0x2021#define USB2_RX_REG1		0x2422#define USB2_RX_REG2		0x2823#define USB2_ANA_REG0		0x3024#define USB2_ANA_REG1		0x3425#define USB2_ANA_REG2		0x3826#define USB2_DIG_REG0		0x3C27#define USB2_DIG_REG1		0x4028#define USB2_DIG_REG2		0x4429#define USB2_DIG_REG3		0x4830#define USB2_TEST_REG0		0x4C31#define USB2_TEST_REG1		0x5032#define USB2_TEST_REG2		0x5433#define USB2_CHARGER_REG0	0x5834#define USB2_OTG_REG0		0x5C35#define USB2_PHY_MON0		0x6036#define USB2_RESETVE_REG0	0x6437#define USB2_ICID_REG0		0x7838#define USB2_ICID_REG1		0x7C39 40/* USB2_PLL_REG0 */41 42/* This is for Ax stepping */43#define USB2_PLL_FBDIV_SHIFT_MMP3		044#define USB2_PLL_FBDIV_MASK_MMP3		(0xFF << 0)45 46#define USB2_PLL_REFDIV_SHIFT_MMP3		847#define USB2_PLL_REFDIV_MASK_MMP3		(0xF << 8)48 49#define USB2_PLL_VDD12_SHIFT_MMP3		1250#define USB2_PLL_VDD18_SHIFT_MMP3		1451 52/* This is for B0 stepping */53#define USB2_PLL_FBDIV_SHIFT_MMP3_B0		054#define USB2_PLL_REFDIV_SHIFT_MMP3_B0		955#define USB2_PLL_VDD18_SHIFT_MMP3_B0		1456#define USB2_PLL_FBDIV_MASK_MMP3_B0		0x01FF57#define USB2_PLL_REFDIV_MASK_MMP3_B0		0x3E0058 59#define USB2_PLL_CAL12_SHIFT_MMP3		060#define USB2_PLL_CALI12_MASK_MMP3		(0x3 << 0)61 62#define USB2_PLL_VCOCAL_START_SHIFT_MMP3	263 64#define USB2_PLL_KVCO_SHIFT_MMP3		465#define USB2_PLL_KVCO_MASK_MMP3			(0x7<<4)66 67#define USB2_PLL_ICP_SHIFT_MMP3			868#define USB2_PLL_ICP_MASK_MMP3			(0x7<<8)69 70#define USB2_PLL_LOCK_BYPASS_SHIFT_MMP3		1271 72#define USB2_PLL_PU_PLL_SHIFT_MMP3		1373#define USB2_PLL_PU_PLL_MASK			(0x1 << 13)74 75#define USB2_PLL_READY_MASK_MMP3		(0x1 << 15)76 77/* USB2_TX_REG0 */78#define USB2_TX_IMPCAL_VTH_SHIFT_MMP3		879#define USB2_TX_IMPCAL_VTH_MASK_MMP3		(0x7 << 8)80 81#define USB2_TX_RCAL_START_SHIFT_MMP3		1382 83/* USB2_TX_REG1 */84#define USB2_TX_CK60_PHSEL_SHIFT_MMP3		085#define USB2_TX_CK60_PHSEL_MASK_MMP3		(0xf << 0)86 87#define USB2_TX_AMP_SHIFT_MMP3			488#define USB2_TX_AMP_MASK_MMP3			(0x7 << 4)89 90#define USB2_TX_VDD12_SHIFT_MMP3		891#define USB2_TX_VDD12_MASK_MMP3			(0x3 << 8)92 93/* USB2_TX_REG2 */94#define USB2_TX_DRV_SLEWRATE_SHIFT		1095 96/* USB2_RX_REG0 */97#define USB2_RX_SQ_THRESH_SHIFT_MMP3		498#define USB2_RX_SQ_THRESH_MASK_MMP3		(0xf << 4)99 100#define USB2_RX_SQ_LENGTH_SHIFT_MMP3		10101#define USB2_RX_SQ_LENGTH_MASK_MMP3		(0x3 << 10)102 103/* USB2_ANA_REG1*/104#define USB2_ANA_PU_ANA_SHIFT_MMP3		14105 106/* USB2_OTG_REG0 */107#define USB2_OTG_PU_OTG_SHIFT_MMP3		3108 109struct mmp3_usb_phy {110	struct phy *phy;111	void __iomem *base;112};113 114static unsigned int u2o_get(void __iomem *base, unsigned int offset)115{116	return readl_relaxed(base + offset);117}118 119static void u2o_set(void __iomem *base, unsigned int offset,120		unsigned int value)121{122	u32 reg;123 124	reg = readl_relaxed(base + offset);125	reg |= value;126	writel_relaxed(reg, base + offset);127	readl_relaxed(base + offset);128}129 130static void u2o_clear(void __iomem *base, unsigned int offset,131		unsigned int value)132{133	u32 reg;134 135	reg = readl_relaxed(base + offset);136	reg &= ~value;137	writel_relaxed(reg, base + offset);138	readl_relaxed(base + offset);139}140 141static int mmp3_usb_phy_init(struct phy *phy)142{143	struct mmp3_usb_phy *mmp3_usb_phy = phy_get_drvdata(phy);144	void __iomem *base = mmp3_usb_phy->base;145 146	if (cpu_is_mmp3_a0()) {147		u2o_clear(base, USB2_PLL_REG0, (USB2_PLL_FBDIV_MASK_MMP3148			| USB2_PLL_REFDIV_MASK_MMP3));149		u2o_set(base, USB2_PLL_REG0,150			0xd << USB2_PLL_REFDIV_SHIFT_MMP3151			| 0xf0 << USB2_PLL_FBDIV_SHIFT_MMP3);152	} else if (cpu_is_mmp3_b0()) {153		u2o_clear(base, USB2_PLL_REG0, USB2_PLL_REFDIV_MASK_MMP3_B0154			| USB2_PLL_FBDIV_MASK_MMP3_B0);155		u2o_set(base, USB2_PLL_REG0,156			0xd << USB2_PLL_REFDIV_SHIFT_MMP3_B0157			| 0xf0 << USB2_PLL_FBDIV_SHIFT_MMP3_B0);158	} else {159		dev_err(&phy->dev, "unsupported silicon revision\n");160		return -ENODEV;161	}162 163	u2o_clear(base, USB2_PLL_REG1, USB2_PLL_PU_PLL_MASK164		| USB2_PLL_ICP_MASK_MMP3165		| USB2_PLL_KVCO_MASK_MMP3166		| USB2_PLL_CALI12_MASK_MMP3);167	u2o_set(base, USB2_PLL_REG1, 1 << USB2_PLL_PU_PLL_SHIFT_MMP3168		| 1 << USB2_PLL_LOCK_BYPASS_SHIFT_MMP3169		| 3 << USB2_PLL_ICP_SHIFT_MMP3170		| 3 << USB2_PLL_KVCO_SHIFT_MMP3171		| 3 << USB2_PLL_CAL12_SHIFT_MMP3);172 173	u2o_clear(base, USB2_TX_REG0, USB2_TX_IMPCAL_VTH_MASK_MMP3);174	u2o_set(base, USB2_TX_REG0, 2 << USB2_TX_IMPCAL_VTH_SHIFT_MMP3);175 176	u2o_clear(base, USB2_TX_REG1, USB2_TX_VDD12_MASK_MMP3177		| USB2_TX_AMP_MASK_MMP3178		| USB2_TX_CK60_PHSEL_MASK_MMP3);179	u2o_set(base, USB2_TX_REG1, 3 << USB2_TX_VDD12_SHIFT_MMP3180		| 4 << USB2_TX_AMP_SHIFT_MMP3181		| 4 << USB2_TX_CK60_PHSEL_SHIFT_MMP3);182 183	u2o_clear(base, USB2_TX_REG2, 3 << USB2_TX_DRV_SLEWRATE_SHIFT);184	u2o_set(base, USB2_TX_REG2, 2 << USB2_TX_DRV_SLEWRATE_SHIFT);185 186	u2o_clear(base, USB2_RX_REG0, USB2_RX_SQ_THRESH_MASK_MMP3);187	u2o_set(base, USB2_RX_REG0, 0xa << USB2_RX_SQ_THRESH_SHIFT_MMP3);188 189	u2o_set(base, USB2_ANA_REG1, 0x1 << USB2_ANA_PU_ANA_SHIFT_MMP3);190 191	u2o_set(base, USB2_OTG_REG0, 0x1 << USB2_OTG_PU_OTG_SHIFT_MMP3);192 193	return 0;194}195 196static int mmp3_usb_phy_calibrate(struct phy *phy)197{198	struct mmp3_usb_phy *mmp3_usb_phy = phy_get_drvdata(phy);199	void __iomem *base = mmp3_usb_phy->base;200	int loops;201 202	/*203	 * PLL VCO and TX Impedance Calibration Timing:204	 *205	 *                _____________________________________206	 * PU  __________|207	 *                        _____________________________208	 * VCOCAL START _________|209	 *                                 ___210	 * REG_RCAL_START ________________|   |________|_______211	 *               | 200us | 400us  | 40| 400us  | USB PHY READY212	 */213 214	udelay(200);215	u2o_set(base, USB2_PLL_REG1, 1 << USB2_PLL_VCOCAL_START_SHIFT_MMP3);216	udelay(400);217	u2o_set(base, USB2_TX_REG0, 1 << USB2_TX_RCAL_START_SHIFT_MMP3);218	udelay(40);219	u2o_clear(base, USB2_TX_REG0, 1 << USB2_TX_RCAL_START_SHIFT_MMP3);220	udelay(400);221 222	loops = 0;223	while ((u2o_get(base, USB2_PLL_REG1) & USB2_PLL_READY_MASK_MMP3) == 0) {224		mdelay(1);225		loops++;226		if (loops > 100) {227			dev_err(&phy->dev, "PLL_READY not set after 100mS.\n");228			return -ETIMEDOUT;229		}230	}231 232	return 0;233}234 235static const struct phy_ops mmp3_usb_phy_ops = {236	.init		= mmp3_usb_phy_init,237	.calibrate	= mmp3_usb_phy_calibrate,238	.owner		= THIS_MODULE,239};240 241static const struct of_device_id mmp3_usb_phy_of_match[] = {242	{ .compatible = "marvell,mmp3-usb-phy", },243	{ },244};245MODULE_DEVICE_TABLE(of, mmp3_usb_phy_of_match);246 247static int mmp3_usb_phy_probe(struct platform_device *pdev)248{249	struct device *dev = &pdev->dev;250	struct mmp3_usb_phy *mmp3_usb_phy;251	struct phy_provider *provider;252 253	mmp3_usb_phy = devm_kzalloc(dev, sizeof(*mmp3_usb_phy), GFP_KERNEL);254	if (!mmp3_usb_phy)255		return -ENOMEM;256 257	mmp3_usb_phy->base = devm_platform_ioremap_resource(pdev, 0);258	if (IS_ERR(mmp3_usb_phy->base)) {259		dev_err(dev, "failed to remap PHY regs\n");260		return PTR_ERR(mmp3_usb_phy->base);261	}262 263	mmp3_usb_phy->phy = devm_phy_create(dev, NULL, &mmp3_usb_phy_ops);264	if (IS_ERR(mmp3_usb_phy->phy)) {265		dev_err(dev, "failed to create PHY\n");266		return PTR_ERR(mmp3_usb_phy->phy);267	}268 269	phy_set_drvdata(mmp3_usb_phy->phy, mmp3_usb_phy);270	provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);271	if (IS_ERR(provider)) {272		dev_err(dev, "failed to register PHY provider\n");273		return PTR_ERR(provider);274	}275 276	return 0;277}278 279static struct platform_driver mmp3_usb_phy_driver = {280	.probe		= mmp3_usb_phy_probe,281	.driver		= {282		.name	= "mmp3-usb-phy",283		.of_match_table = mmp3_usb_phy_of_match,284	},285};286module_platform_driver(mmp3_usb_phy_driver);287 288MODULE_AUTHOR("Lubomir Rintel <lkundrak@v3.sk>");289MODULE_DESCRIPTION("Marvell MMP3 USB PHY Driver");290MODULE_LICENSE("GPL v2");291