cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ux500.c (8516B)


      1// SPDX-License-Identifier: GPL-2.0+
      2/*
      3 * Copyright (C) 2010 ST-Ericsson AB
      4 * Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>
      5 *
      6 * Based on omap2430.c
      7 */
      8
      9#include <linux/module.h>
     10#include <linux/kernel.h>
     11#include <linux/clk.h>
     12#include <linux/err.h>
     13#include <linux/io.h>
     14#include <linux/of.h>
     15#include <linux/platform_device.h>
     16#include <linux/usb/musb-ux500.h>
     17
     18#include "musb_core.h"
     19
     20static const struct musb_hdrc_config ux500_musb_hdrc_config = {
     21	.multipoint	= true,
     22	.dyn_fifo	= true,
     23	.num_eps	= 16,
     24	.ram_bits	= 16,
     25};
     26
     27struct ux500_glue {
     28	struct device		*dev;
     29	struct platform_device	*musb;
     30	struct clk		*clk;
     31};
     32#define glue_to_musb(g)	platform_get_drvdata(g->musb)
     33
     34static void ux500_musb_set_vbus(struct musb *musb, int is_on)
     35{
     36	u8            devctl;
     37	unsigned long timeout = jiffies + msecs_to_jiffies(1000);
     38	/* HDRC controls CPEN, but beware current surges during device
     39	 * connect.  They can trigger transient overcurrent conditions
     40	 * that must be ignored.
     41	 */
     42
     43	devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
     44
     45	if (is_on) {
     46		if (musb->xceiv->otg->state == OTG_STATE_A_IDLE) {
     47			/* start the session */
     48			devctl |= MUSB_DEVCTL_SESSION;
     49			musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
     50			/*
     51			 * Wait for the musb to set as A device to enable the
     52			 * VBUS
     53			 */
     54			while (musb_readb(musb->mregs, MUSB_DEVCTL) & 0x80) {
     55
     56				if (time_after(jiffies, timeout)) {
     57					dev_err(musb->controller,
     58					"configured as A device timeout");
     59					break;
     60				}
     61			}
     62
     63		} else {
     64			musb->is_active = 1;
     65			musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
     66			devctl |= MUSB_DEVCTL_SESSION;
     67			MUSB_HST_MODE(musb);
     68		}
     69	} else {
     70		musb->is_active = 0;
     71
     72		/* NOTE: we're skipping A_WAIT_VFALL -> A_IDLE and jumping
     73		 * right to B_IDLE...
     74		 */
     75		devctl &= ~MUSB_DEVCTL_SESSION;
     76		MUSB_DEV_MODE(musb);
     77	}
     78	musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
     79
     80	/*
     81	 * Devctl values will be updated after vbus goes below
     82	 * session_valid. The time taken depends on the capacitance
     83	 * on VBUS line. The max discharge time can be upto 1 sec
     84	 * as per the spec. Typically on our platform, it is 200ms
     85	 */
     86	if (!is_on)
     87		mdelay(200);
     88
     89	dev_dbg(musb->controller, "VBUS %s, devctl %02x\n",
     90		usb_otg_state_string(musb->xceiv->otg->state),
     91		musb_readb(musb->mregs, MUSB_DEVCTL));
     92}
     93
     94static int musb_otg_notifications(struct notifier_block *nb,
     95		unsigned long event, void *unused)
     96{
     97	struct musb *musb = container_of(nb, struct musb, nb);
     98
     99	dev_dbg(musb->controller, "musb_otg_notifications %ld %s\n",
    100			event, usb_otg_state_string(musb->xceiv->otg->state));
    101
    102	switch (event) {
    103	case UX500_MUSB_ID:
    104		dev_dbg(musb->controller, "ID GND\n");
    105		ux500_musb_set_vbus(musb, 1);
    106		break;
    107	case UX500_MUSB_VBUS:
    108		dev_dbg(musb->controller, "VBUS Connect\n");
    109		break;
    110	case UX500_MUSB_NONE:
    111		dev_dbg(musb->controller, "VBUS Disconnect\n");
    112		if (is_host_active(musb))
    113			ux500_musb_set_vbus(musb, 0);
    114		else
    115			musb->xceiv->otg->state = OTG_STATE_B_IDLE;
    116		break;
    117	default:
    118		dev_dbg(musb->controller, "ID float\n");
    119		return NOTIFY_DONE;
    120	}
    121	return NOTIFY_OK;
    122}
    123
    124static irqreturn_t ux500_musb_interrupt(int irq, void *__hci)
    125{
    126	unsigned long   flags;
    127	irqreturn_t     retval = IRQ_NONE;
    128	struct musb     *musb = __hci;
    129
    130	spin_lock_irqsave(&musb->lock, flags);
    131
    132	musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
    133	musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX);
    134	musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX);
    135
    136	if (musb->int_usb || musb->int_tx || musb->int_rx)
    137		retval = musb_interrupt(musb);
    138
    139	spin_unlock_irqrestore(&musb->lock, flags);
    140
    141	return retval;
    142}
    143
    144static int ux500_musb_init(struct musb *musb)
    145{
    146	int status;
    147
    148	musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
    149	if (IS_ERR_OR_NULL(musb->xceiv)) {
    150		pr_err("HS USB OTG: no transceiver configured\n");
    151		return -EPROBE_DEFER;
    152	}
    153
    154	musb->nb.notifier_call = musb_otg_notifications;
    155	status = usb_register_notifier(musb->xceiv, &musb->nb);
    156	if (status < 0) {
    157		dev_dbg(musb->controller, "notification register failed\n");
    158		return status;
    159	}
    160
    161	musb->isr = ux500_musb_interrupt;
    162
    163	return 0;
    164}
    165
    166static int ux500_musb_exit(struct musb *musb)
    167{
    168	usb_unregister_notifier(musb->xceiv, &musb->nb);
    169
    170	usb_put_phy(musb->xceiv);
    171
    172	return 0;
    173}
    174
    175static const struct musb_platform_ops ux500_ops = {
    176	.quirks		= MUSB_DMA_UX500 | MUSB_INDEXED_EP,
    177#ifdef CONFIG_USB_UX500_DMA
    178	.dma_init	= ux500_dma_controller_create,
    179	.dma_exit	= ux500_dma_controller_destroy,
    180#endif
    181	.init		= ux500_musb_init,
    182	.exit		= ux500_musb_exit,
    183	.fifo_mode	= 5,
    184
    185	.set_vbus	= ux500_musb_set_vbus,
    186};
    187
    188static struct musb_hdrc_platform_data *
    189ux500_of_probe(struct platform_device *pdev, struct device_node *np)
    190{
    191	struct musb_hdrc_platform_data *pdata;
    192	const char *mode;
    193	int strlen;
    194
    195	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
    196	if (!pdata)
    197		return NULL;
    198
    199	mode = of_get_property(np, "dr_mode", &strlen);
    200	if (!mode) {
    201		dev_err(&pdev->dev, "No 'dr_mode' property found\n");
    202		return NULL;
    203	}
    204
    205	if (strlen > 0) {
    206		if (!strcmp(mode, "host"))
    207			pdata->mode = MUSB_HOST;
    208		if (!strcmp(mode, "otg"))
    209			pdata->mode = MUSB_OTG;
    210		if (!strcmp(mode, "peripheral"))
    211			pdata->mode = MUSB_PERIPHERAL;
    212	}
    213
    214	return pdata;
    215}
    216
    217static int ux500_probe(struct platform_device *pdev)
    218{
    219	struct musb_hdrc_platform_data	*pdata = dev_get_platdata(&pdev->dev);
    220	struct device_node		*np = pdev->dev.of_node;
    221	struct platform_device		*musb;
    222	struct ux500_glue		*glue;
    223	struct clk			*clk;
    224	int				ret = -ENOMEM;
    225
    226	if (!pdata) {
    227		if (np) {
    228			pdata = ux500_of_probe(pdev, np);
    229			if (!pdata)
    230				goto err0;
    231
    232			pdev->dev.platform_data = pdata;
    233		} else {
    234			dev_err(&pdev->dev, "no pdata or device tree found\n");
    235			goto err0;
    236		}
    237	}
    238
    239	glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
    240	if (!glue)
    241		goto err0;
    242
    243	musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
    244	if (!musb) {
    245		dev_err(&pdev->dev, "failed to allocate musb device\n");
    246		goto err0;
    247	}
    248
    249	clk = devm_clk_get(&pdev->dev, NULL);
    250	if (IS_ERR(clk)) {
    251		dev_err(&pdev->dev, "failed to get clock\n");
    252		ret = PTR_ERR(clk);
    253		goto err1;
    254	}
    255
    256	ret = clk_prepare_enable(clk);
    257	if (ret) {
    258		dev_err(&pdev->dev, "failed to enable clock\n");
    259		goto err1;
    260	}
    261
    262	musb->dev.parent		= &pdev->dev;
    263	musb->dev.dma_mask		= &pdev->dev.coherent_dma_mask;
    264	musb->dev.coherent_dma_mask	= pdev->dev.coherent_dma_mask;
    265	device_set_of_node_from_dev(&musb->dev, &pdev->dev);
    266
    267	glue->dev			= &pdev->dev;
    268	glue->musb			= musb;
    269	glue->clk			= clk;
    270
    271	pdata->platform_ops		= &ux500_ops;
    272	pdata->config 			= &ux500_musb_hdrc_config;
    273
    274	platform_set_drvdata(pdev, glue);
    275
    276	ret = platform_device_add_resources(musb, pdev->resource, pdev->num_resources);
    277	if (ret) {
    278		dev_err(&pdev->dev, "failed to add resources\n");
    279		goto err2;
    280	}
    281
    282	ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
    283	if (ret) {
    284		dev_err(&pdev->dev, "failed to add platform_data\n");
    285		goto err2;
    286	}
    287
    288	ret = platform_device_add(musb);
    289	if (ret) {
    290		dev_err(&pdev->dev, "failed to register musb device\n");
    291		goto err2;
    292	}
    293
    294	return 0;
    295
    296err2:
    297	clk_disable_unprepare(clk);
    298
    299err1:
    300	platform_device_put(musb);
    301
    302err0:
    303	return ret;
    304}
    305
    306static int ux500_remove(struct platform_device *pdev)
    307{
    308	struct ux500_glue	*glue = platform_get_drvdata(pdev);
    309
    310	platform_device_unregister(glue->musb);
    311	clk_disable_unprepare(glue->clk);
    312
    313	return 0;
    314}
    315
    316#ifdef CONFIG_PM_SLEEP
    317static int ux500_suspend(struct device *dev)
    318{
    319	struct ux500_glue	*glue = dev_get_drvdata(dev);
    320	struct musb		*musb = glue_to_musb(glue);
    321
    322	if (musb)
    323		usb_phy_set_suspend(musb->xceiv, 1);
    324
    325	clk_disable_unprepare(glue->clk);
    326
    327	return 0;
    328}
    329
    330static int ux500_resume(struct device *dev)
    331{
    332	struct ux500_glue	*glue = dev_get_drvdata(dev);
    333	struct musb		*musb = glue_to_musb(glue);
    334	int			ret;
    335
    336	ret = clk_prepare_enable(glue->clk);
    337	if (ret) {
    338		dev_err(dev, "failed to enable clock\n");
    339		return ret;
    340	}
    341
    342	if (musb)
    343		usb_phy_set_suspend(musb->xceiv, 0);
    344
    345	return 0;
    346}
    347#endif
    348
    349static SIMPLE_DEV_PM_OPS(ux500_pm_ops, ux500_suspend, ux500_resume);
    350
    351static const struct of_device_id ux500_match[] = {
    352        { .compatible = "stericsson,db8500-musb", },
    353        {}
    354};
    355
    356MODULE_DEVICE_TABLE(of, ux500_match);
    357
    358static struct platform_driver ux500_driver = {
    359	.probe		= ux500_probe,
    360	.remove		= ux500_remove,
    361	.driver		= {
    362		.name	= "musb-ux500",
    363		.pm	= &ux500_pm_ops,
    364		.of_match_table = ux500_match,
    365	},
    366};
    367
    368MODULE_DESCRIPTION("UX500 MUSB Glue Layer");
    369MODULE_AUTHOR("Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>");
    370MODULE_LICENSE("GPL v2");
    371module_platform_driver(ux500_driver);