0001
0002
0003
0004
0005
0006
0007
0008 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0009
0010 #include <linux/types.h>
0011 #include <linux/module.h>
0012 #include <linux/device.h>
0013 #include <linux/io.h>
0014 #include <linux/mm.h>
0015 #include <linux/slab.h>
0016 #include <linux/stm.h>
0017
0018 #include "intel_th.h"
0019 #include "sth.h"
0020
0021 struct sth_device {
0022 void __iomem *base;
0023 void __iomem *channels;
0024 phys_addr_t channels_phys;
0025 struct device *dev;
0026 struct stm_data stm;
0027 unsigned int sw_nmasters;
0028 };
0029
0030 static struct intel_th_channel __iomem *
0031 sth_channel(struct sth_device *sth, unsigned int master, unsigned int channel)
0032 {
0033 struct intel_th_channel __iomem *sw_map = sth->channels;
0034
0035 return &sw_map[(master - sth->stm.sw_start) * sth->stm.sw_nchannels +
0036 channel];
0037 }
0038
0039 static void sth_iowrite(void __iomem *dest, const unsigned char *payload,
0040 unsigned int size)
0041 {
0042 switch (size) {
0043 #ifdef CONFIG_64BIT
0044 case 8:
0045 writeq_relaxed(*(u64 *)payload, dest);
0046 break;
0047 #endif
0048 case 4:
0049 writel_relaxed(*(u32 *)payload, dest);
0050 break;
0051 case 2:
0052 writew_relaxed(*(u16 *)payload, dest);
0053 break;
0054 case 1:
0055 writeb_relaxed(*(u8 *)payload, dest);
0056 break;
0057 default:
0058 break;
0059 }
0060 }
0061
0062 static ssize_t notrace sth_stm_packet(struct stm_data *stm_data,
0063 unsigned int master,
0064 unsigned int channel,
0065 unsigned int packet,
0066 unsigned int flags,
0067 unsigned int size,
0068 const unsigned char *payload)
0069 {
0070 struct sth_device *sth = container_of(stm_data, struct sth_device, stm);
0071 struct intel_th_channel __iomem *out =
0072 sth_channel(sth, master, channel);
0073 u64 __iomem *outp = &out->Dn;
0074 unsigned long reg = REG_STH_TRIG;
0075
0076 #ifndef CONFIG_64BIT
0077 if (size > 4)
0078 size = 4;
0079 #endif
0080
0081 size = rounddown_pow_of_two(size);
0082
0083 switch (packet) {
0084
0085 case STP_PACKET_GERR:
0086 reg += 4;
0087 fallthrough;
0088
0089 case STP_PACKET_XSYNC:
0090 reg += 8;
0091 fallthrough;
0092
0093 case STP_PACKET_TRIG:
0094 if (flags & STP_PACKET_TIMESTAMPED)
0095 reg += 4;
0096 writeb_relaxed(*payload, sth->base + reg);
0097 break;
0098
0099 case STP_PACKET_MERR:
0100 if (size > 4)
0101 size = 4;
0102
0103 sth_iowrite(&out->MERR, payload, size);
0104 break;
0105
0106 case STP_PACKET_FLAG:
0107 if (flags & STP_PACKET_TIMESTAMPED)
0108 outp = (u64 __iomem *)&out->FLAG_TS;
0109 else
0110 outp = (u64 __iomem *)&out->FLAG;
0111
0112 size = 0;
0113 writeb_relaxed(0, outp);
0114 break;
0115
0116 case STP_PACKET_USER:
0117 if (flags & STP_PACKET_TIMESTAMPED)
0118 outp = &out->USER_TS;
0119 else
0120 outp = &out->USER;
0121 sth_iowrite(outp, payload, size);
0122 break;
0123
0124 case STP_PACKET_DATA:
0125 outp = &out->Dn;
0126
0127 if (flags & STP_PACKET_TIMESTAMPED)
0128 outp += 2;
0129 if (flags & STP_PACKET_MARKED)
0130 outp++;
0131
0132 sth_iowrite(outp, payload, size);
0133 break;
0134 default:
0135 return -ENOTSUPP;
0136 }
0137
0138 return size;
0139 }
0140
0141 static phys_addr_t
0142 sth_stm_mmio_addr(struct stm_data *stm_data, unsigned int master,
0143 unsigned int channel, unsigned int nr_chans)
0144 {
0145 struct sth_device *sth = container_of(stm_data, struct sth_device, stm);
0146 phys_addr_t addr;
0147
0148 master -= sth->stm.sw_start;
0149 addr = sth->channels_phys + (master * sth->stm.sw_nchannels + channel) *
0150 sizeof(struct intel_th_channel);
0151
0152 if (offset_in_page(addr) ||
0153 offset_in_page(nr_chans * sizeof(struct intel_th_channel)))
0154 return 0;
0155
0156 return addr;
0157 }
0158
0159 static int sth_stm_link(struct stm_data *stm_data, unsigned int master,
0160 unsigned int channel)
0161 {
0162 struct sth_device *sth = container_of(stm_data, struct sth_device, stm);
0163
0164 return intel_th_set_output(to_intel_th_device(sth->dev), master);
0165 }
0166
0167 static int intel_th_sw_init(struct sth_device *sth)
0168 {
0169 u32 reg;
0170
0171 reg = ioread32(sth->base + REG_STH_STHCAP1);
0172 sth->stm.sw_nchannels = reg & 0xff;
0173
0174 reg = ioread32(sth->base + REG_STH_STHCAP0);
0175 sth->stm.sw_start = reg & 0xffff;
0176 sth->stm.sw_end = reg >> 16;
0177
0178 sth->sw_nmasters = sth->stm.sw_end - sth->stm.sw_start;
0179 dev_dbg(sth->dev, "sw_start: %x sw_end: %x masters: %x nchannels: %x\n",
0180 sth->stm.sw_start, sth->stm.sw_end, sth->sw_nmasters,
0181 sth->stm.sw_nchannels);
0182
0183 return 0;
0184 }
0185
0186 static int intel_th_sth_probe(struct intel_th_device *thdev)
0187 {
0188 struct device *dev = &thdev->dev;
0189 struct sth_device *sth;
0190 struct resource *res;
0191 void __iomem *base, *channels;
0192 int err;
0193
0194 res = intel_th_device_get_resource(thdev, IORESOURCE_MEM, 0);
0195 if (!res)
0196 return -ENODEV;
0197
0198 base = devm_ioremap(dev, res->start, resource_size(res));
0199 if (!base)
0200 return -ENOMEM;
0201
0202 res = intel_th_device_get_resource(thdev, IORESOURCE_MEM, 1);
0203 if (!res)
0204 return -ENODEV;
0205
0206 channels = devm_ioremap(dev, res->start, resource_size(res));
0207 if (!channels)
0208 return -ENOMEM;
0209
0210 sth = devm_kzalloc(dev, sizeof(*sth), GFP_KERNEL);
0211 if (!sth)
0212 return -ENOMEM;
0213
0214 sth->dev = dev;
0215 sth->base = base;
0216 sth->channels = channels;
0217 sth->channels_phys = res->start;
0218 sth->stm.name = dev_name(dev);
0219 sth->stm.packet = sth_stm_packet;
0220 sth->stm.mmio_addr = sth_stm_mmio_addr;
0221 sth->stm.sw_mmiosz = sizeof(struct intel_th_channel);
0222 sth->stm.link = sth_stm_link;
0223
0224 err = intel_th_sw_init(sth);
0225 if (err)
0226 return err;
0227
0228 err = stm_register_device(dev, &sth->stm, THIS_MODULE);
0229 if (err) {
0230 dev_err(dev, "stm_register_device failed\n");
0231 return err;
0232 }
0233
0234 dev_set_drvdata(dev, sth);
0235
0236 return 0;
0237 }
0238
0239 static void intel_th_sth_remove(struct intel_th_device *thdev)
0240 {
0241 struct sth_device *sth = dev_get_drvdata(&thdev->dev);
0242
0243 stm_unregister_device(&sth->stm);
0244 }
0245
0246 static struct intel_th_driver intel_th_sth_driver = {
0247 .probe = intel_th_sth_probe,
0248 .remove = intel_th_sth_remove,
0249 .driver = {
0250 .name = "sth",
0251 .owner = THIS_MODULE,
0252 },
0253 };
0254
0255 module_driver(intel_th_sth_driver,
0256 intel_th_driver_register,
0257 intel_th_driver_unregister);
0258
0259 MODULE_LICENSE("GPL v2");
0260 MODULE_DESCRIPTION("Intel(R) Trace Hub Software Trace Hub driver");
0261 MODULE_AUTHOR("Alexander Shishkin <alexander.shishkin@intel.com>");