Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * FSI hub master driver
  4 *
  5 * Copyright (C) IBM Corporation 2016
  6 */
  7
  8#include <linux/delay.h>
  9#include <linux/fsi.h>
 10#include <linux/module.h>
 11#include <linux/of.h>
 12#include <linux/slab.h>
 13
 14#include "fsi-master.h"
 15
 16/* Control Registers */
 17#define FSI_MMODE		0x0		/* R/W: mode */
 18#define FSI_MDLYR		0x4		/* R/W: delay */
 19#define FSI_MCRSP		0x8		/* R/W: clock rate */
 20#define FSI_MENP0		0x10		/* R/W: enable */
 21#define FSI_MLEVP0		0x18		/* R: plug detect */
 22#define FSI_MSENP0		0x18		/* S: Set enable */
 23#define FSI_MCENP0		0x20		/* C: Clear enable */
 24#define FSI_MAEB		0x70		/* R: Error address */
 25#define FSI_MVER		0x74		/* R: master version/type */
 26#define FSI_MRESP0		0xd0		/* W: Port reset */
 27#define FSI_MESRB0		0x1d0		/* R: Master error status */
 28#define FSI_MRESB0		0x1d0		/* W: Reset bridge */
 29#define FSI_MECTRL		0x2e0		/* W: Error control */
 30
 31/* MMODE: Mode control */
 32#define FSI_MMODE_EIP		0x80000000	/* Enable interrupt polling */
 33#define FSI_MMODE_ECRC		0x40000000	/* Enable error recovery */
 34#define FSI_MMODE_EPC		0x10000000	/* Enable parity checking */
 35#define FSI_MMODE_P8_TO_LSB	0x00000010	/* Timeout value LSB */
 36						/*   MSB=1, LSB=0 is 0.8 ms */
 37						/*   MSB=0, LSB=1 is 0.9 ms */
 38#define FSI_MMODE_CRS0SHFT	18		/* Clk rate selection 0 shift */
 39#define FSI_MMODE_CRS0MASK	0x3ff		/* Clk rate selection 0 mask */
 40#define FSI_MMODE_CRS1SHFT	8		/* Clk rate selection 1 shift */
 41#define FSI_MMODE_CRS1MASK	0x3ff		/* Clk rate selection 1 mask */
 42
 43/* MRESB: Reset brindge */
 44#define FSI_MRESB_RST_GEN	0x80000000	/* General reset */
 45#define FSI_MRESB_RST_ERR	0x40000000	/* Error Reset */
 46
 47/* MRESB: Reset port */
 48#define FSI_MRESP_RST_ALL_MASTER 0x20000000	/* Reset all FSI masters */
 49#define FSI_MRESP_RST_ALL_LINK	0x10000000	/* Reset all FSI port contr. */
 50#define FSI_MRESP_RST_MCR	0x08000000	/* Reset FSI master reg. */
 51#define FSI_MRESP_RST_PYE	0x04000000	/* Reset FSI parity error */
 52#define FSI_MRESP_RST_ALL	0xfc000000	/* Reset any error */
 53
 54/* MECTRL: Error control */
 55#define FSI_MECTRL_EOAE		0x8000		/* Enable machine check when */
 56						/* master 0 in error */
 57#define FSI_MECTRL_P8_AUTO_TERM	0x4000		/* Auto terminate */
 58
 59#define FSI_ENGID_HUB_MASTER		0x1c
 60#define FSI_HUB_LINK_OFFSET		0x80000
 61#define FSI_HUB_LINK_SIZE		0x80000
 62#define FSI_HUB_MASTER_MAX_LINKS	8
 63
 64#define FSI_LINK_ENABLE_SETUP_TIME	10	/* in mS */
 65
 66/*
 67 * FSI hub master support
 68 *
 69 * A hub master increases the number of potential target devices that the
 70 * primary FSI master can access. For each link a primary master supports,
 71 * each of those links can in turn be chained to a hub master with multiple
 72 * links of its own.
 73 *
 74 * The hub is controlled by a set of control registers exposed as a regular fsi
 75 * device (the hub->upstream device), and provides access to the downstream FSI
 76 * bus as through an address range on the slave itself (->addr and ->size).
 77 *
 78 * [This differs from "cascaded" masters, which expose the entire downstream
 79 * bus entirely through the fsi device address range, and so have a smaller
 80 * accessible address space.]
 81 */
 82struct fsi_master_hub {
 83	struct fsi_master	master;
 84	struct fsi_device	*upstream;
 85	uint32_t		addr, size;	/* slave-relative addr of */
 86						/* master address space */
 87};
 88
 89#define to_fsi_master_hub(m) container_of(m, struct fsi_master_hub, master)
 90
 91static int hub_master_read(struct fsi_master *master, int link,
 92			uint8_t id, uint32_t addr, void *val, size_t size)
 93{
 94	struct fsi_master_hub *hub = to_fsi_master_hub(master);
 95
 96	if (id != 0)
 97		return -EINVAL;
 98
 99	addr += hub->addr + (link * FSI_HUB_LINK_SIZE);
100	return fsi_slave_read(hub->upstream->slave, addr, val, size);
101}
102
103static int hub_master_write(struct fsi_master *master, int link,
104			uint8_t id, uint32_t addr, const void *val, size_t size)
105{
106	struct fsi_master_hub *hub = to_fsi_master_hub(master);
107
108	if (id != 0)
109		return -EINVAL;
110
111	addr += hub->addr + (link * FSI_HUB_LINK_SIZE);
112	return fsi_slave_write(hub->upstream->slave, addr, val, size);
113}
114
115static int hub_master_break(struct fsi_master *master, int link)
116{
117	uint32_t addr;
118	__be32 cmd;
119
120	addr = 0x4;
121	cmd = cpu_to_be32(0xc0de0000);
122
123	return hub_master_write(master, link, 0, addr, &cmd, sizeof(cmd));
124}
125
126static int hub_master_link_enable(struct fsi_master *master, int link)
127{
128	struct fsi_master_hub *hub = to_fsi_master_hub(master);
129	int idx, bit;
130	__be32 reg;
131	int rc;
132
133	idx = link / 32;
134	bit = link % 32;
135
136	reg = cpu_to_be32(0x80000000 >> bit);
137
138	rc = fsi_device_write(hub->upstream, FSI_MSENP0 + (4 * idx), &reg, 4);
139
140	mdelay(FSI_LINK_ENABLE_SETUP_TIME);
141
142	fsi_device_read(hub->upstream, FSI_MENP0 + (4 * idx), &reg, 4);
143
144	return rc;
145}
146
147static void hub_master_release(struct device *dev)
148{
149	struct fsi_master_hub *hub = to_fsi_master_hub(dev_to_fsi_master(dev));
150
151	kfree(hub);
152}
153
154/* mmode encoders */
155static inline u32 fsi_mmode_crs0(u32 x)
156{
157	return (x & FSI_MMODE_CRS0MASK) << FSI_MMODE_CRS0SHFT;
158}
159
160static inline u32 fsi_mmode_crs1(u32 x)
161{
162	return (x & FSI_MMODE_CRS1MASK) << FSI_MMODE_CRS1SHFT;
163}
164
165static int hub_master_init(struct fsi_master_hub *hub)
166{
167	struct fsi_device *dev = hub->upstream;
168	__be32 reg;
169	int rc;
170
171	reg = cpu_to_be32(FSI_MRESP_RST_ALL_MASTER | FSI_MRESP_RST_ALL_LINK
172			| FSI_MRESP_RST_MCR | FSI_MRESP_RST_PYE);
173	rc = fsi_device_write(dev, FSI_MRESP0, &reg, sizeof(reg));
174	if (rc)
175		return rc;
176
177	/* Initialize the MFSI (hub master) engine */
178	reg = cpu_to_be32(FSI_MRESP_RST_ALL_MASTER | FSI_MRESP_RST_ALL_LINK
179			| FSI_MRESP_RST_MCR | FSI_MRESP_RST_PYE);
180	rc = fsi_device_write(dev, FSI_MRESP0, &reg, sizeof(reg));
181	if (rc)
182		return rc;
183
184	reg = cpu_to_be32(FSI_MECTRL_EOAE | FSI_MECTRL_P8_AUTO_TERM);
185	rc = fsi_device_write(dev, FSI_MECTRL, &reg, sizeof(reg));
186	if (rc)
187		return rc;
188
189	reg = cpu_to_be32(FSI_MMODE_EIP | FSI_MMODE_ECRC | FSI_MMODE_EPC
190			| fsi_mmode_crs0(1) | fsi_mmode_crs1(1)
191			| FSI_MMODE_P8_TO_LSB);
192	rc = fsi_device_write(dev, FSI_MMODE, &reg, sizeof(reg));
193	if (rc)
194		return rc;
195
196	reg = cpu_to_be32(0xffff0000);
197	rc = fsi_device_write(dev, FSI_MDLYR, &reg, sizeof(reg));
198	if (rc)
199		return rc;
200
201	reg = cpu_to_be32(~0);
202	rc = fsi_device_write(dev, FSI_MSENP0, &reg, sizeof(reg));
203	if (rc)
204		return rc;
205
206	/* Leave enabled long enough for master logic to set up */
207	mdelay(FSI_LINK_ENABLE_SETUP_TIME);
208
209	rc = fsi_device_write(dev, FSI_MCENP0, &reg, sizeof(reg));
210	if (rc)
211		return rc;
212
213	rc = fsi_device_read(dev, FSI_MAEB, &reg, sizeof(reg));
214	if (rc)
215		return rc;
216
217	reg = cpu_to_be32(FSI_MRESP_RST_ALL_MASTER | FSI_MRESP_RST_ALL_LINK);
218	rc = fsi_device_write(dev, FSI_MRESP0, &reg, sizeof(reg));
219	if (rc)
220		return rc;
221
222	rc = fsi_device_read(dev, FSI_MLEVP0, &reg, sizeof(reg));
223	if (rc)
224		return rc;
225
226	/* Reset the master bridge */
227	reg = cpu_to_be32(FSI_MRESB_RST_GEN);
228	rc = fsi_device_write(dev, FSI_MRESB0, &reg, sizeof(reg));
229	if (rc)
230		return rc;
231
232	reg = cpu_to_be32(FSI_MRESB_RST_ERR);
233	return fsi_device_write(dev, FSI_MRESB0, &reg, sizeof(reg));
234}
235
236static int hub_master_probe(struct device *dev)
237{
238	struct fsi_device *fsi_dev = to_fsi_dev(dev);
239	struct fsi_master_hub *hub;
240	uint32_t reg, links;
241	__be32 __reg;
242	int rc;
243
244	rc = fsi_device_read(fsi_dev, FSI_MVER, &__reg, sizeof(__reg));
245	if (rc)
246		return rc;
247
248	reg = be32_to_cpu(__reg);
249	links = (reg >> 8) & 0xff;
250	dev_dbg(dev, "hub version %08x (%d links)\n", reg, links);
251
252	rc = fsi_slave_claim_range(fsi_dev->slave, FSI_HUB_LINK_OFFSET,
253			FSI_HUB_LINK_SIZE * links);
254	if (rc) {
255		dev_err(dev, "can't claim slave address range for links");
256		return rc;
257	}
258
259	hub = kzalloc(sizeof(*hub), GFP_KERNEL);
260	if (!hub) {
261		rc = -ENOMEM;
262		goto err_release;
263	}
264
265	hub->addr = FSI_HUB_LINK_OFFSET;
266	hub->size = FSI_HUB_LINK_SIZE * links;
267	hub->upstream = fsi_dev;
268
269	hub->master.dev.parent = dev;
270	hub->master.dev.release = hub_master_release;
271	hub->master.dev.of_node = of_node_get(dev_of_node(dev));
272
273	hub->master.n_links = links;
274	hub->master.read = hub_master_read;
275	hub->master.write = hub_master_write;
276	hub->master.send_break = hub_master_break;
277	hub->master.link_enable = hub_master_link_enable;
278
279	dev_set_drvdata(dev, hub);
280
281	hub_master_init(hub);
282
283	rc = fsi_master_register(&hub->master);
284	if (rc)
285		goto err_release;
286
287	/* At this point, fsi_master_register performs the device_initialize(),
288	 * and holds the sole reference on master.dev. This means the device
289	 * will be freed (via ->release) during any subsequent call to
290	 * fsi_master_unregister.  We add our own reference to it here, so we
291	 * can perform cleanup (in _remove()) without it being freed before
292	 * we're ready.
293	 */
294	get_device(&hub->master.dev);
295	return 0;
296
297err_release:
298	fsi_slave_release_range(fsi_dev->slave, FSI_HUB_LINK_OFFSET,
299			FSI_HUB_LINK_SIZE * links);
300	return rc;
301}
302
303static int hub_master_remove(struct device *dev)
304{
305	struct fsi_master_hub *hub = dev_get_drvdata(dev);
306
307	fsi_master_unregister(&hub->master);
308	fsi_slave_release_range(hub->upstream->slave, hub->addr, hub->size);
309	of_node_put(hub->master.dev.of_node);
310
311	/*
312	 * master.dev will likely be ->release()ed after this, which free()s
313	 * the hub
314	 */
315	put_device(&hub->master.dev);
316
317	return 0;
318}
319
320static struct fsi_device_id hub_master_ids[] = {
321	{
322		.engine_type = FSI_ENGID_HUB_MASTER,
323		.version = FSI_VERSION_ANY,
324	},
325	{ 0 }
326};
327
328static struct fsi_driver hub_master_driver = {
329	.id_table = hub_master_ids,
330	.drv = {
331		.name = "fsi-master-hub",
332		.bus = &fsi_bus_type,
333		.probe = hub_master_probe,
334		.remove = hub_master_remove,
335	}
336};
337
338module_fsi_driver(hub_master_driver);
339MODULE_LICENSE("GPL");