xref: /openbmc/linux/drivers/soundwire/sysfs_slave.c (revision bcac59029955ae57d3c660a0a1d6d4c7ae78fb49)
1*bcac5902SPierre-Louis Bossart // SPDX-License-Identifier: GPL-2.0-only
2*bcac5902SPierre-Louis Bossart // Copyright(c) 2015-2020 Intel Corporation.
3*bcac5902SPierre-Louis Bossart 
4*bcac5902SPierre-Louis Bossart #include <linux/device.h>
5*bcac5902SPierre-Louis Bossart #include <linux/mod_devicetable.h>
6*bcac5902SPierre-Louis Bossart #include <linux/slab.h>
7*bcac5902SPierre-Louis Bossart #include <linux/sysfs.h>
8*bcac5902SPierre-Louis Bossart #include <linux/soundwire/sdw.h>
9*bcac5902SPierre-Louis Bossart #include <linux/soundwire/sdw_type.h>
10*bcac5902SPierre-Louis Bossart #include "bus.h"
11*bcac5902SPierre-Louis Bossart #include "sysfs_local.h"
12*bcac5902SPierre-Louis Bossart 
13*bcac5902SPierre-Louis Bossart /*
14*bcac5902SPierre-Louis Bossart  * Slave sysfs
15*bcac5902SPierre-Louis Bossart  */
16*bcac5902SPierre-Louis Bossart 
17*bcac5902SPierre-Louis Bossart /*
18*bcac5902SPierre-Louis Bossart  * The sysfs for Slave reflects the MIPI description as given
19*bcac5902SPierre-Louis Bossart  * in the MIPI DisCo spec
20*bcac5902SPierre-Louis Bossart  *
21*bcac5902SPierre-Louis Bossart  * Base file is device
22*bcac5902SPierre-Louis Bossart  *	|---- modalias
23*bcac5902SPierre-Louis Bossart  *	|---- dev-properties
24*bcac5902SPierre-Louis Bossart  *		|---- mipi_revision
25*bcac5902SPierre-Louis Bossart  *		|---- wake_capable
26*bcac5902SPierre-Louis Bossart  *		|---- test_mode_capable
27*bcac5902SPierre-Louis Bossart  *		|---- clk_stop_mode1
28*bcac5902SPierre-Louis Bossart  *		|---- simple_clk_stop_capable
29*bcac5902SPierre-Louis Bossart  *		|---- clk_stop_timeout
30*bcac5902SPierre-Louis Bossart  *		|---- ch_prep_timeout
31*bcac5902SPierre-Louis Bossart  *		|---- reset_behave
32*bcac5902SPierre-Louis Bossart  *		|---- high_PHY_capable
33*bcac5902SPierre-Louis Bossart  *		|---- paging_support
34*bcac5902SPierre-Louis Bossart  *		|---- bank_delay_support
35*bcac5902SPierre-Louis Bossart  *		|---- p15_behave
36*bcac5902SPierre-Louis Bossart  *		|---- master_count
37*bcac5902SPierre-Louis Bossart  *		|---- source_ports
38*bcac5902SPierre-Louis Bossart  *		|---- sink_ports
39*bcac5902SPierre-Louis Bossart  *	|---- dp0
40*bcac5902SPierre-Louis Bossart  *		|---- max_word
41*bcac5902SPierre-Louis Bossart  *		|---- min_word
42*bcac5902SPierre-Louis Bossart  *		|---- words
43*bcac5902SPierre-Louis Bossart  *		|---- BRA_flow_controlled
44*bcac5902SPierre-Louis Bossart  *		|---- simple_ch_prep_sm
45*bcac5902SPierre-Louis Bossart  *		|---- imp_def_interrupts
46*bcac5902SPierre-Louis Bossart  *	|---- dpN_<sink/src>
47*bcac5902SPierre-Louis Bossart  *		|---- max_word
48*bcac5902SPierre-Louis Bossart  *		|---- min_word
49*bcac5902SPierre-Louis Bossart  *		|---- words
50*bcac5902SPierre-Louis Bossart  *		|---- type
51*bcac5902SPierre-Louis Bossart  *		|---- max_grouping
52*bcac5902SPierre-Louis Bossart  *		|---- simple_ch_prep_sm
53*bcac5902SPierre-Louis Bossart  *		|---- ch_prep_timeout
54*bcac5902SPierre-Louis Bossart  *		|---- imp_def_interrupts
55*bcac5902SPierre-Louis Bossart  *		|---- min_ch
56*bcac5902SPierre-Louis Bossart  *		|---- max_ch
57*bcac5902SPierre-Louis Bossart  *		|---- channels
58*bcac5902SPierre-Louis Bossart  *		|---- ch_combinations
59*bcac5902SPierre-Louis Bossart  *		|---- max_async_buffer
60*bcac5902SPierre-Louis Bossart  *		|---- block_pack_mode
61*bcac5902SPierre-Louis Bossart  *		|---- port_encoding
62*bcac5902SPierre-Louis Bossart  *
63*bcac5902SPierre-Louis Bossart  */
64*bcac5902SPierre-Louis Bossart 
65*bcac5902SPierre-Louis Bossart #define sdw_slave_attr(field, format_string)			\
66*bcac5902SPierre-Louis Bossart static ssize_t field##_show(struct device *dev,			\
67*bcac5902SPierre-Louis Bossart 			    struct device_attribute *attr,	\
68*bcac5902SPierre-Louis Bossart 			    char *buf)				\
69*bcac5902SPierre-Louis Bossart {								\
70*bcac5902SPierre-Louis Bossart 	struct sdw_slave *slave = dev_to_sdw_dev(dev);		\
71*bcac5902SPierre-Louis Bossart 	return sprintf(buf, format_string, slave->prop.field);	\
72*bcac5902SPierre-Louis Bossart }								\
73*bcac5902SPierre-Louis Bossart static DEVICE_ATTR_RO(field)
74*bcac5902SPierre-Louis Bossart 
75*bcac5902SPierre-Louis Bossart sdw_slave_attr(mipi_revision, "0x%x\n");
76*bcac5902SPierre-Louis Bossart sdw_slave_attr(wake_capable, "%d\n");
77*bcac5902SPierre-Louis Bossart sdw_slave_attr(test_mode_capable, "%d\n");
78*bcac5902SPierre-Louis Bossart sdw_slave_attr(clk_stop_mode1, "%d\n");
79*bcac5902SPierre-Louis Bossart sdw_slave_attr(simple_clk_stop_capable, "%d\n");
80*bcac5902SPierre-Louis Bossart sdw_slave_attr(clk_stop_timeout, "%d\n");
81*bcac5902SPierre-Louis Bossart sdw_slave_attr(ch_prep_timeout, "%d\n");
82*bcac5902SPierre-Louis Bossart sdw_slave_attr(reset_behave, "%d\n");
83*bcac5902SPierre-Louis Bossart sdw_slave_attr(high_PHY_capable, "%d\n");
84*bcac5902SPierre-Louis Bossart sdw_slave_attr(paging_support, "%d\n");
85*bcac5902SPierre-Louis Bossart sdw_slave_attr(bank_delay_support, "%d\n");
86*bcac5902SPierre-Louis Bossart sdw_slave_attr(p15_behave, "%d\n");
87*bcac5902SPierre-Louis Bossart sdw_slave_attr(master_count, "%d\n");
88*bcac5902SPierre-Louis Bossart sdw_slave_attr(source_ports, "0x%x\n");
89*bcac5902SPierre-Louis Bossart sdw_slave_attr(sink_ports, "0x%x\n");
90*bcac5902SPierre-Louis Bossart 
91*bcac5902SPierre-Louis Bossart static ssize_t modalias_show(struct device *dev,
92*bcac5902SPierre-Louis Bossart 			     struct device_attribute *attr, char *buf)
93*bcac5902SPierre-Louis Bossart {
94*bcac5902SPierre-Louis Bossart 	struct sdw_slave *slave = dev_to_sdw_dev(dev);
95*bcac5902SPierre-Louis Bossart 
96*bcac5902SPierre-Louis Bossart 	return sdw_slave_modalias(slave, buf, 256);
97*bcac5902SPierre-Louis Bossart }
98*bcac5902SPierre-Louis Bossart static DEVICE_ATTR_RO(modalias);
99*bcac5902SPierre-Louis Bossart 
100*bcac5902SPierre-Louis Bossart static struct attribute *slave_attrs[] = {
101*bcac5902SPierre-Louis Bossart 	&dev_attr_modalias.attr,
102*bcac5902SPierre-Louis Bossart 	NULL,
103*bcac5902SPierre-Louis Bossart };
104*bcac5902SPierre-Louis Bossart ATTRIBUTE_GROUPS(slave);
105*bcac5902SPierre-Louis Bossart 
106*bcac5902SPierre-Louis Bossart static struct attribute *slave_dev_attrs[] = {
107*bcac5902SPierre-Louis Bossart 	&dev_attr_mipi_revision.attr,
108*bcac5902SPierre-Louis Bossart 	&dev_attr_wake_capable.attr,
109*bcac5902SPierre-Louis Bossart 	&dev_attr_test_mode_capable.attr,
110*bcac5902SPierre-Louis Bossart 	&dev_attr_clk_stop_mode1.attr,
111*bcac5902SPierre-Louis Bossart 	&dev_attr_simple_clk_stop_capable.attr,
112*bcac5902SPierre-Louis Bossart 	&dev_attr_clk_stop_timeout.attr,
113*bcac5902SPierre-Louis Bossart 	&dev_attr_ch_prep_timeout.attr,
114*bcac5902SPierre-Louis Bossart 	&dev_attr_reset_behave.attr,
115*bcac5902SPierre-Louis Bossart 	&dev_attr_high_PHY_capable.attr,
116*bcac5902SPierre-Louis Bossart 	&dev_attr_paging_support.attr,
117*bcac5902SPierre-Louis Bossart 	&dev_attr_bank_delay_support.attr,
118*bcac5902SPierre-Louis Bossart 	&dev_attr_p15_behave.attr,
119*bcac5902SPierre-Louis Bossart 	&dev_attr_master_count.attr,
120*bcac5902SPierre-Louis Bossart 	&dev_attr_source_ports.attr,
121*bcac5902SPierre-Louis Bossart 	&dev_attr_sink_ports.attr,
122*bcac5902SPierre-Louis Bossart 	NULL,
123*bcac5902SPierre-Louis Bossart };
124*bcac5902SPierre-Louis Bossart 
125*bcac5902SPierre-Louis Bossart /*
126*bcac5902SPierre-Louis Bossart  * we don't use ATTRIBUTES_GROUP here since we want to add a subdirectory
127*bcac5902SPierre-Louis Bossart  * for device-level properties
128*bcac5902SPierre-Louis Bossart  */
129*bcac5902SPierre-Louis Bossart static struct attribute_group sdw_slave_dev_attr_group = {
130*bcac5902SPierre-Louis Bossart 	.attrs	= slave_dev_attrs,
131*bcac5902SPierre-Louis Bossart 	.name = "dev-properties",
132*bcac5902SPierre-Louis Bossart };
133*bcac5902SPierre-Louis Bossart 
134*bcac5902SPierre-Louis Bossart /*
135*bcac5902SPierre-Louis Bossart  * DP0 sysfs
136*bcac5902SPierre-Louis Bossart  */
137*bcac5902SPierre-Louis Bossart 
138*bcac5902SPierre-Louis Bossart #define sdw_dp0_attr(field, format_string)				\
139*bcac5902SPierre-Louis Bossart static ssize_t field##_show(struct device *dev,				\
140*bcac5902SPierre-Louis Bossart 			    struct device_attribute *attr,		\
141*bcac5902SPierre-Louis Bossart 			    char *buf)					\
142*bcac5902SPierre-Louis Bossart {									\
143*bcac5902SPierre-Louis Bossart 	struct sdw_slave *slave = dev_to_sdw_dev(dev);			\
144*bcac5902SPierre-Louis Bossart 	return sprintf(buf, format_string, slave->prop.dp0_prop->field);\
145*bcac5902SPierre-Louis Bossart }									\
146*bcac5902SPierre-Louis Bossart static DEVICE_ATTR_RO(field)
147*bcac5902SPierre-Louis Bossart 
148*bcac5902SPierre-Louis Bossart sdw_dp0_attr(max_word, "%d\n");
149*bcac5902SPierre-Louis Bossart sdw_dp0_attr(min_word, "%d\n");
150*bcac5902SPierre-Louis Bossart sdw_dp0_attr(BRA_flow_controlled, "%d\n");
151*bcac5902SPierre-Louis Bossart sdw_dp0_attr(simple_ch_prep_sm, "%d\n");
152*bcac5902SPierre-Louis Bossart sdw_dp0_attr(imp_def_interrupts, "0x%x\n");
153*bcac5902SPierre-Louis Bossart 
154*bcac5902SPierre-Louis Bossart static ssize_t words_show(struct device *dev,
155*bcac5902SPierre-Louis Bossart 			  struct device_attribute *attr, char *buf)
156*bcac5902SPierre-Louis Bossart {
157*bcac5902SPierre-Louis Bossart 	struct sdw_slave *slave = dev_to_sdw_dev(dev);
158*bcac5902SPierre-Louis Bossart 	ssize_t size = 0;
159*bcac5902SPierre-Louis Bossart 	int i;
160*bcac5902SPierre-Louis Bossart 
161*bcac5902SPierre-Louis Bossart 	for (i = 0; i < slave->prop.dp0_prop->num_words; i++)
162*bcac5902SPierre-Louis Bossart 		size += sprintf(buf + size, "%d ",
163*bcac5902SPierre-Louis Bossart 				slave->prop.dp0_prop->words[i]);
164*bcac5902SPierre-Louis Bossart 	size += sprintf(buf + size, "\n");
165*bcac5902SPierre-Louis Bossart 
166*bcac5902SPierre-Louis Bossart 	return size;
167*bcac5902SPierre-Louis Bossart }
168*bcac5902SPierre-Louis Bossart static DEVICE_ATTR_RO(words);
169*bcac5902SPierre-Louis Bossart 
170*bcac5902SPierre-Louis Bossart static struct attribute *dp0_attrs[] = {
171*bcac5902SPierre-Louis Bossart 	&dev_attr_max_word.attr,
172*bcac5902SPierre-Louis Bossart 	&dev_attr_min_word.attr,
173*bcac5902SPierre-Louis Bossart 	&dev_attr_words.attr,
174*bcac5902SPierre-Louis Bossart 	&dev_attr_BRA_flow_controlled.attr,
175*bcac5902SPierre-Louis Bossart 	&dev_attr_simple_ch_prep_sm.attr,
176*bcac5902SPierre-Louis Bossart 	&dev_attr_imp_def_interrupts.attr,
177*bcac5902SPierre-Louis Bossart 	NULL,
178*bcac5902SPierre-Louis Bossart };
179*bcac5902SPierre-Louis Bossart 
180*bcac5902SPierre-Louis Bossart /*
181*bcac5902SPierre-Louis Bossart  * we don't use ATTRIBUTES_GROUP here since we want to add a subdirectory
182*bcac5902SPierre-Louis Bossart  * for dp0-level properties
183*bcac5902SPierre-Louis Bossart  */
184*bcac5902SPierre-Louis Bossart static const struct attribute_group dp0_group = {
185*bcac5902SPierre-Louis Bossart 	.attrs = dp0_attrs,
186*bcac5902SPierre-Louis Bossart 	.name = "dp0",
187*bcac5902SPierre-Louis Bossart };
188*bcac5902SPierre-Louis Bossart 
189*bcac5902SPierre-Louis Bossart int sdw_slave_sysfs_init(struct sdw_slave *slave)
190*bcac5902SPierre-Louis Bossart {
191*bcac5902SPierre-Louis Bossart 	int ret;
192*bcac5902SPierre-Louis Bossart 
193*bcac5902SPierre-Louis Bossart 	ret = devm_device_add_groups(&slave->dev, slave_groups);
194*bcac5902SPierre-Louis Bossart 	if (ret < 0)
195*bcac5902SPierre-Louis Bossart 		return ret;
196*bcac5902SPierre-Louis Bossart 
197*bcac5902SPierre-Louis Bossart 	ret = devm_device_add_group(&slave->dev, &sdw_slave_dev_attr_group);
198*bcac5902SPierre-Louis Bossart 	if (ret < 0)
199*bcac5902SPierre-Louis Bossart 		return ret;
200*bcac5902SPierre-Louis Bossart 
201*bcac5902SPierre-Louis Bossart 	if (slave->prop.dp0_prop) {
202*bcac5902SPierre-Louis Bossart 		ret = devm_device_add_group(&slave->dev, &dp0_group);
203*bcac5902SPierre-Louis Bossart 		if (ret < 0)
204*bcac5902SPierre-Louis Bossart 			return ret;
205*bcac5902SPierre-Louis Bossart 	}
206*bcac5902SPierre-Louis Bossart 
207*bcac5902SPierre-Louis Bossart 	if (slave->prop.source_ports || slave->prop.sink_ports) {
208*bcac5902SPierre-Louis Bossart 		ret = sdw_slave_sysfs_dpn_init(slave);
209*bcac5902SPierre-Louis Bossart 		if (ret < 0)
210*bcac5902SPierre-Louis Bossart 			return ret;
211*bcac5902SPierre-Louis Bossart 	}
212*bcac5902SPierre-Louis Bossart 
213*bcac5902SPierre-Louis Bossart 	return 0;
214*bcac5902SPierre-Louis Bossart }
215*bcac5902SPierre-Louis Bossart 
216