18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Allwinner SoCs SRAM Controller Driver 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright (C) 2015 Maxime Ripard 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Author: Maxime Ripard <maxime.ripard@free-electrons.com> 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * This file is licensed under the terms of the GNU General Public 98c2ecf20Sopenharmony_ci * License version 2. This program is licensed "as is" without any 108c2ecf20Sopenharmony_ci * warranty of any kind, whether express or implied. 118c2ecf20Sopenharmony_ci */ 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#include <linux/debugfs.h> 148c2ecf20Sopenharmony_ci#include <linux/io.h> 158c2ecf20Sopenharmony_ci#include <linux/module.h> 168c2ecf20Sopenharmony_ci#include <linux/of.h> 178c2ecf20Sopenharmony_ci#include <linux/of_address.h> 188c2ecf20Sopenharmony_ci#include <linux/of_device.h> 198c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 208c2ecf20Sopenharmony_ci#include <linux/regmap.h> 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci#include <linux/soc/sunxi/sunxi_sram.h> 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_cistruct sunxi_sram_func { 258c2ecf20Sopenharmony_ci char *func; 268c2ecf20Sopenharmony_ci u8 val; 278c2ecf20Sopenharmony_ci u32 reg_val; 288c2ecf20Sopenharmony_ci}; 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_cistruct sunxi_sram_data { 318c2ecf20Sopenharmony_ci char *name; 328c2ecf20Sopenharmony_ci u8 reg; 338c2ecf20Sopenharmony_ci u8 offset; 348c2ecf20Sopenharmony_ci u8 width; 358c2ecf20Sopenharmony_ci struct sunxi_sram_func *func; 368c2ecf20Sopenharmony_ci struct list_head list; 378c2ecf20Sopenharmony_ci}; 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_cistruct sunxi_sram_desc { 408c2ecf20Sopenharmony_ci struct sunxi_sram_data data; 418c2ecf20Sopenharmony_ci bool claimed; 428c2ecf20Sopenharmony_ci}; 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci#define SUNXI_SRAM_MAP(_reg_val, _val, _func) \ 458c2ecf20Sopenharmony_ci { \ 468c2ecf20Sopenharmony_ci .func = _func, \ 478c2ecf20Sopenharmony_ci .val = _val, \ 488c2ecf20Sopenharmony_ci .reg_val = _reg_val, \ 498c2ecf20Sopenharmony_ci } 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci#define SUNXI_SRAM_DATA(_name, _reg, _off, _width, ...) \ 528c2ecf20Sopenharmony_ci { \ 538c2ecf20Sopenharmony_ci .name = _name, \ 548c2ecf20Sopenharmony_ci .reg = _reg, \ 558c2ecf20Sopenharmony_ci .offset = _off, \ 568c2ecf20Sopenharmony_ci .width = _width, \ 578c2ecf20Sopenharmony_ci .func = (struct sunxi_sram_func[]){ \ 588c2ecf20Sopenharmony_ci __VA_ARGS__, { } }, \ 598c2ecf20Sopenharmony_ci } 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_cistatic struct sunxi_sram_desc sun4i_a10_sram_a3_a4 = { 628c2ecf20Sopenharmony_ci .data = SUNXI_SRAM_DATA("A3-A4", 0x4, 0x4, 2, 638c2ecf20Sopenharmony_ci SUNXI_SRAM_MAP(0, 0, "cpu"), 648c2ecf20Sopenharmony_ci SUNXI_SRAM_MAP(1, 1, "emac")), 658c2ecf20Sopenharmony_ci}; 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_cistatic struct sunxi_sram_desc sun4i_a10_sram_c1 = { 688c2ecf20Sopenharmony_ci .data = SUNXI_SRAM_DATA("C1", 0x0, 0x0, 31, 698c2ecf20Sopenharmony_ci SUNXI_SRAM_MAP(0, 0, "cpu"), 708c2ecf20Sopenharmony_ci SUNXI_SRAM_MAP(0x7fffffff, 1, "ve")), 718c2ecf20Sopenharmony_ci}; 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_cistatic struct sunxi_sram_desc sun4i_a10_sram_d = { 748c2ecf20Sopenharmony_ci .data = SUNXI_SRAM_DATA("D", 0x4, 0x0, 1, 758c2ecf20Sopenharmony_ci SUNXI_SRAM_MAP(0, 0, "cpu"), 768c2ecf20Sopenharmony_ci SUNXI_SRAM_MAP(1, 1, "usb-otg")), 778c2ecf20Sopenharmony_ci}; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_cistatic struct sunxi_sram_desc sun50i_a64_sram_c = { 808c2ecf20Sopenharmony_ci .data = SUNXI_SRAM_DATA("C", 0x4, 24, 1, 818c2ecf20Sopenharmony_ci SUNXI_SRAM_MAP(1, 0, "cpu"), 828c2ecf20Sopenharmony_ci SUNXI_SRAM_MAP(0, 1, "de2")), 838c2ecf20Sopenharmony_ci}; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_cistatic const struct of_device_id sunxi_sram_dt_ids[] = { 868c2ecf20Sopenharmony_ci { 878c2ecf20Sopenharmony_ci .compatible = "allwinner,sun4i-a10-sram-a3-a4", 888c2ecf20Sopenharmony_ci .data = &sun4i_a10_sram_a3_a4.data, 898c2ecf20Sopenharmony_ci }, 908c2ecf20Sopenharmony_ci { 918c2ecf20Sopenharmony_ci .compatible = "allwinner,sun4i-a10-sram-c1", 928c2ecf20Sopenharmony_ci .data = &sun4i_a10_sram_c1.data, 938c2ecf20Sopenharmony_ci }, 948c2ecf20Sopenharmony_ci { 958c2ecf20Sopenharmony_ci .compatible = "allwinner,sun4i-a10-sram-d", 968c2ecf20Sopenharmony_ci .data = &sun4i_a10_sram_d.data, 978c2ecf20Sopenharmony_ci }, 988c2ecf20Sopenharmony_ci { 998c2ecf20Sopenharmony_ci .compatible = "allwinner,sun50i-a64-sram-c", 1008c2ecf20Sopenharmony_ci .data = &sun50i_a64_sram_c.data, 1018c2ecf20Sopenharmony_ci }, 1028c2ecf20Sopenharmony_ci {} 1038c2ecf20Sopenharmony_ci}; 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_cistatic struct device *sram_dev; 1068c2ecf20Sopenharmony_cistatic LIST_HEAD(claimed_sram); 1078c2ecf20Sopenharmony_cistatic DEFINE_SPINLOCK(sram_lock); 1088c2ecf20Sopenharmony_cistatic void __iomem *base; 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_cistatic int sunxi_sram_show(struct seq_file *s, void *data) 1118c2ecf20Sopenharmony_ci{ 1128c2ecf20Sopenharmony_ci struct device_node *sram_node, *section_node; 1138c2ecf20Sopenharmony_ci const struct sunxi_sram_data *sram_data; 1148c2ecf20Sopenharmony_ci const struct of_device_id *match; 1158c2ecf20Sopenharmony_ci struct sunxi_sram_func *func; 1168c2ecf20Sopenharmony_ci const __be32 *sram_addr_p, *section_addr_p; 1178c2ecf20Sopenharmony_ci u32 val; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci seq_puts(s, "Allwinner sunXi SRAM\n"); 1208c2ecf20Sopenharmony_ci seq_puts(s, "--------------------\n\n"); 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci for_each_child_of_node(sram_dev->of_node, sram_node) { 1238c2ecf20Sopenharmony_ci sram_addr_p = of_get_address(sram_node, 0, NULL, NULL); 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci seq_printf(s, "sram@%08x\n", 1268c2ecf20Sopenharmony_ci be32_to_cpu(*sram_addr_p)); 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci for_each_child_of_node(sram_node, section_node) { 1298c2ecf20Sopenharmony_ci match = of_match_node(sunxi_sram_dt_ids, section_node); 1308c2ecf20Sopenharmony_ci if (!match) 1318c2ecf20Sopenharmony_ci continue; 1328c2ecf20Sopenharmony_ci sram_data = match->data; 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci section_addr_p = of_get_address(section_node, 0, 1358c2ecf20Sopenharmony_ci NULL, NULL); 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci seq_printf(s, "\tsection@%04x\t(%s)\n", 1388c2ecf20Sopenharmony_ci be32_to_cpu(*section_addr_p), 1398c2ecf20Sopenharmony_ci sram_data->name); 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci val = readl(base + sram_data->reg); 1428c2ecf20Sopenharmony_ci val >>= sram_data->offset; 1438c2ecf20Sopenharmony_ci val &= GENMASK(sram_data->width - 1, 0); 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci for (func = sram_data->func; func->func; func++) { 1468c2ecf20Sopenharmony_ci seq_printf(s, "\t\t%s%c\n", func->func, 1478c2ecf20Sopenharmony_ci func->reg_val == val ? 1488c2ecf20Sopenharmony_ci '*' : ' '); 1498c2ecf20Sopenharmony_ci } 1508c2ecf20Sopenharmony_ci } 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci seq_puts(s, "\n"); 1538c2ecf20Sopenharmony_ci } 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci return 0; 1568c2ecf20Sopenharmony_ci} 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(sunxi_sram); 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_cistatic inline struct sunxi_sram_desc *to_sram_desc(const struct sunxi_sram_data *data) 1618c2ecf20Sopenharmony_ci{ 1628c2ecf20Sopenharmony_ci return container_of(data, struct sunxi_sram_desc, data); 1638c2ecf20Sopenharmony_ci} 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_cistatic const struct sunxi_sram_data *sunxi_sram_of_parse(struct device_node *node, 1668c2ecf20Sopenharmony_ci unsigned int *reg_value) 1678c2ecf20Sopenharmony_ci{ 1688c2ecf20Sopenharmony_ci const struct of_device_id *match; 1698c2ecf20Sopenharmony_ci const struct sunxi_sram_data *data; 1708c2ecf20Sopenharmony_ci struct sunxi_sram_func *func; 1718c2ecf20Sopenharmony_ci struct of_phandle_args args; 1728c2ecf20Sopenharmony_ci u8 val; 1738c2ecf20Sopenharmony_ci int ret; 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci ret = of_parse_phandle_with_fixed_args(node, "allwinner,sram", 1, 0, 1768c2ecf20Sopenharmony_ci &args); 1778c2ecf20Sopenharmony_ci if (ret) 1788c2ecf20Sopenharmony_ci return ERR_PTR(ret); 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci if (!of_device_is_available(args.np)) { 1818c2ecf20Sopenharmony_ci ret = -EBUSY; 1828c2ecf20Sopenharmony_ci goto err; 1838c2ecf20Sopenharmony_ci } 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci val = args.args[0]; 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci match = of_match_node(sunxi_sram_dt_ids, args.np); 1888c2ecf20Sopenharmony_ci if (!match) { 1898c2ecf20Sopenharmony_ci ret = -EINVAL; 1908c2ecf20Sopenharmony_ci goto err; 1918c2ecf20Sopenharmony_ci } 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci data = match->data; 1948c2ecf20Sopenharmony_ci if (!data) { 1958c2ecf20Sopenharmony_ci ret = -EINVAL; 1968c2ecf20Sopenharmony_ci goto err; 1978c2ecf20Sopenharmony_ci } 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci for (func = data->func; func->func; func++) { 2008c2ecf20Sopenharmony_ci if (val == func->val) { 2018c2ecf20Sopenharmony_ci if (reg_value) 2028c2ecf20Sopenharmony_ci *reg_value = func->reg_val; 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci break; 2058c2ecf20Sopenharmony_ci } 2068c2ecf20Sopenharmony_ci } 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci if (!func->func) { 2098c2ecf20Sopenharmony_ci ret = -EINVAL; 2108c2ecf20Sopenharmony_ci goto err; 2118c2ecf20Sopenharmony_ci } 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci of_node_put(args.np); 2148c2ecf20Sopenharmony_ci return match->data; 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_cierr: 2178c2ecf20Sopenharmony_ci of_node_put(args.np); 2188c2ecf20Sopenharmony_ci return ERR_PTR(ret); 2198c2ecf20Sopenharmony_ci} 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ciint sunxi_sram_claim(struct device *dev) 2228c2ecf20Sopenharmony_ci{ 2238c2ecf20Sopenharmony_ci const struct sunxi_sram_data *sram_data; 2248c2ecf20Sopenharmony_ci struct sunxi_sram_desc *sram_desc; 2258c2ecf20Sopenharmony_ci unsigned int device; 2268c2ecf20Sopenharmony_ci u32 val, mask; 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci if (IS_ERR(base)) 2298c2ecf20Sopenharmony_ci return PTR_ERR(base); 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci if (!base) 2328c2ecf20Sopenharmony_ci return -EPROBE_DEFER; 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci if (!dev || !dev->of_node) 2358c2ecf20Sopenharmony_ci return -EINVAL; 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci sram_data = sunxi_sram_of_parse(dev->of_node, &device); 2388c2ecf20Sopenharmony_ci if (IS_ERR(sram_data)) 2398c2ecf20Sopenharmony_ci return PTR_ERR(sram_data); 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci sram_desc = to_sram_desc(sram_data); 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci spin_lock(&sram_lock); 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci if (sram_desc->claimed) { 2468c2ecf20Sopenharmony_ci spin_unlock(&sram_lock); 2478c2ecf20Sopenharmony_ci return -EBUSY; 2488c2ecf20Sopenharmony_ci } 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci mask = GENMASK(sram_data->offset + sram_data->width - 1, 2518c2ecf20Sopenharmony_ci sram_data->offset); 2528c2ecf20Sopenharmony_ci val = readl(base + sram_data->reg); 2538c2ecf20Sopenharmony_ci val &= ~mask; 2548c2ecf20Sopenharmony_ci writel(val | ((device << sram_data->offset) & mask), 2558c2ecf20Sopenharmony_ci base + sram_data->reg); 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci sram_desc->claimed = true; 2588c2ecf20Sopenharmony_ci spin_unlock(&sram_lock); 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci return 0; 2618c2ecf20Sopenharmony_ci} 2628c2ecf20Sopenharmony_ciEXPORT_SYMBOL(sunxi_sram_claim); 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ciint sunxi_sram_release(struct device *dev) 2658c2ecf20Sopenharmony_ci{ 2668c2ecf20Sopenharmony_ci const struct sunxi_sram_data *sram_data; 2678c2ecf20Sopenharmony_ci struct sunxi_sram_desc *sram_desc; 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci if (!dev || !dev->of_node) 2708c2ecf20Sopenharmony_ci return -EINVAL; 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci sram_data = sunxi_sram_of_parse(dev->of_node, NULL); 2738c2ecf20Sopenharmony_ci if (IS_ERR(sram_data)) 2748c2ecf20Sopenharmony_ci return -EINVAL; 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci sram_desc = to_sram_desc(sram_data); 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci spin_lock(&sram_lock); 2798c2ecf20Sopenharmony_ci sram_desc->claimed = false; 2808c2ecf20Sopenharmony_ci spin_unlock(&sram_lock); 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci return 0; 2838c2ecf20Sopenharmony_ci} 2848c2ecf20Sopenharmony_ciEXPORT_SYMBOL(sunxi_sram_release); 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_cistruct sunxi_sramc_variant { 2878c2ecf20Sopenharmony_ci bool has_emac_clock; 2888c2ecf20Sopenharmony_ci}; 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_cistatic const struct sunxi_sramc_variant sun4i_a10_sramc_variant = { 2918c2ecf20Sopenharmony_ci /* Nothing special */ 2928c2ecf20Sopenharmony_ci}; 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_cistatic const struct sunxi_sramc_variant sun8i_h3_sramc_variant = { 2958c2ecf20Sopenharmony_ci .has_emac_clock = true, 2968c2ecf20Sopenharmony_ci}; 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_cistatic const struct sunxi_sramc_variant sun50i_a64_sramc_variant = { 2998c2ecf20Sopenharmony_ci .has_emac_clock = true, 3008c2ecf20Sopenharmony_ci}; 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci#define SUNXI_SRAM_EMAC_CLOCK_REG 0x30 3038c2ecf20Sopenharmony_cistatic bool sunxi_sram_regmap_accessible_reg(struct device *dev, 3048c2ecf20Sopenharmony_ci unsigned int reg) 3058c2ecf20Sopenharmony_ci{ 3068c2ecf20Sopenharmony_ci if (reg == SUNXI_SRAM_EMAC_CLOCK_REG) 3078c2ecf20Sopenharmony_ci return true; 3088c2ecf20Sopenharmony_ci return false; 3098c2ecf20Sopenharmony_ci} 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_cistatic struct regmap_config sunxi_sram_emac_clock_regmap = { 3128c2ecf20Sopenharmony_ci .reg_bits = 32, 3138c2ecf20Sopenharmony_ci .val_bits = 32, 3148c2ecf20Sopenharmony_ci .reg_stride = 4, 3158c2ecf20Sopenharmony_ci /* last defined register */ 3168c2ecf20Sopenharmony_ci .max_register = SUNXI_SRAM_EMAC_CLOCK_REG, 3178c2ecf20Sopenharmony_ci /* other devices have no business accessing other registers */ 3188c2ecf20Sopenharmony_ci .readable_reg = sunxi_sram_regmap_accessible_reg, 3198c2ecf20Sopenharmony_ci .writeable_reg = sunxi_sram_regmap_accessible_reg, 3208c2ecf20Sopenharmony_ci}; 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_cistatic int __init sunxi_sram_probe(struct platform_device *pdev) 3238c2ecf20Sopenharmony_ci{ 3248c2ecf20Sopenharmony_ci struct regmap *emac_clock; 3258c2ecf20Sopenharmony_ci const struct sunxi_sramc_variant *variant; 3268c2ecf20Sopenharmony_ci struct device *dev = &pdev->dev; 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci sram_dev = &pdev->dev; 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci variant = of_device_get_match_data(&pdev->dev); 3318c2ecf20Sopenharmony_ci if (!variant) 3328c2ecf20Sopenharmony_ci return -EINVAL; 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci base = devm_platform_ioremap_resource(pdev, 0); 3358c2ecf20Sopenharmony_ci if (IS_ERR(base)) 3368c2ecf20Sopenharmony_ci return PTR_ERR(base); 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci if (variant->has_emac_clock) { 3398c2ecf20Sopenharmony_ci emac_clock = devm_regmap_init_mmio(&pdev->dev, base, 3408c2ecf20Sopenharmony_ci &sunxi_sram_emac_clock_regmap); 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci if (IS_ERR(emac_clock)) 3438c2ecf20Sopenharmony_ci return PTR_ERR(emac_clock); 3448c2ecf20Sopenharmony_ci } 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci of_platform_populate(dev->of_node, NULL, NULL, dev); 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci debugfs_create_file("sram", 0444, NULL, NULL, &sunxi_sram_fops); 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci return 0; 3518c2ecf20Sopenharmony_ci} 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_cistatic const struct of_device_id sunxi_sram_dt_match[] = { 3548c2ecf20Sopenharmony_ci { 3558c2ecf20Sopenharmony_ci .compatible = "allwinner,sun4i-a10-sram-controller", 3568c2ecf20Sopenharmony_ci .data = &sun4i_a10_sramc_variant, 3578c2ecf20Sopenharmony_ci }, 3588c2ecf20Sopenharmony_ci { 3598c2ecf20Sopenharmony_ci .compatible = "allwinner,sun4i-a10-system-control", 3608c2ecf20Sopenharmony_ci .data = &sun4i_a10_sramc_variant, 3618c2ecf20Sopenharmony_ci }, 3628c2ecf20Sopenharmony_ci { 3638c2ecf20Sopenharmony_ci .compatible = "allwinner,sun5i-a13-system-control", 3648c2ecf20Sopenharmony_ci .data = &sun4i_a10_sramc_variant, 3658c2ecf20Sopenharmony_ci }, 3668c2ecf20Sopenharmony_ci { 3678c2ecf20Sopenharmony_ci .compatible = "allwinner,sun8i-a23-system-control", 3688c2ecf20Sopenharmony_ci .data = &sun4i_a10_sramc_variant, 3698c2ecf20Sopenharmony_ci }, 3708c2ecf20Sopenharmony_ci { 3718c2ecf20Sopenharmony_ci .compatible = "allwinner,sun8i-h3-system-control", 3728c2ecf20Sopenharmony_ci .data = &sun8i_h3_sramc_variant, 3738c2ecf20Sopenharmony_ci }, 3748c2ecf20Sopenharmony_ci { 3758c2ecf20Sopenharmony_ci .compatible = "allwinner,sun50i-a64-sram-controller", 3768c2ecf20Sopenharmony_ci .data = &sun50i_a64_sramc_variant, 3778c2ecf20Sopenharmony_ci }, 3788c2ecf20Sopenharmony_ci { 3798c2ecf20Sopenharmony_ci .compatible = "allwinner,sun50i-a64-system-control", 3808c2ecf20Sopenharmony_ci .data = &sun50i_a64_sramc_variant, 3818c2ecf20Sopenharmony_ci }, 3828c2ecf20Sopenharmony_ci { 3838c2ecf20Sopenharmony_ci .compatible = "allwinner,sun50i-h5-system-control", 3848c2ecf20Sopenharmony_ci .data = &sun50i_a64_sramc_variant, 3858c2ecf20Sopenharmony_ci }, 3868c2ecf20Sopenharmony_ci { }, 3878c2ecf20Sopenharmony_ci}; 3888c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, sunxi_sram_dt_match); 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_cistatic struct platform_driver sunxi_sram_driver = { 3918c2ecf20Sopenharmony_ci .driver = { 3928c2ecf20Sopenharmony_ci .name = "sunxi-sram", 3938c2ecf20Sopenharmony_ci .of_match_table = sunxi_sram_dt_match, 3948c2ecf20Sopenharmony_ci }, 3958c2ecf20Sopenharmony_ci}; 3968c2ecf20Sopenharmony_cibuiltin_platform_driver_probe(sunxi_sram_driver, sunxi_sram_probe); 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ciMODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>"); 3998c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Allwinner sunXi SRAM Controller Driver"); 4008c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 401