Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Intel(R) Trace Hub Software Trace Hub support
0004  *
0005  * Copyright (C) 2014-2015 Intel Corporation.
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     /* Global packets (GERR, XSYNC, TRIG) are sent with register writes */
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>");