Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Copyright (C) 2020 Maxime Ripard <maxime@cerno.tech> */
0003 
0004 #include <linux/device.h>
0005 #include <linux/dma-map-ops.h>
0006 #include <linux/init.h>
0007 #include <linux/notifier.h>
0008 #include <linux/of.h>
0009 #include <linux/platform_device.h>
0010 
0011 static const char * const sunxi_mbus_devices[] = {
0012     /*
0013      * The display engine virtual devices are not strictly speaking
0014      * connected to the MBUS, but since DRM will perform all the
0015      * memory allocations and DMA operations through that device, we
0016      * need to have the quirk on those devices too.
0017      */
0018     "allwinner,sun4i-a10-display-engine",
0019     "allwinner,sun5i-a10s-display-engine",
0020     "allwinner,sun5i-a13-display-engine",
0021     "allwinner,sun6i-a31-display-engine",
0022     "allwinner,sun6i-a31s-display-engine",
0023     "allwinner,sun7i-a20-display-engine",
0024     "allwinner,sun8i-a23-display-engine",
0025     "allwinner,sun8i-a33-display-engine",
0026     "allwinner,sun9i-a80-display-engine",
0027 
0028     /*
0029      * And now we have the regular devices connected to the MBUS
0030      * (that we know of).
0031      */
0032     "allwinner,sun4i-a10-csi1",
0033     "allwinner,sun4i-a10-display-backend",
0034     "allwinner,sun4i-a10-display-frontend",
0035     "allwinner,sun4i-a10-video-engine",
0036     "allwinner,sun5i-a13-display-backend",
0037     "allwinner,sun5i-a13-video-engine",
0038     "allwinner,sun6i-a31-csi",
0039     "allwinner,sun6i-a31-display-backend",
0040     "allwinner,sun7i-a20-csi0",
0041     "allwinner,sun7i-a20-display-backend",
0042     "allwinner,sun7i-a20-display-frontend",
0043     "allwinner,sun7i-a20-video-engine",
0044     "allwinner,sun8i-a23-display-backend",
0045     "allwinner,sun8i-a23-display-frontend",
0046     "allwinner,sun8i-a33-display-backend",
0047     "allwinner,sun8i-a33-display-frontend",
0048     "allwinner,sun8i-a33-video-engine",
0049     "allwinner,sun8i-a83t-csi",
0050     "allwinner,sun8i-h3-csi",
0051     "allwinner,sun8i-h3-video-engine",
0052     "allwinner,sun8i-v3s-csi",
0053     "allwinner,sun9i-a80-display-backend",
0054     "allwinner,sun50i-a64-csi",
0055     "allwinner,sun50i-a64-video-engine",
0056     "allwinner,sun50i-h5-video-engine",
0057     NULL,
0058 };
0059 
0060 static int sunxi_mbus_notifier(struct notifier_block *nb,
0061                    unsigned long event, void *__dev)
0062 {
0063     struct device *dev = __dev;
0064     int ret;
0065 
0066     if (event != BUS_NOTIFY_ADD_DEVICE)
0067         return NOTIFY_DONE;
0068 
0069     /*
0070      * Only the devices that need a large memory bandwidth do DMA
0071      * directly over the memory bus (called MBUS), instead of going
0072      * through the regular system bus.
0073      */
0074     if (!of_device_compatible_match(dev->of_node, sunxi_mbus_devices))
0075         return NOTIFY_DONE;
0076 
0077     /*
0078      * Devices with an interconnects property have the MBUS
0079      * relationship described in their DT and dealt with by
0080      * of_dma_configure, so we can just skip them.
0081      *
0082      * Older DTs or SoCs who are not clearly understood need to set
0083      * that DMA offset though.
0084      */
0085     if (of_find_property(dev->of_node, "interconnects", NULL))
0086         return NOTIFY_DONE;
0087 
0088     ret = dma_direct_set_offset(dev, PHYS_OFFSET, 0, SZ_4G);
0089     if (ret)
0090         dev_err(dev, "Couldn't setup our DMA offset: %d\n", ret);
0091 
0092     return NOTIFY_DONE;
0093 }
0094 
0095 static struct notifier_block sunxi_mbus_nb = {
0096     .notifier_call = sunxi_mbus_notifier,
0097 };
0098 
0099 static const char * const sunxi_mbus_platforms[] __initconst = {
0100     "allwinner,sun4i-a10",
0101     "allwinner,sun5i-a10s",
0102     "allwinner,sun5i-a13",
0103     "allwinner,sun6i-a31",
0104     "allwinner,sun7i-a20",
0105     "allwinner,sun8i-a23",
0106     "allwinner,sun8i-a33",
0107     "allwinner,sun8i-a83t",
0108     "allwinner,sun8i-h3",
0109     "allwinner,sun8i-r40",
0110     "allwinner,sun8i-v3",
0111     "allwinner,sun8i-v3s",
0112     "allwinner,sun9i-a80",
0113     "allwinner,sun50i-a64",
0114     "allwinner,sun50i-h5",
0115     "nextthing,gr8",
0116     NULL,
0117 };
0118 
0119 static int __init sunxi_mbus_init(void)
0120 {
0121     if (!of_device_compatible_match(of_root, sunxi_mbus_platforms))
0122         return 0;
0123 
0124     bus_register_notifier(&platform_bus_type, &sunxi_mbus_nb);
0125     return 0;
0126 }
0127 arch_initcall(sunxi_mbus_init);