1/*
2 * Renesas R-Car Gen1 SRU/SSI support
3 *
4 * Copyright (C) 2013 Renesas Solutions Corp.
5 * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12/*
13 * #define DEBUG
14 *
15 * you can also add below in
16 * ${LINUX}/drivers/base/regmap/regmap.c
17 * for regmap debug
18 *
19 * #define LOG_DEVICE "xxxx.rcar_sound"
20 */
21
22#include "rsnd.h"
23
24struct rsnd_gen {
25	struct rsnd_gen_ops *ops;
26
27	/* RSND_BASE_MAX base */
28	void __iomem *base[RSND_BASE_MAX];
29	phys_addr_t res[RSND_BASE_MAX];
30	struct regmap *regmap[RSND_BASE_MAX];
31
32	/* RSND_REG_MAX base */
33	struct regmap_field *regs[RSND_REG_MAX];
34};
35
36#define rsnd_priv_to_gen(p)	((struct rsnd_gen *)(p)->gen)
37
38struct rsnd_regmap_field_conf {
39	int idx;
40	unsigned int reg_offset;
41	unsigned int id_offset;
42};
43
44#define RSND_REG_SET(id, offset, _id_offset)	\
45{						\
46	.idx = id,				\
47	.reg_offset = offset,			\
48	.id_offset = _id_offset,		\
49}
50/* single address mapping */
51#define RSND_GEN_S_REG(id, offset)	\
52	RSND_REG_SET(RSND_REG_##id, offset, 0)
53
54/* multi address mapping */
55#define RSND_GEN_M_REG(id, offset, _id_offset)	\
56	RSND_REG_SET(RSND_REG_##id, offset, _id_offset)
57
58/*
59 *		basic function
60 */
61static int rsnd_is_accessible_reg(struct rsnd_priv *priv,
62				  struct rsnd_gen *gen, enum rsnd_reg reg)
63{
64	if (!gen->regs[reg]) {
65		struct device *dev = rsnd_priv_to_dev(priv);
66
67		dev_err(dev, "unsupported register access %x\n", reg);
68		return 0;
69	}
70
71	return 1;
72}
73
74u32 rsnd_read(struct rsnd_priv *priv,
75	      struct rsnd_mod *mod, enum rsnd_reg reg)
76{
77	struct device *dev = rsnd_priv_to_dev(priv);
78	struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
79	u32 val;
80
81	if (!rsnd_is_accessible_reg(priv, gen, reg))
82		return 0;
83
84	regmap_fields_read(gen->regs[reg], rsnd_mod_id(mod), &val);
85
86	dev_dbg(dev, "r %s[%d] - %4d : %08x\n",
87		rsnd_mod_name(mod), rsnd_mod_id(mod), reg, val);
88
89	return val;
90}
91
92void rsnd_write(struct rsnd_priv *priv,
93		struct rsnd_mod *mod,
94		enum rsnd_reg reg, u32 data)
95{
96	struct device *dev = rsnd_priv_to_dev(priv);
97	struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
98
99	if (!rsnd_is_accessible_reg(priv, gen, reg))
100		return;
101
102	dev_dbg(dev, "w %s[%d] - %4d : %08x\n",
103		rsnd_mod_name(mod), rsnd_mod_id(mod), reg, data);
104
105	regmap_fields_write(gen->regs[reg], rsnd_mod_id(mod), data);
106}
107
108void rsnd_force_write(struct rsnd_priv *priv,
109		      struct rsnd_mod *mod,
110		      enum rsnd_reg reg, u32 data)
111{
112	struct device *dev = rsnd_priv_to_dev(priv);
113	struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
114
115	if (!rsnd_is_accessible_reg(priv, gen, reg))
116		return;
117
118	dev_dbg(dev, "w %s[%d] - %4d : %08x\n",
119		rsnd_mod_name(mod), rsnd_mod_id(mod), reg, data);
120
121	regmap_fields_force_write(gen->regs[reg], rsnd_mod_id(mod), data);
122}
123
124void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod,
125	       enum rsnd_reg reg, u32 mask, u32 data)
126{
127	struct device *dev = rsnd_priv_to_dev(priv);
128	struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
129
130	if (!rsnd_is_accessible_reg(priv, gen, reg))
131		return;
132
133	dev_dbg(dev, "b %s[%d] - %4d : %08x/%08x\n",
134		rsnd_mod_name(mod), rsnd_mod_id(mod), reg, data, mask);
135
136	regmap_fields_update_bits(gen->regs[reg], rsnd_mod_id(mod),
137				  mask, data);
138}
139
140phys_addr_t rsnd_gen_get_phy_addr(struct rsnd_priv *priv, int reg_id)
141{
142	struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
143
144	return	gen->res[reg_id];
145}
146
147#define rsnd_gen_regmap_init(priv, id_size, reg_id, name, conf)		\
148	_rsnd_gen_regmap_init(priv, id_size, reg_id, name, conf, ARRAY_SIZE(conf))
149static int _rsnd_gen_regmap_init(struct rsnd_priv *priv,
150				 int id_size,
151				 int reg_id,
152				 const char *name,
153				 struct rsnd_regmap_field_conf *conf,
154				 int conf_size)
155{
156	struct platform_device *pdev = rsnd_priv_to_pdev(priv);
157	struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
158	struct device *dev = rsnd_priv_to_dev(priv);
159	struct resource *res;
160	struct regmap_config regc;
161	struct regmap_field *regs;
162	struct regmap *regmap;
163	struct reg_field regf;
164	void __iomem *base;
165	int i;
166
167	memset(&regc, 0, sizeof(regc));
168	regc.reg_bits = 32;
169	regc.val_bits = 32;
170	regc.reg_stride = 4;
171	regc.name = name;
172
173	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
174	if (!res)
175		res = platform_get_resource(pdev, IORESOURCE_MEM, reg_id);
176	if (!res)
177		return -ENODEV;
178
179	base = devm_ioremap_resource(dev, res);
180	if (IS_ERR(base))
181		return PTR_ERR(base);
182
183	regmap = devm_regmap_init_mmio(dev, base, &regc);
184	if (IS_ERR(regmap))
185		return PTR_ERR(regmap);
186
187	/* RSND_BASE_MAX base */
188	gen->base[reg_id] = base;
189	gen->regmap[reg_id] = regmap;
190	gen->res[reg_id] = res->start;
191
192	for (i = 0; i < conf_size; i++) {
193
194		regf.reg	= conf[i].reg_offset;
195		regf.id_offset	= conf[i].id_offset;
196		regf.lsb	= 0;
197		regf.msb	= 31;
198		regf.id_size	= id_size;
199
200		regs = devm_regmap_field_alloc(dev, regmap, regf);
201		if (IS_ERR(regs))
202			return PTR_ERR(regs);
203
204		/* RSND_REG_MAX base */
205		gen->regs[conf[i].idx] = regs;
206	}
207
208	return 0;
209}
210
211/*
212 *		Gen2
213 */
214static int rsnd_gen2_probe(struct platform_device *pdev,
215			   struct rsnd_priv *priv)
216{
217	struct rsnd_regmap_field_conf conf_ssiu[] = {
218		RSND_GEN_S_REG(SSI_MODE0,	0x800),
219		RSND_GEN_S_REG(SSI_MODE1,	0x804),
220		/* FIXME: it needs SSI_MODE2/3 in the future */
221		RSND_GEN_M_REG(SSI_BUSIF_MODE,	0x0,	0x80),
222		RSND_GEN_M_REG(SSI_BUSIF_ADINR,	0x4,	0x80),
223		RSND_GEN_M_REG(SSI_BUSIF_DALIGN,0x8,	0x80),
224		RSND_GEN_M_REG(SSI_CTRL,	0x10,	0x80),
225		RSND_GEN_M_REG(SSI_INT_ENABLE,	0x18,	0x80),
226	};
227	struct rsnd_regmap_field_conf conf_scu[] = {
228		RSND_GEN_M_REG(SRC_BUSIF_MODE,	0x0,	0x20),
229		RSND_GEN_M_REG(SRC_BUSIF_DALIGN,0x8,	0x20),
230		RSND_GEN_M_REG(SRC_ROUTE_MODE0,	0xc,	0x20),
231		RSND_GEN_M_REG(SRC_CTRL,	0x10,	0x20),
232		RSND_GEN_M_REG(SRC_INT_ENABLE0,	0x18,	0x20),
233		RSND_GEN_M_REG(CMD_ROUTE_SLCT,	0x18c,	0x20),
234		RSND_GEN_M_REG(CMD_CTRL,	0x190,	0x20),
235		RSND_GEN_S_REG(SCU_SYS_STATUS0,	0x1c8),
236		RSND_GEN_S_REG(SCU_SYS_INT_EN0,	0x1cc),
237		RSND_GEN_S_REG(SCU_SYS_STATUS1,	0x1d0),
238		RSND_GEN_S_REG(SCU_SYS_INT_EN1,	0x1d4),
239		RSND_GEN_M_REG(SRC_SWRSR,	0x200,	0x40),
240		RSND_GEN_M_REG(SRC_SRCIR,	0x204,	0x40),
241		RSND_GEN_M_REG(SRC_ADINR,	0x214,	0x40),
242		RSND_GEN_M_REG(SRC_IFSCR,	0x21c,	0x40),
243		RSND_GEN_M_REG(SRC_IFSVR,	0x220,	0x40),
244		RSND_GEN_M_REG(SRC_SRCCR,	0x224,	0x40),
245		RSND_GEN_M_REG(SRC_BSDSR,	0x22c,	0x40),
246		RSND_GEN_M_REG(SRC_BSISR,	0x238,	0x40),
247		RSND_GEN_M_REG(CTU_CTUIR,	0x504,	0x100),
248		RSND_GEN_M_REG(CTU_ADINR,	0x508,	0x100),
249		RSND_GEN_M_REG(MIX_SWRSR,	0xd00,	0x40),
250		RSND_GEN_M_REG(MIX_MIXIR,	0xd04,	0x40),
251		RSND_GEN_M_REG(MIX_ADINR,	0xd08,	0x40),
252		RSND_GEN_M_REG(MIX_MIXMR,	0xd10,	0x40),
253		RSND_GEN_M_REG(MIX_MVPDR,	0xd14,	0x40),
254		RSND_GEN_M_REG(MIX_MDBAR,	0xd18,	0x40),
255		RSND_GEN_M_REG(MIX_MDBBR,	0xd1c,	0x40),
256		RSND_GEN_M_REG(MIX_MDBCR,	0xd20,	0x40),
257		RSND_GEN_M_REG(MIX_MDBDR,	0xd24,	0x40),
258		RSND_GEN_M_REG(MIX_MDBER,	0xd28,	0x40),
259		RSND_GEN_M_REG(DVC_SWRSR,	0xe00,	0x100),
260		RSND_GEN_M_REG(DVC_DVUIR,	0xe04,	0x100),
261		RSND_GEN_M_REG(DVC_ADINR,	0xe08,	0x100),
262		RSND_GEN_M_REG(DVC_DVUCR,	0xe10,	0x100),
263		RSND_GEN_M_REG(DVC_ZCMCR,	0xe14,	0x100),
264		RSND_GEN_M_REG(DVC_VRCTR,	0xe18,	0x100),
265		RSND_GEN_M_REG(DVC_VRPDR,	0xe1c,	0x100),
266		RSND_GEN_M_REG(DVC_VRDBR,	0xe20,	0x100),
267		RSND_GEN_M_REG(DVC_VOL0R,	0xe28,	0x100),
268		RSND_GEN_M_REG(DVC_VOL1R,	0xe2c,	0x100),
269		RSND_GEN_M_REG(DVC_DVUER,	0xe48,	0x100),
270	};
271	struct rsnd_regmap_field_conf conf_adg[] = {
272		RSND_GEN_S_REG(BRRA,		0x00),
273		RSND_GEN_S_REG(BRRB,		0x04),
274		RSND_GEN_S_REG(SSICKR,		0x08),
275		RSND_GEN_S_REG(AUDIO_CLK_SEL0,	0x0c),
276		RSND_GEN_S_REG(AUDIO_CLK_SEL1,	0x10),
277		RSND_GEN_S_REG(AUDIO_CLK_SEL2,	0x14),
278		RSND_GEN_S_REG(DIV_EN,		0x30),
279		RSND_GEN_S_REG(SRCIN_TIMSEL0,	0x34),
280		RSND_GEN_S_REG(SRCIN_TIMSEL1,	0x38),
281		RSND_GEN_S_REG(SRCIN_TIMSEL2,	0x3c),
282		RSND_GEN_S_REG(SRCIN_TIMSEL3,	0x40),
283		RSND_GEN_S_REG(SRCIN_TIMSEL4,	0x44),
284		RSND_GEN_S_REG(SRCOUT_TIMSEL0,	0x48),
285		RSND_GEN_S_REG(SRCOUT_TIMSEL1,	0x4c),
286		RSND_GEN_S_REG(SRCOUT_TIMSEL2,	0x50),
287		RSND_GEN_S_REG(SRCOUT_TIMSEL3,	0x54),
288		RSND_GEN_S_REG(SRCOUT_TIMSEL4,	0x58),
289		RSND_GEN_S_REG(CMDOUT_TIMSEL,	0x5c),
290	};
291	struct rsnd_regmap_field_conf conf_ssi[] = {
292		RSND_GEN_M_REG(SSICR,		0x00,	0x40),
293		RSND_GEN_M_REG(SSISR,		0x04,	0x40),
294		RSND_GEN_M_REG(SSITDR,		0x08,	0x40),
295		RSND_GEN_M_REG(SSIRDR,		0x0c,	0x40),
296		RSND_GEN_M_REG(SSIWSR,		0x20,	0x40),
297	};
298	int ret_ssiu;
299	int ret_scu;
300	int ret_adg;
301	int ret_ssi;
302
303	ret_ssiu = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_SSIU, "ssiu", conf_ssiu);
304	ret_scu  = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_SCU,  "scu",  conf_scu);
305	ret_adg  = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_ADG,  "adg",  conf_adg);
306	ret_ssi  = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_SSI,  "ssi",  conf_ssi);
307	if (ret_ssiu < 0 ||
308	    ret_scu  < 0 ||
309	    ret_adg  < 0 ||
310	    ret_ssi  < 0)
311		return ret_ssiu | ret_scu | ret_adg | ret_ssi;
312
313	return 0;
314}
315
316/*
317 *		Gen1
318 */
319
320static int rsnd_gen1_probe(struct platform_device *pdev,
321			   struct rsnd_priv *priv)
322{
323	struct rsnd_regmap_field_conf conf_sru[] = {
324		RSND_GEN_S_REG(SRC_ROUTE_SEL,	0x00),
325		RSND_GEN_S_REG(SRC_TMG_SEL0,	0x08),
326		RSND_GEN_S_REG(SRC_TMG_SEL1,	0x0c),
327		RSND_GEN_S_REG(SRC_TMG_SEL2,	0x10),
328		RSND_GEN_S_REG(SRC_ROUTE_CTRL,	0xc0),
329		RSND_GEN_S_REG(SSI_MODE0,	0xD0),
330		RSND_GEN_S_REG(SSI_MODE1,	0xD4),
331		RSND_GEN_M_REG(SRC_BUSIF_MODE,	0x20,	0x4),
332		RSND_GEN_M_REG(SRC_ROUTE_MODE0,	0x50,	0x8),
333		RSND_GEN_M_REG(SRC_SWRSR,	0x200,	0x40),
334		RSND_GEN_M_REG(SRC_SRCIR,	0x204,	0x40),
335		RSND_GEN_M_REG(SRC_ADINR,	0x214,	0x40),
336		RSND_GEN_M_REG(SRC_IFSCR,	0x21c,	0x40),
337		RSND_GEN_M_REG(SRC_IFSVR,	0x220,	0x40),
338		RSND_GEN_M_REG(SRC_SRCCR,	0x224,	0x40),
339		RSND_GEN_M_REG(SRC_MNFSR,	0x228,	0x40),
340		/*
341		 * ADD US
342		 *
343		 * SRC_STATUS
344		 * SRC_INT_EN
345		 * SCU_SYS_STATUS0
346		 * SCU_SYS_STATUS1
347		 * SCU_SYS_INT_EN0
348		 * SCU_SYS_INT_EN1
349		 */
350	};
351	struct rsnd_regmap_field_conf conf_adg[] = {
352		RSND_GEN_S_REG(BRRA,		0x00),
353		RSND_GEN_S_REG(BRRB,		0x04),
354		RSND_GEN_S_REG(SSICKR,		0x08),
355		RSND_GEN_S_REG(AUDIO_CLK_SEL0,	0x0c),
356		RSND_GEN_S_REG(AUDIO_CLK_SEL1,	0x10),
357		RSND_GEN_S_REG(AUDIO_CLK_SEL3,	0x18),
358		RSND_GEN_S_REG(AUDIO_CLK_SEL4,	0x1c),
359		RSND_GEN_S_REG(AUDIO_CLK_SEL5,	0x20),
360	};
361	struct rsnd_regmap_field_conf conf_ssi[] = {
362		RSND_GEN_M_REG(SSICR,		0x00,	0x40),
363		RSND_GEN_M_REG(SSISR,		0x04,	0x40),
364		RSND_GEN_M_REG(SSITDR,		0x08,	0x40),
365		RSND_GEN_M_REG(SSIRDR,		0x0c,	0x40),
366		RSND_GEN_M_REG(SSIWSR,		0x20,	0x40),
367	};
368	int ret_sru;
369	int ret_adg;
370	int ret_ssi;
371
372	ret_sru  = rsnd_gen_regmap_init(priv, 9, RSND_GEN1_SRU, "sru", conf_sru);
373	ret_adg  = rsnd_gen_regmap_init(priv, 9, RSND_GEN1_ADG, "adg", conf_adg);
374	ret_ssi  = rsnd_gen_regmap_init(priv, 9, RSND_GEN1_SSI, "ssi", conf_ssi);
375	if (ret_sru  < 0 ||
376	    ret_adg  < 0 ||
377	    ret_ssi  < 0)
378		return ret_sru | ret_adg | ret_ssi;
379
380	return 0;
381}
382
383/*
384 *		Gen
385 */
386static void rsnd_of_parse_gen(struct platform_device *pdev,
387			      const struct rsnd_of_data *of_data,
388			      struct rsnd_priv *priv)
389{
390	struct rcar_snd_info *info = priv->info;
391
392	if (!of_data)
393		return;
394
395	info->flags = of_data->flags;
396}
397
398int rsnd_gen_probe(struct platform_device *pdev,
399		   const struct rsnd_of_data *of_data,
400		   struct rsnd_priv *priv)
401{
402	struct device *dev = rsnd_priv_to_dev(priv);
403	struct rsnd_gen *gen;
404	int ret;
405
406	rsnd_of_parse_gen(pdev, of_data, priv);
407
408	gen = devm_kzalloc(dev, sizeof(*gen), GFP_KERNEL);
409	if (!gen) {
410		dev_err(dev, "GEN allocate failed\n");
411		return -ENOMEM;
412	}
413
414	priv->gen = gen;
415
416	ret = -ENODEV;
417	if (rsnd_is_gen1(priv))
418		ret = rsnd_gen1_probe(pdev, priv);
419	else if (rsnd_is_gen2(priv))
420		ret = rsnd_gen2_probe(pdev, priv);
421
422	if (ret < 0)
423		dev_err(dev, "unknown generation R-Car sound device\n");
424
425	return ret;
426}
427