cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ctu.c (8917B)


      1// SPDX-License-Identifier: GPL-2.0
      2//
      3// ctu.c
      4//
      5// Copyright (c) 2015 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
      6
      7#include "rsnd.h"
      8
      9#define CTU_NAME_SIZE	16
     10#define CTU_NAME "ctu"
     11
     12/*
     13 * User needs to setup CTU by amixer, and its settings are
     14 * based on below registers
     15 *
     16 * CTUn_CPMDR : amixser set "CTU Pass"
     17 * CTUn_SV0xR : amixser set "CTU SV0"
     18 * CTUn_SV1xR : amixser set "CTU SV1"
     19 * CTUn_SV2xR : amixser set "CTU SV2"
     20 * CTUn_SV3xR : amixser set "CTU SV3"
     21 *
     22 * [CTU Pass]
     23 * 0000: default
     24 * 0001: Connect input data of channel 0
     25 * 0010: Connect input data of channel 1
     26 * 0011: Connect input data of channel 2
     27 * 0100: Connect input data of channel 3
     28 * 0101: Connect input data of channel 4
     29 * 0110: Connect input data of channel 5
     30 * 0111: Connect input data of channel 6
     31 * 1000: Connect input data of channel 7
     32 * 1001: Connect calculated data by scale values of matrix row 0
     33 * 1010: Connect calculated data by scale values of matrix row 1
     34 * 1011: Connect calculated data by scale values of matrix row 2
     35 * 1100: Connect calculated data by scale values of matrix row 3
     36 *
     37 * [CTU SVx]
     38 * [Output0] = [SV00, SV01, SV02, SV03, SV04, SV05, SV06, SV07]
     39 * [Output1] = [SV10, SV11, SV12, SV13, SV14, SV15, SV16, SV17]
     40 * [Output2] = [SV20, SV21, SV22, SV23, SV24, SV25, SV26, SV27]
     41 * [Output3] = [SV30, SV31, SV32, SV33, SV34, SV35, SV36, SV37]
     42 * [Output4] = [ 0,   0,    0,    0,    0,    0,    0,    0   ]
     43 * [Output5] = [ 0,   0,    0,    0,    0,    0,    0,    0   ]
     44 * [Output6] = [ 0,   0,    0,    0,    0,    0,    0,    0   ]
     45 * [Output7] = [ 0,   0,    0,    0,    0,    0,    0,    0   ]
     46 *
     47 * [SVxx]
     48 * Plus					Minus
     49 * value	time		dB	value		time		dB
     50 * -----------------------------------------------------------------------
     51 * H'7F_FFFF	2		6	H'80_0000	2		6
     52 * ...
     53 * H'40_0000	1		0	H'C0_0000	1		0
     54 * ...
     55 * H'00_0001	2.38 x 10^-7	-132
     56 * H'00_0000	0		Mute	H'FF_FFFF	2.38 x 10^-7	-132
     57 *
     58 *
     59 * Ex) Input ch -> Output ch
     60 *	1ch     ->  0ch
     61 *	0ch     ->  1ch
     62 *
     63 *	amixer set "CTU Reset" on
     64 *	amixer set "CTU Pass" 9,10
     65 *	amixer set "CTU SV0" 0,4194304
     66 *	amixer set "CTU SV1" 4194304,0
     67 * or
     68 *	amixer set "CTU Reset" on
     69 *	amixer set "CTU Pass" 2,1
     70 */
     71
     72struct rsnd_ctu {
     73	struct rsnd_mod mod;
     74	struct rsnd_kctrl_cfg_m pass;
     75	struct rsnd_kctrl_cfg_m sv[4];
     76	struct rsnd_kctrl_cfg_s reset;
     77	int channels;
     78	u32 flags;
     79};
     80
     81#define KCTRL_INITIALIZED	(1 << 0)
     82
     83#define rsnd_ctu_nr(priv) ((priv)->ctu_nr)
     84#define for_each_rsnd_ctu(pos, priv, i)					\
     85	for ((i) = 0;							\
     86	     ((i) < rsnd_ctu_nr(priv)) &&				\
     87		     ((pos) = (struct rsnd_ctu *)(priv)->ctu + i);	\
     88	     i++)
     89
     90#define rsnd_mod_to_ctu(_mod)	\
     91	container_of((_mod), struct rsnd_ctu, mod)
     92
     93#define rsnd_ctu_get(priv, id) ((struct rsnd_ctu *)(priv->ctu) + id)
     94
     95static void rsnd_ctu_activation(struct rsnd_mod *mod)
     96{
     97	rsnd_mod_write(mod, CTU_SWRSR, 0);
     98	rsnd_mod_write(mod, CTU_SWRSR, 1);
     99}
    100
    101static void rsnd_ctu_halt(struct rsnd_mod *mod)
    102{
    103	rsnd_mod_write(mod, CTU_CTUIR, 1);
    104	rsnd_mod_write(mod, CTU_SWRSR, 0);
    105}
    106
    107static int rsnd_ctu_probe_(struct rsnd_mod *mod,
    108			   struct rsnd_dai_stream *io,
    109			   struct rsnd_priv *priv)
    110{
    111	return rsnd_cmd_attach(io, rsnd_mod_id(mod));
    112}
    113
    114static void rsnd_ctu_value_init(struct rsnd_dai_stream *io,
    115			       struct rsnd_mod *mod)
    116{
    117	struct rsnd_ctu *ctu = rsnd_mod_to_ctu(mod);
    118	u32 cpmdr = 0;
    119	u32 scmdr = 0;
    120	int i, j;
    121
    122	for (i = 0; i < RSND_MAX_CHANNELS; i++) {
    123		u32 val = rsnd_kctrl_valm(ctu->pass, i);
    124
    125		cpmdr |= val << (28 - (i * 4));
    126
    127		if ((val > 0x8) && (scmdr < (val - 0x8)))
    128			scmdr = val - 0x8;
    129	}
    130
    131	rsnd_mod_write(mod, CTU_CTUIR, 1);
    132
    133	rsnd_mod_write(mod, CTU_ADINR, rsnd_runtime_channel_original(io));
    134
    135	rsnd_mod_write(mod, CTU_CPMDR, cpmdr);
    136
    137	rsnd_mod_write(mod, CTU_SCMDR, scmdr);
    138
    139	for (i = 0; i < 4; i++) {
    140
    141		if (i >= scmdr)
    142			break;
    143
    144		for (j = 0; j < RSND_MAX_CHANNELS; j++)
    145			rsnd_mod_write(mod, CTU_SVxxR(i, j), rsnd_kctrl_valm(ctu->sv[i], j));
    146	}
    147
    148	rsnd_mod_write(mod, CTU_CTUIR, 0);
    149}
    150
    151static void rsnd_ctu_value_reset(struct rsnd_dai_stream *io,
    152				 struct rsnd_mod *mod)
    153{
    154	struct rsnd_ctu *ctu = rsnd_mod_to_ctu(mod);
    155	int i;
    156
    157	if (!rsnd_kctrl_vals(ctu->reset))
    158		return;
    159
    160	for (i = 0; i < RSND_MAX_CHANNELS; i++) {
    161		rsnd_kctrl_valm(ctu->pass, i) = 0;
    162		rsnd_kctrl_valm(ctu->sv[0],  i) = 0;
    163		rsnd_kctrl_valm(ctu->sv[1],  i) = 0;
    164		rsnd_kctrl_valm(ctu->sv[2],  i) = 0;
    165		rsnd_kctrl_valm(ctu->sv[3],  i) = 0;
    166	}
    167	rsnd_kctrl_vals(ctu->reset) = 0;
    168}
    169
    170static int rsnd_ctu_init(struct rsnd_mod *mod,
    171			 struct rsnd_dai_stream *io,
    172			 struct rsnd_priv *priv)
    173{
    174	rsnd_mod_power_on(mod);
    175
    176	rsnd_ctu_activation(mod);
    177
    178	rsnd_ctu_value_init(io, mod);
    179
    180	return 0;
    181}
    182
    183static int rsnd_ctu_quit(struct rsnd_mod *mod,
    184			 struct rsnd_dai_stream *io,
    185			 struct rsnd_priv *priv)
    186{
    187	rsnd_ctu_halt(mod);
    188
    189	rsnd_mod_power_off(mod);
    190
    191	return 0;
    192}
    193
    194static int rsnd_ctu_pcm_new(struct rsnd_mod *mod,
    195			    struct rsnd_dai_stream *io,
    196			    struct snd_soc_pcm_runtime *rtd)
    197{
    198	struct rsnd_ctu *ctu = rsnd_mod_to_ctu(mod);
    199	int ret;
    200
    201	if (rsnd_flags_has(ctu, KCTRL_INITIALIZED))
    202		return 0;
    203
    204	/* CTU Pass */
    205	ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU Pass",
    206			       rsnd_kctrl_accept_anytime,
    207			       NULL,
    208			       &ctu->pass, RSND_MAX_CHANNELS,
    209			       0xC);
    210	if (ret < 0)
    211		return ret;
    212
    213	/* ROW0 */
    214	ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU SV0",
    215			       rsnd_kctrl_accept_anytime,
    216			       NULL,
    217			       &ctu->sv[0], RSND_MAX_CHANNELS,
    218			       0x00FFFFFF);
    219	if (ret < 0)
    220		return ret;
    221
    222	/* ROW1 */
    223	ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU SV1",
    224			       rsnd_kctrl_accept_anytime,
    225			       NULL,
    226			       &ctu->sv[1], RSND_MAX_CHANNELS,
    227			       0x00FFFFFF);
    228	if (ret < 0)
    229		return ret;
    230
    231	/* ROW2 */
    232	ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU SV2",
    233			       rsnd_kctrl_accept_anytime,
    234			       NULL,
    235			       &ctu->sv[2], RSND_MAX_CHANNELS,
    236			       0x00FFFFFF);
    237	if (ret < 0)
    238		return ret;
    239
    240	/* ROW3 */
    241	ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU SV3",
    242			       rsnd_kctrl_accept_anytime,
    243			       NULL,
    244			       &ctu->sv[3], RSND_MAX_CHANNELS,
    245			       0x00FFFFFF);
    246	if (ret < 0)
    247		return ret;
    248
    249	/* Reset */
    250	ret = rsnd_kctrl_new_s(mod, io, rtd, "CTU Reset",
    251			       rsnd_kctrl_accept_anytime,
    252			       rsnd_ctu_value_reset,
    253			       &ctu->reset, 1);
    254
    255	rsnd_flags_set(ctu, KCTRL_INITIALIZED);
    256
    257	return ret;
    258}
    259
    260static int rsnd_ctu_id(struct rsnd_mod *mod)
    261{
    262	/*
    263	 * ctu00: -> 0, ctu01: -> 0, ctu02: -> 0, ctu03: -> 0
    264	 * ctu10: -> 1, ctu11: -> 1, ctu12: -> 1, ctu13: -> 1
    265	 */
    266	return mod->id / 4;
    267}
    268
    269static int rsnd_ctu_id_sub(struct rsnd_mod *mod)
    270{
    271	/*
    272	 * ctu00: -> 0, ctu01: -> 1, ctu02: -> 2, ctu03: -> 3
    273	 * ctu10: -> 0, ctu11: -> 1, ctu12: -> 2, ctu13: -> 3
    274	 */
    275	return mod->id % 4;
    276}
    277
    278#ifdef CONFIG_DEBUG_FS
    279static void rsnd_ctu_debug_info(struct seq_file *m,
    280				struct rsnd_dai_stream *io,
    281				struct rsnd_mod *mod)
    282{
    283	rsnd_debugfs_mod_reg_show(m, mod, RSND_GEN2_SCU,
    284				  0x500 + rsnd_mod_id_raw(mod) * 0x100, 0x100);
    285}
    286#define DEBUG_INFO .debug_info = rsnd_ctu_debug_info
    287#else
    288#define DEBUG_INFO
    289#endif
    290
    291static struct rsnd_mod_ops rsnd_ctu_ops = {
    292	.name		= CTU_NAME,
    293	.probe		= rsnd_ctu_probe_,
    294	.init		= rsnd_ctu_init,
    295	.quit		= rsnd_ctu_quit,
    296	.pcm_new	= rsnd_ctu_pcm_new,
    297	.get_status	= rsnd_mod_get_status,
    298	.id		= rsnd_ctu_id,
    299	.id_sub		= rsnd_ctu_id_sub,
    300	.id_cmd		= rsnd_mod_id_raw,
    301	DEBUG_INFO
    302};
    303
    304struct rsnd_mod *rsnd_ctu_mod_get(struct rsnd_priv *priv, int id)
    305{
    306	if (WARN_ON(id < 0 || id >= rsnd_ctu_nr(priv)))
    307		id = 0;
    308
    309	return rsnd_mod_get(rsnd_ctu_get(priv, id));
    310}
    311
    312int rsnd_ctu_probe(struct rsnd_priv *priv)
    313{
    314	struct device_node *node;
    315	struct device_node *np;
    316	struct device *dev = rsnd_priv_to_dev(priv);
    317	struct rsnd_ctu *ctu;
    318	struct clk *clk;
    319	char name[CTU_NAME_SIZE];
    320	int i, nr, ret;
    321
    322	/* This driver doesn't support Gen1 at this point */
    323	if (rsnd_is_gen1(priv))
    324		return 0;
    325
    326	node = rsnd_ctu_of_node(priv);
    327	if (!node)
    328		return 0; /* not used is not error */
    329
    330	nr = of_get_child_count(node);
    331	if (!nr) {
    332		ret = -EINVAL;
    333		goto rsnd_ctu_probe_done;
    334	}
    335
    336	ctu = devm_kcalloc(dev, nr, sizeof(*ctu), GFP_KERNEL);
    337	if (!ctu) {
    338		ret = -ENOMEM;
    339		goto rsnd_ctu_probe_done;
    340	}
    341
    342	priv->ctu_nr	= nr;
    343	priv->ctu	= ctu;
    344
    345	i = 0;
    346	ret = 0;
    347	for_each_child_of_node(node, np) {
    348		ctu = rsnd_ctu_get(priv, i);
    349
    350		/*
    351		 * CTU00, CTU01, CTU02, CTU03 => CTU0
    352		 * CTU10, CTU11, CTU12, CTU13 => CTU1
    353		 */
    354		snprintf(name, CTU_NAME_SIZE, "%s.%d",
    355			 CTU_NAME, i / 4);
    356
    357		clk = devm_clk_get(dev, name);
    358		if (IS_ERR(clk)) {
    359			ret = PTR_ERR(clk);
    360			of_node_put(np);
    361			goto rsnd_ctu_probe_done;
    362		}
    363
    364		ret = rsnd_mod_init(priv, rsnd_mod_get(ctu), &rsnd_ctu_ops,
    365				    clk, RSND_MOD_CTU, i);
    366		if (ret) {
    367			of_node_put(np);
    368			goto rsnd_ctu_probe_done;
    369		}
    370
    371		i++;
    372	}
    373
    374
    375rsnd_ctu_probe_done:
    376	of_node_put(node);
    377
    378	return ret;
    379}
    380
    381void rsnd_ctu_remove(struct rsnd_priv *priv)
    382{
    383	struct rsnd_ctu *ctu;
    384	int i;
    385
    386	for_each_rsnd_ctu(ctu, priv, i) {
    387		rsnd_mod_quit(rsnd_mod_get(ctu));
    388	}
    389}