lkml.org 
[lkml]   [2024]   [Apr]   [7]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    From
    SubjectRE: [PATCH v2 4/6] firmware: arm_scmi: add initial support for i.MX MISC protocol
    Date
    > Subject: Re: [PATCH v2 4/6] firmware: arm_scmi: add initial support for iMX
    > MISC protocol
    >
    > Hi Peng,
    >
    > On 24-04-07, Peng Fan wrote:
    > > > Subject: Re: [PATCH v2 4/6] firmware: arm_scmi: add initial support
    > > > for i.MX MISC protocol
    > > >
    > > > Hi Peng,
    > > >
    > > > On 24-04-05, Peng Fan (OSS) wrote:
    > > > > From: Peng Fan <peng.fan@nxp.com>
    > > > >
    > > > > The i.MX MISC protocol is for misc settings, such as gpio expander
    > > > > wakeup.
    > > >
    > > > Can you elaborate a bit more please?
    > >
    > > The gpio expander is under M33(SCMI firmware used core) I2C control,
    >
    > Due to missing technical references I guess that your specific EVK has an i2c-
    > expander connected to the system-critical-i2c bus? The system-critical-i2c
    > should be only used for system critical topics like PMIC control.

    Right.

    >
    > > But the gpio expander supports board function such as PCIE_WAKEUP,
    > > BTN_WAKEUP. So these are managed by MISC protocol.
    >
    > This seems more like an specific i.MX95-EVK problem too me since you have
    > conneccted the i2c-gpio-expander to the system-critical-i2c bus instead of
    > using an bus available within Linux. Also can you please provide me a link
    > with the propsoal for the MISC protocol? I can't find any references within the
    > SCMI v3.2

    It is i.MX VENDOR Extension, not a standard one in Spec.

    > https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdevelo
    > per.arm.com%2Fdocumentation%2Fden0056%2Fe%2F&data=05%7C02%7Cp
    > eng.fan%40nxp.com%7C6120357a772045a0618808dc56f22c95%7C686ea1d
    > 3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C638480845336536607%7CUnk
    > nown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik
    > 1haWwiLCJXVCI6Mn0%3D%7C0%7C%7C%7C&sdata=NI%2F8WMPuGzJwD74
    > 1jcuknHZUR5uI2me9iEeWbeDKshE%3D&reserved=0 nor within the SCP
    > firmware git:
    > https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub
    > .com%2FARM-software%2FSCP-
    > firmware&data=05%7C02%7Cpeng.fan%40nxp.com%7C6120357a772045a06
    > 18808dc56f22c95%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C
    > 638480845336550459%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAw
    > MDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0%7C%7C%7C
    > &sdata=N3bT9ItgvL4Z9xP1oxlmDTG%2FFjsXkuhJIA9wooJWfcM%3D&reserve
    > d=0.
    >
    > > SAI_CLK_MSEL in WAKEUP BLK CTRL is also managed by MISC Protocol.
    >
    > You recently said that we need blk-ctrl drivers for managing/controlling the
    > GPR stuff within Linux since the SCMI firmware does not support this. Now
    > blk-ctrl GPR control is supported by the firmware?

    AONMIX/WAKEUPMIX BLK CTRL is managed by SCMI firmware, for other
    non system critical BLK CTRLs, they are managed by Linux directly, such as
    GPU/VPU BLK CTRL and etc.

    Regards,
    Peng.
    >
    > Regards,
    > Marco
    >
    > >
    > > And etc...
    > >
    > > I will add more info in commit log in next version later, after I get
    > > more reviews on the patchset.
    > >
    > > Thanks,
    > > Peng.
    > >
    > > >
    > > > Regards,
    > > > Marco
    > > >
    > > >
    > > > >
    > > > > Signed-off-by: Peng Fan <peng.fan@nxp.com>
    > > > > ---
    > > > > drivers/firmware/arm_scmi/Kconfig | 10 ++
    > > > > drivers/firmware/arm_scmi/Makefile | 1 +
    > > > > drivers/firmware/arm_scmi/imx-sm-misc.c | 305
    > > > ++++++++++++++++++++++++++++++++
    > > > > include/linux/scmi_imx_protocol.h | 17 ++
    > > > > 4 files changed, 333 insertions(+)
    > > > >
    > > > > diff --git a/drivers/firmware/arm_scmi/Kconfig
    > > > > b/drivers/firmware/arm_scmi/Kconfig
    > > > > index 56d11c9d9f47..bfeae92f6420 100644
    > > > > --- a/drivers/firmware/arm_scmi/Kconfig
    > > > > +++ b/drivers/firmware/arm_scmi/Kconfig
    > > > > @@ -191,3 +191,13 @@ config IMX_SCMI_BBM_EXT
    > > > > and BUTTON.
    > > > >
    > > > > This driver can also be built as a module.
    > > > > +
    > > > > +config IMX_SCMI_MISC_EXT
    > > > > + tristate "i.MX SCMI MISC EXTENSION"
    > > > > + depends on ARM_SCMI_PROTOCOL || (COMPILE_TEST && OF)
    > > > > + default y if ARCH_MXC
    > > > > + help
    > > > > + This enables i.MX System MISC control logic such as gpio expander
    > > > > + wakeup
    > > > > +
    > > > > + This driver can also be built as a module.
    > > > > diff --git a/drivers/firmware/arm_scmi/Makefile
    > > > > b/drivers/firmware/arm_scmi/Makefile
    > > > > index 327687acf857..a23fde721222 100644
    > > > > --- a/drivers/firmware/arm_scmi/Makefile
    > > > > +++ b/drivers/firmware/arm_scmi/Makefile
    > > > > @@ -12,6 +12,7 @@ scmi-transport-
    > > > $(CONFIG_ARM_SCMI_TRANSPORT_VIRTIO)
    > > > > += virtio.o
    > > > > scmi-transport-$(CONFIG_ARM_SCMI_TRANSPORT_OPTEE) += optee.o
    > > > > scmi-protocols-y = base.o clock.o perf.o power.o reset.o sensors.o
    > > > > system.o voltage.o powercap.o
    > > > > scmi-protocols-$(CONFIG_IMX_SCMI_BBM_EXT) += imx-sm-bbm.o
    > > > > +scmi-protocols-$(CONFIG_IMX_SCMI_MISC_EXT) += imx-sm-misc.o
    > > > > scmi-module-objs := $(scmi-driver-y) $(scmi-protocols-y)
    > > > > $(scmi-transport-y)
    > > > >
    > > > > obj-$(CONFIG_ARM_SCMI_PROTOCOL) += scmi-core.o diff --git
    > > > > a/drivers/firmware/arm_scmi/imx-sm-misc.c
    > > > > b/drivers/firmware/arm_scmi/imx-sm-misc.c
    > > > > new file mode 100644
    > > > > index 000000000000..1b0ec2281518
    > > > > --- /dev/null
    > > > > +++ b/drivers/firmware/arm_scmi/imx-sm-misc.c
    > > > > @@ -0,0 +1,305 @@
    > > > > +// SPDX-License-Identifier: GPL-2.0
    > > > > +/*
    > > > > + * System control and Management Interface (SCMI) NXP MISC
    > > > > +Protocol
    > > > > + *
    > > > > + * Copyright 2024 NXP
    > > > > + */
    > > > > +
    > > > > +#define pr_fmt(fmt) "SCMI Notifications MISC - " fmt
    > > > > +
    > > > > +#include <linux/bits.h>
    > > > > +#include <linux/io.h>
    > > > > +#include <linux/module.h>
    > > > > +#include <linux/of.h>
    > > > > +#include <linux/platform_device.h> #include
    > > > > +<linux/scmi_protocol.h> #include <linux/scmi_imx_protocol.h>
    > > > > +
    > > > > +#include "protocols.h"
    > > > > +#include "notify.h"
    > > > > +
    > > > > +#define SCMI_PROTOCOL_SUPPORTED_VERSION 0x10000
    > > > > +
    > > > > +enum scmi_imx_misc_protocol_cmd {
    > > > > + SCMI_IMX_MISC_CTRL_SET = 0x3,
    > > > > + SCMI_IMX_MISC_CTRL_GET = 0x4,
    > > > > + SCMI_IMX_MISC_CTRL_NOTIFY = 0x8, };
    > > > > +
    > > > > +struct scmi_imx_misc_info {
    > > > > + u32 version;
    > > > > + u32 nr_dev_ctrl;
    > > > > + u32 nr_brd_ctrl;
    > > > > + u32 nr_reason;
    > > > > +};
    > > > > +
    > > > > +struct scmi_msg_imx_misc_protocol_attributes {
    > > > > + __le32 attributes;
    > > > > +};
    > > > > +
    > > > > +#define GET_BRD_CTRLS_NR(x) le32_get_bits((x), GENMASK(31,
    > > > 24))
    > > > > +#define GET_REASONS_NR(x) le32_get_bits((x), GENMASK(23,
    > 16))
    > > > > +#define GET_DEV_CTRLS_NR(x) le32_get_bits((x), GENMASK(15, 0))
    > > > > +#define BRD_CTRL_START_ID BIT(15)
    > > > > +
    > > > > +struct scmi_imx_misc_ctrl_set_in {
    > > > > + __le32 id;
    > > > > + __le32 num;
    > > > > + __le32 value[MISC_MAX_VAL];
    > > > > +};
    > > > > +
    > > > > +struct scmi_imx_misc_ctrl_notify_in {
    > > > > + __le32 ctrl_id;
    > > > > + __le32 flags;
    > > > > +};
    > > > > +
    > > > > +struct scmi_imx_misc_ctrl_notify_payld {
    > > > > + __le32 ctrl_id;
    > > > > + __le32 flags;
    > > > > +};
    > > > > +
    > > > > +struct scmi_imx_misc_ctrl_get_out {
    > > > > + __le32 num;
    > > > > + __le32 *val;
    > > > > +};
    > > > > +
    > > > > +static int scmi_imx_misc_attributes_get(const struct
    > > > > +scmi_protocol_handle
    > > > *ph,
    > > > > + struct scmi_imx_misc_info *mi) {
    > > > > + int ret;
    > > > > + struct scmi_xfer *t;
    > > > > + struct scmi_msg_imx_misc_protocol_attributes *attr;
    > > > > +
    > > > > + ret = ph->xops->xfer_get_init(ph, PROTOCOL_ATTRIBUTES, 0,
    > > > > + sizeof(*attr), &t);
    > > > > + if (ret)
    > > > > + return ret;
    > > > > +
    > > > > + attr = t->rx.buf;
    > > > > +
    > > > > + ret = ph->xops->do_xfer(ph, t);
    > > > > + if (!ret) {
    > > > > + mi->nr_dev_ctrl = GET_DEV_CTRLS_NR(attr->attributes);
    > > > > + mi->nr_brd_ctrl = GET_BRD_CTRLS_NR(attr->attributes);
    > > > > + mi->nr_reason = GET_REASONS_NR(attr->attributes);
    > > > > + dev_info(ph->dev, "i.MX MISC NUM DEV CTRL: %d, NUM
    > > > BRD CTRL: %d,NUM Reason: %d\n",
    > > > > + mi->nr_dev_ctrl, mi->nr_brd_ctrl, mi->nr_reason);
    > > > > + }
    > > > > +
    > > > > + ph->xops->xfer_put(ph, t);
    > > > > +
    > > > > + return ret;
    > > > > +}
    > > > > +
    > > > > +static int scmi_imx_misc_ctrl_validate_id(const struct
    > > > scmi_protocol_handle *ph,
    > > > > + u32 ctrl_id)
    > > > > +{
    > > > > + struct scmi_imx_misc_info *mi = ph->get_priv(ph);
    > > > > +
    > > > > + if ((ctrl_id < BRD_CTRL_START_ID) && (ctrl_id > mi->nr_dev_ctrl))
    > > > > + return -EINVAL;
    > > > > + if (ctrl_id >= BRD_CTRL_START_ID + mi->nr_brd_ctrl)
    > > > > + return -EINVAL;
    > > > > +
    > > > > + return 0;
    > > > > +}
    > > > > +
    > > > > +static int scmi_imx_misc_ctrl_notify(const struct
    > > > > +scmi_protocol_handle
    > > > *ph,
    > > > > + u32 ctrl_id, u32 flags)
    > > > > +{
    > > > > + struct scmi_imx_misc_ctrl_notify_in *in;
    > > > > + struct scmi_xfer *t;
    > > > > + int ret;
    > > > > +
    > > > > + ret = scmi_imx_misc_ctrl_validate_id(ph, ctrl_id);
    > > > > + if (ret)
    > > > > + return ret;
    > > > > +
    > > > > + ret = ph->xops->xfer_get_init(ph, SCMI_IMX_MISC_CTRL_NOTIFY,
    > > > > + sizeof(*in), 0, &t);
    > > > > + if (ret)
    > > > > + return ret;
    > > > > +
    > > > > + in = t->tx.buf;
    > > > > + in->ctrl_id = cpu_to_le32(ctrl_id);
    > > > > + in->flags = cpu_to_le32(flags);
    > > > > +
    > > > > + ret = ph->xops->do_xfer(ph, t);
    > > > > +
    > > > > + ph->xops->xfer_put(ph, t);
    > > > > +
    > > > > + return ret;
    > > > > +}
    > > > > +
    > > > > +static int
    > > > > +scmi_imx_misc_ctrl_set_notify_enabled(const struct
    > > > scmi_protocol_handle *ph,
    > > > > + u8 evt_id, u32 src_id, bool enable) {
    > > > > + int ret;
    > > > > +
    > > > > + ret = scmi_imx_misc_ctrl_notify(ph, src_id, enable ? evt_id : 0);
    > > > > + if (ret)
    > > > > + dev_err(ph->dev, "FAIL_ENABLED - evt[%X] src[%d] -
    > > > ret:%d\n",
    > > > > + evt_id, src_id, ret);
    > > > > +
    > > > > + return ret;
    > > > > +}
    > > > > +
    > > > > +static int scmi_imx_misc_ctrl_get_num_sources(const struct
    > > > > +scmi_protocol_handle *ph) {
    > > > > + return GENMASK(15, 0);
    > > > > +}
    > > > > +
    > > > > +static void *
    > > > > +scmi_imx_misc_ctrl_fill_custom_report(const struct
    > > > > +scmi_protocol_handle
    > > > *ph,
    > > > > + u8 evt_id, ktime_t timestamp,
    > > > > + const void *payld, size_t payld_sz,
    > > > > + void *report, u32 *src_id) {
    > > > > + const struct scmi_imx_misc_ctrl_notify_payld *p = payld;
    > > > > + struct scmi_imx_misc_ctrl_notify_report *r = report;
    > > > > +
    > > > > + if (sizeof(*p) != payld_sz)
    > > > > + return NULL;
    > > > > +
    > > > > + r->timestamp = timestamp;
    > > > > + r->ctrl_id = p->ctrl_id;
    > > > > + r->flags = p->flags;
    > > > > + *src_id = r->ctrl_id;
    > > > > + dev_dbg(ph->dev, "%s: ctrl_id: %d flags: %d\n", __func__,
    > > > > + r->ctrl_id, r->flags);
    > > > > +
    > > > > + return r;
    > > > > +}
    > > > > +
    > > > > +static const struct scmi_event_ops scmi_imx_misc_event_ops = {
    > > > > + .get_num_sources = scmi_imx_misc_ctrl_get_num_sources,
    > > > > + .set_notify_enabled = scmi_imx_misc_ctrl_set_notify_enabled,
    > > > > + .fill_custom_report = scmi_imx_misc_ctrl_fill_custom_report,
    > > > > +};
    > > > > +
    > > > > +static const struct scmi_event scmi_imx_misc_events[] = {
    > > > > + {
    > > > > + .id = SCMI_EVENT_IMX_MISC_CONTROL_DISABLED,
    > > > > + .max_payld_sz = sizeof(struct
    > > > scmi_imx_misc_ctrl_notify_payld),
    > > > > + .max_report_sz = sizeof(struct
    > > > scmi_imx_misc_ctrl_notify_report),
    > > > > + },
    > > > > + {
    > > > > + .id = SCMI_EVENT_IMX_MISC_CONTROL_FALLING_EDGE,
    > > > > + .max_payld_sz = sizeof(struct
    > > > scmi_imx_misc_ctrl_notify_payld),
    > > > > + .max_report_sz = sizeof(struct
    > > > scmi_imx_misc_ctrl_notify_report),
    > > > > + },
    > > > > + {
    > > > > + .id = SCMI_EVENT_IMX_MISC_CONTROL_RISING_EDGE,
    > > > > + .max_payld_sz = sizeof(struct
    > > > scmi_imx_misc_ctrl_notify_payld),
    > > > > + .max_report_sz = sizeof(struct
    > > > scmi_imx_misc_ctrl_notify_report),
    > > > > + }
    > > > > +};
    > > > > +
    > > > > +static struct scmi_protocol_events scmi_imx_misc_protocol_events = {
    > > > > + .queue_sz = SCMI_PROTO_QUEUE_SZ,
    > > > > + .ops = &scmi_imx_misc_event_ops,
    > > > > + .evts = scmi_imx_misc_events,
    > > > > + .num_events = ARRAY_SIZE(scmi_imx_misc_events), };
    > > > > +
    > > > > +static int scmi_imx_misc_protocol_init(const struct
    > > > > +scmi_protocol_handle *ph) {
    > > > > + struct scmi_imx_misc_info *minfo;
    > > > > + u32 version;
    > > > > + int ret;
    > > > > +
    > > > > + ret = ph->xops->version_get(ph, &version);
    > > > > + if (ret)
    > > > > + return ret;
    > > > > +
    > > > > + dev_info(ph->dev, "NXP SM MISC Version %d.%d\n",
    > > > > + PROTOCOL_REV_MAJOR(version),
    > > > PROTOCOL_REV_MINOR(version));
    > > > > +
    > > > > + minfo = devm_kzalloc(ph->dev, sizeof(*minfo), GFP_KERNEL);
    > > > > + if (!minfo)
    > > > > + return -ENOMEM;
    > > > > +
    > > > > + ret = scmi_imx_misc_attributes_get(ph, minfo);
    > > > > + if (ret)
    > > > > + return ret;
    > > > > +
    > > > > + return ph->set_priv(ph, minfo, version); }
    > > > > +
    > > > > +static int scmi_imx_misc_ctrl_get(const struct scmi_protocol_handle
    > *ph,
    > > > > + u32 ctrl_id, u32 *num, u32 *val) {
    > > > > + struct scmi_imx_misc_ctrl_get_out *out;
    > > > > + struct scmi_xfer *t;
    > > > > + int ret, i;
    > > > > +
    > > > > + ret = scmi_imx_misc_ctrl_validate_id(ph, ctrl_id);
    > > > > + if (ret)
    > > > > + return ret;
    > > > > +
    > > > > + ret = ph->xops->xfer_get_init(ph, SCMI_IMX_MISC_CTRL_GET,
    > > > sizeof(u32),
    > > > > + 0, &t);
    > > > > + if (ret)
    > > > > + return ret;
    > > > > +
    > > > > + put_unaligned_le32(ctrl_id, t->tx.buf);
    > > > > + ret = ph->xops->do_xfer(ph, t);
    > > > > + if (!ret) {
    > > > > + out = t->rx.buf;
    > > > > + *num = le32_to_cpu(out->num);
    > > > > + for (i = 0; i < *num && i < MISC_MAX_VAL; i++)
    > > > > + val[i] = le32_to_cpu(out->val[i]);
    > > > > + }
    > > > > +
    > > > > + ph->xops->xfer_put(ph, t);
    > > > > +
    > > > > + return ret;
    > > > > +}
    > > > > +
    > > > > +static int scmi_imx_misc_ctrl_set(const struct scmi_protocol_handle
    > *ph,
    > > > > + u32 ctrl_id, u32 num, u32 *val) {
    > > > > + struct scmi_imx_misc_ctrl_set_in *in;
    > > > > + struct scmi_xfer *t;
    > > > > + int ret, i;
    > > > > +
    > > > > + ret = scmi_imx_misc_ctrl_validate_id(ph, ctrl_id);
    > > > > + if (ret)
    > > > > + return ret;
    > > > > +
    > > > > + if (num > MISC_MAX_VAL)
    > > > > + return -EINVAL;
    > > > > +
    > > > > + ret = ph->xops->xfer_get_init(ph, SCMI_IMX_MISC_CTRL_SET,
    > > > sizeof(*in),
    > > > > + 0, &t);
    > > > > + if (ret)
    > > > > + return ret;
    > > > > +
    > > > > + in = t->tx.buf;
    > > > > + in->id = cpu_to_le32(ctrl_id);
    > > > > + in->num = cpu_to_le32(num);
    > > > > + for (i = 0; i < num; i++)
    > > > > + in->value[i] = cpu_to_le32(val[i]);
    > > > > +
    > > > > + ret = ph->xops->do_xfer(ph, t);
    > > > > +
    > > > > + ph->xops->xfer_put(ph, t);
    > > > > +
    > > > > + return ret;
    > > > > +}
    > > > > +
    > > > > +static const struct scmi_imx_misc_proto_ops
    > > > > +scmi_imx_misc_proto_ops =
    > > > {
    > > > > + .misc_ctrl_set = scmi_imx_misc_ctrl_set,
    > > > > + .misc_ctrl_get = scmi_imx_misc_ctrl_get, };
    > > > > +
    > > > > +static const struct scmi_protocol scmi_imx_misc = {
    > > > > + .id = SCMI_PROTOCOL_IMX_MISC,
    > > > > + .owner = THIS_MODULE,
    > > > > + .instance_init = &scmi_imx_misc_protocol_init,
    > > > > + .ops = &scmi_imx_misc_proto_ops,
    > > > > + .events = &scmi_imx_misc_protocol_events,
    > > > > + .supported_version = SCMI_PROTOCOL_SUPPORTED_VERSION, };
    > > > > +module_scmi_protocol(scmi_imx_misc);
    > > > > diff --git a/include/linux/scmi_imx_protocol.h
    > > > > b/include/linux/scmi_imx_protocol.h
    > > > > index 90ce011a4429..a69bd4a20f0f 100644
    > > > > --- a/include/linux/scmi_imx_protocol.h
    > > > > +++ b/include/linux/scmi_imx_protocol.h
    > > > > @@ -13,8 +13,14 @@
    > > > > #include <linux/notifier.h>
    > > > > #include <linux/types.h>
    > > > >
    > > > > +#define SCMI_PAYLOAD_LEN 100
    > > > > +
    > > > > +#define SCMI_ARRAY(X, Y) ((SCMI_PAYLOAD_LEN - (X)) / sizeof(Y))
    > > > > +#define MISC_MAX_VAL SCMI_ARRAY(8, uint32_t)
    > > > > +
    > > > > enum scmi_nxp_protocol {
    > > > > SCMI_PROTOCOL_IMX_BBM = 0x81,
    > > > > + SCMI_PROTOCOL_IMX_MISC = 0x84,
    > > > > };
    > > > >
    > > > > struct scmi_imx_bbm_proto_ops {
    > > > > @@ -42,4 +48,15 @@ struct scmi_imx_bbm_notif_report {
    > > > > unsigned int rtc_id;
    > > > > unsigned int rtc_evt;
    > > > > };
    > > > > +
    > > > > +struct scmi_imx_misc_ctrl_notify_report {
    > > > > + ktime_t timestamp;
    > > > > + unsigned int ctrl_id;
    > > > > + unsigned int flags;
    > > > > +};
    > > > > +
    > > > > +struct scmi_imx_misc_proto_ops {
    > > > > + int (*misc_ctrl_set)(const struct scmi_protocol_handle *ph, u32
    > > > > +id,
    > > > u32 num, u32 *val);
    > > > > + int (*misc_ctrl_get)(const struct scmi_protocol_handle *ph, u32
    > > > > +id,
    > > > > +u32 *num, u32 *val); };
    > > > > #endif
    > > > >
    > > > > --
    > > > > 2.37.1
    > > > >
    > > > >
    > > > >
    > >

    \
     
     \ /
      Last update: 2024-05-27 16:27    [W:3.341 / U:2.272 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site