1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (C) 2020 Lubomir Rintel <lkundrak@v3.sk>
6 #include <linux/delay.h>
8 #include <linux/module.h>
9 #include <linux/phy/phy.h>
10 #include <linux/platform_device.h>
12 #define HSIC_CTRL 0x08
13 #define HSIC_ENABLE BIT(7)
14 #define PLL_BYPASS BIT(4)
16 static int mmp3_hsic_phy_init(struct phy
*phy
)
18 void __iomem
*base
= (void __iomem
*)phy_get_drvdata(phy
);
21 hsic_ctrl
= readl_relaxed(base
+ HSIC_CTRL
);
22 hsic_ctrl
|= HSIC_ENABLE
;
23 hsic_ctrl
|= PLL_BYPASS
;
24 writel_relaxed(hsic_ctrl
, base
+ HSIC_CTRL
);
29 static const struct phy_ops mmp3_hsic_phy_ops
= {
30 .init
= mmp3_hsic_phy_init
,
34 static const struct of_device_id mmp3_hsic_phy_of_match
[] = {
35 { .compatible
= "marvell,mmp3-hsic-phy", },
38 MODULE_DEVICE_TABLE(of
, mmp3_hsic_phy_of_match
);
40 static int mmp3_hsic_phy_probe(struct platform_device
*pdev
)
42 struct device
*dev
= &pdev
->dev
;
43 struct phy_provider
*provider
;
44 struct resource
*resource
;
48 resource
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
49 base
= devm_ioremap_resource(dev
, resource
);
51 dev_err(dev
, "failed to remap PHY regs\n");
55 phy
= devm_phy_create(dev
, NULL
, &mmp3_hsic_phy_ops
);
57 dev_err(dev
, "failed to create PHY\n");
61 phy_set_drvdata(phy
, (void *)base
);
62 provider
= devm_of_phy_provider_register(dev
, of_phy_simple_xlate
);
63 if (IS_ERR(provider
)) {
64 dev_err(dev
, "failed to register PHY provider\n");
65 return PTR_ERR(provider
);
71 static struct platform_driver mmp3_hsic_phy_driver
= {
72 .probe
= mmp3_hsic_phy_probe
,
74 .name
= "mmp3-hsic-phy",
75 .of_match_table
= mmp3_hsic_phy_of_match
,
78 module_platform_driver(mmp3_hsic_phy_driver
);
80 MODULE_AUTHOR("Lubomir Rintel <lkundrak@v3.sk>");
81 MODULE_DESCRIPTION("Marvell MMP3 USB HSIC PHY Driver");
82 MODULE_LICENSE("GPL");