1122394Sharti// SPDX-License-Identifier: GPL-2.0 2122394Sharti/* 3122394Sharti * cdns3-starfive.c - StarFive specific Glue layer for Cadence USB Controller 4122394Sharti * 5122394Sharti * Copyright (C) 2023 StarFive Technology Co., Ltd. 6122394Sharti * 7133211Sharti * Author: Minda Chen <minda.chen@starfivetech.com> 8216594Ssyrinx */ 9216594Ssyrinx 10216594Ssyrinx#include <linux/bits.h> 11216594Ssyrinx#include <linux/clk.h> 12216594Ssyrinx#include <linux/module.h> 13216594Ssyrinx#include <linux/mfd/syscon.h> 14133211Sharti#include <linux/kernel.h> 15133211Sharti#include <linux/platform_device.h> 16133211Sharti#include <linux/io.h> 17133211Sharti#include <linux/of_platform.h> 18133211Sharti#include <linux/reset.h> 19122394Sharti#include <linux/regmap.h> 20122394Sharti#include <linux/usb/otg.h> 21122394Sharti#include "core.h" 22133211Sharti 23133211Sharti#define USB_STRAP_HOST BIT(17) 24133211Sharti#define USB_STRAP_DEVICE BIT(18) 25133211Sharti#define USB_STRAP_MASK GENMASK(18, 16) 26133211Sharti 27133211Sharti#define USB_SUSPENDM_HOST BIT(19) 28133211Sharti#define USB_SUSPENDM_MASK BIT(19) 29133211Sharti 30133211Sharti#define USB_MISC_CFG_MASK GENMASK(23, 20) 31133211Sharti#define USB_SUSPENDM_BYPS BIT(20) 32133211Sharti#define USB_PLL_EN BIT(22) 33133211Sharti#define USB_REFCLK_MODE BIT(23) 34122394Sharti 35156066Shartistruct cdns_starfive { 36122394Sharti struct device *dev; 37122394Sharti struct regmap *stg_syscon; 38122394Sharti struct reset_control *resets; 39216294Ssyrinx struct clk_bulk_data *clks; 40216294Ssyrinx int num_clks; 41122394Sharti u32 stg_usb_mode; 42122394Sharti}; 43124861Sharti 44150920Shartistatic void cdns_mode_init(struct platform_device *pdev, 45122394Sharti struct cdns_starfive *data) 46122394Sharti{ 47122394Sharti enum usb_dr_mode mode; 48122394Sharti 49122394Sharti regmap_update_bits(data->stg_syscon, data->stg_usb_mode, 50122394Sharti USB_MISC_CFG_MASK, 51122394Sharti USB_SUSPENDM_BYPS | USB_PLL_EN | USB_REFCLK_MODE); 52122394Sharti 53122394Sharti /* dr mode setting */ 54122394Sharti mode = usb_get_dr_mode(&pdev->dev); 55122394Sharti 56122394Sharti switch (mode) { 57122394Sharti case USB_DR_MODE_HOST: 58145557Sharti regmap_update_bits(data->stg_syscon, 59145557Sharti data->stg_usb_mode, 60145557Sharti USB_STRAP_MASK, 61145557Sharti USB_STRAP_HOST); 62145557Sharti regmap_update_bits(data->stg_syscon, 63156066Sharti data->stg_usb_mode, 64122394Sharti USB_SUSPENDM_MASK, 65122394Sharti USB_SUSPENDM_HOST); 66122394Sharti break; 67122394Sharti 68122394Sharti case USB_DR_MODE_PERIPHERAL: 69122394Sharti regmap_update_bits(data->stg_syscon, data->stg_usb_mode, 70122394Sharti USB_STRAP_MASK, USB_STRAP_DEVICE); 71216294Ssyrinx regmap_update_bits(data->stg_syscon, data->stg_usb_mode, 72122394Sharti USB_SUSPENDM_MASK, 0); 73146525Sharti break; 74146525Sharti default: 75122394Sharti break; 76122394Sharti } 77122394Sharti} 78122394Sharti 79122394Shartistatic int cdns_clk_rst_init(struct cdns_starfive *data) 80122394Sharti{ 81122394Sharti int ret; 82122394Sharti 83122394Sharti ret = clk_bulk_prepare_enable(data->num_clks, data->clks); 84122394Sharti if (ret) 85122394Sharti return dev_err_probe(data->dev, ret, 86122394Sharti "failed to enable clocks\n"); 87122394Sharti 88122394Sharti ret = reset_control_deassert(data->resets); 89122394Sharti if (ret) { 90122394Sharti dev_err(data->dev, "failed to reset clocks\n"); 91122394Sharti goto err_clk_init; 92122394Sharti } 93122394Sharti 94122394Sharti return ret; 95124861Sharti 96122394Shartierr_clk_init: 97122394Sharti clk_bulk_disable_unprepare(data->num_clks, data->clks); 98122394Sharti return ret; 99216294Ssyrinx} 100216294Ssyrinx 101216294Ssyrinxstatic void cdns_clk_rst_deinit(struct cdns_starfive *data) 102216294Ssyrinx{ 103216294Ssyrinx reset_control_assert(data->resets); 104122394Sharti clk_bulk_disable_unprepare(data->num_clks, data->clks); 105122394Sharti} 106122394Sharti 107216594Ssyrinxstatic int cdns_starfive_probe(struct platform_device *pdev) 108216594Ssyrinx{ 109122394Sharti struct device *dev = &pdev->dev; 110122394Sharti struct cdns_starfive *data; 111122394Sharti unsigned int args; 112122394Sharti int ret; 113122394Sharti 114122394Sharti data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 115122394Sharti if (!data) 116122394Sharti return -ENOMEM; 117122394Sharti 118122394Sharti data->dev = dev; 119122394Sharti 120122394Sharti data->stg_syscon = 121216294Ssyrinx syscon_regmap_lookup_by_phandle_args(pdev->dev.of_node, 122216294Ssyrinx "starfive,stg-syscon", 1, &args); 123216294Ssyrinx 124216294Ssyrinx if (IS_ERR(data->stg_syscon)) 125216294Ssyrinx return dev_err_probe(dev, PTR_ERR(data->stg_syscon), 126216294Ssyrinx "Failed to parse starfive,stg-syscon\n"); 127216294Ssyrinx 128216294Ssyrinx data->stg_usb_mode = args; 129216294Ssyrinx 130216294Ssyrinx data->num_clks = devm_clk_bulk_get_all(data->dev, &data->clks); 131216294Ssyrinx if (data->num_clks < 0) 132216294Ssyrinx return dev_err_probe(data->dev, -ENODEV, 133216294Ssyrinx "Failed to get clocks\n"); 134216294Ssyrinx 135216294Ssyrinx data->resets = devm_reset_control_array_get_exclusive(data->dev); 136216294Ssyrinx if (IS_ERR(data->resets)) 137216294Ssyrinx return dev_err_probe(data->dev, PTR_ERR(data->resets), 138216294Ssyrinx "Failed to get resets"); 139216294Ssyrinx 140216294Ssyrinx cdns_mode_init(pdev, data); 141216294Ssyrinx ret = cdns_clk_rst_init(data); 142216294Ssyrinx if (ret) 143216294Ssyrinx return ret; 144122394Sharti 145122394Sharti ret = of_platform_populate(dev->of_node, NULL, NULL, dev); 146122394Sharti if (ret) { 147122394Sharti dev_err(dev, "Failed to create children\n"); 148122394Sharti cdns_clk_rst_deinit(data); 149122394Sharti return ret; 150122394Sharti } 151122394Sharti 152122394Sharti device_set_wakeup_capable(dev, true); 153122394Sharti pm_runtime_set_active(dev); 154122394Sharti pm_runtime_enable(dev); 155122394Sharti platform_set_drvdata(pdev, data); 156122394Sharti 157122394Sharti return 0; 158122394Sharti} 159122394Sharti 160122394Shartistatic int cdns_starfive_remove_core(struct device *dev, void *c) 161122394Sharti{ 162122394Sharti struct platform_device *pdev = to_platform_device(dev); 163122394Sharti 164122394Sharti platform_device_unregister(pdev); 165122394Sharti 166122394Sharti return 0; 167122394Sharti} 168122394Sharti 169122394Shartistatic void cdns_starfive_remove(struct platform_device *pdev) 170216294Ssyrinx{ 171216294Ssyrinx struct device *dev = &pdev->dev; 172216294Ssyrinx struct cdns_starfive *data = dev_get_drvdata(dev); 173122394Sharti 174122394Sharti pm_runtime_get_sync(dev); 175122394Sharti device_for_each_child(dev, NULL, cdns_starfive_remove_core); 176216294Ssyrinx 177122394Sharti pm_runtime_disable(dev); 178124861Sharti pm_runtime_put_noidle(dev); 179122394Sharti cdns_clk_rst_deinit(data); 180122394Sharti platform_set_drvdata(pdev, NULL); 181124861Sharti} 182122394Sharti 183122394Sharti#ifdef CONFIG_PM 184122394Shartistatic int cdns_starfive_runtime_resume(struct device *dev) 185122394Sharti{ 186122394Sharti struct cdns_starfive *data = dev_get_drvdata(dev); 187122394Sharti 188122394Sharti return clk_bulk_prepare_enable(data->num_clks, data->clks); 189122394Sharti} 190122394Sharti 191122394Shartistatic int cdns_starfive_runtime_suspend(struct device *dev) 192122394Sharti{ 193122394Sharti struct cdns_starfive *data = dev_get_drvdata(dev); 194122394Sharti 195122394Sharti clk_bulk_disable_unprepare(data->num_clks, data->clks); 196122394Sharti 197122394Sharti return 0; 198122394Sharti} 199122394Sharti 200216294Ssyrinx#ifdef CONFIG_PM_SLEEP 201216294Ssyrinxstatic int cdns_starfive_resume(struct device *dev) 202216294Ssyrinx{ 203216294Ssyrinx struct cdns_starfive *data = dev_get_drvdata(dev); 204216294Ssyrinx 205216294Ssyrinx return cdns_clk_rst_init(data); 206122394Sharti} 207122394Sharti 208122394Shartistatic int cdns_starfive_suspend(struct device *dev) 209122394Sharti{ 210122394Sharti struct cdns_starfive *data = dev_get_drvdata(dev); 211122394Sharti 212122394Sharti cdns_clk_rst_deinit(data); 213216294Ssyrinx 214216294Ssyrinx return 0; 215216294Ssyrinx} 216122394Sharti#endif 217122394Sharti#endif 218122394Sharti 219122394Shartistatic const struct dev_pm_ops cdns_starfive_pm_ops = { 220122394Sharti SET_RUNTIME_PM_OPS(cdns_starfive_runtime_suspend, 221216294Ssyrinx cdns_starfive_runtime_resume, NULL) 222122394Sharti SET_SYSTEM_SLEEP_PM_OPS(cdns_starfive_suspend, cdns_starfive_resume) 223122394Sharti}; 224122394Sharti 225122394Shartistatic const struct of_device_id cdns_starfive_of_match[] = { 226122394Sharti { .compatible = "starfive,jh7110-usb", }, 227122394Sharti { /* sentinel */ } 228145557Sharti}; 229145557ShartiMODULE_DEVICE_TABLE(of, cdns_starfive_of_match); 230145557Sharti 231145557Shartistatic struct platform_driver cdns_starfive_driver = { 232145557Sharti .probe = cdns_starfive_probe, 233124861Sharti .remove_new = cdns_starfive_remove, 234124861Sharti .driver = { 235124861Sharti .name = "cdns3-starfive", 236124861Sharti .of_match_table = cdns_starfive_of_match, 237124861Sharti .pm = &cdns_starfive_pm_ops, 238124861Sharti }, 239122394Sharti}; 240122394Shartimodule_platform_driver(cdns_starfive_driver); 241122394Sharti 242122394ShartiMODULE_ALIAS("platform:cdns3-starfive"); 243122394ShartiMODULE_LICENSE("GPL v2"); 244122394ShartiMODULE_DESCRIPTION("Cadence USB3 StarFive Glue Layer"); 245122394Sharti