xref: /openbmc/linux/drivers/soc/sunxi/sunxi_sram.c (revision adedd5d1)
14af34b57SMaxime Ripard /*
24af34b57SMaxime Ripard  * Allwinner SoCs SRAM Controller Driver
34af34b57SMaxime Ripard  *
44af34b57SMaxime Ripard  * Copyright (C) 2015 Maxime Ripard
54af34b57SMaxime Ripard  *
64af34b57SMaxime Ripard  * Author: Maxime Ripard <maxime.ripard@free-electrons.com>
74af34b57SMaxime Ripard  *
84af34b57SMaxime Ripard  * This file is licensed under the terms of the GNU General Public
94af34b57SMaxime Ripard  * License version 2.  This program is licensed "as is" without any
104af34b57SMaxime Ripard  * warranty of any kind, whether express or implied.
114af34b57SMaxime Ripard  */
124af34b57SMaxime Ripard 
134af34b57SMaxime Ripard #include <linux/debugfs.h>
144af34b57SMaxime Ripard #include <linux/io.h>
154af34b57SMaxime Ripard #include <linux/module.h>
164af34b57SMaxime Ripard #include <linux/of.h>
174af34b57SMaxime Ripard #include <linux/of_address.h>
18*adedd5d1SRob Herring #include <linux/of_platform.h>
194af34b57SMaxime Ripard #include <linux/platform_device.h>
205828729bSIcenowy Zheng #include <linux/regmap.h>
214af34b57SMaxime Ripard 
224af34b57SMaxime Ripard #include <linux/soc/sunxi/sunxi_sram.h>
234af34b57SMaxime Ripard 
244af34b57SMaxime Ripard struct sunxi_sram_func {
254af34b57SMaxime Ripard 	char	*func;
264af34b57SMaxime Ripard 	u8	val;
278fed2ce9SIcenowy Zheng 	u32	reg_val;
284af34b57SMaxime Ripard };
294af34b57SMaxime Ripard 
304af34b57SMaxime Ripard struct sunxi_sram_data {
314af34b57SMaxime Ripard 	char			*name;
324af34b57SMaxime Ripard 	u8			reg;
334af34b57SMaxime Ripard 	u8			offset;
344af34b57SMaxime Ripard 	u8			width;
354af34b57SMaxime Ripard 	struct sunxi_sram_func	*func;
364af34b57SMaxime Ripard 	struct list_head	list;
374af34b57SMaxime Ripard };
384af34b57SMaxime Ripard 
394af34b57SMaxime Ripard struct sunxi_sram_desc {
404af34b57SMaxime Ripard 	struct sunxi_sram_data	data;
414af34b57SMaxime Ripard 	bool			claimed;
424af34b57SMaxime Ripard };
434af34b57SMaxime Ripard 
448fed2ce9SIcenowy Zheng #define SUNXI_SRAM_MAP(_reg_val, _val, _func)			\
454af34b57SMaxime Ripard 	{							\
464af34b57SMaxime Ripard 		.func = _func,					\
474af34b57SMaxime Ripard 		.val = _val,					\
488fed2ce9SIcenowy Zheng 		.reg_val = _reg_val,				\
494af34b57SMaxime Ripard 	}
504af34b57SMaxime Ripard 
514af34b57SMaxime Ripard #define SUNXI_SRAM_DATA(_name, _reg, _off, _width, ...)		\
524af34b57SMaxime Ripard 	{							\
534af34b57SMaxime Ripard 		.name = _name,					\
544af34b57SMaxime Ripard 		.reg = _reg,					\
554af34b57SMaxime Ripard 		.offset = _off,					\
564af34b57SMaxime Ripard 		.width = _width,				\
574af34b57SMaxime Ripard 		.func = (struct sunxi_sram_func[]){		\
584af34b57SMaxime Ripard 			__VA_ARGS__, { } },			\
594af34b57SMaxime Ripard 	}
604af34b57SMaxime Ripard 
614af34b57SMaxime Ripard static struct sunxi_sram_desc sun4i_a10_sram_a3_a4 = {
624af34b57SMaxime Ripard 	.data	= SUNXI_SRAM_DATA("A3-A4", 0x4, 0x4, 2,
638fed2ce9SIcenowy Zheng 				  SUNXI_SRAM_MAP(0, 0, "cpu"),
648fed2ce9SIcenowy Zheng 				  SUNXI_SRAM_MAP(1, 1, "emac")),
654af34b57SMaxime Ripard };
664af34b57SMaxime Ripard 
675fdec16bSMaxime Ripard static struct sunxi_sram_desc sun4i_a10_sram_c1 = {
685fdec16bSMaxime Ripard 	.data	= SUNXI_SRAM_DATA("C1", 0x0, 0x0, 31,
695fdec16bSMaxime Ripard 				  SUNXI_SRAM_MAP(0, 0, "cpu"),
705fdec16bSMaxime Ripard 				  SUNXI_SRAM_MAP(0x7fffffff, 1, "ve")),
715fdec16bSMaxime Ripard };
725fdec16bSMaxime Ripard 
734af34b57SMaxime Ripard static struct sunxi_sram_desc sun4i_a10_sram_d = {
744af34b57SMaxime Ripard 	.data	= SUNXI_SRAM_DATA("D", 0x4, 0x0, 1,
758fed2ce9SIcenowy Zheng 				  SUNXI_SRAM_MAP(0, 0, "cpu"),
768fed2ce9SIcenowy Zheng 				  SUNXI_SRAM_MAP(1, 1, "usb-otg")),
774af34b57SMaxime Ripard };
784af34b57SMaxime Ripard 
795e4fb642SIcenowy Zheng static struct sunxi_sram_desc sun50i_a64_sram_c = {
805e4fb642SIcenowy Zheng 	.data	= SUNXI_SRAM_DATA("C", 0x4, 24, 1,
81e3c95edbSSamuel Holland 				  SUNXI_SRAM_MAP(1, 0, "cpu"),
82e3c95edbSSamuel Holland 				  SUNXI_SRAM_MAP(0, 1, "de2")),
835e4fb642SIcenowy Zheng };
845e4fb642SIcenowy Zheng 
854af34b57SMaxime Ripard static const struct of_device_id sunxi_sram_dt_ids[] = {
864af34b57SMaxime Ripard 	{
874af34b57SMaxime Ripard 		.compatible	= "allwinner,sun4i-a10-sram-a3-a4",
884af34b57SMaxime Ripard 		.data		= &sun4i_a10_sram_a3_a4.data,
894af34b57SMaxime Ripard 	},
904af34b57SMaxime Ripard 	{
915fdec16bSMaxime Ripard 		.compatible	= "allwinner,sun4i-a10-sram-c1",
925fdec16bSMaxime Ripard 		.data		= &sun4i_a10_sram_c1.data,
935fdec16bSMaxime Ripard 	},
945fdec16bSMaxime Ripard 	{
954af34b57SMaxime Ripard 		.compatible	= "allwinner,sun4i-a10-sram-d",
964af34b57SMaxime Ripard 		.data		= &sun4i_a10_sram_d.data,
974af34b57SMaxime Ripard 	},
985e4fb642SIcenowy Zheng 	{
995e4fb642SIcenowy Zheng 		.compatible	= "allwinner,sun50i-a64-sram-c",
1005e4fb642SIcenowy Zheng 		.data		= &sun50i_a64_sram_c.data,
1015e4fb642SIcenowy Zheng 	},
1024af34b57SMaxime Ripard 	{}
1034af34b57SMaxime Ripard };
1044af34b57SMaxime Ripard 
1054af34b57SMaxime Ripard static struct device *sram_dev;
1064af34b57SMaxime Ripard static LIST_HEAD(claimed_sram);
1074af34b57SMaxime Ripard static DEFINE_SPINLOCK(sram_lock);
1084af34b57SMaxime Ripard static void __iomem *base;
1094af34b57SMaxime Ripard 
sunxi_sram_show(struct seq_file * s,void * data)1104af34b57SMaxime Ripard static int sunxi_sram_show(struct seq_file *s, void *data)
1114af34b57SMaxime Ripard {
1124af34b57SMaxime Ripard 	struct device_node *sram_node, *section_node;
1134af34b57SMaxime Ripard 	const struct sunxi_sram_data *sram_data;
1144af34b57SMaxime Ripard 	const struct of_device_id *match;
1154af34b57SMaxime Ripard 	struct sunxi_sram_func *func;
1164af34b57SMaxime Ripard 	const __be32 *sram_addr_p, *section_addr_p;
1174af34b57SMaxime Ripard 	u32 val;
1184af34b57SMaxime Ripard 
1194af34b57SMaxime Ripard 	seq_puts(s, "Allwinner sunXi SRAM\n");
1204af34b57SMaxime Ripard 	seq_puts(s, "--------------------\n\n");
1214af34b57SMaxime Ripard 
1224af34b57SMaxime Ripard 	for_each_child_of_node(sram_dev->of_node, sram_node) {
12373b7d7f2SSamuel Holland 		if (!of_device_is_compatible(sram_node, "mmio-sram"))
12473b7d7f2SSamuel Holland 			continue;
12573b7d7f2SSamuel Holland 
1264af34b57SMaxime Ripard 		sram_addr_p = of_get_address(sram_node, 0, NULL, NULL);
1274af34b57SMaxime Ripard 
1284af34b57SMaxime Ripard 		seq_printf(s, "sram@%08x\n",
1294af34b57SMaxime Ripard 			   be32_to_cpu(*sram_addr_p));
1304af34b57SMaxime Ripard 
1314af34b57SMaxime Ripard 		for_each_child_of_node(sram_node, section_node) {
1324af34b57SMaxime Ripard 			match = of_match_node(sunxi_sram_dt_ids, section_node);
1334af34b57SMaxime Ripard 			if (!match)
1344af34b57SMaxime Ripard 				continue;
1354af34b57SMaxime Ripard 			sram_data = match->data;
1364af34b57SMaxime Ripard 
1374af34b57SMaxime Ripard 			section_addr_p = of_get_address(section_node, 0,
1384af34b57SMaxime Ripard 							NULL, NULL);
1394af34b57SMaxime Ripard 
1404af34b57SMaxime Ripard 			seq_printf(s, "\tsection@%04x\t(%s)\n",
1414af34b57SMaxime Ripard 				   be32_to_cpu(*section_addr_p),
1424af34b57SMaxime Ripard 				   sram_data->name);
1434af34b57SMaxime Ripard 
1444af34b57SMaxime Ripard 			val = readl(base + sram_data->reg);
1454af34b57SMaxime Ripard 			val >>= sram_data->offset;
146febe6569SJens Kuske 			val &= GENMASK(sram_data->width - 1, 0);
1474af34b57SMaxime Ripard 
1484af34b57SMaxime Ripard 			for (func = sram_data->func; func->func; func++) {
1494af34b57SMaxime Ripard 				seq_printf(s, "\t\t%s%c\n", func->func,
1508fed2ce9SIcenowy Zheng 					   func->reg_val == val ?
1518fed2ce9SIcenowy Zheng 					   '*' : ' ');
1524af34b57SMaxime Ripard 			}
1534af34b57SMaxime Ripard 		}
1544af34b57SMaxime Ripard 
1554af34b57SMaxime Ripard 		seq_puts(s, "\n");
1564af34b57SMaxime Ripard 	}
1574af34b57SMaxime Ripard 
1584af34b57SMaxime Ripard 	return 0;
1594af34b57SMaxime Ripard }
1604af34b57SMaxime Ripard 
1612a8c9f12SYangtao Li DEFINE_SHOW_ATTRIBUTE(sunxi_sram);
1624af34b57SMaxime Ripard 
to_sram_desc(const struct sunxi_sram_data * data)1634af34b57SMaxime Ripard static inline struct sunxi_sram_desc *to_sram_desc(const struct sunxi_sram_data *data)
1644af34b57SMaxime Ripard {
1654af34b57SMaxime Ripard 	return container_of(data, struct sunxi_sram_desc, data);
1664af34b57SMaxime Ripard }
1674af34b57SMaxime Ripard 
sunxi_sram_of_parse(struct device_node * node,unsigned int * reg_value)1684af34b57SMaxime Ripard static const struct sunxi_sram_data *sunxi_sram_of_parse(struct device_node *node,
1698fed2ce9SIcenowy Zheng 							 unsigned int *reg_value)
1704af34b57SMaxime Ripard {
1714af34b57SMaxime Ripard 	const struct of_device_id *match;
1728fed2ce9SIcenowy Zheng 	const struct sunxi_sram_data *data;
1738fed2ce9SIcenowy Zheng 	struct sunxi_sram_func *func;
1744af34b57SMaxime Ripard 	struct of_phandle_args args;
1758fed2ce9SIcenowy Zheng 	u8 val;
1764af34b57SMaxime Ripard 	int ret;
1774af34b57SMaxime Ripard 
1784af34b57SMaxime Ripard 	ret = of_parse_phandle_with_fixed_args(node, "allwinner,sram", 1, 0,
1794af34b57SMaxime Ripard 					       &args);
1804af34b57SMaxime Ripard 	if (ret)
1814af34b57SMaxime Ripard 		return ERR_PTR(ret);
1824af34b57SMaxime Ripard 
1834af34b57SMaxime Ripard 	if (!of_device_is_available(args.np)) {
1844af34b57SMaxime Ripard 		ret = -EBUSY;
1854af34b57SMaxime Ripard 		goto err;
1864af34b57SMaxime Ripard 	}
1874af34b57SMaxime Ripard 
1888fed2ce9SIcenowy Zheng 	val = args.args[0];
1894af34b57SMaxime Ripard 
1904af34b57SMaxime Ripard 	match = of_match_node(sunxi_sram_dt_ids, args.np);
1914af34b57SMaxime Ripard 	if (!match) {
1924af34b57SMaxime Ripard 		ret = -EINVAL;
1934af34b57SMaxime Ripard 		goto err;
1944af34b57SMaxime Ripard 	}
1954af34b57SMaxime Ripard 
1968fed2ce9SIcenowy Zheng 	data = match->data;
1978fed2ce9SIcenowy Zheng 	if (!data) {
1988fed2ce9SIcenowy Zheng 		ret = -EINVAL;
1998fed2ce9SIcenowy Zheng 		goto err;
2001893a2d5SJason Yan 	}
2018fed2ce9SIcenowy Zheng 
2028fed2ce9SIcenowy Zheng 	for (func = data->func; func->func; func++) {
2038fed2ce9SIcenowy Zheng 		if (val == func->val) {
2048fed2ce9SIcenowy Zheng 			if (reg_value)
2058fed2ce9SIcenowy Zheng 				*reg_value = func->reg_val;
2068fed2ce9SIcenowy Zheng 
2078fed2ce9SIcenowy Zheng 			break;
2088fed2ce9SIcenowy Zheng 		}
2098fed2ce9SIcenowy Zheng 	}
2108fed2ce9SIcenowy Zheng 
2118fed2ce9SIcenowy Zheng 	if (!func->func) {
2128fed2ce9SIcenowy Zheng 		ret = -EINVAL;
2138fed2ce9SIcenowy Zheng 		goto err;
2148fed2ce9SIcenowy Zheng 	}
2158fed2ce9SIcenowy Zheng 
2164af34b57SMaxime Ripard 	of_node_put(args.np);
2174af34b57SMaxime Ripard 	return match->data;
2184af34b57SMaxime Ripard 
2194af34b57SMaxime Ripard err:
2204af34b57SMaxime Ripard 	of_node_put(args.np);
2214af34b57SMaxime Ripard 	return ERR_PTR(ret);
2224af34b57SMaxime Ripard }
2234af34b57SMaxime Ripard 
sunxi_sram_claim(struct device * dev)2244af34b57SMaxime Ripard int sunxi_sram_claim(struct device *dev)
2254af34b57SMaxime Ripard {
2264af34b57SMaxime Ripard 	const struct sunxi_sram_data *sram_data;
2274af34b57SMaxime Ripard 	struct sunxi_sram_desc *sram_desc;
2284af34b57SMaxime Ripard 	unsigned int device;
2294af34b57SMaxime Ripard 	u32 val, mask;
2304af34b57SMaxime Ripard 
2314af34b57SMaxime Ripard 	if (IS_ERR(base))
2322262a65fSIcenowy Zheng 		return PTR_ERR(base);
2332262a65fSIcenowy Zheng 
2342262a65fSIcenowy Zheng 	if (!base)
2354af34b57SMaxime Ripard 		return -EPROBE_DEFER;
2364af34b57SMaxime Ripard 
2374af34b57SMaxime Ripard 	if (!dev || !dev->of_node)
2384af34b57SMaxime Ripard 		return -EINVAL;
2394af34b57SMaxime Ripard 
2404af34b57SMaxime Ripard 	sram_data = sunxi_sram_of_parse(dev->of_node, &device);
2414af34b57SMaxime Ripard 	if (IS_ERR(sram_data))
2424af34b57SMaxime Ripard 		return PTR_ERR(sram_data);
2434af34b57SMaxime Ripard 
2444af34b57SMaxime Ripard 	sram_desc = to_sram_desc(sram_data);
2454af34b57SMaxime Ripard 
2464af34b57SMaxime Ripard 	spin_lock(&sram_lock);
2474af34b57SMaxime Ripard 
2484af34b57SMaxime Ripard 	if (sram_desc->claimed) {
2494af34b57SMaxime Ripard 		spin_unlock(&sram_lock);
2504af34b57SMaxime Ripard 		return -EBUSY;
2514af34b57SMaxime Ripard 	}
2524af34b57SMaxime Ripard 
253febe6569SJens Kuske 	mask = GENMASK(sram_data->offset + sram_data->width - 1,
254febe6569SJens Kuske 		       sram_data->offset);
2554af34b57SMaxime Ripard 	val = readl(base + sram_data->reg);
2564af34b57SMaxime Ripard 	val &= ~mask;
2574af34b57SMaxime Ripard 	writel(val | ((device << sram_data->offset) & mask),
2584af34b57SMaxime Ripard 	       base + sram_data->reg);
2594af34b57SMaxime Ripard 
260fd362baaSSamuel Holland 	sram_desc->claimed = true;
2614af34b57SMaxime Ripard 	spin_unlock(&sram_lock);
2624af34b57SMaxime Ripard 
2634af34b57SMaxime Ripard 	return 0;
2644af34b57SMaxime Ripard }
2654af34b57SMaxime Ripard EXPORT_SYMBOL(sunxi_sram_claim);
2664af34b57SMaxime Ripard 
sunxi_sram_release(struct device * dev)267460d9cb6SSamuel Holland void sunxi_sram_release(struct device *dev)
2684af34b57SMaxime Ripard {
2694af34b57SMaxime Ripard 	const struct sunxi_sram_data *sram_data;
2704af34b57SMaxime Ripard 	struct sunxi_sram_desc *sram_desc;
2714af34b57SMaxime Ripard 
2724af34b57SMaxime Ripard 	if (!dev || !dev->of_node)
273460d9cb6SSamuel Holland 		return;
2744af34b57SMaxime Ripard 
2754af34b57SMaxime Ripard 	sram_data = sunxi_sram_of_parse(dev->of_node, NULL);
2764af34b57SMaxime Ripard 	if (IS_ERR(sram_data))
277460d9cb6SSamuel Holland 		return;
2784af34b57SMaxime Ripard 
2794af34b57SMaxime Ripard 	sram_desc = to_sram_desc(sram_data);
2804af34b57SMaxime Ripard 
2814af34b57SMaxime Ripard 	spin_lock(&sram_lock);
2824af34b57SMaxime Ripard 	sram_desc->claimed = false;
2834af34b57SMaxime Ripard 	spin_unlock(&sram_lock);
2844af34b57SMaxime Ripard }
2854af34b57SMaxime Ripard EXPORT_SYMBOL(sunxi_sram_release);
2864af34b57SMaxime Ripard 
2875828729bSIcenowy Zheng struct sunxi_sramc_variant {
2889117d0c9SAndre Przywara 	int num_emac_clocks;
289dd2ae2ecSSamuel Holland 	bool has_ldo_ctrl;
2905828729bSIcenowy Zheng };
2915828729bSIcenowy Zheng 
2925828729bSIcenowy Zheng static const struct sunxi_sramc_variant sun4i_a10_sramc_variant = {
2935828729bSIcenowy Zheng 	/* Nothing special */
2945828729bSIcenowy Zheng };
2955828729bSIcenowy Zheng 
29615e53723SPaul Kocialkowski static const struct sunxi_sramc_variant sun8i_h3_sramc_variant = {
2979117d0c9SAndre Przywara 	.num_emac_clocks = 1,
29815e53723SPaul Kocialkowski };
29915e53723SPaul Kocialkowski 
3001f698cb1SSamuel Holland static const struct sunxi_sramc_variant sun20i_d1_sramc_variant = {
3011f698cb1SSamuel Holland 	.num_emac_clocks = 1,
3021f698cb1SSamuel Holland 	.has_ldo_ctrl = true,
3031f698cb1SSamuel Holland };
3041f698cb1SSamuel Holland 
3055828729bSIcenowy Zheng static const struct sunxi_sramc_variant sun50i_a64_sramc_variant = {
3069117d0c9SAndre Przywara 	.num_emac_clocks = 1,
3079117d0c9SAndre Przywara };
3089117d0c9SAndre Przywara 
3099117d0c9SAndre Przywara static const struct sunxi_sramc_variant sun50i_h616_sramc_variant = {
3109117d0c9SAndre Przywara 	.num_emac_clocks = 2,
3115828729bSIcenowy Zheng };
3125828729bSIcenowy Zheng 
3135828729bSIcenowy Zheng #define SUNXI_SRAM_EMAC_CLOCK_REG	0x30
314dd2ae2ecSSamuel Holland #define SUNXI_SYS_LDO_CTRL_REG		0x150
315dd2ae2ecSSamuel Holland 
sunxi_sram_regmap_accessible_reg(struct device * dev,unsigned int reg)3165828729bSIcenowy Zheng static bool sunxi_sram_regmap_accessible_reg(struct device *dev,
3175828729bSIcenowy Zheng 					     unsigned int reg)
3185828729bSIcenowy Zheng {
319ee07b905SSamuel Holland 	const struct sunxi_sramc_variant *variant = dev_get_drvdata(dev);
3209117d0c9SAndre Przywara 
321dd2ae2ecSSamuel Holland 	if (reg >= SUNXI_SRAM_EMAC_CLOCK_REG &&
322dd2ae2ecSSamuel Holland 	    reg <  SUNXI_SRAM_EMAC_CLOCK_REG + variant->num_emac_clocks * 4)
3239117d0c9SAndre Przywara 		return true;
324dd2ae2ecSSamuel Holland 	if (reg == SUNXI_SYS_LDO_CTRL_REG && variant->has_ldo_ctrl)
325dd2ae2ecSSamuel Holland 		return true;
326dd2ae2ecSSamuel Holland 
327dd2ae2ecSSamuel Holland 	return false;
3285828729bSIcenowy Zheng }
3295828729bSIcenowy Zheng 
330dd2ae2ecSSamuel Holland static struct regmap_config sunxi_sram_regmap_config = {
3315828729bSIcenowy Zheng 	.reg_bits       = 32,
3325828729bSIcenowy Zheng 	.val_bits       = 32,
3335828729bSIcenowy Zheng 	.reg_stride     = 4,
3345828729bSIcenowy Zheng 	/* last defined register */
335dd2ae2ecSSamuel Holland 	.max_register   = SUNXI_SYS_LDO_CTRL_REG,
3365828729bSIcenowy Zheng 	/* other devices have no business accessing other registers */
3375828729bSIcenowy Zheng 	.readable_reg	= sunxi_sram_regmap_accessible_reg,
3385828729bSIcenowy Zheng 	.writeable_reg	= sunxi_sram_regmap_accessible_reg,
3395828729bSIcenowy Zheng };
3405828729bSIcenowy Zheng 
sunxi_sram_probe(struct platform_device * pdev)34190e10a1fSSamuel Holland static int __init sunxi_sram_probe(struct platform_device *pdev)
3424af34b57SMaxime Ripard {
3435828729bSIcenowy Zheng 	const struct sunxi_sramc_variant *variant;
34449fad91aSSamuel Holland 	struct device *dev = &pdev->dev;
345dd2ae2ecSSamuel Holland 	struct regmap *regmap;
3464af34b57SMaxime Ripard 
3474af34b57SMaxime Ripard 	sram_dev = &pdev->dev;
3484af34b57SMaxime Ripard 
3495828729bSIcenowy Zheng 	variant = of_device_get_match_data(&pdev->dev);
3505828729bSIcenowy Zheng 	if (!variant)
3515828729bSIcenowy Zheng 		return -EINVAL;
3525828729bSIcenowy Zheng 
353ee07b905SSamuel Holland 	dev_set_drvdata(dev, (struct sunxi_sramc_variant *)variant);
354ee07b905SSamuel Holland 
3551f3753a5SCai Huoqing 	base = devm_platform_ioremap_resource(pdev, 0);
3564af34b57SMaxime Ripard 	if (IS_ERR(base))
3574af34b57SMaxime Ripard 		return PTR_ERR(base);
3584af34b57SMaxime Ripard 
359dd2ae2ecSSamuel Holland 	if (variant->num_emac_clocks || variant->has_ldo_ctrl) {
360dd2ae2ecSSamuel Holland 		regmap = devm_regmap_init_mmio(dev, base, &sunxi_sram_regmap_config);
361dd2ae2ecSSamuel Holland 		if (IS_ERR(regmap))
362dd2ae2ecSSamuel Holland 			return PTR_ERR(regmap);
3635828729bSIcenowy Zheng 	}
3645828729bSIcenowy Zheng 
36549fad91aSSamuel Holland 	of_platform_populate(dev->of_node, NULL, NULL, dev);
36649fad91aSSamuel Holland 
36749fad91aSSamuel Holland 	debugfs_create_file("sram", 0444, NULL, NULL, &sunxi_sram_fops);
36849fad91aSSamuel Holland 
3694af34b57SMaxime Ripard 	return 0;
3704af34b57SMaxime Ripard }
3714af34b57SMaxime Ripard 
3724af34b57SMaxime Ripard static const struct of_device_id sunxi_sram_dt_match[] = {
3735828729bSIcenowy Zheng 	{
3745828729bSIcenowy Zheng 		.compatible = "allwinner,sun4i-a10-sram-controller",
3755828729bSIcenowy Zheng 		.data = &sun4i_a10_sramc_variant,
3765828729bSIcenowy Zheng 	},
3775828729bSIcenowy Zheng 	{
378acc26f59SPaul Kocialkowski 		.compatible = "allwinner,sun4i-a10-system-control",
379acc26f59SPaul Kocialkowski 		.data = &sun4i_a10_sramc_variant,
380acc26f59SPaul Kocialkowski 	},
381acc26f59SPaul Kocialkowski 	{
3827377330aSMaxime Ripard 		.compatible = "allwinner,sun5i-a13-system-control",
3837377330aSMaxime Ripard 		.data = &sun4i_a10_sramc_variant,
3847377330aSMaxime Ripard 	},
3857377330aSMaxime Ripard 	{
3867377330aSMaxime Ripard 		.compatible = "allwinner,sun8i-a23-system-control",
3877377330aSMaxime Ripard 		.data = &sun4i_a10_sramc_variant,
3887377330aSMaxime Ripard 	},
3897377330aSMaxime Ripard 	{
3907377330aSMaxime Ripard 		.compatible = "allwinner,sun8i-h3-system-control",
39115e53723SPaul Kocialkowski 		.data = &sun8i_h3_sramc_variant,
3927377330aSMaxime Ripard 	},
3937377330aSMaxime Ripard 	{
3941f698cb1SSamuel Holland 		.compatible = "allwinner,sun20i-d1-system-control",
3951f698cb1SSamuel Holland 		.data = &sun20i_d1_sramc_variant,
3961f698cb1SSamuel Holland 	},
3971f698cb1SSamuel Holland 	{
3985828729bSIcenowy Zheng 		.compatible = "allwinner,sun50i-a64-sram-controller",
3995828729bSIcenowy Zheng 		.data = &sun50i_a64_sramc_variant,
4005828729bSIcenowy Zheng 	},
401ede18ae3SChen-Yu Tsai 	{
402ede18ae3SChen-Yu Tsai 		.compatible = "allwinner,sun50i-a64-system-control",
403ede18ae3SChen-Yu Tsai 		.data = &sun50i_a64_sramc_variant,
404ede18ae3SChen-Yu Tsai 	},
405c7739268SPaul Kocialkowski 	{
406c7739268SPaul Kocialkowski 		.compatible = "allwinner,sun50i-h5-system-control",
407c7739268SPaul Kocialkowski 		.data = &sun50i_a64_sramc_variant,
408c7739268SPaul Kocialkowski 	},
4099117d0c9SAndre Przywara 	{
4109117d0c9SAndre Przywara 		.compatible = "allwinner,sun50i-h616-system-control",
4119117d0c9SAndre Przywara 		.data = &sun50i_h616_sramc_variant,
4129117d0c9SAndre Przywara 	},
4134af34b57SMaxime Ripard 	{ },
4144af34b57SMaxime Ripard };
4154af34b57SMaxime Ripard MODULE_DEVICE_TABLE(of, sunxi_sram_dt_match);
4164af34b57SMaxime Ripard 
4174af34b57SMaxime Ripard static struct platform_driver sunxi_sram_driver = {
4184af34b57SMaxime Ripard 	.driver = {
4194af34b57SMaxime Ripard 		.name		= "sunxi-sram",
4204af34b57SMaxime Ripard 		.of_match_table	= sunxi_sram_dt_match,
4214af34b57SMaxime Ripard 	},
4224af34b57SMaxime Ripard };
42390e10a1fSSamuel Holland builtin_platform_driver_probe(sunxi_sram_driver, sunxi_sram_probe);
4244af34b57SMaxime Ripard 
4254af34b57SMaxime Ripard MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
4264af34b57SMaxime Ripard MODULE_DESCRIPTION("Allwinner sunXi SRAM Controller Driver");
427