* [PATCH 0/2] clk: meson: axg-audio: add reset support
@ 2019-07-03 12:26 Jerome Brunet
2019-07-03 12:26 ` [PATCH 1/2] dt-bindings: clock: meson: add resets to the audio clock controller Jerome Brunet
2019-07-03 12:26 ` [PATCH 2/2] clk: meson: axg-audio: add g12a reset support Jerome Brunet
0 siblings, 2 replies; 6+ messages in thread
From: Jerome Brunet @ 2019-07-03 12:26 UTC (permalink / raw)
To: Neil Armstrong
Cc: Jerome Brunet, Kevin Hilman, linux-amlogic, linux-clk, linux-kernel
This patchset adds support for the reset provided in the register space
of the g12a audio clock controller
Jerome Brunet (2):
dt-bindings: clock: meson: add resets to the audio clock controller
clk: meson: axg-audio: add g12a reset support
.../bindings/clock/amlogic,axg-audio-clkc.txt | 1 +
drivers/clk/meson/axg-audio.c | 107 +++++++++++++++++-
drivers/clk/meson/axg-audio.h | 1 +
.../reset/amlogic,meson-g12a-audio-reset.h | 38 +++++++
4 files changed, 145 insertions(+), 2 deletions(-)
create mode 100644 include/dt-bindings/reset/amlogic,meson-g12a-audio-reset.h
--
2.21.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 1/2] dt-bindings: clock: meson: add resets to the audio clock controller
2019-07-03 12:26 [PATCH 0/2] clk: meson: axg-audio: add reset support Jerome Brunet
@ 2019-07-03 12:26 ` Jerome Brunet
2019-07-03 12:26 ` [PATCH 2/2] clk: meson: axg-audio: add g12a reset support Jerome Brunet
1 sibling, 0 replies; 6+ messages in thread
From: Jerome Brunet @ 2019-07-03 12:26 UTC (permalink / raw)
To: Neil Armstrong
Cc: Jerome Brunet, Kevin Hilman, linux-amlogic, linux-clk, linux-kernel
Add the documentation and bindings for the resets provided by the g12a
audio clock controller
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
.../bindings/clock/amlogic,axg-audio-clkc.txt | 1 +
.../reset/amlogic,meson-g12a-audio-reset.h | 38 +++++++++++++++++++
2 files changed, 39 insertions(+)
create mode 100644 include/dt-bindings/reset/amlogic,meson-g12a-audio-reset.h
diff --git a/Documentation/devicetree/bindings/clock/amlogic,axg-audio-clkc.txt b/Documentation/devicetree/bindings/clock/amlogic,axg-audio-clkc.txt
index 0f777749f4f1..b3957d10d241 100644
--- a/Documentation/devicetree/bindings/clock/amlogic,axg-audio-clkc.txt
+++ b/Documentation/devicetree/bindings/clock/amlogic,axg-audio-clkc.txt
@@ -22,6 +22,7 @@ Required Properties:
components.
- resets : phandle of the internal reset line
- #clock-cells : should be 1.
+- #reset-cells : should be 1 on the g12a (and following) soc family
Each clock is assigned an identifier and client nodes can use this identifier
to specify the clock which they consume. All available clocks are defined as
diff --git a/include/dt-bindings/reset/amlogic,meson-g12a-audio-reset.h b/include/dt-bindings/reset/amlogic,meson-g12a-audio-reset.h
new file mode 100644
index 000000000000..14b78dabed0e
--- /dev/null
+++ b/include/dt-bindings/reset/amlogic,meson-g12a-audio-reset.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 BayLibre, SAS.
+ * Author: Jerome Brunet <jbrunet@baylibre.com>
+ *
+ */
+
+#ifndef _DT_BINDINGS_AMLOGIC_MESON_G12A_AUDIO_RESET_H
+#define _DT_BINDINGS_AMLOGIC_MESON_G12A_AUDIO_RESET_H
+
+#define AUD_RESET_PDM 0
+#define AUD_RESET_TDMIN_A 1
+#define AUD_RESET_TDMIN_B 2
+#define AUD_RESET_TDMIN_C 3
+#define AUD_RESET_TDMIN_LB 4
+#define AUD_RESET_LOOPBACK 5
+#define AUD_RESET_TODDR_A 6
+#define AUD_RESET_TODDR_B 7
+#define AUD_RESET_TODDR_C 8
+#define AUD_RESET_FRDDR_A 9
+#define AUD_RESET_FRDDR_B 10
+#define AUD_RESET_FRDDR_C 11
+#define AUD_RESET_TDMOUT_A 12
+#define AUD_RESET_TDMOUT_B 13
+#define AUD_RESET_TDMOUT_C 14
+#define AUD_RESET_SPDIFOUT 15
+#define AUD_RESET_SPDIFOUT_B 16
+#define AUD_RESET_SPDIFIN 17
+#define AUD_RESET_EQDRC 18
+#define AUD_RESET_RESAMPLE 19
+#define AUD_RESET_DDRARB 20
+#define AUD_RESET_POWDET 21
+#define AUD_RESET_TORAM 22
+#define AUD_RESET_TOACODEC 23
+#define AUD_RESET_TOHDMITX 24
+#define AUD_RESET_CLKTREE 25
+
+#endif
--
2.21.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 2/2] clk: meson: axg-audio: add g12a reset support
2019-07-03 12:26 [PATCH 0/2] clk: meson: axg-audio: add reset support Jerome Brunet
2019-07-03 12:26 ` [PATCH 1/2] dt-bindings: clock: meson: add resets to the audio clock controller Jerome Brunet
@ 2019-07-03 12:26 ` Jerome Brunet
2019-07-22 7:24 ` Neil Armstrong
2019-07-29 22:29 ` Stephen Boyd
1 sibling, 2 replies; 6+ messages in thread
From: Jerome Brunet @ 2019-07-03 12:26 UTC (permalink / raw)
To: Neil Armstrong
Cc: Jerome Brunet, Kevin Hilman, linux-amlogic, linux-clk, linux-kernel
On the g12a, the register space dedicated to the audio clock also
provides some resets. Let the clock controller register a reset
provider as well for this SoC family.
the axg SoC family does not appear to provide this feature.
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
drivers/clk/meson/axg-audio.c | 107 +++++++++++++++++++++++++++++++++-
drivers/clk/meson/axg-audio.h | 1 +
2 files changed, 106 insertions(+), 2 deletions(-)
diff --git a/drivers/clk/meson/axg-audio.c b/drivers/clk/meson/axg-audio.c
index 8028ff6f6610..ce163bd03aad 100644
--- a/drivers/clk/meson/axg-audio.c
+++ b/drivers/clk/meson/axg-audio.c
@@ -12,6 +12,7 @@
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/reset.h>
+#include <linux/reset-controller.h>
#include <linux/slab.h>
#include "axg-audio.h"
@@ -916,6 +917,84 @@ static int axg_register_clk_hw_inputs(struct device *dev,
return 0;
}
+struct axg_audio_reset_data {
+ struct reset_controller_dev rstc;
+ struct regmap *map;
+ unsigned int offset;
+};
+
+static void axg_audio_reset_reg_and_bit(struct axg_audio_reset_data *rst,
+ unsigned long id,
+ unsigned int *reg,
+ unsigned int *bit)
+{
+ unsigned int stride = regmap_get_reg_stride(rst->map);
+
+ *reg = (id / (stride * BITS_PER_BYTE)) * stride;
+ *reg += rst->offset;
+ *bit = id % (stride * BITS_PER_BYTE);
+}
+
+static int axg_audio_reset_update(struct reset_controller_dev *rcdev,
+ unsigned long id, bool assert)
+{
+ struct axg_audio_reset_data *rst =
+ container_of(rcdev, struct axg_audio_reset_data, rstc);
+ unsigned int offset, bit;
+
+ axg_audio_reset_reg_and_bit(rst, id, &offset, &bit);
+
+ regmap_update_bits(rst->map, offset, BIT(bit),
+ assert ? BIT(bit) : 0);
+
+ return 0;
+}
+
+static int axg_audio_reset_status(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ struct axg_audio_reset_data *rst =
+ container_of(rcdev, struct axg_audio_reset_data, rstc);
+ unsigned int val, offset, bit;
+
+ axg_audio_reset_reg_and_bit(rst, id, &offset, &bit);
+
+ regmap_read(rst->map, offset, &val);
+
+ return !!(val & BIT(bit));
+}
+
+static int axg_audio_reset_assert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ return axg_audio_reset_update(rcdev, id, true);
+}
+
+static int axg_audio_reset_deassert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ return axg_audio_reset_update(rcdev, id, false);
+}
+
+static int axg_audio_reset_toggle(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ int ret;
+
+ ret = axg_audio_reset_assert(rcdev, id);
+ if (ret)
+ return ret;
+
+ return axg_audio_reset_deassert(rcdev, id);
+}
+
+static const struct reset_control_ops axg_audio_rstc_ops = {
+ .assert = axg_audio_reset_assert,
+ .deassert = axg_audio_reset_deassert,
+ .reset = axg_audio_reset_toggle,
+ .status = axg_audio_reset_status,
+};
+
static const struct regmap_config axg_audio_regmap_cfg = {
.reg_bits = 32,
.val_bits = 32,
@@ -925,12 +1004,15 @@ static const struct regmap_config axg_audio_regmap_cfg = {
struct audioclk_data {
struct clk_hw_onecell_data *hw_onecell_data;
+ unsigned int reset_offset;
+ unsigned int reset_num;
};
static int axg_audio_clkc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
const struct audioclk_data *data;
+ struct axg_audio_reset_data *rst;
struct regmap *map;
struct resource *res;
void __iomem *regs;
@@ -1005,8 +1087,27 @@ static int axg_audio_clkc_probe(struct platform_device *pdev)
}
}
- return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
- data->hw_onecell_data);
+ ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
+ data->hw_onecell_data);
+ if (ret)
+ return ret;
+
+ /* Stop here if there is no reset */
+ if (!data->reset_num)
+ return 0;
+
+ rst = devm_kzalloc(dev, sizeof(*rst), GFP_KERNEL);
+ if (!rst)
+ return -ENOMEM;
+
+ rst->map = map;
+ rst->offset = data->reset_offset;
+ rst->rstc.nr_resets = data->reset_num;
+ rst->rstc.ops = &axg_audio_rstc_ops;
+ rst->rstc.of_node = dev->of_node;
+ rst->rstc.owner = THIS_MODULE;
+
+ return ret = devm_reset_controller_register(dev, &rst->rstc);
}
static const struct audioclk_data axg_audioclk_data = {
@@ -1015,6 +1116,8 @@ static const struct audioclk_data axg_audioclk_data = {
static const struct audioclk_data g12a_audioclk_data = {
.hw_onecell_data = &g12a_audio_hw_onecell_data,
+ .reset_offset = AUDIO_SW_RESET,
+ .reset_num = 26,
};
static const struct of_device_id clkc_match_table[] = {
diff --git a/drivers/clk/meson/axg-audio.h b/drivers/clk/meson/axg-audio.h
index 5d972d55d6c7..c00e28b2e1a9 100644
--- a/drivers/clk/meson/axg-audio.h
+++ b/drivers/clk/meson/axg-audio.h
@@ -22,6 +22,7 @@
#define AUDIO_MCLK_F_CTRL 0x018
#define AUDIO_MST_PAD_CTRL0 0x01c
#define AUDIO_MST_PAD_CTRL1 0x020
+#define AUDIO_SW_RESET 0x024
#define AUDIO_MST_A_SCLK_CTRL0 0x040
#define AUDIO_MST_A_SCLK_CTRL1 0x044
#define AUDIO_MST_B_SCLK_CTRL0 0x048
--
2.21.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 2/2] clk: meson: axg-audio: add g12a reset support
2019-07-03 12:26 ` [PATCH 2/2] clk: meson: axg-audio: add g12a reset support Jerome Brunet
@ 2019-07-22 7:24 ` Neil Armstrong
2019-07-29 22:29 ` Stephen Boyd
1 sibling, 0 replies; 6+ messages in thread
From: Neil Armstrong @ 2019-07-22 7:24 UTC (permalink / raw)
To: Jerome Brunet; +Cc: Kevin Hilman, linux-amlogic, linux-clk, linux-kernel
On 03/07/2019 14:26, Jerome Brunet wrote:
> On the g12a, the register space dedicated to the audio clock also
> provides some resets. Let the clock controller register a reset
> provider as well for this SoC family.
>
> the axg SoC family does not appear to provide this feature.
>
> Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
> ---
> drivers/clk/meson/axg-audio.c | 107 +++++++++++++++++++++++++++++++++-
> drivers/clk/meson/axg-audio.h | 1 +
> 2 files changed, 106 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/clk/meson/axg-audio.c b/drivers/clk/meson/axg-audio.c
> index 8028ff6f6610..ce163bd03aad 100644
> --- a/drivers/clk/meson/axg-audio.c
> +++ b/drivers/clk/meson/axg-audio.c
> @@ -12,6 +12,7 @@
> #include <linux/platform_device.h>
> #include <linux/regmap.h>
> #include <linux/reset.h>
> +#include <linux/reset-controller.h>
> #include <linux/slab.h>
>
> #include "axg-audio.h"
> @@ -916,6 +917,84 @@ static int axg_register_clk_hw_inputs(struct device *dev,
> return 0;
> }
>
> +struct axg_audio_reset_data {
> + struct reset_controller_dev rstc;
> + struct regmap *map;
> + unsigned int offset;
> +};
> +
> +static void axg_audio_reset_reg_and_bit(struct axg_audio_reset_data *rst,
> + unsigned long id,
> + unsigned int *reg,
> + unsigned int *bit)
> +{
> + unsigned int stride = regmap_get_reg_stride(rst->map);
> +
> + *reg = (id / (stride * BITS_PER_BYTE)) * stride;
> + *reg += rst->offset;
> + *bit = id % (stride * BITS_PER_BYTE);
> +}
> +
> +static int axg_audio_reset_update(struct reset_controller_dev *rcdev,
> + unsigned long id, bool assert)
> +{
> + struct axg_audio_reset_data *rst =
> + container_of(rcdev, struct axg_audio_reset_data, rstc);
> + unsigned int offset, bit;
> +
> + axg_audio_reset_reg_and_bit(rst, id, &offset, &bit);
> +
> + regmap_update_bits(rst->map, offset, BIT(bit),
> + assert ? BIT(bit) : 0);
> +
> + return 0;
> +}
> +
> +static int axg_audio_reset_status(struct reset_controller_dev *rcdev,
> + unsigned long id)
> +{
> + struct axg_audio_reset_data *rst =
> + container_of(rcdev, struct axg_audio_reset_data, rstc);
> + unsigned int val, offset, bit;
> +
> + axg_audio_reset_reg_and_bit(rst, id, &offset, &bit);
> +
> + regmap_read(rst->map, offset, &val);
> +
> + return !!(val & BIT(bit));
> +}
> +
> +static int axg_audio_reset_assert(struct reset_controller_dev *rcdev,
> + unsigned long id)
> +{
> + return axg_audio_reset_update(rcdev, id, true);
> +}
> +
> +static int axg_audio_reset_deassert(struct reset_controller_dev *rcdev,
> + unsigned long id)
> +{
> + return axg_audio_reset_update(rcdev, id, false);
> +}
> +
> +static int axg_audio_reset_toggle(struct reset_controller_dev *rcdev,
> + unsigned long id)
> +{
> + int ret;
> +
> + ret = axg_audio_reset_assert(rcdev, id);
> + if (ret)
> + return ret;
> +
> + return axg_audio_reset_deassert(rcdev, id);
> +}
> +
> +static const struct reset_control_ops axg_audio_rstc_ops = {
> + .assert = axg_audio_reset_assert,
> + .deassert = axg_audio_reset_deassert,
> + .reset = axg_audio_reset_toggle,
> + .status = axg_audio_reset_status,
> +};
> +
> static const struct regmap_config axg_audio_regmap_cfg = {
> .reg_bits = 32,
> .val_bits = 32,
> @@ -925,12 +1004,15 @@ static const struct regmap_config axg_audio_regmap_cfg = {
>
> struct audioclk_data {
> struct clk_hw_onecell_data *hw_onecell_data;
> + unsigned int reset_offset;
> + unsigned int reset_num;
> };
>
> static int axg_audio_clkc_probe(struct platform_device *pdev)
> {
> struct device *dev = &pdev->dev;
> const struct audioclk_data *data;
> + struct axg_audio_reset_data *rst;
> struct regmap *map;
> struct resource *res;
> void __iomem *regs;
> @@ -1005,8 +1087,27 @@ static int axg_audio_clkc_probe(struct platform_device *pdev)
> }
> }
>
> - return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
> - data->hw_onecell_data);
> + ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
> + data->hw_onecell_data);
> + if (ret)
> + return ret;
> +
> + /* Stop here if there is no reset */
> + if (!data->reset_num)
> + return 0;
> +
> + rst = devm_kzalloc(dev, sizeof(*rst), GFP_KERNEL);
> + if (!rst)
> + return -ENOMEM;
> +
> + rst->map = map;
> + rst->offset = data->reset_offset;
> + rst->rstc.nr_resets = data->reset_num;
> + rst->rstc.ops = &axg_audio_rstc_ops;
> + rst->rstc.of_node = dev->of_node;
> + rst->rstc.owner = THIS_MODULE;
> +
> + return ret = devm_reset_controller_register(dev, &rst->rstc);
> }
>
> static const struct audioclk_data axg_audioclk_data = {
> @@ -1015,6 +1116,8 @@ static const struct audioclk_data axg_audioclk_data = {
>
> static const struct audioclk_data g12a_audioclk_data = {
> .hw_onecell_data = &g12a_audio_hw_onecell_data,
> + .reset_offset = AUDIO_SW_RESET,
> + .reset_num = 26,
> };
>
> static const struct of_device_id clkc_match_table[] = {
> diff --git a/drivers/clk/meson/axg-audio.h b/drivers/clk/meson/axg-audio.h
> index 5d972d55d6c7..c00e28b2e1a9 100644
> --- a/drivers/clk/meson/axg-audio.h
> +++ b/drivers/clk/meson/axg-audio.h
> @@ -22,6 +22,7 @@
> #define AUDIO_MCLK_F_CTRL 0x018
> #define AUDIO_MST_PAD_CTRL0 0x01c
> #define AUDIO_MST_PAD_CTRL1 0x020
> +#define AUDIO_SW_RESET 0x024
> #define AUDIO_MST_A_SCLK_CTRL0 0x040
> #define AUDIO_MST_A_SCLK_CTRL1 0x044
> #define AUDIO_MST_B_SCLK_CTRL0 0x048
>
Reviewed-by: Neil Armstrong <narmstrong@baylibre.com>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 2/2] clk: meson: axg-audio: add g12a reset support
2019-07-03 12:26 ` [PATCH 2/2] clk: meson: axg-audio: add g12a reset support Jerome Brunet
2019-07-22 7:24 ` Neil Armstrong
@ 2019-07-29 22:29 ` Stephen Boyd
2019-07-30 7:16 ` Jerome Brunet
1 sibling, 1 reply; 6+ messages in thread
From: Stephen Boyd @ 2019-07-29 22:29 UTC (permalink / raw)
To: Jerome Brunet, Neil Armstrong
Cc: Jerome Brunet, Kevin Hilman, linux-amlogic, linux-clk, linux-kernel
Quoting Jerome Brunet (2019-07-03 05:26:14)
> @@ -1005,8 +1087,27 @@ static int axg_audio_clkc_probe(struct platform_device *pdev)
> }
> }
>
> - return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
> - data->hw_onecell_data);
> + ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
> + data->hw_onecell_data);
> + if (ret)
> + return ret;
> +
> + /* Stop here if there is no reset */
> + if (!data->reset_num)
> + return 0;
> +
> + rst = devm_kzalloc(dev, sizeof(*rst), GFP_KERNEL);
> + if (!rst)
> + return -ENOMEM;
> +
> + rst->map = map;
> + rst->offset = data->reset_offset;
> + rst->rstc.nr_resets = data->reset_num;
> + rst->rstc.ops = &axg_audio_rstc_ops;
> + rst->rstc.of_node = dev->of_node;
> + rst->rstc.owner = THIS_MODULE;
> +
> + return ret = devm_reset_controller_register(dev, &rst->rstc);
IS this a typo? Just return devm instead?
> }
>
> static const struct audioclk_data axg_audioclk_data = {
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 2/2] clk: meson: axg-audio: add g12a reset support
2019-07-29 22:29 ` Stephen Boyd
@ 2019-07-30 7:16 ` Jerome Brunet
0 siblings, 0 replies; 6+ messages in thread
From: Jerome Brunet @ 2019-07-30 7:16 UTC (permalink / raw)
To: Stephen Boyd, Neil Armstrong
Cc: Kevin Hilman, linux-amlogic, linux-clk, linux-kernel
On Mon 29 Jul 2019 at 15:29, Stephen Boyd <sboyd@kernel.org> wrote:
> Quoting Jerome Brunet (2019-07-03 05:26:14)
>> @@ -1005,8 +1087,27 @@ static int axg_audio_clkc_probe(struct platform_device *pdev)
>> }
>> }
>>
>> - return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
>> - data->hw_onecell_data);
>> + ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
>> + data->hw_onecell_data);
>> + if (ret)
>> + return ret;
>> +
>> + /* Stop here if there is no reset */
>> + if (!data->reset_num)
>> + return 0;
>> +
>> + rst = devm_kzalloc(dev, sizeof(*rst), GFP_KERNEL);
>> + if (!rst)
>> + return -ENOMEM;
>> +
>> + rst->map = map;
>> + rst->offset = data->reset_offset;
>> + rst->rstc.nr_resets = data->reset_num;
>> + rst->rstc.ops = &axg_audio_rstc_ops;
>> + rst->rstc.of_node = dev->of_node;
>> + rst->rstc.owner = THIS_MODULE;
>> +
>> + return ret = devm_reset_controller_register(dev, &rst->rstc);
>
> IS this a typo? Just return devm instead?
Typo it is. Thanks for pointing it out.
>
>> }
>>
>> static const struct audioclk_data axg_audioclk_data = {
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2019-07-30 7:16 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-07-03 12:26 [PATCH 0/2] clk: meson: axg-audio: add reset support Jerome Brunet
2019-07-03 12:26 ` [PATCH 1/2] dt-bindings: clock: meson: add resets to the audio clock controller Jerome Brunet
2019-07-03 12:26 ` [PATCH 2/2] clk: meson: axg-audio: add g12a reset support Jerome Brunet
2019-07-22 7:24 ` Neil Armstrong
2019-07-29 22:29 ` Stephen Boyd
2019-07-30 7:16 ` Jerome Brunet
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).