Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Intel(R) Trace Hub Global Trace Hub
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Copyright (C) 2014-2015 Intel Corporation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/bitmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <linux/pm_runtime.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include "intel_th.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include "gth.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) struct gth_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25)  * struct gth_output - GTH view on an output port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26)  * @gth:	backlink to the GTH device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27)  * @output:	link to output device's output descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28)  * @index:	output port number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29)  * @port_type:	one of GTH_* port type values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30)  * @master:	bitmap of masters configured for this output
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) struct gth_output {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	struct gth_device	*gth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	struct intel_th_output	*output;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 	unsigned int		index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	unsigned int		port_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	DECLARE_BITMAP(master, TH_CONFIGURABLE_MASTERS + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41)  * struct gth_device - GTH device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42)  * @dev:	driver core's device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43)  * @base:	register window base address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44)  * @output_group:	attributes describing output ports
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45)  * @master_group:	attributes describing master assignments
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46)  * @output:		output ports
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47)  * @master:		master/output port assignments
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48)  * @gth_lock:		serializes accesses to GTH bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) struct gth_device {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	struct device		*dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	void __iomem		*base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	struct attribute_group	output_group;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	struct attribute_group	master_group;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	struct gth_output	output[TH_POSSIBLE_OUTPUTS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	signed char		master[TH_CONFIGURABLE_MASTERS + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	spinlock_t		gth_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) static void gth_output_set(struct gth_device *gth, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 			   unsigned int config)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	unsigned long reg = port & 4 ? REG_GTH_GTHOPT1 : REG_GTH_GTHOPT0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	int shift = (port & 3) * 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	val = ioread32(gth->base + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	val &= ~(0xff << shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	val |= config << shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	iowrite32(val, gth->base + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) static unsigned int gth_output_get(struct gth_device *gth, int port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	unsigned long reg = port & 4 ? REG_GTH_GTHOPT1 : REG_GTH_GTHOPT0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	int shift = (port & 3) * 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	val = ioread32(gth->base + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	val &= 0xff << shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	val >>= shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) static void gth_smcfreq_set(struct gth_device *gth, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 			    unsigned int freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	unsigned long reg = REG_GTH_SMCR0 + ((port / 2) * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	int shift = (port & 1) * 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	val = ioread32(gth->base + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	val &= ~(0xffff << shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	val |= freq << shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	iowrite32(val, gth->base + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) static unsigned int gth_smcfreq_get(struct gth_device *gth, int port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	unsigned long reg = REG_GTH_SMCR0 + ((port / 2) * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	int shift = (port & 1) * 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	val = ioread32(gth->base + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	val &= 0xffff << shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	val >>= shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)  * "masters" attribute group
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) struct master_attribute {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	struct device_attribute	attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	struct gth_device	*gth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	unsigned int		master;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) gth_master_set(struct gth_device *gth, unsigned int master, int port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	unsigned int reg = REG_GTH_SWDEST0 + ((master >> 1) & ~3u);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	unsigned int shift = (master & 0x7) * 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	if (master >= 256) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 		reg = REG_GTH_GSWTDEST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 		shift = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	val = ioread32(gth->base + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	val &= ~(0xf << shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	if (port >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 		val |= (0x8 | port) << shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	iowrite32(val, gth->base + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) static ssize_t master_attr_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 				struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 				char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	struct master_attribute *ma =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 		container_of(attr, struct master_attribute, attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	struct gth_device *gth = ma->gth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	size_t count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	int port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	spin_lock(&gth->gth_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	port = gth->master[ma->master];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	spin_unlock(&gth->gth_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	if (port >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 		count = snprintf(buf, PAGE_SIZE, "%x\n", port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 		count = snprintf(buf, PAGE_SIZE, "disabled\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) static ssize_t master_attr_store(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 				 struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 				 const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 	struct master_attribute *ma =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 		container_of(attr, struct master_attribute, attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	struct gth_device *gth = ma->gth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	int old_port, port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	if (kstrtoint(buf, 10, &port) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	if (port >= TH_POSSIBLE_OUTPUTS || port < -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	spin_lock(&gth->gth_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	/* disconnect from the previous output port, if any */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	old_port = gth->master[ma->master];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	if (old_port >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 		gth->master[ma->master] = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 		clear_bit(ma->master, gth->output[old_port].master);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 		 * if the port is active, program this setting,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 		 * implies that runtime PM is on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 		if (gth->output[old_port].output->active)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 			gth_master_set(gth, ma->master, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	/* connect to the new output port, if any */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	if (port >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 		/* check if there's a driver for this port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 		if (!gth->output[port].output) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 			count = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 			goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 		set_bit(ma->master, gth->output[port].master);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 		/* if the port is active, program this setting, see above */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 		if (gth->output[port].output->active)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 			gth_master_set(gth, ma->master, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	gth->master[ma->master] = port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 	spin_unlock(&gth->gth_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 	return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) struct output_attribute {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 	struct device_attribute attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	struct gth_device	*gth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 	unsigned int		port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	unsigned int		parm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) #define OUTPUT_PARM(_name, _mask, _r, _w, _what)			\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	[TH_OUTPUT_PARM(_name)] = { .name = __stringify(_name),		\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 				    .get = gth_ ## _what ## _get,	\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 				    .set = gth_ ## _what ## _set,	\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 				    .mask = (_mask),			\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 				    .readable = (_r),			\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 				    .writable = (_w) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) static const struct output_parm {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 	const char	*name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 	unsigned int	(*get)(struct gth_device *gth, int port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	void		(*set)(struct gth_device *gth, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 			       unsigned int val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 	unsigned int	mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 	unsigned int	readable : 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 			writable : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) } output_parms[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	OUTPUT_PARM(port,	0x7,	1, 0, output),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	OUTPUT_PARM(null,	BIT(3),	1, 1, output),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	OUTPUT_PARM(drop,	BIT(4),	1, 1, output),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	OUTPUT_PARM(reset,	BIT(5),	1, 0, output),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	OUTPUT_PARM(flush,	BIT(7),	0, 1, output),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 	OUTPUT_PARM(smcfreq,	0xffff,	1, 1, smcfreq),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) gth_output_parm_set(struct gth_device *gth, int port, unsigned int parm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 		    unsigned int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 	unsigned int config = output_parms[parm].get(gth, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 	unsigned int mask = output_parms[parm].mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 	unsigned int shift = __ffs(mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	config &= ~mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 	config |= (val << shift) & mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 	output_parms[parm].set(gth, port, config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) static unsigned int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) gth_output_parm_get(struct gth_device *gth, int port, unsigned int parm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 	unsigned int config = output_parms[parm].get(gth, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	unsigned int mask = output_parms[parm].mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	unsigned int shift = __ffs(mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	config &= mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 	config >>= shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 	return config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)  * Reset outputs and sources
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) static int intel_th_gth_reset(struct gth_device *gth)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 	int port, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	reg = ioread32(gth->base + REG_GTH_SCRPD0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 	if (reg & SCRPD_DEBUGGER_IN_USE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 		return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 	/* Always save/restore STH and TU registers in S0ix entry/exit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 	reg |= SCRPD_STH_IS_ENABLED | SCRPD_TRIGGER_IS_ENABLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 	iowrite32(reg, gth->base + REG_GTH_SCRPD0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	/* output ports */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 	for (port = 0; port < 8; port++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 		if (gth_output_parm_get(gth, port, TH_OUTPUT_PARM(port)) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 		    GTH_NONE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 		gth_output_set(gth, port, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 		gth_smcfreq_set(gth, port, 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 	/* disable overrides */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 	iowrite32(0, gth->base + REG_GTH_DESTOVR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 	/* masters swdest_0~31 and gswdest */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	for (i = 0; i < 33; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 		iowrite32(0, gth->base + REG_GTH_SWDEST0 + i * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 	/* sources */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 	iowrite32(0, gth->base + REG_GTH_SCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 	iowrite32(0xfc, gth->base + REG_GTH_SCR2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	/* setup CTS for single trigger */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 	iowrite32(CTS_EVENT_ENABLE_IF_ANYTHING, gth->base + REG_CTS_C0S0_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 	iowrite32(CTS_ACTION_CONTROL_SET_STATE(CTS_STATE_IDLE) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 		  CTS_ACTION_CONTROL_TRIGGER, gth->base + REG_CTS_C0S0_ACT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)  * "outputs" attribute group
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) static ssize_t output_attr_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 				struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 				char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 	struct output_attribute *oa =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 		container_of(attr, struct output_attribute, attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 	struct gth_device *gth = oa->gth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 	size_t count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 	pm_runtime_get_sync(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 	spin_lock(&gth->gth_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 	count = snprintf(buf, PAGE_SIZE, "%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 			 gth_output_parm_get(gth, oa->port, oa->parm));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 	spin_unlock(&gth->gth_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 	pm_runtime_put(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 	return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) static ssize_t output_attr_store(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 				 struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 				 const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 	struct output_attribute *oa =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 		container_of(attr, struct output_attribute, attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 	struct gth_device *gth = oa->gth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 	unsigned int config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 	if (kstrtouint(buf, 16, &config) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 	pm_runtime_get_sync(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 	spin_lock(&gth->gth_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 	gth_output_parm_set(gth, oa->port, oa->parm, config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 	spin_unlock(&gth->gth_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 	pm_runtime_put(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 	return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) static int intel_th_master_attributes(struct gth_device *gth)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 	struct master_attribute *master_attrs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 	struct attribute **attrs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 	int i, nattrs = TH_CONFIGURABLE_MASTERS + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 	attrs = devm_kcalloc(gth->dev, nattrs, sizeof(void *), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 	if (!attrs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 	master_attrs = devm_kcalloc(gth->dev, nattrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 				    sizeof(struct master_attribute),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 				    GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 	if (!master_attrs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 	for (i = 0; i < TH_CONFIGURABLE_MASTERS + 1; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 		char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 		name = devm_kasprintf(gth->dev, GFP_KERNEL, "%d%s", i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 				      i == TH_CONFIGURABLE_MASTERS ? "+" : "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 		if (!name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 			return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 		master_attrs[i].attr.attr.name = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 		master_attrs[i].attr.attr.mode = S_IRUGO | S_IWUSR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 		master_attrs[i].attr.show = master_attr_show;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 		master_attrs[i].attr.store = master_attr_store;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 		sysfs_attr_init(&master_attrs[i].attr.attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 		attrs[i] = &master_attrs[i].attr.attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 		master_attrs[i].gth = gth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 		master_attrs[i].master = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 	gth->master_group.name	= "masters";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 	gth->master_group.attrs = attrs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 	return sysfs_create_group(&gth->dev->kobj, &gth->master_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) static int intel_th_output_attributes(struct gth_device *gth)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 	struct output_attribute *out_attrs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 	struct attribute **attrs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 	int i, j, nouts = TH_POSSIBLE_OUTPUTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 	int nparms = ARRAY_SIZE(output_parms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 	int nattrs = nouts * nparms + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 	attrs = devm_kcalloc(gth->dev, nattrs, sizeof(void *), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 	if (!attrs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 	out_attrs = devm_kcalloc(gth->dev, nattrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 				 sizeof(struct output_attribute),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 				 GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 	if (!out_attrs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 	for (i = 0; i < nouts; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 		for (j = 0; j < nparms; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 			unsigned int idx = i * nparms + j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 			char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 			name = devm_kasprintf(gth->dev, GFP_KERNEL, "%d_%s", i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 					      output_parms[j].name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 			if (!name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 				return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 			out_attrs[idx].attr.attr.name = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 			if (output_parms[j].readable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 				out_attrs[idx].attr.attr.mode |= S_IRUGO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 				out_attrs[idx].attr.show = output_attr_show;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 			if (output_parms[j].writable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 				out_attrs[idx].attr.attr.mode |= S_IWUSR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 				out_attrs[idx].attr.store = output_attr_store;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 			sysfs_attr_init(&out_attrs[idx].attr.attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 			attrs[idx] = &out_attrs[idx].attr.attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 			out_attrs[idx].gth = gth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 			out_attrs[idx].port = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 			out_attrs[idx].parm = j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 	gth->output_group.name	= "outputs";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 	gth->output_group.attrs = attrs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 	return sysfs_create_group(&gth->dev->kobj, &gth->output_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)  * intel_th_gth_stop() - stop tracing to an output device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)  * @gth:		GTH device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)  * @output:		output device's descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)  * @capture_done:	set when no more traces will be captured
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)  * This will stop tracing using force storeEn off signal and wait for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)  * pipelines to be empty for the corresponding output port.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) static void intel_th_gth_stop(struct gth_device *gth,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 			      struct intel_th_output *output,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 			      bool capture_done)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 	struct intel_th_device *outdev =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 		container_of(output, struct intel_th_device, output);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 	struct intel_th_driver *outdrv =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 		to_intel_th_driver(outdev->dev.driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 	unsigned long count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 	u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 	u32 scr2 = 0xfc | (capture_done ? 1 : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 	iowrite32(0, gth->base + REG_GTH_SCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 	iowrite32(scr2, gth->base + REG_GTH_SCR2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 	/* wait on pipeline empty for the given port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 	for (reg = 0, count = GTH_PLE_WAITLOOP_DEPTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 	     count && !(reg & BIT(output->port)); count--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 		reg = ioread32(gth->base + REG_GTH_STAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 		cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 	if (!count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 		dev_dbg(gth->dev, "timeout waiting for GTH[%d] PLE\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 			output->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 	/* wait on output piepline empty */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 	if (outdrv->wait_empty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 		outdrv->wait_empty(outdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 	/* clear force capture done for next captures */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 	iowrite32(0xfc, gth->base + REG_GTH_SCR2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)  * intel_th_gth_start() - start tracing to an output device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)  * @gth:	GTH device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)  * @output:	output device's descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)  * This will start tracing using force storeEn signal.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) static void intel_th_gth_start(struct gth_device *gth,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 			       struct intel_th_output *output)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 	u32 scr = 0xfc0000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 	if (output->multiblock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 		scr |= 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 	iowrite32(scr, gth->base + REG_GTH_SCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 	iowrite32(0, gth->base + REG_GTH_SCR2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)  * intel_th_gth_disable() - disable tracing to an output device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)  * @thdev:	GTH device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)  * @output:	output device's descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)  * This will deconfigure all masters set to output to this device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)  * disable tracing using force storeEn off signal and wait for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)  * "pipeline empty" bit for corresponding output port.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) static void intel_th_gth_disable(struct intel_th_device *thdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 				 struct intel_th_output *output)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 	struct gth_device *gth = dev_get_drvdata(&thdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) 	int master;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) 	u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) 	spin_lock(&gth->gth_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) 	output->active = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) 	for_each_set_bit(master, gth->output[output->port].master,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 			 TH_CONFIGURABLE_MASTERS + 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) 		gth_master_set(gth, master, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 	spin_unlock(&gth->gth_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 	intel_th_gth_stop(gth, output, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 	reg = ioread32(gth->base + REG_GTH_SCRPD0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 	reg &= ~output->scratchpad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 	iowrite32(reg, gth->base + REG_GTH_SCRPD0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) static void gth_tscu_resync(struct gth_device *gth)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 	u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 	reg = ioread32(gth->base + REG_TSCU_TSUCTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) 	reg &= ~TSUCTRL_CTCRESYNC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 	iowrite32(reg, gth->base + REG_TSCU_TSUCTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) static void intel_th_gth_prepare(struct intel_th_device *thdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) 				 struct intel_th_output *output)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) 	struct gth_device *gth = dev_get_drvdata(&thdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) 	int count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) 	 * Wait until the output port is in reset before we start
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 	 * programming it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) 	for (count = GTH_PLE_WAITLOOP_DEPTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) 	     count && !(gth_output_get(gth, output->port) & BIT(5)); count--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) 		cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)  * intel_th_gth_enable() - enable tracing to an output device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)  * @thdev:	GTH device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)  * @output:	output device's descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)  * This will configure all masters set to output to this device and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)  * enable tracing using force storeEn signal.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) static void intel_th_gth_enable(struct intel_th_device *thdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) 				struct intel_th_output *output)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) 	struct gth_device *gth = dev_get_drvdata(&thdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) 	struct intel_th *th = to_intel_th(thdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) 	int master;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) 	u32 scrpd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) 	spin_lock(&gth->gth_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) 	for_each_set_bit(master, gth->output[output->port].master,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) 			 TH_CONFIGURABLE_MASTERS + 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) 		gth_master_set(gth, master, output->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) 	output->active = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) 	spin_unlock(&gth->gth_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) 	if (INTEL_TH_CAP(th, tscu_enable))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) 		gth_tscu_resync(gth);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) 	scrpd = ioread32(gth->base + REG_GTH_SCRPD0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) 	scrpd |= output->scratchpad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) 	iowrite32(scrpd, gth->base + REG_GTH_SCRPD0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) 	intel_th_gth_start(gth, output);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)  * intel_th_gth_switch() - execute a switch sequence
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)  * @thdev:	GTH device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)  * @output:	output device's descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)  * This will execute a switch sequence that will trigger a switch window
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)  * when tracing to MSC in multi-block mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) static void intel_th_gth_switch(struct intel_th_device *thdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) 				struct intel_th_output *output)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) 	struct gth_device *gth = dev_get_drvdata(&thdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) 	unsigned long count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) 	u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) 	/* trigger */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) 	iowrite32(0, gth->base + REG_CTS_CTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) 	iowrite32(CTS_CTL_SEQUENCER_ENABLE, gth->base + REG_CTS_CTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) 	/* wait on trigger status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) 	for (reg = 0, count = CTS_TRIG_WAITLOOP_DEPTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) 	     count && !(reg & BIT(4)); count--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) 		reg = ioread32(gth->base + REG_CTS_STAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) 		cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) 	if (!count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) 		dev_dbg(&thdev->dev, "timeout waiting for CTS Trigger\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) 	/* De-assert the trigger */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) 	iowrite32(0, gth->base + REG_CTS_CTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) 	intel_th_gth_stop(gth, output, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) 	intel_th_gth_start(gth, output);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)  * intel_th_gth_assign() - assign output device to a GTH output port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)  * @thdev:	GTH device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654)  * @othdev:	output device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)  * This will match a given output device parameters against present
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)  * output ports on the GTH and fill out relevant bits in output device's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)  * descriptor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)  * Return:	0 on success, -errno on error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) static int intel_th_gth_assign(struct intel_th_device *thdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) 			       struct intel_th_device *othdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) 	struct gth_device *gth = dev_get_drvdata(&thdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) 	int i, id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) 	if (thdev->host_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) 		return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) 	if (othdev->type != INTEL_TH_OUTPUT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) 	for (i = 0, id = 0; i < TH_POSSIBLE_OUTPUTS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) 		if (gth->output[i].port_type != othdev->output.type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) 		if (othdev->id == -1 || othdev->id == id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) 			goto found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) 		id++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) 	return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) found:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) 	spin_lock(&gth->gth_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) 	othdev->output.port = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) 	othdev->output.active = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) 	gth->output[i].output = &othdev->output;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) 	spin_unlock(&gth->gth_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697)  * intel_th_gth_unassign() - deassociate an output device from its output port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)  * @thdev:	GTH device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)  * @othdev:	output device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) static void intel_th_gth_unassign(struct intel_th_device *thdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) 				  struct intel_th_device *othdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) 	struct gth_device *gth = dev_get_drvdata(&thdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) 	int port = othdev->output.port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) 	int master;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) 	if (thdev->host_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) 	spin_lock(&gth->gth_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) 	othdev->output.port = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) 	othdev->output.active = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) 	gth->output[port].output = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) 	for (master = 0; master < TH_CONFIGURABLE_MASTERS + 1; master++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) 		if (gth->master[master] == port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) 			gth->master[master] = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) 	spin_unlock(&gth->gth_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) intel_th_gth_set_output(struct intel_th_device *thdev, unsigned int master)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) 	struct gth_device *gth = dev_get_drvdata(&thdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) 	int port = 0; /* FIXME: make default output configurable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) 	 * everything above TH_CONFIGURABLE_MASTERS is controlled by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) 	 * same register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) 	if (master > TH_CONFIGURABLE_MASTERS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) 		master = TH_CONFIGURABLE_MASTERS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) 	spin_lock(&gth->gth_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) 	if (gth->master[master] == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) 		set_bit(master, gth->output[port].master);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) 		gth->master[master] = port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) 	spin_unlock(&gth->gth_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) static int intel_th_gth_probe(struct intel_th_device *thdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) 	struct device *dev = &thdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) 	struct intel_th *th = dev_get_drvdata(dev->parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) 	struct gth_device *gth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) 	struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) 	void __iomem *base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) 	int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) 	res = intel_th_device_get_resource(thdev, IORESOURCE_MEM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) 	if (!res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) 	base = devm_ioremap(dev, res->start, resource_size(res));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) 	if (!base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) 	gth = devm_kzalloc(dev, sizeof(*gth), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) 	if (!gth)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) 	gth->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) 	gth->base = base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) 	spin_lock_init(&gth->gth_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) 	dev_set_drvdata(dev, gth);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) 	 * Host mode can be signalled via SW means or via SCRPD_DEBUGGER_IN_USE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) 	 * bit. Either way, don't reset HW in this case, and don't export any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) 	 * capture configuration attributes. Also, refuse to assign output
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) 	 * drivers to ports, see intel_th_gth_assign().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) 	if (thdev->host_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) 	ret = intel_th_gth_reset(gth);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) 		if (ret != -EBUSY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) 		thdev->host_mode = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) 	for (i = 0; i < TH_CONFIGURABLE_MASTERS + 1; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) 		gth->master[i] = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) 	for (i = 0; i < TH_POSSIBLE_OUTPUTS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) 		gth->output[i].gth = gth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) 		gth->output[i].index = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) 		gth->output[i].port_type =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) 			gth_output_parm_get(gth, i, TH_OUTPUT_PARM(port));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) 		if (gth->output[i].port_type == GTH_NONE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) 		ret = intel_th_output_enable(th, gth->output[i].port_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) 		/* -ENODEV is ok, we just won't have that device enumerated */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) 		if (ret && ret != -ENODEV)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) 	if (intel_th_output_attributes(gth) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) 	    intel_th_master_attributes(gth)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) 		pr_warn("Can't initialize sysfs attributes\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) 		if (gth->output_group.attrs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) 			sysfs_remove_group(&gth->dev->kobj, &gth->output_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) static void intel_th_gth_remove(struct intel_th_device *thdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) 	struct gth_device *gth = dev_get_drvdata(&thdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) 	sysfs_remove_group(&gth->dev->kobj, &gth->output_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) 	sysfs_remove_group(&gth->dev->kobj, &gth->master_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) static struct intel_th_driver intel_th_gth_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) 	.probe		= intel_th_gth_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) 	.remove		= intel_th_gth_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) 	.assign		= intel_th_gth_assign,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) 	.unassign	= intel_th_gth_unassign,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) 	.set_output	= intel_th_gth_set_output,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) 	.prepare	= intel_th_gth_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) 	.enable		= intel_th_gth_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) 	.trig_switch	= intel_th_gth_switch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) 	.disable	= intel_th_gth_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) 	.driver	= {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) 		.name	= "gth",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) 		.owner	= THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) module_driver(intel_th_gth_driver,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) 	      intel_th_driver_register,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) 	      intel_th_driver_unregister);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) MODULE_ALIAS("intel_th_switch");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) MODULE_DESCRIPTION("Intel(R) Trace Hub Global Trace Hub driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) MODULE_AUTHOR("Alexander Shishkin <alexander.shishkin@linux.intel.com>");