Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.15.
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * DFL device driver for EMIF private feature
  4 *
  5 * Copyright (C) 2020 Intel Corporation, Inc.
  6 *
  7 */
  8#include <linux/bitfield.h>
  9#include <linux/dfl.h>
 10#include <linux/errno.h>
 11#include <linux/io.h>
 12#include <linux/iopoll.h>
 13#include <linux/io-64-nonatomic-lo-hi.h>
 14#include <linux/kernel.h>
 15#include <linux/module.h>
 16#include <linux/spinlock.h>
 17#include <linux/types.h>
 18
 19#define FME_FEATURE_ID_EMIF		0x9
 20
 21#define EMIF_STAT			0x8
 22#define EMIF_STAT_INIT_DONE_SFT		0
 23#define EMIF_STAT_CALC_FAIL_SFT		8
 24#define EMIF_STAT_CLEAR_BUSY_SFT	16
 25#define EMIF_CTRL			0x10
 26#define EMIF_CTRL_CLEAR_EN_SFT		0
 27#define EMIF_CTRL_CLEAR_EN_MSK		GENMASK_ULL(3, 0)
 28
 29#define EMIF_POLL_INVL			10000 /* us */
 30#define EMIF_POLL_TIMEOUT		5000000 /* us */
 31
 32struct dfl_emif {
 33	struct device *dev;
 34	void __iomem *base;
 35	spinlock_t lock;	/* Serialises access to EMIF_CTRL reg */
 36};
 37
 38struct emif_attr {
 39	struct device_attribute attr;
 40	u32 shift;
 41	u32 index;
 42};
 43
 44#define to_emif_attr(dev_attr) \
 45	container_of(dev_attr, struct emif_attr, attr)
 46
 47static ssize_t emif_state_show(struct device *dev,
 48			       struct device_attribute *attr, char *buf)
 49{
 50	struct emif_attr *eattr = to_emif_attr(attr);
 51	struct dfl_emif *de = dev_get_drvdata(dev);
 52	u64 val;
 53
 54	val = readq(de->base + EMIF_STAT);
 55
 56	return sysfs_emit(buf, "%u\n",
 57			  !!(val & BIT_ULL(eattr->shift + eattr->index)));
 58}
 59
 60static ssize_t emif_clear_store(struct device *dev,
 61				struct device_attribute *attr,
 62				const char *buf, size_t count)
 63{
 64	struct emif_attr *eattr = to_emif_attr(attr);
 65	struct dfl_emif *de = dev_get_drvdata(dev);
 66	u64 clear_busy_msk, clear_en_msk, val;
 67	void __iomem *base = de->base;
 68
 69	if (!sysfs_streq(buf, "1"))
 70		return -EINVAL;
 71
 72	clear_busy_msk = BIT_ULL(EMIF_STAT_CLEAR_BUSY_SFT + eattr->index);
 73	clear_en_msk = BIT_ULL(EMIF_CTRL_CLEAR_EN_SFT + eattr->index);
 74
 75	spin_lock(&de->lock);
 76	/* The CLEAR_EN field is WO, but other fields are RW */
 77	val = readq(base + EMIF_CTRL);
 78	val &= ~EMIF_CTRL_CLEAR_EN_MSK;
 79	val |= clear_en_msk;
 80	writeq(val, base + EMIF_CTRL);
 81	spin_unlock(&de->lock);
 82
 83	if (readq_poll_timeout(base + EMIF_STAT, val,
 84			       !(val & clear_busy_msk),
 85			       EMIF_POLL_INVL, EMIF_POLL_TIMEOUT)) {
 86		dev_err(de->dev, "timeout, fail to clear\n");
 87		return -ETIMEDOUT;
 88	}
 89
 90	return count;
 91}
 92
 93#define emif_state_attr(_name, _shift, _index)				\
 94	static struct emif_attr emif_attr_##inf##_index##_##_name =	\
 95		{ .attr = __ATTR(inf##_index##_##_name, 0444,		\
 96				 emif_state_show, NULL),		\
 97		  .shift = (_shift), .index = (_index) }
 98
 99#define emif_clear_attr(_index)						\
100	static struct emif_attr emif_attr_##inf##_index##_clear =	\
101		{ .attr = __ATTR(inf##_index##_clear, 0200,		\
102				 NULL, emif_clear_store),		\
103		  .index = (_index) }
104
105emif_state_attr(init_done, EMIF_STAT_INIT_DONE_SFT, 0);
106emif_state_attr(init_done, EMIF_STAT_INIT_DONE_SFT, 1);
107emif_state_attr(init_done, EMIF_STAT_INIT_DONE_SFT, 2);
108emif_state_attr(init_done, EMIF_STAT_INIT_DONE_SFT, 3);
109
110emif_state_attr(cal_fail, EMIF_STAT_CALC_FAIL_SFT, 0);
111emif_state_attr(cal_fail, EMIF_STAT_CALC_FAIL_SFT, 1);
112emif_state_attr(cal_fail, EMIF_STAT_CALC_FAIL_SFT, 2);
113emif_state_attr(cal_fail, EMIF_STAT_CALC_FAIL_SFT, 3);
114
115emif_clear_attr(0);
116emif_clear_attr(1);
117emif_clear_attr(2);
118emif_clear_attr(3);
119
120static struct attribute *dfl_emif_attrs[] = {
121	&emif_attr_inf0_init_done.attr.attr,
122	&emif_attr_inf0_cal_fail.attr.attr,
123	&emif_attr_inf0_clear.attr.attr,
124
125	&emif_attr_inf1_init_done.attr.attr,
126	&emif_attr_inf1_cal_fail.attr.attr,
127	&emif_attr_inf1_clear.attr.attr,
128
129	&emif_attr_inf2_init_done.attr.attr,
130	&emif_attr_inf2_cal_fail.attr.attr,
131	&emif_attr_inf2_clear.attr.attr,
132
133	&emif_attr_inf3_init_done.attr.attr,
134	&emif_attr_inf3_cal_fail.attr.attr,
135	&emif_attr_inf3_clear.attr.attr,
136
137	NULL,
138};
139
140static umode_t dfl_emif_visible(struct kobject *kobj,
141				struct attribute *attr, int n)
142{
143	struct dfl_emif *de = dev_get_drvdata(kobj_to_dev(kobj));
144	struct emif_attr *eattr = container_of(attr, struct emif_attr,
145					       attr.attr);
146	u64 val;
147
148	/*
149	 * This device supports upto 4 memory interfaces, but not all
150	 * interfaces are used on different platforms. The read out value of
151	 * CLEAN_EN field (which is a bitmap) could tell how many interfaces
152	 * are available.
153	 */
154	val = FIELD_GET(EMIF_CTRL_CLEAR_EN_MSK, readq(de->base + EMIF_CTRL));
155
156	return (val & BIT_ULL(eattr->index)) ? attr->mode : 0;
157}
158
159static const struct attribute_group dfl_emif_group = {
160	.is_visible = dfl_emif_visible,
161	.attrs = dfl_emif_attrs,
162};
163
164static const struct attribute_group *dfl_emif_groups[] = {
165	&dfl_emif_group,
166	NULL,
167};
168
169static int dfl_emif_probe(struct dfl_device *ddev)
170{
171	struct device *dev = &ddev->dev;
172	struct dfl_emif *de;
173
174	de = devm_kzalloc(dev, sizeof(*de), GFP_KERNEL);
175	if (!de)
176		return -ENOMEM;
177
178	de->base = devm_ioremap_resource(dev, &ddev->mmio_res);
179	if (IS_ERR(de->base))
180		return PTR_ERR(de->base);
181
182	de->dev = dev;
183	spin_lock_init(&de->lock);
184	dev_set_drvdata(dev, de);
185
186	return 0;
187}
188
189static const struct dfl_device_id dfl_emif_ids[] = {
190	{ FME_ID, FME_FEATURE_ID_EMIF },
191	{ }
192};
193MODULE_DEVICE_TABLE(dfl, dfl_emif_ids);
194
195static struct dfl_driver dfl_emif_driver = {
196	.drv	= {
197		.name       = "dfl-emif",
198		.dev_groups = dfl_emif_groups,
199	},
200	.id_table = dfl_emif_ids,
201	.probe   = dfl_emif_probe,
202};
203module_dfl_driver(dfl_emif_driver);
204
205MODULE_DESCRIPTION("DFL EMIF driver");
206MODULE_AUTHOR("Intel Corporation");
207MODULE_LICENSE("GPL v2");