^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(>h->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(>h->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(>h->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(>h->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(>h->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(>h->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(>h->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(>h->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(>h->dev->kobj, >h->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(>h->dev->kobj, >h->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(>h->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(>h->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(>h->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(>h->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(>h->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(>h->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(>h->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(>h->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(>h->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(>h->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(>h->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(>h->dev->kobj, >h->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(>h->dev->kobj, >h->output_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) sysfs_remove_group(>h->dev->kobj, >h->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>");