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

jz4740.c (7913B)


      1// SPDX-License-Identifier: GPL-2.0+
      2/*
      3 * Ingenic JZ4740 "glue layer"
      4 *
      5 * Copyright (C) 2013, Apelete Seketeli <apelete@seketeli.net>
      6 */
      7
      8#include <linux/clk.h>
      9#include <linux/dma-mapping.h>
     10#include <linux/errno.h>
     11#include <linux/kernel.h>
     12#include <linux/module.h>
     13#include <linux/of_device.h>
     14#include <linux/platform_device.h>
     15#include <linux/usb/role.h>
     16#include <linux/usb/usb_phy_generic.h>
     17
     18#include "musb_core.h"
     19
     20struct jz4740_glue {
     21	struct platform_device	*pdev;
     22	struct musb		*musb;
     23	struct clk		*clk;
     24	struct usb_role_switch	*role_sw;
     25};
     26
     27static irqreturn_t jz4740_musb_interrupt(int irq, void *__hci)
     28{
     29	unsigned long	flags;
     30	irqreturn_t	retval = IRQ_NONE, retval_dma = IRQ_NONE;
     31	struct musb	*musb = __hci;
     32
     33	if (IS_ENABLED(CONFIG_USB_INVENTRA_DMA) && musb->dma_controller)
     34		retval_dma = dma_controller_irq(irq, musb->dma_controller);
     35
     36	spin_lock_irqsave(&musb->lock, flags);
     37
     38	musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
     39	musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX);
     40	musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX);
     41
     42	/*
     43	 * The controller is gadget only, the state of the host mode IRQ bits is
     44	 * undefined. Mask them to make sure that the musb driver core will
     45	 * never see them set
     46	 */
     47	musb->int_usb &= MUSB_INTR_SUSPEND | MUSB_INTR_RESUME |
     48			 MUSB_INTR_RESET | MUSB_INTR_SOF;
     49
     50	if (musb->int_usb || musb->int_tx || musb->int_rx)
     51		retval = musb_interrupt(musb);
     52
     53	spin_unlock_irqrestore(&musb->lock, flags);
     54
     55	if (retval == IRQ_HANDLED || retval_dma == IRQ_HANDLED)
     56		return IRQ_HANDLED;
     57
     58	return IRQ_NONE;
     59}
     60
     61static struct musb_fifo_cfg jz4740_musb_fifo_cfg[] = {
     62	{ .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, },
     63	{ .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, },
     64	{ .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 64, },
     65};
     66
     67static const struct musb_hdrc_config jz4740_musb_config = {
     68	/* Silicon does not implement USB OTG. */
     69	.multipoint	= 0,
     70	/* Max EPs scanned, driver will decide which EP can be used. */
     71	.num_eps	= 4,
     72	/* RAMbits needed to configure EPs from table */
     73	.ram_bits	= 9,
     74	.fifo_cfg	= jz4740_musb_fifo_cfg,
     75	.fifo_cfg_size	= ARRAY_SIZE(jz4740_musb_fifo_cfg),
     76};
     77
     78static int jz4740_musb_role_switch_set(struct usb_role_switch *sw,
     79				       enum usb_role role)
     80{
     81	struct jz4740_glue *glue = usb_role_switch_get_drvdata(sw);
     82	struct usb_phy *phy = glue->musb->xceiv;
     83
     84	switch (role) {
     85	case USB_ROLE_NONE:
     86		atomic_notifier_call_chain(&phy->notifier, USB_EVENT_NONE, phy);
     87		break;
     88	case USB_ROLE_DEVICE:
     89		atomic_notifier_call_chain(&phy->notifier, USB_EVENT_VBUS, phy);
     90		break;
     91	case USB_ROLE_HOST:
     92		atomic_notifier_call_chain(&phy->notifier, USB_EVENT_ID, phy);
     93		break;
     94	}
     95
     96	return 0;
     97}
     98
     99static int jz4740_musb_init(struct musb *musb)
    100{
    101	struct device *dev = musb->controller->parent;
    102	struct jz4740_glue *glue = dev_get_drvdata(dev);
    103	struct usb_role_switch_desc role_sw_desc = {
    104		.set = jz4740_musb_role_switch_set,
    105		.driver_data = glue,
    106		.fwnode = dev_fwnode(dev),
    107	};
    108	int err;
    109
    110	glue->musb = musb;
    111
    112	if (dev->of_node)
    113		musb->xceiv = devm_usb_get_phy_by_phandle(dev, "phys", 0);
    114	else
    115		musb->xceiv = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
    116	if (IS_ERR(musb->xceiv)) {
    117		err = PTR_ERR(musb->xceiv);
    118		if (err != -EPROBE_DEFER)
    119			dev_err(dev, "No transceiver configured: %d\n", err);
    120		return err;
    121	}
    122
    123	glue->role_sw = usb_role_switch_register(dev, &role_sw_desc);
    124	if (IS_ERR(glue->role_sw)) {
    125		dev_err(dev, "Failed to register USB role switch\n");
    126		return PTR_ERR(glue->role_sw);
    127	}
    128
    129	/*
    130	 * Silicon does not implement ConfigData register.
    131	 * Set dyn_fifo to avoid reading EP config from hardware.
    132	 */
    133	musb->dyn_fifo = true;
    134
    135	musb->isr = jz4740_musb_interrupt;
    136
    137	return 0;
    138}
    139
    140static int jz4740_musb_exit(struct musb *musb)
    141{
    142	struct jz4740_glue *glue = dev_get_drvdata(musb->controller->parent);
    143
    144	usb_role_switch_unregister(glue->role_sw);
    145
    146	return 0;
    147}
    148
    149static const struct musb_platform_ops jz4740_musb_ops = {
    150	.quirks		= MUSB_DMA_INVENTRA | MUSB_INDEXED_EP,
    151	.fifo_mode	= 2,
    152	.init		= jz4740_musb_init,
    153	.exit		= jz4740_musb_exit,
    154#ifdef CONFIG_USB_INVENTRA_DMA
    155	.dma_init	= musbhs_dma_controller_create_noirq,
    156	.dma_exit	= musbhs_dma_controller_destroy,
    157#endif
    158};
    159
    160static const struct musb_hdrc_platform_data jz4740_musb_pdata = {
    161	.mode		= MUSB_PERIPHERAL,
    162	.config		= &jz4740_musb_config,
    163	.platform_ops	= &jz4740_musb_ops,
    164};
    165
    166static struct musb_fifo_cfg jz4770_musb_fifo_cfg[] = {
    167	{ .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, },
    168	{ .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, },
    169	{ .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 512, },
    170	{ .hw_ep_num = 2, .style = FIFO_RX, .maxpacket = 512, },
    171	{ .hw_ep_num = 3, .style = FIFO_TX, .maxpacket = 512, },
    172	{ .hw_ep_num = 3, .style = FIFO_RX, .maxpacket = 512, },
    173	{ .hw_ep_num = 4, .style = FIFO_TX, .maxpacket = 512, },
    174	{ .hw_ep_num = 4, .style = FIFO_RX, .maxpacket = 512, },
    175	{ .hw_ep_num = 5, .style = FIFO_TX, .maxpacket = 512, },
    176	{ .hw_ep_num = 5, .style = FIFO_RX, .maxpacket = 512, },
    177};
    178
    179static struct musb_hdrc_config jz4770_musb_config = {
    180	.multipoint	= 1,
    181	.num_eps	= 11,
    182	.ram_bits	= 11,
    183	.fifo_cfg	= jz4770_musb_fifo_cfg,
    184	.fifo_cfg_size	= ARRAY_SIZE(jz4770_musb_fifo_cfg),
    185};
    186
    187static const struct musb_hdrc_platform_data jz4770_musb_pdata = {
    188	.mode		= MUSB_PERIPHERAL, /* TODO: support OTG */
    189	.config		= &jz4770_musb_config,
    190	.platform_ops	= &jz4740_musb_ops,
    191};
    192
    193static int jz4740_probe(struct platform_device *pdev)
    194{
    195	struct device			*dev = &pdev->dev;
    196	const struct musb_hdrc_platform_data *pdata;
    197	struct platform_device		*musb;
    198	struct jz4740_glue		*glue;
    199	struct clk			*clk;
    200	int				ret;
    201
    202	glue = devm_kzalloc(dev, sizeof(*glue), GFP_KERNEL);
    203	if (!glue)
    204		return -ENOMEM;
    205
    206	pdata = of_device_get_match_data(dev);
    207	if (!pdata) {
    208		dev_err(dev, "missing platform data\n");
    209		return -EINVAL;
    210	}
    211
    212	musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
    213	if (!musb) {
    214		dev_err(dev, "failed to allocate musb device\n");
    215		return -ENOMEM;
    216	}
    217
    218	clk = devm_clk_get(dev, "udc");
    219	if (IS_ERR(clk)) {
    220		dev_err(dev, "failed to get clock\n");
    221		ret = PTR_ERR(clk);
    222		goto err_platform_device_put;
    223	}
    224
    225	ret = clk_prepare_enable(clk);
    226	if (ret) {
    227		dev_err(dev, "failed to enable clock\n");
    228		goto err_platform_device_put;
    229	}
    230
    231	musb->dev.parent		= dev;
    232	musb->dev.dma_mask		= &musb->dev.coherent_dma_mask;
    233	musb->dev.coherent_dma_mask	= DMA_BIT_MASK(32);
    234	device_set_of_node_from_dev(&musb->dev, dev);
    235
    236	glue->pdev			= musb;
    237	glue->clk			= clk;
    238
    239	platform_set_drvdata(pdev, glue);
    240
    241	ret = platform_device_add_resources(musb, pdev->resource,
    242					    pdev->num_resources);
    243	if (ret) {
    244		dev_err(dev, "failed to add resources\n");
    245		goto err_clk_disable;
    246	}
    247
    248	ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
    249	if (ret) {
    250		dev_err(dev, "failed to add platform_data\n");
    251		goto err_clk_disable;
    252	}
    253
    254	ret = platform_device_add(musb);
    255	if (ret) {
    256		dev_err(dev, "failed to register musb device\n");
    257		goto err_clk_disable;
    258	}
    259
    260	return 0;
    261
    262err_clk_disable:
    263	clk_disable_unprepare(clk);
    264err_platform_device_put:
    265	platform_device_put(musb);
    266	return ret;
    267}
    268
    269static int jz4740_remove(struct platform_device *pdev)
    270{
    271	struct jz4740_glue *glue = platform_get_drvdata(pdev);
    272
    273	platform_device_unregister(glue->pdev);
    274	clk_disable_unprepare(glue->clk);
    275
    276	return 0;
    277}
    278
    279static const struct of_device_id jz4740_musb_of_match[] = {
    280	{ .compatible = "ingenic,jz4740-musb", .data = &jz4740_musb_pdata },
    281	{ .compatible = "ingenic,jz4770-musb", .data = &jz4770_musb_pdata },
    282	{ /* sentinel */ },
    283};
    284MODULE_DEVICE_TABLE(of, jz4740_musb_of_match);
    285
    286static struct platform_driver jz4740_driver = {
    287	.probe		= jz4740_probe,
    288	.remove		= jz4740_remove,
    289	.driver		= {
    290		.name	= "musb-jz4740",
    291		.of_match_table = jz4740_musb_of_match,
    292	},
    293};
    294
    295MODULE_DESCRIPTION("JZ4740 MUSB Glue Layer");
    296MODULE_AUTHOR("Apelete Seketeli <apelete@seketeli.net>");
    297MODULE_LICENSE("GPL v2");
    298module_platform_driver(jz4740_driver);