Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 // Copyright(c) 2015-2020 Intel Corporation.
0003 
0004 #include <linux/device.h>
0005 #include <linux/mod_devicetable.h>
0006 #include <linux/slab.h>
0007 #include <linux/sysfs.h>
0008 #include <linux/soundwire/sdw.h>
0009 #include <linux/soundwire/sdw_type.h>
0010 #include "bus.h"
0011 #include "sysfs_local.h"
0012 
0013 /*
0014  * Slave sysfs
0015  */
0016 
0017 /*
0018  * The sysfs for Slave reflects the MIPI description as given
0019  * in the MIPI DisCo spec.
0020  * status and device_number come directly from the MIPI SoundWire
0021  * 1.x specification.
0022  *
0023  * Base file is device
0024  *  |---- status
0025  *  |---- device_number
0026  *  |---- modalias
0027  *  |---- dev-properties
0028  *      |---- mipi_revision
0029  *      |---- wake_capable
0030  *      |---- test_mode_capable
0031  *      |---- clk_stop_mode1
0032  *      |---- simple_clk_stop_capable
0033  *      |---- clk_stop_timeout
0034  *      |---- ch_prep_timeout
0035  *      |---- reset_behave
0036  *      |---- high_PHY_capable
0037  *      |---- paging_support
0038  *      |---- bank_delay_support
0039  *      |---- p15_behave
0040  *      |---- master_count
0041  *      |---- source_ports
0042  *      |---- sink_ports
0043  *  |---- dp0
0044  *      |---- max_word
0045  *      |---- min_word
0046  *      |---- words
0047  *      |---- BRA_flow_controlled
0048  *      |---- simple_ch_prep_sm
0049  *      |---- imp_def_interrupts
0050  *  |---- dpN_<sink/src>
0051  *      |---- max_word
0052  *      |---- min_word
0053  *      |---- words
0054  *      |---- type
0055  *      |---- max_grouping
0056  *      |---- simple_ch_prep_sm
0057  *      |---- ch_prep_timeout
0058  *      |---- imp_def_interrupts
0059  *      |---- min_ch
0060  *      |---- max_ch
0061  *      |---- channels
0062  *      |---- ch_combinations
0063  *      |---- max_async_buffer
0064  *      |---- block_pack_mode
0065  *      |---- port_encoding
0066  *
0067  */
0068 
0069 #define sdw_slave_attr(field, format_string)            \
0070 static ssize_t field##_show(struct device *dev,         \
0071                 struct device_attribute *attr,  \
0072                 char *buf)              \
0073 {                               \
0074     struct sdw_slave *slave = dev_to_sdw_dev(dev);      \
0075     return sprintf(buf, format_string, slave->prop.field);  \
0076 }                               \
0077 static DEVICE_ATTR_RO(field)
0078 
0079 sdw_slave_attr(mipi_revision, "0x%x\n");
0080 sdw_slave_attr(wake_capable, "%d\n");
0081 sdw_slave_attr(test_mode_capable, "%d\n");
0082 sdw_slave_attr(clk_stop_mode1, "%d\n");
0083 sdw_slave_attr(simple_clk_stop_capable, "%d\n");
0084 sdw_slave_attr(clk_stop_timeout, "%d\n");
0085 sdw_slave_attr(ch_prep_timeout, "%d\n");
0086 sdw_slave_attr(reset_behave, "%d\n");
0087 sdw_slave_attr(high_PHY_capable, "%d\n");
0088 sdw_slave_attr(paging_support, "%d\n");
0089 sdw_slave_attr(bank_delay_support, "%d\n");
0090 sdw_slave_attr(p15_behave, "%d\n");
0091 sdw_slave_attr(master_count, "%d\n");
0092 sdw_slave_attr(source_ports, "0x%x\n");
0093 sdw_slave_attr(sink_ports, "0x%x\n");
0094 
0095 static ssize_t modalias_show(struct device *dev,
0096                  struct device_attribute *attr, char *buf)
0097 {
0098     struct sdw_slave *slave = dev_to_sdw_dev(dev);
0099 
0100     return sdw_slave_modalias(slave, buf, 256);
0101 }
0102 static DEVICE_ATTR_RO(modalias);
0103 
0104 static struct attribute *slave_attrs[] = {
0105     &dev_attr_modalias.attr,
0106     NULL,
0107 };
0108 ATTRIBUTE_GROUPS(slave);
0109 
0110 static struct attribute *slave_dev_attrs[] = {
0111     &dev_attr_mipi_revision.attr,
0112     &dev_attr_wake_capable.attr,
0113     &dev_attr_test_mode_capable.attr,
0114     &dev_attr_clk_stop_mode1.attr,
0115     &dev_attr_simple_clk_stop_capable.attr,
0116     &dev_attr_clk_stop_timeout.attr,
0117     &dev_attr_ch_prep_timeout.attr,
0118     &dev_attr_reset_behave.attr,
0119     &dev_attr_high_PHY_capable.attr,
0120     &dev_attr_paging_support.attr,
0121     &dev_attr_bank_delay_support.attr,
0122     &dev_attr_p15_behave.attr,
0123     &dev_attr_master_count.attr,
0124     &dev_attr_source_ports.attr,
0125     &dev_attr_sink_ports.attr,
0126     NULL,
0127 };
0128 
0129 /*
0130  * we don't use ATTRIBUTES_GROUP here since we want to add a subdirectory
0131  * for device-level properties
0132  */
0133 static const struct attribute_group sdw_slave_dev_attr_group = {
0134     .attrs  = slave_dev_attrs,
0135     .name = "dev-properties",
0136 };
0137 
0138 /*
0139  * DP0 sysfs
0140  */
0141 
0142 #define sdw_dp0_attr(field, format_string)              \
0143 static ssize_t field##_show(struct device *dev,             \
0144                 struct device_attribute *attr,      \
0145                 char *buf)                  \
0146 {                                   \
0147     struct sdw_slave *slave = dev_to_sdw_dev(dev);          \
0148     return sprintf(buf, format_string, slave->prop.dp0_prop->field);\
0149 }                                   \
0150 static DEVICE_ATTR_RO(field)
0151 
0152 sdw_dp0_attr(max_word, "%d\n");
0153 sdw_dp0_attr(min_word, "%d\n");
0154 sdw_dp0_attr(BRA_flow_controlled, "%d\n");
0155 sdw_dp0_attr(simple_ch_prep_sm, "%d\n");
0156 sdw_dp0_attr(imp_def_interrupts, "0x%x\n");
0157 
0158 static ssize_t words_show(struct device *dev,
0159               struct device_attribute *attr, char *buf)
0160 {
0161     struct sdw_slave *slave = dev_to_sdw_dev(dev);
0162     ssize_t size = 0;
0163     int i;
0164 
0165     for (i = 0; i < slave->prop.dp0_prop->num_words; i++)
0166         size += sprintf(buf + size, "%d ",
0167                 slave->prop.dp0_prop->words[i]);
0168     size += sprintf(buf + size, "\n");
0169 
0170     return size;
0171 }
0172 static DEVICE_ATTR_RO(words);
0173 
0174 static struct attribute *dp0_attrs[] = {
0175     &dev_attr_max_word.attr,
0176     &dev_attr_min_word.attr,
0177     &dev_attr_words.attr,
0178     &dev_attr_BRA_flow_controlled.attr,
0179     &dev_attr_simple_ch_prep_sm.attr,
0180     &dev_attr_imp_def_interrupts.attr,
0181     NULL,
0182 };
0183 
0184 /*
0185  * we don't use ATTRIBUTES_GROUP here since we want to add a subdirectory
0186  * for dp0-level properties
0187  */
0188 static const struct attribute_group dp0_group = {
0189     .attrs = dp0_attrs,
0190     .name = "dp0",
0191 };
0192 
0193 int sdw_slave_sysfs_init(struct sdw_slave *slave)
0194 {
0195     int ret;
0196 
0197     ret = devm_device_add_groups(&slave->dev, slave_groups);
0198     if (ret < 0)
0199         return ret;
0200 
0201     ret = devm_device_add_group(&slave->dev, &sdw_slave_dev_attr_group);
0202     if (ret < 0)
0203         return ret;
0204 
0205     if (slave->prop.dp0_prop) {
0206         ret = devm_device_add_group(&slave->dev, &dp0_group);
0207         if (ret < 0)
0208             return ret;
0209     }
0210 
0211     if (slave->prop.source_ports || slave->prop.sink_ports) {
0212         ret = sdw_slave_sysfs_dpn_init(slave);
0213         if (ret < 0)
0214             return ret;
0215     }
0216 
0217     return 0;
0218 }
0219 
0220 /*
0221  * the status is shown in capital letters for UNATTACHED and RESERVED
0222  * on purpose, to highligh users to the fact that these status values
0223  * are not expected.
0224  */
0225 static const char *const slave_status[] = {
0226     [SDW_SLAVE_UNATTACHED] =  "UNATTACHED",
0227     [SDW_SLAVE_ATTACHED] = "Attached",
0228     [SDW_SLAVE_ALERT] = "Alert",
0229     [SDW_SLAVE_RESERVED] = "RESERVED",
0230 };
0231 
0232 static ssize_t status_show(struct device *dev,
0233                struct device_attribute *attr, char *buf)
0234 {
0235     struct sdw_slave *slave = dev_to_sdw_dev(dev);
0236 
0237     return sprintf(buf, "%s\n", slave_status[slave->status]);
0238 }
0239 static DEVICE_ATTR_RO(status);
0240 
0241 static ssize_t device_number_show(struct device *dev,
0242                   struct device_attribute *attr, char *buf)
0243 {
0244     struct sdw_slave *slave = dev_to_sdw_dev(dev);
0245 
0246     if (slave->status == SDW_SLAVE_UNATTACHED)
0247         return sprintf(buf, "%s", "N/A");
0248     else
0249         return sprintf(buf, "%d", slave->dev_num);
0250 }
0251 static DEVICE_ATTR_RO(device_number);
0252 
0253 static struct attribute *slave_status_attrs[] = {
0254     &dev_attr_status.attr,
0255     &dev_attr_device_number.attr,
0256     NULL,
0257 };
0258 
0259 /*
0260  * we don't use ATTRIBUTES_GROUP here since the group is used in a
0261  * separate file and can't be handled as a static.
0262  */
0263 static const struct attribute_group sdw_slave_status_attr_group = {
0264     .attrs  = slave_status_attrs,
0265 };
0266 
0267 const struct attribute_group *sdw_slave_status_attr_groups[] = {
0268     &sdw_slave_status_attr_group,
0269     NULL
0270 };