1 // SPDX-License-Identifier: GPL-2.0
3 * Intel(R) Trace Hub Software Trace Hub support
5 * Copyright (C) 2014-2015 Intel Corporation.
8 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
10 #include <linux/types.h>
11 #include <linux/module.h>
12 #include <linux/device.h>
15 #include <linux/slab.h>
16 #include <linux/stm.h>
23 void __iomem
*channels
;
24 phys_addr_t channels_phys
;
27 unsigned int sw_nmasters
;
30 static struct intel_th_channel __iomem
*
31 sth_channel(struct sth_device
*sth
, unsigned int master
, unsigned int channel
)
33 struct intel_th_channel __iomem
*sw_map
= sth
->channels
;
35 return &sw_map
[(master
- sth
->stm
.sw_start
) * sth
->stm
.sw_nchannels
+
39 static void sth_iowrite(void __iomem
*dest
, const unsigned char *payload
,
45 writeq_relaxed(*(u64
*)payload
, dest
);
49 writel_relaxed(*(u32
*)payload
, dest
);
52 writew_relaxed(*(u16
*)payload
, dest
);
55 writeb_relaxed(*(u8
*)payload
, dest
);
62 static ssize_t notrace
sth_stm_packet(struct stm_data
*stm_data
,
68 const unsigned char *payload
)
70 struct sth_device
*sth
= container_of(stm_data
, struct sth_device
, stm
);
71 struct intel_th_channel __iomem
*out
=
72 sth_channel(sth
, master
, channel
);
73 u64 __iomem
*outp
= &out
->Dn
;
74 unsigned long reg
= REG_STH_TRIG
;
81 size
= rounddown_pow_of_two(size
);
84 /* Global packets (GERR, XSYNC, TRIG) are sent with register writes */
87 case STP_PACKET_XSYNC
:
90 if (flags
& STP_PACKET_TIMESTAMPED
)
92 writeb_relaxed(*payload
, sth
->base
+ reg
);
99 sth_iowrite(&out
->MERR
, payload
, size
);
102 case STP_PACKET_FLAG
:
103 if (flags
& STP_PACKET_TIMESTAMPED
)
104 outp
= (u64 __iomem
*)&out
->FLAG_TS
;
106 outp
= (u64 __iomem
*)&out
->FLAG
;
109 writeb_relaxed(0, outp
);
112 case STP_PACKET_USER
:
113 if (flags
& STP_PACKET_TIMESTAMPED
)
114 outp
= &out
->USER_TS
;
117 sth_iowrite(outp
, payload
, size
);
120 case STP_PACKET_DATA
:
123 if (flags
& STP_PACKET_TIMESTAMPED
)
125 if (flags
& STP_PACKET_MARKED
)
128 sth_iowrite(outp
, payload
, size
);
138 sth_stm_mmio_addr(struct stm_data
*stm_data
, unsigned int master
,
139 unsigned int channel
, unsigned int nr_chans
)
141 struct sth_device
*sth
= container_of(stm_data
, struct sth_device
, stm
);
144 master
-= sth
->stm
.sw_start
;
145 addr
= sth
->channels_phys
+ (master
* sth
->stm
.sw_nchannels
+ channel
) *
146 sizeof(struct intel_th_channel
);
148 if (offset_in_page(addr
) ||
149 offset_in_page(nr_chans
* sizeof(struct intel_th_channel
)))
155 static int sth_stm_link(struct stm_data
*stm_data
, unsigned int master
,
156 unsigned int channel
)
158 struct sth_device
*sth
= container_of(stm_data
, struct sth_device
, stm
);
160 intel_th_set_output(to_intel_th_device(sth
->dev
), master
);
165 static int intel_th_sw_init(struct sth_device
*sth
)
169 reg
= ioread32(sth
->base
+ REG_STH_STHCAP1
);
170 sth
->stm
.sw_nchannels
= reg
& 0xff;
172 reg
= ioread32(sth
->base
+ REG_STH_STHCAP0
);
173 sth
->stm
.sw_start
= reg
& 0xffff;
174 sth
->stm
.sw_end
= reg
>> 16;
176 sth
->sw_nmasters
= sth
->stm
.sw_end
- sth
->stm
.sw_start
;
177 dev_dbg(sth
->dev
, "sw_start: %x sw_end: %x masters: %x nchannels: %x\n",
178 sth
->stm
.sw_start
, sth
->stm
.sw_end
, sth
->sw_nmasters
,
179 sth
->stm
.sw_nchannels
);
184 static int intel_th_sth_probe(struct intel_th_device
*thdev
)
186 struct device
*dev
= &thdev
->dev
;
187 struct sth_device
*sth
;
188 struct resource
*res
;
189 void __iomem
*base
, *channels
;
192 res
= intel_th_device_get_resource(thdev
, IORESOURCE_MEM
, 0);
196 base
= devm_ioremap(dev
, res
->start
, resource_size(res
));
200 res
= intel_th_device_get_resource(thdev
, IORESOURCE_MEM
, 1);
204 channels
= devm_ioremap(dev
, res
->start
, resource_size(res
));
208 sth
= devm_kzalloc(dev
, sizeof(*sth
), GFP_KERNEL
);
214 sth
->channels
= channels
;
215 sth
->channels_phys
= res
->start
;
216 sth
->stm
.name
= dev_name(dev
);
217 sth
->stm
.packet
= sth_stm_packet
;
218 sth
->stm
.mmio_addr
= sth_stm_mmio_addr
;
219 sth
->stm
.sw_mmiosz
= sizeof(struct intel_th_channel
);
220 sth
->stm
.link
= sth_stm_link
;
222 err
= intel_th_sw_init(sth
);
226 err
= stm_register_device(dev
, &sth
->stm
, THIS_MODULE
);
228 dev_err(dev
, "stm_register_device failed\n");
232 dev_set_drvdata(dev
, sth
);
237 static void intel_th_sth_remove(struct intel_th_device
*thdev
)
239 struct sth_device
*sth
= dev_get_drvdata(&thdev
->dev
);
241 stm_unregister_device(&sth
->stm
);
244 static struct intel_th_driver intel_th_sth_driver
= {
245 .probe
= intel_th_sth_probe
,
246 .remove
= intel_th_sth_remove
,
249 .owner
= THIS_MODULE
,
253 module_driver(intel_th_sth_driver
,
254 intel_th_driver_register
,
255 intel_th_driver_unregister
);
257 MODULE_LICENSE("GPL v2");
258 MODULE_DESCRIPTION("Intel(R) Trace Hub Software Trace Hub driver");
259 MODULE_AUTHOR("Alexander Shishkin <alexander.shishkin@intel.com>");