146432Sphk// SPDX-License-Identifier: GPL-2.0 246432Sphk/* Copyright (C) 2020 Maxime Ripard <maxime@cerno.tech> */ 346432Sphk 446432Sphk#include <linux/device.h> 546432Sphk#include <linux/dma-map-ops.h> 646432Sphk#include <linux/init.h> 746432Sphk#include <linux/notifier.h> 846432Sphk#include <linux/of.h> 946432Sphk#include <linux/platform_device.h> 10117280Scharnier 11117280Scharnierstatic const char * const sunxi_mbus_devices[] = { 12117280Scharnier /* 13112705Smaxim * The display engine virtual devices are not strictly speaking 1446155Sphk * connected to the MBUS, but since DRM will perform all the 15158428Smatteo * memory allocations and DMA operations through that device, we 1678723Sdd * need to have the quirk on those devices too. 1746155Sphk */ 1878723Sdd "allwinner,sun4i-a10-display-engine", 1946155Sphk "allwinner,sun5i-a10s-display-engine", 2078723Sdd "allwinner,sun5i-a13-display-engine", 21129848Smaxim "allwinner,sun6i-a31-display-engine", 22112705Smaxim "allwinner,sun6i-a31s-display-engine", 23112705Smaxim "allwinner,sun7i-a20-display-engine", 24133743Smaxim "allwinner,sun8i-a23-display-engine", 25112705Smaxim "allwinner,sun8i-a33-display-engine", 2678723Sdd "allwinner,sun9i-a80-display-engine", 2778723Sdd 2878723Sdd /* 2978723Sdd * And now we have the regular devices connected to the MBUS 3078723Sdd * (that we know of). 31112705Smaxim */ 32133743Smaxim "allwinner,sun4i-a10-csi1", 33112705Smaxim "allwinner,sun4i-a10-display-backend", 34129848Smaxim "allwinner,sun4i-a10-display-frontend", 35129848Smaxim "allwinner,sun4i-a10-video-engine", 36129848Smaxim "allwinner,sun5i-a13-display-backend", 37129848Smaxim "allwinner,sun5i-a13-video-engine", 38129848Smaxim "allwinner,sun6i-a31-csi", 39129848Smaxim "allwinner,sun6i-a31-display-backend", 40129848Smaxim "allwinner,sun7i-a20-csi0", 41129848Smaxim "allwinner,sun7i-a20-display-backend", 42129848Smaxim "allwinner,sun7i-a20-display-frontend", 43129848Smaxim "allwinner,sun7i-a20-video-engine", 44129848Smaxim "allwinner,sun8i-a23-display-backend", 45129848Smaxim "allwinner,sun8i-a23-display-frontend", 46129848Smaxim "allwinner,sun8i-a33-display-backend", 47129848Smaxim "allwinner,sun8i-a33-display-frontend", 48129848Smaxim "allwinner,sun8i-a33-video-engine", 49129848Smaxim "allwinner,sun8i-a83t-csi", 5046155Sphk "allwinner,sun8i-h3-csi", 5146155Sphk "allwinner,sun8i-h3-video-engine", 5246155Sphk "allwinner,sun8i-v3s-csi", 53137808Sdelphij "allwinner,sun9i-a80-display-backend", 5446155Sphk "allwinner,sun50i-a64-csi", 55137808Sdelphij "allwinner,sun50i-a64-video-engine", 5646155Sphk "allwinner,sun50i-h5-video-engine", 57136051Sstefanf NULL, 58158475Smatteo}; 59158475Smatteo 60133743Smaximstatic int sunxi_mbus_notifier(struct notifier_block *nb, 61137807Sdelphij unsigned long event, void *__dev) 62158475Smatteo{ 63153056Sphilip struct device *dev = __dev; 6446155Sphk int ret; 65153056Sphilip 66158475Smatteo if (event != BUS_NOTIFY_ADD_DEVICE) 67153056Sphilip return NOTIFY_DONE; 68153056Sphilip 69112705Smaxim /* 70158428Smatteo * Only the devices that need a large memory bandwidth do DMA 71112705Smaxim * directly over the memory bus (called MBUS), instead of going 72113277Smike * through the regular system bus. 73113277Smike */ 74113277Smike if (!of_device_compatible_match(dev->of_node, sunxi_mbus_devices)) 75153056Sphilip return NOTIFY_DONE; 76153056Sphilip 77153056Sphilip /* 78153056Sphilip * Devices with an interconnects property have the MBUS 79158428Smatteo * relationship described in their DT and dealt with by 80158475Smatteo * of_dma_configure, so we can just skip them. 81158475Smatteo * 82158475Smatteo * Older DTs or SoCs who are not clearly understood need to set 83158475Smatteo * that DMA offset though. 84158428Smatteo */ 85112705Smaxim if (of_property_present(dev->of_node, "interconnects")) 86112705Smaxim return NOTIFY_DONE; 87129848Smaxim 88112705Smaxim ret = dma_direct_set_offset(dev, PHYS_OFFSET, 0, SZ_4G); 89129848Smaxim if (ret) 90129848Smaxim dev_err(dev, "Couldn't setup our DMA offset: %d\n", ret); 91129848Smaxim 92129848Smaxim return NOTIFY_DONE; 93133743Smaxim} 94133743Smaxim 95133743Smaximstatic struct notifier_block sunxi_mbus_nb = { 96112705Smaxim .notifier_call = sunxi_mbus_notifier, 97112705Smaxim}; 98112705Smaxim 99113277Smikestatic const char * const sunxi_mbus_platforms[] __initconst = { 100112705Smaxim "allwinner,sun4i-a10", 101112705Smaxim "allwinner,sun5i-a10s", 102112705Smaxim "allwinner,sun5i-a13", 103112705Smaxim "allwinner,sun6i-a31", 104129848Smaxim "allwinner,sun7i-a20", 105129848Smaxim "allwinner,sun8i-a23", 106133743Smaxim "allwinner,sun8i-a33", 107133743Smaxim "allwinner,sun8i-a83t", 108129848Smaxim "allwinner,sun8i-h3", 109129848Smaxim "allwinner,sun8i-r40", 110131182Spjd "allwinner,sun8i-v3", 111131182Spjd "allwinner,sun8i-v3s", 112131182Spjd "allwinner,sun9i-a80", 113131182Spjd "allwinner,sun50i-a64", 11451399Sphk "allwinner,sun50i-h5", 11551399Sphk "nextthing,gr8", 116131182Spjd NULL, 117112705Smaxim}; 118112972Smaxim 119112972Smaximstatic int __init sunxi_mbus_init(void) 12046432Sphk{ 121153056Sphilip if (!of_device_compatible_match(of_root, sunxi_mbus_platforms)) 122153056Sphilip return 0; 123153056Sphilip 124153056Sphilip bus_register_notifier(&platform_bus_type, &sunxi_mbus_nb); 125153056Sphilip return 0; 126113277Smike} 127113277Smikearch_initcall(sunxi_mbus_init); 128112972Smaxim