($INBOX_DIR/description missing)
 help / color / mirror / Atom feed
* Re: [PATCH v1 3/3] Bluetooth: NXP: Add protocol support for NXP Bluetooth chipsets
From: Ilpo Järvinen @ 2023-02-13 16:32 UTC (permalink / raw)
  To: Neeraj sanjay kale
  Cc: davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
	pabeni@redhat.com, robh+dt@kernel.org,
	krzysztof.kozlowski+dt@linaro.org, marcel@holtmann.org,
	johan.hedberg@gmail.com, luiz.dentz@gmail.com, Greg Kroah-Hartman,
	Jiri Slaby, Netdev, devicetree@vger.kernel.org, LKML,
	linux-bluetooth@vger.kernel.org, linux-serial, Amitkumar Karwar,
	Rohit Fule, Sherry Sun
In-Reply-To: <AM9PR04MB8603E350AC2E06CB788909C0E7DD9@AM9PR04MB8603.eurprd04.prod.outlook.com>

[-- Attachment #1: Type: text/plain, Size: 14607 bytes --]

On Mon, 13 Feb 2023, Neeraj sanjay kale wrote:

> Hi Ilpo,
> 
> Thank you for your review comments and sorry for the delay in replying to some of your queries.

I made some additional comments against v2 and I meant those ones were not 
addressed, the ones I made for v1 you've addressed I think.

-- 
 i.

> 
> > From: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
> > Sent: Wednesday, January 25, 2023 4:53 PM
> > To: Neeraj sanjay kale <neeraj.sanjaykale@nxp.com>
> > Cc: davem@davemloft.net; edumazet@google.com; kuba@kernel.org;
> > pabeni@redhat.com; robh+dt@kernel.org;
> > krzysztof.kozlowski+dt@linaro.org; marcel@holtmann.org;
> > johan.hedberg@gmail.com; luiz.dentz@gmail.com; Greg Kroah-Hartman
> > <gregkh@linuxfoundation.org>; Jiri Slaby <jirislaby@kernel.org>; Netdev
> > <netdev@vger.kernel.org>; devicetree@vger.kernel.org; LKML <linux-
> > kernel@vger.kernel.org>; linux-bluetooth@vger.kernel.org; linux-serial
> > <linux-serial@vger.kernel.org>; Amitkumar Karwar
> > <amitkumar.karwar@nxp.com>; Rohit Fule <rohit.fule@nxp.com>; Sherry
> > Sun <sherry.sun@nxp.com>
> > Subject: Re: [PATCH v1 3/3] Bluetooth: NXP: Add protocol support for
> > NXP Bluetooth chipsets
> > 
> > > This adds a driver based on serdev driver for the NXP BT serial
> > > protocol based on running H:4, which can enable the built-in
> > > Bluetooth device inside a generic NXP BT chip.
> > >
> > > This driver has Power Save feature that will put the chip into
> > > sleep state whenever there is no activity for 2000ms, and will
> > > be woken up when any activity is to be initiated.
> > >
> > > This driver enables the power save feature by default by sending
> > > the vendor specific commands to the chip during setup.
> > >
> > > During setup, the driver is capable of reading the bootloader
> > > signature unique to every chip, and downloading corresponding
> > > FW file defined in a user-space config file. The firmware file
> > > name can be defined in DTS file as well, in which case the
> > > user-space config file will be ignored.
> > >
> > > Signed-off-by: Neeraj Sanjay Kale <neeraj.sanjaykale@nxp.com>
> > > ---
> > >  MAINTAINERS                |    7 +
> > >  drivers/bluetooth/Kconfig  |   11 +
> > >  drivers/bluetooth/Makefile |    1 +
> > >  drivers/bluetooth/btnxp.c  | 1337
> > ++++++++++++++++++++++++++++++++++++
> > >  drivers/bluetooth/btnxp.h  |  230 +++++++
> > >  5 files changed, 1586 insertions(+)
> > >  create mode 100644 drivers/bluetooth/btnxp.c
> > >  create mode 100644 drivers/bluetooth/btnxp.h
> > >
> > > +static int ps_init_work(struct hci_dev *hdev)
> > > +{
> > > +     struct ps_data *psdata = kzalloc(sizeof(*psdata), GFP_KERNEL);
> > > +     struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
> > > +
> > > +     if (!psdata) {
> > > +             BT_ERR("Can't allocate control structure for Power Save feature");
> > > +             return -ENOMEM;
> > > +     }
> > > +     nxpdev->psdata = psdata;
> > > +
> > > +     memset(psdata, 0, sizeof(*psdata));
> > 
> > Why memset to zero kzalloc'ed mem?
> I have removed all memset calls after kzalloc.
> > 
> 
> 
> 
> > > +static int send_ps_cmd(struct hci_dev *hdev, void *data)
> > > +{
> > > +     struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
> > > +     struct ps_data *psdata = nxpdev->psdata;
> > > +     u8 pcmd;
> > > +     struct sk_buff *skb;
> > > +     u8 *status;
> > > +
> > > +     if (psdata->ps_mode ==  PS_MODE_ENABLE)
> > > +             pcmd = BT_PS_ENABLE;
> > > +     else
> > > +             pcmd = BT_PS_DISABLE;
> > > +
> > > +     psdata->driver_sent_cmd = true; /* set flag to prevent re-sending
> > command in nxp_enqueue */
> > > +     skb = __hci_cmd_sync(hdev, HCI_NXP_AUTO_SLEEP_MODE, 1, &pcmd,
> > HCI_CMD_TIMEOUT);
> > > +     psdata->driver_sent_cmd = false;
> > 
> > A helper for these 3 lines?
> Added a new function where ever setting psdata->driver_sent_cmd and __hci_cmd_sync() is needed.
> 
> 
> 
> > 
> > Do you need to free the skb?
> Yes. Freed skb's where ever it needs to be freed in v2 and v3 patches.
> 
> 
> 
> > > +     for (i = 0; i < map_table_size; i++) {
> > 
> > Isn't this just ARRAY_SIZE(chip_id_name_table)? use it directly here,
> > no need for the extra variable?
> > 
> > > +             if (!strcmp(chip_id_name_table[i].chip_name, name_str))
> > > +                     return chip_id_name_table[i].chip_id;
> > > +     }
> > > +
> > > +     return 0;  /* invalid name_str */
> > 
> > Put such comment preferrably to function's comment if you want to note
> > things like this or create a properly named define for it.
> I have slightly changed the way FW Download behaves, and removed this function.
> 
> 
> 
> > strncpy(fw_mod_params[param_index].fw_name,
> > > +                                                     value, MAX_FW_FILE_NAME_LEN);
> > > +                                     } else if (!strcmp(label, OPER_SPEED_TAG)) {
> > > +                                             ret = kstrtouint(value, 10,
> > > +                                             &fw_mod_params[param_index].oper_speed);
> > > +                                     } else if (!strcmp(label, FW_DL_PRI_BAUDRATE_TAG))
> > {
> > > +                                             ret = kstrtouint(value, 10,
> > > +
> > &fw_mod_params[param_index].fw_dnld_pri_baudrate);
> > > +                                     } else if (!strcmp(label, FW_DL_SEC_BAUDRATE_TAG))
> > {
> > > +                                             ret = kstrtouint(value, 10,
> > > +
> > &fw_mod_params[param_index].fw_dnld_sec_baudrate);
> > > +                                     } else if (!strcmp(label, FW_INIT_BAUDRATE)) {
> > > +                                             ret = kstrtouint(value, 10,
> > > +
> > &fw_mod_params[param_index].fw_init_baudrate);
> > > +                                     } else {
> > > +                                             BT_ERR("Unknown tag: %s", label);
> > > +                                             ret = -1;
> > > +                                             goto err;
> > > +                                     }
> > 
> > Your indent is way too deep here, refactor the line processing into
> > another function to make it readable?
> > 
> > Wouldn't something like sscanf() make it a bit simpler?
> 
> Created a new function to handle updating this data and used sscanf().
> 
> 
> 
> > > +             } else {
> > > +                     *dptr = sptr[i];
> > > +                     dptr++;
> > 
> > What prevents dptr becoming larger than the size allocated for line?
> Used array index method instead of dptr pointer to fill the line. Added check for index.
> 
> > > +static bool nxp_fw_change_baudrate(struct hci_dev *hdev, u16 req_len)
> > > +{
> > > +     struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
> > > +     static u8 nxp_cmd5_header[HDR_LEN] = {
> > 
> > It would be good to prefix HDR_LEN with something to make it more specific
> > to this use case.
> We need this HDR_LEN macro while sending cmd7 as well. Hence kept this unchanged.
> 
> > 
> > > +                                                     0x05, 0x00, 0x00, 0x00,
> > > +                                                     0x00, 0x00, 0x00, 0x00,
> > > +                                                     0x2c, 0x00, 0x00, 0x00,
> > > +                                                     0x77, 0xdb, 0xfd, 0xe0};
> > > +     static u8 uart_config[60] = {0};
> > 
> > Is this some structure actually? You seem to be filling it always with
> > the same stuff in same order?
> > 
> > You probably need to handle byte-order properly too.
> Handled cmd5 and cmd7 in a proper way using structures and handled byte-ordering.
> 
> > > +static u32 nxp_get_data_len(const u8 *buf)
> > > +{
> > > +     return (buf[8] | (buf[9] << 8));
> > 
> > Custom byte-order func? Use std ones instead.
> Resolved in v2 patch.
> 
> > > +     if (nxpdev->fw_dnld_sec_baudrate != nxpdev->current_baudrate) {
> > > +             if (!timeout_changed) {
> > > +                     nxp_send_ack(NXP_ACK_V1, hdev);
> > > +                     timeout_changed = nxp_fw_change_timeout(hdev, req->len);
> > 
> > You never test if there was enough data? If there isn't req will be NULL
> > which you don't check before dereferencing req->len.
> Added check for req before dereferencing it.
> 
> 
> > > +             if (req->len & 0x01) {
> > > +                     /* The CRC did not match at the other end.
> > > +                      * That's why the request to re-send.
> > > +                      * Simply send the same bytes again.
> > > +                      */
> > > +                     requested_len = nxpdev->fw_sent_bytes;
> > > +                     BT_ERR("CRC error. Resend %d bytes of FW.", requested_len);
> > > +             } else {
> > > +                     /* Increment offset by number of previous successfully sent
> > bytes */
> > > +                     nxpdev->fw_dnld_offset += nxpdev->fw_sent_bytes;
> > > +                     requested_len = req->len;
> > > +             }
> > > +
> > > +             /* The FW bin file is made up of many blocks of
> > > +              * 16 byte header and payload data chunks. If the
> > > +              * FW has requested a header, read the payload length
> > > +              * info from the header, and then send the header.
> > > +              * In the next iteration, the FW should request the
> > > +              * payload data chunk, which should be equal to the
> > > +              * payload length read from header. If there is a
> > > +              * mismatch, clearly the driver and FW are out of sync,
> > > +              * and we need to re-send the previous header again.
> > > +              */
> > > +             if (requested_len == expected_len) {
> > > +                     if (requested_len == HDR_LEN)
> > > +                             expected_len = nxp_get_data_len(nxpdev->fw->data +
> > > +                                                                     nxpdev->fw_dnld_offset);
> > > +                     else
> > > +                             expected_len = HDR_LEN;
> > 
> > How can you ever end up into this else branch? Why assign expected_len
> > here?
> There are 2 scenarios where requested_len == expected_len.
> One, where requested_len is 16, which means a header was requested.
> Another, where requested_len is not 16, which means payload was requested.
> 
> So if header was requested, we calculate the payload length which should be equal to requested_len in next iteration.
> Similarly, if payload was requested, then in the next iteration the FW should request for a 16 bit header.
> The expected_len is expected to toggle between 2 values: 16 and (e.g.) 2048.
> 
> > 
> > > +             } else {
> > > +                     if (requested_len == HDR_LEN) {
> > 
> > Never true.
> Ideally we should not end up in this else part, but there are various customers and module vendors who use NXP chipsets within their products, which are already out in the market. Whenever the driver sends the cmd5 and cmd7 packets, we sometimes observe this scenario where the FW requests 16 bit header in 2 consecutive iterations, and we need to be sure that we re-send the 16 bit header, and not the 16 bit payload. 
> This happens when the chip updates it's baudrate while receiving the 1st header, and discards it due to CRC mismatch, and requests the header again.
> 
> >
> > > +                             /* FW download out of sync. Send previous chunk again> */
> > > +                            nxpdev->fw_dnld_offset -= nxpdev->fw_sent_bytes;
> > > +                             expected_len = HDR_LEN;> > +                     }
> > > +            }
> > > +
> 
> > > +static int nxp_recv_fw_req_v3(struct hci_dev *hdev, struct sk_buff *skb)
> > > +{
> > > +     struct V3_DATA_REQ *req = skb_pull_data(skb, sizeof(struct
> > V3_DATA_REQ));
> > > +     struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
> > > +     static bool timeout_changed;
> > > +     static bool baudrate_changed;
> > > +
> > > +     if (!req || !nxpdev || !strlen(nxpdev->fw_name) || !nxpdev->fw->data)
> > > +             return 0;
> > 
> > Who is expected to free the skb? These functions or one of the callers?
> > (Which one? I lost track of the callchain and error passing too).
> Added kfree_skb() in the called functions.
> 
> 
> > > +                     strncpy(nxpdev->fw_name, fw_path,
> > MAX_FW_FILE_NAME_LEN);
> > > +                     strncpy(nxpdev->fw_name + strlen(fw_path), fw_name_dt,
> > > +                                     MAX_FW_FILE_NAME_LEN);
> > 
> > How can this second one be correct if you use +strlen(fw_path) for the
> > pointer. Why not use snprintf()?
> Replaced strncpy with snprintfs()
> 
> 
> 
> > > +static int nxp_enqueue(struct hci_dev *hdev, struct sk_buff *skb)
> > > +{
> > > +     struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
> > > +     struct ps_data *psdata = nxpdev->psdata;
> > > +     struct hci_command_hdr *hdr;
> > > +     u8 *param;
> > > +
> > > +     /* if commands are received from user space (e.g. hcitool), update
> > > +      * driver flags accordingly and ask driver to re-send the command
> > > +      */
> > > +     if (bt_cb(skb)->pkt_type == HCI_COMMAND_PKT && !psdata-
> > >driver_sent_cmd) {
> > 
> > Should you need to check psdata for NULL before dereferencing it?
> Added checks for psdata before dereferencing it.
> 
> 
> > > +/* Bluetooth vendor command : Sleep mode */
> > > +#define HCI_NXP_AUTO_SLEEP_MODE      0xFC23
> > 
> > Try to change all hex letters to lowercase.
> Changed all hex letters to lowercase.
> 
> > > +struct V1_DATA_REQ {
> > > +     u16 len;
> > > +     u16 len_comp;
> > > +} __packed;
> > > +
> > > +struct V3_DATA_REQ {
> > > +     u16 len;
> > > +     u32 offset;
> > > +     u16 error;
> > > +     u8 crc;
> > > +} __packed;
> > > +
> > > +struct V3_START_IND {
> > > +     u16 chip_id;
> > > +     u8 loader_ver;
> > > +     u8 crc;
> > > +} __packed;
> > 
> > Struct names should be lowercased. Multibyte fields need to specify
> > byte-order?
> Resolved.
> 
> > > +
> > > +#define SWAPL(x) ((((x) >> 24) & 0xff) \
> > > +                              | (((x) >> 8) & 0xff00) \
> > > +                              | (((x) << 8) & 0xff0000L) \
> > > +                              | (((x) << 24) & 0xff000000L))
> > 
> > Perhaps something existing under include/ could do swap for you?
> Added call to a standard swab32() function.
> 
> > --
> >  i.
> 
> Please review the V3 patch and let me know if you have any suggestions or comments.

^ permalink raw reply

* Re: remove arch/sh
From: John Paul Adrian Glaubitz @ 2023-02-13 16:30 UTC (permalink / raw)
  To: Stephen Rothwell
  Cc: Christoph Hellwig, Yoshinori Sato, Rich Felker, Arnd Bergmann,
	Greg Kroah-Hartman, Laurent Pinchart, Kieran Bingham,
	Geert Uytterhoeven, linux-kernel, linux-watchdog, devicetree,
	linux-arch, dmaengine, dri-devel, linux-renesas-soc, linux-i2c,
	linux-input, linux-media, linux-mmc, linux-mtd, netdev,
	linux-gpio, linux-rtc, linux-spi, linux-serial, linux-usb,
	linux-fbdev, alsa-devel, linux-sh
In-Reply-To: <20230206100856.603a0f8f@canb.auug.org.au>

Hi Steve!

On Mon, 2023-02-06 at 10:08 +1100, Stephen Rothwell wrote:
> Hi,
> 
> On Fri, 3 Feb 2023 09:30:37 +0100 Christoph Hellwig <hch@lst.de> wrote:
> > 
> > On Fri, Feb 03, 2023 at 09:24:46AM +0100, John Paul Adrian Glaubitz wrote:
> > > Since this is my very first time stepping up as a kernel maintainer, I was hoping
> > > to get some pointers on what to do to make this happen.
> > > 
> > > So far, we have set up a new kernel tree and I have set up a local development and
> > > test environment for SH kernels using my SH7785LCR board as the target platform.
> > > 
> > > Do I just need to send a patch asking to change the corresponding entry in the
> > > MAINTAINERS file?  
> > 
> > I'm not sure a there is a document, but:
> > 
> >  - add the MAINTAINERS change to your tree
> >  - ask Stephen to get your tree included in linux-next
> 
> And by "Stephen", Christoph means me.  When you are ready, please send
> me a request to include your tree/branch in linux-next (usually the
> branch is called something like "for-next" or just "next") telling me
> the git URL, and the contacts I should send email to if there are
> conflicts/build issues with the branch.  I will then fetch the branch
> every time I create a new linux-next release (most work days), so all
> you need to do is update that branch each time you are ready to publish
> more commits.

I'm in the MAINTAINERS now in Linus' tree. I have requested a kernel.org
account now and will hopefully have my trees set up later this week.

I'll let you know about the URLs as soon as possible.

Adrian

-- 
 .''`.  John Paul Adrian Glaubitz
: :' :  Debian Developer
`. `'   Physicist
  `-    GPG: 62FF 8A75 84E0 2956 9546  0006 7426 3B37 F5B5 F913

^ permalink raw reply

* Re: [PATCH v1 3/3] Bluetooth: NXP: Add protocol support for NXP Bluetooth chipsets
From: Neeraj sanjay kale @ 2023-02-13 16:25 UTC (permalink / raw)
  To: Ilpo Järvinen
  Cc: davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
	pabeni@redhat.com, robh+dt@kernel.org,
	krzysztof.kozlowski+dt@linaro.org, marcel@holtmann.org,
	johan.hedberg@gmail.com, luiz.dentz@gmail.com, Greg Kroah-Hartman,
	Jiri Slaby, Netdev, devicetree@vger.kernel.org, LKML,
	linux-bluetooth@vger.kernel.org, linux-serial, Amitkumar Karwar,
	Rohit Fule, Sherry Sun
In-Reply-To: <bd10dd58-35ff-e0e2-5ac4-97df1f6a30a8@linux.intel.com>

Hi Ilpo,

Thank you for your review comments and sorry for the delay in replying to some of your queries.

> From: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
> Sent: Wednesday, January 25, 2023 4:53 PM
> To: Neeraj sanjay kale <neeraj.sanjaykale@nxp.com>
> Cc: davem@davemloft.net; edumazet@google.com; kuba@kernel.org;
> pabeni@redhat.com; robh+dt@kernel.org;
> krzysztof.kozlowski+dt@linaro.org; marcel@holtmann.org;
> johan.hedberg@gmail.com; luiz.dentz@gmail.com; Greg Kroah-Hartman
> <gregkh@linuxfoundation.org>; Jiri Slaby <jirislaby@kernel.org>; Netdev
> <netdev@vger.kernel.org>; devicetree@vger.kernel.org; LKML <linux-
> kernel@vger.kernel.org>; linux-bluetooth@vger.kernel.org; linux-serial
> <linux-serial@vger.kernel.org>; Amitkumar Karwar
> <amitkumar.karwar@nxp.com>; Rohit Fule <rohit.fule@nxp.com>; Sherry
> Sun <sherry.sun@nxp.com>
> Subject: Re: [PATCH v1 3/3] Bluetooth: NXP: Add protocol support for
> NXP Bluetooth chipsets
> 
> > This adds a driver based on serdev driver for the NXP BT serial
> > protocol based on running H:4, which can enable the built-in
> > Bluetooth device inside a generic NXP BT chip.
> >
> > This driver has Power Save feature that will put the chip into
> > sleep state whenever there is no activity for 2000ms, and will
> > be woken up when any activity is to be initiated.
> >
> > This driver enables the power save feature by default by sending
> > the vendor specific commands to the chip during setup.
> >
> > During setup, the driver is capable of reading the bootloader
> > signature unique to every chip, and downloading corresponding
> > FW file defined in a user-space config file. The firmware file
> > name can be defined in DTS file as well, in which case the
> > user-space config file will be ignored.
> >
> > Signed-off-by: Neeraj Sanjay Kale <neeraj.sanjaykale@nxp.com>
> > ---
> >  MAINTAINERS                |    7 +
> >  drivers/bluetooth/Kconfig  |   11 +
> >  drivers/bluetooth/Makefile |    1 +
> >  drivers/bluetooth/btnxp.c  | 1337
> ++++++++++++++++++++++++++++++++++++
> >  drivers/bluetooth/btnxp.h  |  230 +++++++
> >  5 files changed, 1586 insertions(+)
> >  create mode 100644 drivers/bluetooth/btnxp.c
> >  create mode 100644 drivers/bluetooth/btnxp.h
> >
> > +static int ps_init_work(struct hci_dev *hdev)
> > +{
> > +     struct ps_data *psdata = kzalloc(sizeof(*psdata), GFP_KERNEL);
> > +     struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
> > +
> > +     if (!psdata) {
> > +             BT_ERR("Can't allocate control structure for Power Save feature");
> > +             return -ENOMEM;
> > +     }
> > +     nxpdev->psdata = psdata;
> > +
> > +     memset(psdata, 0, sizeof(*psdata));
> 
> Why memset to zero kzalloc'ed mem?
I have removed all memset calls after kzalloc.
> 



> > +static int send_ps_cmd(struct hci_dev *hdev, void *data)
> > +{
> > +     struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
> > +     struct ps_data *psdata = nxpdev->psdata;
> > +     u8 pcmd;
> > +     struct sk_buff *skb;
> > +     u8 *status;
> > +
> > +     if (psdata->ps_mode ==  PS_MODE_ENABLE)
> > +             pcmd = BT_PS_ENABLE;
> > +     else
> > +             pcmd = BT_PS_DISABLE;
> > +
> > +     psdata->driver_sent_cmd = true; /* set flag to prevent re-sending
> command in nxp_enqueue */
> > +     skb = __hci_cmd_sync(hdev, HCI_NXP_AUTO_SLEEP_MODE, 1, &pcmd,
> HCI_CMD_TIMEOUT);
> > +     psdata->driver_sent_cmd = false;
> 
> A helper for these 3 lines?
Added a new function where ever setting psdata->driver_sent_cmd and __hci_cmd_sync() is needed.



> 
> Do you need to free the skb?
Yes. Freed skb's where ever it needs to be freed in v2 and v3 patches.



> > +     for (i = 0; i < map_table_size; i++) {
> 
> Isn't this just ARRAY_SIZE(chip_id_name_table)? use it directly here,
> no need for the extra variable?
> 
> > +             if (!strcmp(chip_id_name_table[i].chip_name, name_str))
> > +                     return chip_id_name_table[i].chip_id;
> > +     }
> > +
> > +     return 0;  /* invalid name_str */
> 
> Put such comment preferrably to function's comment if you want to note
> things like this or create a properly named define for it.
I have slightly changed the way FW Download behaves, and removed this function.



> strncpy(fw_mod_params[param_index].fw_name,
> > +                                                     value, MAX_FW_FILE_NAME_LEN);
> > +                                     } else if (!strcmp(label, OPER_SPEED_TAG)) {
> > +                                             ret = kstrtouint(value, 10,
> > +                                             &fw_mod_params[param_index].oper_speed);
> > +                                     } else if (!strcmp(label, FW_DL_PRI_BAUDRATE_TAG))
> {
> > +                                             ret = kstrtouint(value, 10,
> > +
> &fw_mod_params[param_index].fw_dnld_pri_baudrate);
> > +                                     } else if (!strcmp(label, FW_DL_SEC_BAUDRATE_TAG))
> {
> > +                                             ret = kstrtouint(value, 10,
> > +
> &fw_mod_params[param_index].fw_dnld_sec_baudrate);
> > +                                     } else if (!strcmp(label, FW_INIT_BAUDRATE)) {
> > +                                             ret = kstrtouint(value, 10,
> > +
> &fw_mod_params[param_index].fw_init_baudrate);
> > +                                     } else {
> > +                                             BT_ERR("Unknown tag: %s", label);
> > +                                             ret = -1;
> > +                                             goto err;
> > +                                     }
> 
> Your indent is way too deep here, refactor the line processing into
> another function to make it readable?
> 
> Wouldn't something like sscanf() make it a bit simpler?

Created a new function to handle updating this data and used sscanf().



> > +             } else {
> > +                     *dptr = sptr[i];
> > +                     dptr++;
> 
> What prevents dptr becoming larger than the size allocated for line?
Used array index method instead of dptr pointer to fill the line. Added check for index.

> > +static bool nxp_fw_change_baudrate(struct hci_dev *hdev, u16 req_len)
> > +{
> > +     struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
> > +     static u8 nxp_cmd5_header[HDR_LEN] = {
> 
> It would be good to prefix HDR_LEN with something to make it more specific
> to this use case.
We need this HDR_LEN macro while sending cmd7 as well. Hence kept this unchanged.

> 
> > +                                                     0x05, 0x00, 0x00, 0x00,
> > +                                                     0x00, 0x00, 0x00, 0x00,
> > +                                                     0x2c, 0x00, 0x00, 0x00,
> > +                                                     0x77, 0xdb, 0xfd, 0xe0};
> > +     static u8 uart_config[60] = {0};
> 
> Is this some structure actually? You seem to be filling it always with
> the same stuff in same order?
> 
> You probably need to handle byte-order properly too.
Handled cmd5 and cmd7 in a proper way using structures and handled byte-ordering.

> > +static u32 nxp_get_data_len(const u8 *buf)
> > +{
> > +     return (buf[8] | (buf[9] << 8));
> 
> Custom byte-order func? Use std ones instead.
Resolved in v2 patch.

> > +     if (nxpdev->fw_dnld_sec_baudrate != nxpdev->current_baudrate) {
> > +             if (!timeout_changed) {
> > +                     nxp_send_ack(NXP_ACK_V1, hdev);
> > +                     timeout_changed = nxp_fw_change_timeout(hdev, req->len);
> 
> You never test if there was enough data? If there isn't req will be NULL
> which you don't check before dereferencing req->len.
Added check for req before dereferencing it.


> > +             if (req->len & 0x01) {
> > +                     /* The CRC did not match at the other end.
> > +                      * That's why the request to re-send.
> > +                      * Simply send the same bytes again.
> > +                      */
> > +                     requested_len = nxpdev->fw_sent_bytes;
> > +                     BT_ERR("CRC error. Resend %d bytes of FW.", requested_len);
> > +             } else {
> > +                     /* Increment offset by number of previous successfully sent
> bytes */
> > +                     nxpdev->fw_dnld_offset += nxpdev->fw_sent_bytes;
> > +                     requested_len = req->len;
> > +             }
> > +
> > +             /* The FW bin file is made up of many blocks of
> > +              * 16 byte header and payload data chunks. If the
> > +              * FW has requested a header, read the payload length
> > +              * info from the header, and then send the header.
> > +              * In the next iteration, the FW should request the
> > +              * payload data chunk, which should be equal to the
> > +              * payload length read from header. If there is a
> > +              * mismatch, clearly the driver and FW are out of sync,
> > +              * and we need to re-send the previous header again.
> > +              */
> > +             if (requested_len == expected_len) {
> > +                     if (requested_len == HDR_LEN)
> > +                             expected_len = nxp_get_data_len(nxpdev->fw->data +
> > +                                                                     nxpdev->fw_dnld_offset);
> > +                     else
> > +                             expected_len = HDR_LEN;
> 
> How can you ever end up into this else branch? Why assign expected_len
> here?
There are 2 scenarios where requested_len == expected_len.
One, where requested_len is 16, which means a header was requested.
Another, where requested_len is not 16, which means payload was requested.

So if header was requested, we calculate the payload length which should be equal to requested_len in next iteration.
Similarly, if payload was requested, then in the next iteration the FW should request for a 16 bit header.
The expected_len is expected to toggle between 2 values: 16 and (e.g.) 2048.

> 
> > +             } else {
> > +                     if (requested_len == HDR_LEN) {
> 
> Never true.
Ideally we should not end up in this else part, but there are various customers and module vendors who use NXP chipsets within their products, which are already out in the market. Whenever the driver sends the cmd5 and cmd7 packets, we sometimes observe this scenario where the FW requests 16 bit header in 2 consecutive iterations, and we need to be sure that we re-send the 16 bit header, and not the 16 bit payload. 
This happens when the chip updates it's baudrate while receiving the 1st header, and discards it due to CRC mismatch, and requests the header again.

>
> > +                             /* FW download out of sync. Send previous chunk again> */
> > +                            nxpdev->fw_dnld_offset -= nxpdev->fw_sent_bytes;
> > +                             expected_len = HDR_LEN;> > +                     }
> > +            }
> > +

> > +static int nxp_recv_fw_req_v3(struct hci_dev *hdev, struct sk_buff *skb)
> > +{
> > +     struct V3_DATA_REQ *req = skb_pull_data(skb, sizeof(struct
> V3_DATA_REQ));
> > +     struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
> > +     static bool timeout_changed;
> > +     static bool baudrate_changed;
> > +
> > +     if (!req || !nxpdev || !strlen(nxpdev->fw_name) || !nxpdev->fw->data)
> > +             return 0;
> 
> Who is expected to free the skb? These functions or one of the callers?
> (Which one? I lost track of the callchain and error passing too).
Added kfree_skb() in the called functions.


> > +                     strncpy(nxpdev->fw_name, fw_path,
> MAX_FW_FILE_NAME_LEN);
> > +                     strncpy(nxpdev->fw_name + strlen(fw_path), fw_name_dt,
> > +                                     MAX_FW_FILE_NAME_LEN);
> 
> How can this second one be correct if you use +strlen(fw_path) for the
> pointer. Why not use snprintf()?
Replaced strncpy with snprintfs()



> > +static int nxp_enqueue(struct hci_dev *hdev, struct sk_buff *skb)
> > +{
> > +     struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
> > +     struct ps_data *psdata = nxpdev->psdata;
> > +     struct hci_command_hdr *hdr;
> > +     u8 *param;
> > +
> > +     /* if commands are received from user space (e.g. hcitool), update
> > +      * driver flags accordingly and ask driver to re-send the command
> > +      */
> > +     if (bt_cb(skb)->pkt_type == HCI_COMMAND_PKT && !psdata-
> >driver_sent_cmd) {
> 
> Should you need to check psdata for NULL before dereferencing it?
Added checks for psdata before dereferencing it.


> > +/* Bluetooth vendor command : Sleep mode */
> > +#define HCI_NXP_AUTO_SLEEP_MODE      0xFC23
> 
> Try to change all hex letters to lowercase.
Changed all hex letters to lowercase.

> > +struct V1_DATA_REQ {
> > +     u16 len;
> > +     u16 len_comp;
> > +} __packed;
> > +
> > +struct V3_DATA_REQ {
> > +     u16 len;
> > +     u32 offset;
> > +     u16 error;
> > +     u8 crc;
> > +} __packed;
> > +
> > +struct V3_START_IND {
> > +     u16 chip_id;
> > +     u8 loader_ver;
> > +     u8 crc;
> > +} __packed;
> 
> Struct names should be lowercased. Multibyte fields need to specify
> byte-order?
Resolved.

> > +
> > +#define SWAPL(x) ((((x) >> 24) & 0xff) \
> > +                              | (((x) >> 8) & 0xff00) \
> > +                              | (((x) << 8) & 0xff0000L) \
> > +                              | (((x) << 24) & 0xff000000L))
> 
> Perhaps something existing under include/ could do swap for you?
Added call to a standard swab32() function.

> --
>  i.

Please review the V3 patch and let me know if you have any suggestions or comments.

Thank you,
Neeraj

^ permalink raw reply

* RE: [PATCH v3 3/3] serial: 8250_em: Add serial_out() to struct serial8250_em_hw_info
From: Biju Das @ 2023-02-13 16:06 UTC (permalink / raw)
  To: Ilpo Järvinen, Jiri Slaby, Andy Shevchenko
  Cc: Geert Uytterhoeven, Magnus Damm, Niklas Söderlund,
	Greg Kroah-Hartman, linux-serial, Fabrizio Castro,
	linux-renesas-soc@vger.kernel.org
In-Reply-To: <OS0PR01MB59228E1C6038C8609BBABF5286DD9@OS0PR01MB5922.jpnprd01.prod.outlook.com>

Hi All,

> Subject: RE: [PATCH v3 3/3] serial: 8250_em: Add serial_out() to struct
> serial8250_em_hw_info
> 
> Hi Ilpo Järvinen,
> 
> Thanks for feedback.
> 
> > -----Original Message-----
> > From: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
> > Sent: Monday, February 13, 2023 12:05 PM
> > To: Biju Das <biju.das.jz@bp.renesas.com>
> > Cc: Jiri Slaby <jirislaby@kernel.org>; Geert Uytterhoeven
> > <geert+renesas@glider.be>; Magnus Damm <magnus.damm@gmail.com>; Niklas
> > Söderlund <niklas.soderlund@ragnatech.se>; Greg Kroah-Hartman
> > <gregkh@linuxfoundation.org>; linux-serial
> > <linux-serial@vger.kernel.org>; Fabrizio Castro
> > <fabrizio.castro.jz@renesas.com>; linux-renesas- soc@vger.kernel.org
> > Subject: RE: [PATCH v3 3/3] serial: 8250_em: Add serial_out() to
> > struct serial8250_em_hw_info
> >
> > On Mon, 13 Feb 2023, Biju Das wrote:
> >
> > > Hi Ilpo,
> > >
> > > Thanks for the feedback.
> > >
> > > > Subject: RE: [PATCH v3 3/3] serial: 8250_em: Add serial_out() to
> > > > struct serial8250_em_hw_info
> > > >
> > > > On Mon, 13 Feb 2023, Biju Das wrote:
> > > >
> > > > > Hi Jiri Slaby,
> > > > >
> > > > > Thanks for the feedback.
> > > > >
> > > > > > Subject: Re: [PATCH v3 3/3] serial: 8250_em: Add serial_out()
> > > > > > to struct serial8250_em_hw_info
> > > > > >
> > > > > > On 13. 02. 23, 10:31, Biju Das wrote:
> > > > > > > So looks like similar to other macros, UART_FCR_EM (0x3) is
> > > > > > > sensible
> > > > one.
> > > > > > >
> > > > > > > UART_FCR_RO_OFFSET (9)
> > > > > > > UART_FCR_RO_EM (UART_FCR_EM + UART_FCR_RO_OFFSET)
> > > > > > >
> > > > > > >
> > > > > > > static unsigned int serial8250_em_serial_in(struct uart_port
> > > > > > > *p, int
> > > > > > > offset) case UART_FCR_RO_EM:
> > > > > > > 	return readl(p->membase + (offset - UART_FCR_RO_OFFSET <<
> > > > > > > 2));
> > > > > >
> > > > > >
> > > > > > Please send a complete patch as a reply. I am completely lost now.
> > > > >
> > > > > Please find the complete patc.
> > > > >
> > > > >
> > > > > From e597ae60eb170c1f1b650e1e533bf4e12c09f822 Mon Sep 17
> > > > > 00:00:00
> > > > > 2001
> > > > > From: Biju Das <biju.das.jz@bp.renesas.com>
> > > > > Date: Tue, 7 Feb 2023 15:07:13 +0000
> > > > > Subject: [PATCH] serial: 8250_em: Add serial_out() to struct
> > > > > serial8250_em_hw_info
> > > > >
> > > > > As per RZ/V2M hardware manual(Rev.1.30 Jun, 2022), UART IP has a
> > > > > restriction as mentioned below.
> > > > >
> > > > > 40.6.1 Point for Caution when Changing the Register Settings:
> > > > >
> > > > > When changing the settings of the following registers, a PRESETn
> > > > > master reset or FIFO reset + SW reset (FCR[2],FCR[1], HCR0[7])
> > > > > must be input to re-initialize them.
> > > > >
> > > > > Target Registers: FCR, LCR, MCR, DLL, DLM, HCR0.
> > > > >
> > > > > This patch adds serial_out() to struct serial8250_em_hw_info to
> > > > > handle this difference between emma mobile and rz/v2m.
> > > > >
> > > > > DLL/DLM register can be updated only by setting LCR[7]. So the
> > > > > updation of LCR[7] will perform reset for DLL/DLM register changes.
> > > > >
> > > > > Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
> > > > > ---
> > > > >  drivers/tty/serial/8250/8250_em.c | 70
> > > > > ++++++++++++++++++++++++++++++-
> > > > >  1 file changed, 69 insertions(+), 1 deletion(-)
> > > > >
> > > > > diff --git a/drivers/tty/serial/8250/8250_em.c
> > > > > b/drivers/tty/serial/8250/8250_em.c
> > > > > index 69cd3b611501..c1c64f48ee7e 100644
> > > > > --- a/drivers/tty/serial/8250/8250_em.c
> > > > > +++ b/drivers/tty/serial/8250/8250_em.c
> > > > > @@ -17,12 +17,23 @@
> > > > >
> > > > >  #include "8250.h"
> > > > >
> > > > > +#define UART_FCR_EM 3
> > > > >  #define UART_DLL_EM 9
> > > > >  #define UART_DLM_EM 10
> > > > > +#define UART_HCR0_EM 11
> > > > > +
> > > > > +#define UART_FCR_R_EM	(UART_FCR_EM + UART_HCR0_EM)
> > > >
> > > > It's easy to lose track of all this, IMHO this would be simple:
> > > >
> > > > /*
> > > >  * A high value for UART_FCR_EM avoids overlapping with existing
> > > > UART_*
> > > >  * register defines. UART_FCR_EM_HW is the real HW register offset.
> > > >  */
> > > > #define UART_FCR_EM 12
> > >
> > > I will change it to #define UART_FCR_EM 14
> > >
> > > And will add the below unused HW status registers in the driver.
> > >
> > > #define UART_HCR2_EM 12 (@30)
> > > #define UART_HCR3_EM 13 (@34)
> > >
> > > Is it ok?
> >
> > It's okay, that number is pseudo one anyway so the actual number
> > doesn't matter. One could just as well pick some large number such as
> > 0x10003 or so if the collision with real regs is a concern.
> 
> OK will use 0x10003, as pseudo offset.

I would like to use same Hardware restriction for both RZ/V2M and EMMA-Mobile
as both the SoC's have same register sets and it works ok on both these platforms,
after this restriction is applied.

I guess it is ok for everyone.

Cheers,
Biju

^ permalink raw reply

* RE: [PATCH v3 2/3] serial: 8250_em: Update RZ/V2M port type as PORT_16750
From: Biju Das @ 2023-02-13 16:02 UTC (permalink / raw)
  To: Jiri Slaby, Greg Kroah-Hartman, Andy Shevchenko,
	Ilpo Järvinen
  Cc: Geert Uytterhoeven, linux-serial@vger.kernel.org, Fabrizio Castro,
	linux-renesas-soc@vger.kernel.org, Niklas Söderlund
In-Reply-To: <af36a245-a73e-0f58-9c15-8435f542c4a1@kernel.org>

Hi All,

> -----Original Message-----
> From: Jiri Slaby <jirislaby@kernel.org>
> Sent: Monday, February 13, 2023 6:26 AM
> To: Biju Das <biju.das.jz@bp.renesas.com>; Greg Kroah-Hartman
> <gregkh@linuxfoundation.org>
> Cc: Geert Uytterhoeven <geert+renesas@glider.be>; linux-
> serial@vger.kernel.org; Fabrizio Castro <fabrizio.castro.jz@renesas.com>;
> linux-renesas-soc@vger.kernel.org; Ilpo Järvinen
> <ilpo.jarvinen@linux.intel.com>
> Subject: Re: [PATCH v3 2/3] serial: 8250_em: Update RZ/V2M port type as
> PORT_16750
> 
> On 10. 02. 23, 21:34, Biju Das wrote:
> > The UART IP found on RZ/V2M SoC is Register-compatible with the
> > general-purpose 16750 UART chip. This patch updates RZ/V2M port type
> > from 16550A->16750 and also enables 64-bytes fifo support.
> >
> > Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
> > Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
> 
> Reviewed-by: Jiri Slaby <jirislaby@kernel.org>
> 

Thanks Niklas, for testing on EMEV2.

EMMA-mobile has same register layout like RZ/V2M
and is Register-compatible with the general-purpose 16750 UART chip.

So, I would like to add same type and flags for both the SoCs,
for the next version of the patch series.

I guess it is ok for everyone.

Cheers,
Biju

^ permalink raw reply

* Re: [PATCH v3 3/3] Bluetooth: NXP: Add protocol support for NXP Bluetooth chipsets
From: Ilpo Järvinen @ 2023-02-13 15:06 UTC (permalink / raw)
  To: Neeraj Sanjay Kale
  Cc: davem, edumazet, kuba, pabeni, robh+dt, krzysztof.kozlowski+dt,
	marcel, johan.hedberg, luiz.dentz, Greg Kroah-Hartman, Jiri Slaby,
	alok.a.tiwari, hdanton, leon, Netdev, devicetree, LKML,
	linux-bluetooth, linux-serial, amitkumar.karwar, rohit.fule,
	sherry.sun
In-Reply-To: <20230213145432.1192911-4-neeraj.sanjaykale@nxp.com>

[-- Attachment #1: Type: text/plain, Size: 43468 bytes --]

Hi,

You didn't address my comments I made for v2.

-- 
 i.


On Mon, 13 Feb 2023, Neeraj Sanjay Kale wrote:

> This adds a driver based on serdev driver for the NXP BT serial
> protocol based on running H:4, which can enable the built-in
> Bluetooth device inside a generic NXP BT chip.
> 
> This driver has Power Save feature that will put the chip into
> sleep state whenever there is no activity for 2000ms, and will
> be woken up when any activity is to be initiated over UART.
> 
> This driver enables the power save feature by default by sending
> the vendor specific commands to the chip during setup.
> 
> During setup, the driver checks if a FW is already running on the
> chip based on the CTS line, and downloads device specific FW file
> into the chip over UART.
> 
> The driver contains certain device specific default parameters
> related to FW filename, baudrate and timeouts which can be
> overwritten by an optional user space config file. These parameters
> may vary from one module vendor to another.
> 
> Signed-off-by: Neeraj Sanjay Kale <neeraj.sanjaykale@nxp.com>
> ---
> v2: Removed conf file support and added static data for each chip
> based on compatibility devices mentioned in DT bindings. Handled
> potential memory leaks and null pointer dereference issues,
> simplified FW download feature, handled byte-order and few cosmetic
> changes. (Ilpo Järvinen, Alok Tiwari, Hillf Danton)
> v3: Added conf file support necessary to support different vendor
> modules, moved .h file contents to .c, cosmetic changes. (Luiz
> Augusto von Dentz, Rob Herring, Leon Romanovsky)
> ---
>  drivers/bluetooth/Kconfig     |   11 +
>  drivers/bluetooth/Makefile    |    1 +
>  drivers/bluetooth/btnxpuart.c | 1370 +++++++++++++++++++++++++++++++++
>  3 files changed, 1382 insertions(+)
>  create mode 100644 drivers/bluetooth/btnxpuart.c
> 
> diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig
> index 5a1a7bec3c42..773b40d34b7b 100644
> --- a/drivers/bluetooth/Kconfig
> +++ b/drivers/bluetooth/Kconfig
> @@ -465,4 +465,15 @@ config BT_VIRTIO
>  	  Say Y here to compile support for HCI over Virtio into the
>  	  kernel or say M to compile as a module.
>  
> +config BT_NXPUART
> +	tristate "NXP protocol support"
> +	depends on SERIAL_DEV_BUS
> +	help
> +	  NXP is serial driver required for NXP Bluetooth
> +	  devices with UART interface.
> +
> +	  Say Y here to compile support for NXP Bluetooth UART device into
> +	  the kernel, or say M here to compile as a module.
> +
> +
>  endmenu
> diff --git a/drivers/bluetooth/Makefile b/drivers/bluetooth/Makefile
> index e0b261f24fc9..7a5967e9ac48 100644
> --- a/drivers/bluetooth/Makefile
> +++ b/drivers/bluetooth/Makefile
> @@ -29,6 +29,7 @@ obj-$(CONFIG_BT_QCA)		+= btqca.o
>  obj-$(CONFIG_BT_MTK)		+= btmtk.o
>  
>  obj-$(CONFIG_BT_VIRTIO)		+= virtio_bt.o
> +obj-$(CONFIG_BT_NXPUART)	+= btnxpuart.o
>  
>  obj-$(CONFIG_BT_HCIUART_NOKIA)	+= hci_nokia.o
>  
> diff --git a/drivers/bluetooth/btnxpuart.c b/drivers/bluetooth/btnxpuart.c
> new file mode 100644
> index 000000000000..d774564d47ce
> --- /dev/null
> +++ b/drivers/bluetooth/btnxpuart.c
> @@ -0,0 +1,1370 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + *  NXP Bluetooth driver
> + *  Copyright 2018-2023 NXP
> + */
> +
> +#include <linux/module.h>
> +#include <linux/kernel.h>
> +
> +#include <linux/serdev.h>
> +#include <linux/of.h>
> +#include <linux/skbuff.h>
> +#include <asm/unaligned.h>
> +#include <linux/firmware.h>
> +#include <linux/string.h>
> +#include <linux/crc8.h>
> +
> +#include <net/bluetooth/bluetooth.h>
> +#include <net/bluetooth/hci_core.h>
> +
> +#include "h4_recv.h"
> +
> +#define BTNXPUART_TX_STATE_ACTIVE	1
> +#define BTNXPUART_FW_DOWNLOADING	2
> +
> +#define MAX_TAG_STR_LEN				20
> +#define BT_FW_CONF_FILE				"nxp/bt_mod_para.conf"
> +#define USER_CONFIG_TAG				"user_config"
> +#define FW_NAME_TAG					"fw_name"
> +#define OPER_SPEED_TAG				"oper_speed"
> +#define FW_DL_PRI_BAUDRATE_TAG		"fw_dl_pri_speed"
> +#define FW_DL_SEC_BAUDRATE_TAG		"fw_dl_sec_speed"
> +#define FW_INIT_BAUDRATE			"fw_init_speed"
> +#define PS_INTERVAL_MS				"ps_interval_ms"
> +
> +#define FIRMWARE_W8987	"nxp/sdiouart8987_combo_v0.bin"
> +#define FIRMWARE_W8997	"nxp/uartuart8997_bt_v4.bin"
> +#define FIRMWARE_W9098	"nxp/uartuart9098_bt_v1.bin"
> +#define FIRMWARE_IW416	"nxp/sdiouartiw416_combo_v0.bin"
> +#define FIRMWARE_IW612	"nxp/sduart_nw61x_v1.bin.se"
> +
> +#define MAX_FW_FILE_NAME_LEN    50
> +
> +/* Default ps timeout period in milli-second */
> +#define PS_DEFAULT_TIMEOUT_PERIOD     2000
> +
> +/* wakeup methods */
> +#define WAKEUP_METHOD_DTR       0
> +#define WAKEUP_METHOD_BREAK     1
> +#define WAKEUP_METHOD_EXT_BREAK 2
> +#define WAKEUP_METHOD_RTS       3
> +#define WAKEUP_METHOD_INVALID   0xff
> +
> +/* power save mode status */
> +#define PS_MODE_DISABLE         0
> +#define PS_MODE_ENABLE          1
> +
> +/* Power Save Commands to ps_work_func  */
> +#define PS_CMD_EXIT_PS          1
> +#define PS_CMD_ENTER_PS         2
> +
> +/* power save state */
> +#define PS_STATE_AWAKE          0
> +#define PS_STATE_SLEEP          1
> +
> +/* Bluetooth vendor command : Sleep mode */
> +#define HCI_NXP_AUTO_SLEEP_MODE	0xfc23
> +/* Bluetooth vendor command : Wakeup method */
> +#define HCI_NXP_WAKEUP_METHOD	0xfc53
> +/* Bluetooth vendor command : Set operational baudrate */
> +#define HCI_NXP_SET_OPER_SPEED	0xfc09
> +
> +/* Bluetooth Power State : Vendor cmd params */
> +#define BT_PS_ENABLE			0x02
> +#define BT_PS_DISABLE			0x03
> +
> +/* Bluetooth Host Wakeup Methods */
> +#define BT_HOST_WAKEUP_METHOD_NONE      0x00
> +#define BT_HOST_WAKEUP_METHOD_DTR       0x01
> +#define BT_HOST_WAKEUP_METHOD_BREAK     0x02
> +#define BT_HOST_WAKEUP_METHOD_GPIO      0x03
> +
> +/* Bluetooth Chip Wakeup Methods */
> +#define BT_CTRL_WAKEUP_METHOD_DSR       0x00
> +#define BT_CTRL_WAKEUP_METHOD_BREAK     0x01
> +#define BT_CTRL_WAKEUP_METHOD_GPIO      0x02
> +#define BT_CTRL_WAKEUP_METHOD_EXT_BREAK 0x04
> +#define BT_CTRL_WAKEUP_METHOD_RTS       0x05
> +
> +struct ps_data {
> +	u8    ps_mode;
> +	u8    cur_psmode;
> +	u8    ps_state;
> +	u8    ps_cmd;
> +	u8    wakeupmode;
> +	u8    cur_wakeupmode;
> +	bool  driver_sent_cmd;
> +	u8    timer_on;
> +	u32   interval;
> +	struct hci_dev *hdev;
> +	struct work_struct work;
> +	struct timer_list ps_timer;
> +};
> +
> +struct btnxpuart_data {
> +	u32 fw_dnld_pri_baudrate;
> +	u32 fw_dnld_sec_baudrate;
> +	u32 fw_init_baudrate;
> +	u32 oper_speed;
> +	u32 ps_interval_ms;
> +	const u8 *fw_name;
> +};
> +
> +struct btnxpuart_dev {
> +	struct hci_dev *hdev;
> +	struct serdev_device *serdev;
> +
> +	struct work_struct tx_work;
> +	unsigned long tx_state;
> +	struct sk_buff_head txq;
> +	struct sk_buff *rx_skb;
> +
> +	const struct firmware *fw;
> +	const struct firmware *fw_config;
> +	u8 fw_name[MAX_FW_FILE_NAME_LEN];
> +	u32 fw_dnld_v1_offset;
> +	u32 fw_v1_sent_bytes;
> +	u32 fw_v3_offset_correction;
> +	wait_queue_head_t suspend_wait_q;
> +
> +	u32 new_baudrate;
> +	u32 current_baudrate;
> +
> +	struct ps_data *psdata;
> +	struct btnxpuart_data *nxp_data;
> +};
> +
> +#define NXP_V1_FW_REQ_PKT      0xa5
> +#define NXP_V1_CHIP_VER_PKT    0xaa
> +#define NXP_V3_FW_REQ_PKT      0xa7
> +#define NXP_V3_CHIP_VER_PKT    0xab
> +
> +#define NXP_ACK_V1             0x5a
> +#define NXP_NAK_V1             0xbf
> +#define NXP_ACK_V3             0x7a
> +#define NXP_NAK_V3             0x7b
> +#define NXP_CRC_ERROR_V3       0x7c
> +
> +#define HDR_LEN					16
> +
> +#define NXP_RECV_FW_REQ_V1 \
> +	.type = NXP_V1_FW_REQ_PKT, \
> +	.hlen = 4, \
> +	.loff = 0, \
> +	.lsize = 0, \
> +	.maxlen = 4
> +
> +#define NXP_RECV_CHIP_VER_V3 \
> +	.type = NXP_V3_CHIP_VER_PKT, \
> +	.hlen = 4, \
> +	.loff = 0, \
> +	.lsize = 0, \
> +	.maxlen = 4
> +
> +#define NXP_RECV_FW_REQ_V3 \
> +	.type = NXP_V3_FW_REQ_PKT, \
> +	.hlen = 9, \
> +	.loff = 0, \
> +	.lsize = 0, \
> +	.maxlen = 9
> +
> +struct v1_data_req {
> +	__le16 len;
> +	__le16 len_comp;
> +} __packed;
> +
> +struct v3_data_req {
> +	__le16 len;
> +	__le32 offset;
> +	__le16 error;
> +	u8 crc;
> +} __packed;
> +
> +struct v3_start_ind {
> +	__le16 chip_id;
> +	u8 loader_ver;
> +	u8 crc;
> +} __packed;
> +
> +/* UART register addresses of BT chip */
> +#define CLKDIVADDR       0x7f00008f
> +#define UARTDIVADDR      0x7f000090
> +#define UARTMCRADDR      0x7f000091
> +#define UARTREINITADDR   0x7f000092
> +#define UARTICRADDR      0x7f000093
> +#define UARTFCRADDR      0x7f000094
> +
> +#define MCR   0x00000022
> +#define INIT  0x00000001
> +#define ICR   0x000000c7
> +#define FCR   0x000000c7
> +
> +#define POLYNOMIAL8				0x07
> +#define POLYNOMIAL32			0x04c11db7L
> +
> +struct uart_reg {
> +	__le32 address;
> +	__le32 value;
> +} __packed;
> +
> +struct uart_config {
> +	struct uart_reg clkdiv;
> +	struct uart_reg uartdiv;
> +	struct uart_reg mcr;
> +	struct uart_reg re_init;
> +	struct uart_reg icr;
> +	struct uart_reg fcr;
> +	__le32 crc;
> +} __packed;
> +
> +struct nxp_bootloader_cmd {
> +	__le32 header;
> +	__le32 arg;
> +	__le32 payload_len;
> +	__le32 crc;
> +} __packed;
> +
> +static u8 crc8_table[CRC8_TABLE_SIZE];
> +static unsigned long crc32_table[256];
> +
> +/* Default Power Save configuration */
> +int wakeupmode = WAKEUP_METHOD_BREAK;
> +int ps_mode = PS_MODE_ENABLE;
> +
> +static struct sk_buff *nxp_drv_send_cmd(struct hci_dev *hdev, u16 opcode,
> +										u32 plen,
> +										void *param)
> +{
> +	struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
> +	struct ps_data *psdata = nxpdev->psdata;
> +	struct sk_buff *skb;
> +
> +	psdata->driver_sent_cmd = true;	/* set flag to prevent re-sending command in nxp_enqueue */
> +	skb = __hci_cmd_sync(hdev, opcode, plen, param, HCI_CMD_TIMEOUT);
> +	psdata->driver_sent_cmd = false;
> +
> +	return skb;
> +}
> +
> +static void btnxpuart_tx_wakeup(struct btnxpuart_dev *nxpdev)
> +{
> +	if (schedule_work(&nxpdev->tx_work))
> +		set_bit(BTNXPUART_TX_STATE_ACTIVE, &nxpdev->tx_state);
> +}
> +
> +/* NXP Power Save Feature */
> +static void ps_start_timer(struct btnxpuart_dev *nxpdev)
> +{
> +	struct ps_data *psdata = nxpdev->psdata;
> +
> +	if (!psdata)
> +		return;
> +
> +	if (psdata->cur_psmode == PS_MODE_ENABLE) {
> +		psdata->timer_on = 1;
> +		mod_timer(&psdata->ps_timer, jiffies + (psdata->interval * HZ) / 1000);
> +	}
> +}
> +
> +static void ps_cancel_timer(struct btnxpuart_dev *nxpdev)
> +{
> +	struct ps_data *psdata = nxpdev->psdata;
> +
> +	if (!psdata)
> +		return;
> +
> +	flush_work(&psdata->work);
> +	if (psdata->timer_on)
> +		del_timer_sync(&psdata->ps_timer);
> +	kfree(psdata);
> +}
> +
> +static void ps_control(struct hci_dev *hdev, u8 ps_state)
> +{
> +	struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
> +	struct ps_data *psdata = nxpdev->psdata;
> +
> +	if (psdata->ps_state == ps_state)
> +		return;
> +
> +	switch (psdata->cur_wakeupmode) {
> +	case WAKEUP_METHOD_DTR:
> +		if (ps_state == PS_STATE_AWAKE)
> +			serdev_device_set_tiocm(nxpdev->serdev, TIOCM_DTR, 0);
> +		else
> +			serdev_device_set_tiocm(nxpdev->serdev, 0, TIOCM_DTR);
> +		break;
> +	case WAKEUP_METHOD_BREAK:
> +	default:
> +		bt_dev_info(hdev, "Set UART break: %s", ps_state == PS_STATE_AWAKE ? "off" : "on");
> +		if (ps_state == PS_STATE_AWAKE)
> +			serdev_device_break_ctl(nxpdev->serdev, 0);
> +		else
> +			serdev_device_break_ctl(nxpdev->serdev, -1);
> +		break;
> +	}
> +	psdata->ps_state = ps_state;
> +	if (ps_state == PS_STATE_AWAKE)
> +		btnxpuart_tx_wakeup(nxpdev);
> +}
> +
> +static void ps_work_func(struct work_struct *work)
> +{
> +	struct ps_data *data = container_of(work, struct ps_data, work);
> +
> +	if (data->ps_cmd == PS_CMD_ENTER_PS && data->cur_psmode == PS_MODE_ENABLE)
> +		ps_control(data->hdev, PS_STATE_SLEEP);
> +	else if (data->ps_cmd == PS_CMD_EXIT_PS)
> +		ps_control(data->hdev, PS_STATE_AWAKE);
> +}
> +
> +static void ps_timeout_func(struct timer_list *t)
> +{
> +	struct ps_data *data = from_timer(data, t, ps_timer);
> +	struct hci_dev *hdev = data->hdev;
> +	struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
> +
> +	data->timer_on = 0;
> +	if (test_bit(BTNXPUART_TX_STATE_ACTIVE, &nxpdev->tx_state)) {
> +		ps_start_timer(nxpdev);
> +	} else {
> +		data->ps_cmd = PS_CMD_ENTER_PS;
> +		schedule_work(&data->work);
> +	}
> +}
> +
> +static int ps_init_work(struct hci_dev *hdev)
> +{
> +	struct ps_data *psdata = kzalloc(sizeof(*psdata), GFP_KERNEL);
> +	struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
> +	struct btnxpuart_data *nxp_data = nxpdev->nxp_data;
> +
> +	if (!psdata) {
> +		bt_dev_err(hdev, "Can't allocate control structure for Power Save feature");
> +		return -ENOMEM;
> +	}
> +	nxpdev->psdata = psdata;
> +
> +	psdata->interval = nxp_data->ps_interval_ms;
> +	psdata->ps_state = PS_STATE_AWAKE;
> +	psdata->ps_mode = ps_mode;
> +	psdata->hdev = hdev;
> +
> +	switch (wakeupmode) {
> +	case WAKEUP_METHOD_DTR:
> +		psdata->wakeupmode = WAKEUP_METHOD_DTR;
> +		break;
> +	case WAKEUP_METHOD_BREAK:
> +	default:
> +		psdata->wakeupmode = WAKEUP_METHOD_BREAK;
> +		break;
> +	}
> +	psdata->cur_psmode = PS_MODE_DISABLE;
> +	psdata->cur_wakeupmode = WAKEUP_METHOD_INVALID;
> +	INIT_WORK(&psdata->work, ps_work_func);
> +
> +	return 0;
> +}
> +
> +static void ps_init_timer(struct hci_dev *hdev)
> +{
> +	struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
> +	struct ps_data *psdata = nxpdev->psdata;
> +
> +	psdata->timer_on = 0;
> +	timer_setup(&psdata->ps_timer, ps_timeout_func, 0);
> +}
> +
> +static int ps_wakeup(struct btnxpuart_dev *nxpdev)
> +{
> +	struct ps_data *psdata = nxpdev->psdata;
> +
> +	if (psdata->ps_state == PS_STATE_AWAKE)
> +		return 0;
> +	psdata->ps_cmd = PS_CMD_EXIT_PS;
> +	schedule_work(&psdata->work);
> +
> +	return 1;
> +}
> +
> +static int send_ps_cmd(struct hci_dev *hdev, void *data)
> +{
> +	struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
> +	struct ps_data *psdata = nxpdev->psdata;
> +	u8 pcmd;
> +	struct sk_buff *skb;
> +	u8 *status;
> +
> +	if (psdata->ps_mode == PS_MODE_ENABLE)
> +		pcmd = BT_PS_ENABLE;
> +	else
> +		pcmd = BT_PS_DISABLE;
> +
> +	skb = nxp_drv_send_cmd(hdev, HCI_NXP_AUTO_SLEEP_MODE, 1, &pcmd);
> +	if (IS_ERR(skb)) {
> +		bt_dev_err(hdev, "Setting Power Save mode failed (%ld)", PTR_ERR(skb));
> +		return PTR_ERR(skb);
> +	}
> +
> +	status = skb_pull_data(skb, 1);
> +	if (status) {
> +		if (!*status)
> +			psdata->cur_psmode = psdata->ps_mode;
> +		else
> +			psdata->ps_mode = psdata->cur_psmode;
> +		if (psdata->cur_psmode == PS_MODE_ENABLE)
> +			ps_start_timer(nxpdev);
> +		else
> +			ps_wakeup(nxpdev);
> +		bt_dev_info(hdev, "Power Save mode response: status=%d, ps_mode=%d",
> +					*status, psdata->cur_psmode);
> +	}
> +	kfree_skb(skb);
> +
> +	return 0;
> +}
> +
> +static int send_wakeup_method_cmd(struct hci_dev *hdev, void *data)
> +{
> +	struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
> +	struct ps_data *psdata = nxpdev->psdata;
> +	u8 pcmd[4];
> +	struct sk_buff *skb;
> +	u8 *status;
> +
> +	pcmd[0] = BT_HOST_WAKEUP_METHOD_NONE;
> +	pcmd[1] = 0xff;
> +	switch (psdata->wakeupmode) {
> +	case WAKEUP_METHOD_DTR:
> +		pcmd[2] = BT_CTRL_WAKEUP_METHOD_DSR;
> +		break;
> +	case WAKEUP_METHOD_BREAK:
> +	default:
> +		pcmd[2] = BT_CTRL_WAKEUP_METHOD_BREAK;
> +		break;
> +	}
> +	pcmd[3] = 0xff;
> +
> +	skb = nxp_drv_send_cmd(hdev, HCI_NXP_WAKEUP_METHOD, 4, pcmd);
> +	if (IS_ERR(skb)) {
> +		bt_dev_err(hdev, "Setting wake-up method failed (%ld)", PTR_ERR(skb));
> +		return PTR_ERR(skb);
> +	}
> +
> +	status = skb_pull_data(skb, 1);
> +	if (status) {
> +		if (*status == 0)
> +			psdata->cur_wakeupmode = psdata->wakeupmode;
> +		else
> +			psdata->wakeupmode = psdata->cur_wakeupmode;
> +		bt_dev_info(hdev, "Set Wakeup Method response: status=%d, wakeupmode=%d",
> +					*status, psdata->cur_wakeupmode);
> +	}
> +	kfree_skb(skb);
> +
> +	return 0;
> +}
> +
> +static int ps_init(struct hci_dev *hdev)
> +{
> +	struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
> +	struct ps_data *psdata = nxpdev->psdata;
> +
> +	serdev_device_set_tiocm(nxpdev->serdev, TIOCM_RTS, 0);
> +
> +	switch (psdata->wakeupmode) {
> +	case WAKEUP_METHOD_DTR:
> +		serdev_device_set_tiocm(nxpdev->serdev, 0, TIOCM_DTR);
> +		serdev_device_set_tiocm(nxpdev->serdev, TIOCM_DTR, 0);
> +		break;
> +	case WAKEUP_METHOD_BREAK:
> +	default:
> +		serdev_device_break_ctl(nxpdev->serdev, -1);
> +		usleep_range(5000, 10000);
> +		serdev_device_break_ctl(nxpdev->serdev, 0);
> +		usleep_range(5000, 10000);
> +		break;
> +	}
> +	if (!test_bit(HCI_RUNNING, &hdev->flags)) {
> +		bt_dev_err(hdev, "HCI_RUNNING is not set");
> +		return -EBUSY;
> +	}
> +	if (psdata->cur_wakeupmode != psdata->wakeupmode)
> +		hci_cmd_sync_queue(hdev, send_wakeup_method_cmd, NULL, NULL);
> +	if (psdata->cur_psmode != psdata->ps_mode)
> +		hci_cmd_sync_queue(hdev, send_ps_cmd, NULL, NULL);
> +
> +	return 0;
> +}
> +
> +/* NXP Firmware Download Feature */
> +static void nxp_fw_dnld_gen_crc32_table(void)
> +{
> +	int i, j;
> +	unsigned long crc_accum;
> +
> +	for (i = 0; i < 256; i++) {
> +		crc_accum = ((unsigned long)i << 24);
> +		for (j = 0; j < 8; j++) {
> +			if (crc_accum & 0x80000000L)
> +				crc_accum = (crc_accum << 1) ^ POLYNOMIAL32;
> +			else
> +				crc_accum = (crc_accum << 1);
> +		}
> +		crc32_table[i] = crc_accum;
> +	}
> +}
> +
> +static unsigned long nxp_fw_dnld_update_crc(unsigned long crc_accum,
> +									char *data_blk_ptr,
> +									int data_blk_size)
> +{
> +	unsigned long i, j;
> +
> +	for (j = 0; j < data_blk_size; j++) {
> +		i = ((unsigned long)(crc_accum >> 24) ^ *data_blk_ptr++) & 0xff;
> +		crc_accum = (crc_accum << 8) ^ crc32_table[i];
> +	}
> +	return crc_accum;
> +}
> +
> +static int nxp_download_firmware(struct hci_dev *hdev)
> +{
> +	struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
> +	struct btnxpuart_data *nxp_data = nxpdev->nxp_data;
> +	int err = 0;
> +
> +	nxpdev->fw_dnld_v1_offset = 0;
> +	nxpdev->fw_v1_sent_bytes = 0;
> +
> +	crc8_populate_msb(crc8_table, POLYNOMIAL8);
> +	nxp_fw_dnld_gen_crc32_table();
> +
> +	if (!strlen(nxpdev->fw_name))
> +		snprintf(nxpdev->fw_name, MAX_FW_FILE_NAME_LEN, "%s",
> +				 nxp_data->fw_name);
> +
> +	bt_dev_info(hdev, "Request Firmware: %s", nxpdev->fw_name);
> +	err = request_firmware(&nxpdev->fw, nxpdev->fw_name, &hdev->dev);
> +	if (err < 0) {
> +		bt_dev_err(hdev, "Firmware file %s not found", nxpdev->fw_name);
> +		clear_bit(BTNXPUART_FW_DOWNLOADING, &nxpdev->tx_state);
> +		return err;
> +	}
> +
> +	serdev_device_set_baudrate(nxpdev->serdev, nxp_data->fw_dnld_pri_baudrate);
> +	serdev_device_set_flow_control(nxpdev->serdev, 0);
> +	nxpdev->current_baudrate = nxp_data->fw_dnld_pri_baudrate;
> +	nxpdev->fw_v3_offset_correction = 0;
> +
> +	/* Wait till FW is downloaded and CTS becomes low */
> +	err = wait_event_interruptible_timeout(nxpdev->suspend_wait_q,
> +							!test_bit(BTNXPUART_FW_DOWNLOADING,
> +									  &nxpdev->tx_state),
> +							msecs_to_jiffies(60000));
> +	if (err == 0) {
> +		bt_dev_err(hdev, "FW Download Timeout.");
> +		return -ETIMEDOUT;
> +	}
> +
> +	serdev_device_set_flow_control(nxpdev->serdev, 1);
> +	err = serdev_device_wait_for_cts(nxpdev->serdev, 1, 60000);
> +	if (err < 0) {
> +		bt_dev_err(hdev, "CTS is still high. FW Download failed.");
> +		return err;
> +	}
> +	bt_dev_info(hdev, "CTS is low");
> +	release_firmware(nxpdev->fw);
> +
> +	/* Allow the downloaded FW to initialize */
> +	usleep_range(1000000, 1200000);
> +
> +	return 0;
> +}
> +
> +static int nxp_send_ack(u8 ack, struct hci_dev *hdev)
> +{
> +	struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
> +	u8 ack_nak[2];
> +
> +	if (ack == NXP_ACK_V1 || ack == NXP_NAK_V1) {
> +		ack_nak[0] = ack;
> +		serdev_device_write_buf(nxpdev->serdev, ack_nak, 1);
> +	} else if (ack == NXP_ACK_V3) {
> +		ack_nak[0] = ack;
> +		ack_nak[1] = crc8(crc8_table, ack_nak, 1, 0xff);
> +		serdev_device_write_buf(nxpdev->serdev, ack_nak, 2);
> +	}
> +	return 0;
> +}
> +
> +static bool nxp_fw_change_baudrate(struct hci_dev *hdev, u16 req_len)
> +{
> +	struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
> +	struct nxp_bootloader_cmd nxp_cmd5;
> +	struct uart_config uart_config;
> +
> +	if (req_len == sizeof(nxp_cmd5)) {
> +		nxp_cmd5.header = __cpu_to_le32(5);
> +		nxp_cmd5.arg = 0;
> +		nxp_cmd5.payload_len = __cpu_to_le32(sizeof(uart_config));
> +		nxp_cmd5.crc = swab32(nxp_fw_dnld_update_crc(0UL,
> +									 (char *)&nxp_cmd5,
> +									 sizeof(nxp_cmd5) - 4));
> +
> +		serdev_device_write_buf(nxpdev->serdev, (u8 *)&nxp_cmd5, req_len);
> +		nxpdev->fw_v3_offset_correction += req_len;
> +	} else if (req_len == sizeof(uart_config)) {
> +		uart_config.clkdiv.address = __cpu_to_le32(CLKDIVADDR);
> +		uart_config.clkdiv.value = __cpu_to_le32(0x00c00000);
> +		uart_config.uartdiv.address = __cpu_to_le32(UARTDIVADDR);
> +		uart_config.uartdiv.value = __cpu_to_le32(1);
> +		uart_config.mcr.address = __cpu_to_le32(UARTMCRADDR);
> +		uart_config.mcr.value = __cpu_to_le32(MCR);
> +		uart_config.re_init.address = __cpu_to_le32(UARTREINITADDR);
> +		uart_config.re_init.value = __cpu_to_le32(INIT);
> +		uart_config.icr.address = __cpu_to_le32(UARTICRADDR);
> +		uart_config.icr.value = __cpu_to_le32(ICR);
> +		uart_config.fcr.address = __cpu_to_le32(UARTFCRADDR);
> +		uart_config.fcr.value = __cpu_to_le32(FCR);
> +		uart_config.crc = swab32(nxp_fw_dnld_update_crc(0UL,
> +									(char *)&uart_config,
> +									sizeof(uart_config) - 4));
> +		serdev_device_write_buf(nxpdev->serdev, (u8 *)&uart_config, req_len);
> +		serdev_device_wait_until_sent(nxpdev->serdev, 0);
> +		nxpdev->fw_v3_offset_correction += req_len;
> +		return true;
> +	}
> +	return false;
> +}
> +
> +static bool nxp_fw_change_timeout(struct hci_dev *hdev, u16 req_len)
> +{
> +	struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
> +	struct nxp_bootloader_cmd nxp_cmd7;
> +
> +	if (req_len != sizeof(nxp_cmd7))
> +		return false;
> +
> +	nxp_cmd7.header = __cpu_to_le32(7);
> +	nxp_cmd7.arg = __cpu_to_le32(0x70);
> +	nxp_cmd7.payload_len = 0;
> +	nxp_cmd7.crc = swab32(nxp_fw_dnld_update_crc(0UL,
> +								(char *)&nxp_cmd7,
> +								sizeof(nxp_cmd7) - 4));
> +
> +	serdev_device_write_buf(nxpdev->serdev, (u8 *)&nxp_cmd7, req_len);
> +	serdev_device_wait_until_sent(nxpdev->serdev, 0);
> +	nxpdev->fw_v3_offset_correction += req_len;
> +	return true;
> +}
> +
> +static u32 nxp_get_data_len(const u8 *buf)
> +{
> +	struct nxp_bootloader_cmd *hdr = (struct nxp_bootloader_cmd *)buf;
> +
> +	return __le32_to_cpu(hdr->payload_len);
> +}
> +
> +/* for legacy chipsets with V1 bootloader */
> +static int nxp_recv_fw_req_v1(struct hci_dev *hdev, struct sk_buff *skb)
> +{
> +	struct v1_data_req *req = skb_pull_data(skb, sizeof(struct v1_data_req));
> +	struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
> +	struct btnxpuart_data *nxp_data = nxpdev->nxp_data;
> +	static bool timeout_changed;
> +	static bool baudrate_changed;
> +	u32 requested_len;
> +	static u32 expected_len = HDR_LEN;
> +
> +	if (!test_bit(BTNXPUART_FW_DOWNLOADING, &nxpdev->tx_state))
> +		goto ret;
> +
> +	if (!nxpdev->fw)
> +		goto ret;
> +
> +	if (req && (req->len ^ req->len_comp) != 0xffff) {
> +		bt_dev_info(hdev, "ERR: Send NAK");
> +		nxp_send_ack(NXP_NAK_V1, hdev);
> +		goto ret;
> +	}
> +	nxp_send_ack(NXP_ACK_V1, hdev);
> +
> +	if (nxp_data->fw_dnld_sec_baudrate != nxpdev->current_baudrate) {
> +		if (!timeout_changed) {
> +			timeout_changed = nxp_fw_change_timeout(hdev, req->len);
> +			goto ret;
> +		}
> +		if (!baudrate_changed) {
> +			baudrate_changed = nxp_fw_change_baudrate(hdev, req->len);
> +			if (baudrate_changed) {
> +				serdev_device_set_baudrate(nxpdev->serdev,
> +								nxp_data->fw_dnld_sec_baudrate);
> +				serdev_device_set_flow_control(nxpdev->serdev, 1);
> +				nxpdev->current_baudrate = nxp_data->fw_dnld_sec_baudrate;
> +			}
> +			goto ret;
> +		}
> +	}
> +
> +	requested_len = req->len;
> +	if (requested_len == 0) {
> +		bt_dev_info(hdev, "FW Downloaded Successfully: %zu bytes", nxpdev->fw->size);
> +		clear_bit(BTNXPUART_FW_DOWNLOADING, &nxpdev->tx_state);
> +		wake_up_interruptible(&nxpdev->suspend_wait_q);
> +		goto ret;
> +	}
> +	if (requested_len & 0x01) {
> +		/* The CRC did not match at the other end.
> +		 * Simply send the same bytes again.
> +		 */
> +		requested_len = nxpdev->fw_v1_sent_bytes;
> +		bt_dev_err(hdev, "CRC error. Resend %d bytes of FW.", requested_len);
> +	} else {
> +		nxpdev->fw_dnld_v1_offset += nxpdev->fw_v1_sent_bytes;
> +
> +		/* The FW bin file is made up of many blocks of
> +		 * 16 byte header and payload data chunks. If the
> +		 * FW has requested a header, read the payload length
> +		 * info from the header, before sending the header.
> +		 * In the next iteration, the FW should request the
> +		 * payload data chunk, which should be equal to the
> +		 * payload length read from header. If there is a
> +		 * mismatch, clearly the driver and FW are out of sync,
> +		 * and we need to re-send the previous header again.
> +		 */
> +		if (requested_len == expected_len) {
> +			if (requested_len == HDR_LEN)
> +				expected_len = nxp_get_data_len(nxpdev->fw->data +
> +									nxpdev->fw_dnld_v1_offset);
> +			else
> +				expected_len = HDR_LEN;
> +		} else {
> +			if (requested_len == HDR_LEN) {
> +				/* FW download out of sync. Send previous chunk again */
> +				nxpdev->fw_dnld_v1_offset -= nxpdev->fw_v1_sent_bytes;
> +				expected_len = HDR_LEN;
> +			}
> +		}
> +	}
> +
> +	if (nxpdev->fw_dnld_v1_offset + requested_len <= nxpdev->fw->size)
> +		serdev_device_write_buf(nxpdev->serdev,
> +				nxpdev->fw->data + nxpdev->fw_dnld_v1_offset,
> +				requested_len);
> +	nxpdev->fw_v1_sent_bytes = requested_len;
> +
> +ret:
> +	kfree_skb(skb);
> +	return 0;
> +}
> +
> +static int nxp_recv_chip_ver_v3(struct hci_dev *hdev, struct sk_buff *skb)
> +{
> +	struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
> +
> +	if (test_bit(BTNXPUART_FW_DOWNLOADING, &nxpdev->tx_state))
> +		nxp_send_ack(NXP_ACK_V3, hdev);
> +	kfree_skb(skb);
> +	return 0;
> +}
> +
> +static int nxp_recv_fw_req_v3(struct hci_dev *hdev, struct sk_buff *skb)
> +{
> +	struct v3_data_req *req = skb_pull_data(skb, sizeof(struct v3_data_req));
> +	struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
> +	struct btnxpuart_data *nxp_data = nxpdev->nxp_data;
> +	static bool timeout_changed;
> +	static bool baudrate_changed;
> +
> +	if (!req || !nxpdev || !nxpdev->fw->data)
> +		goto ret;
> +
> +	if (!test_bit(BTNXPUART_FW_DOWNLOADING, &nxpdev->tx_state))
> +		goto ret;
> +
> +	nxp_send_ack(NXP_ACK_V3, hdev);
> +
> +	if (nxpdev->current_baudrate != nxp_data->fw_dnld_sec_baudrate) {
> +		if (!timeout_changed) {
> +			timeout_changed = nxp_fw_change_timeout(hdev, req->len);
> +			goto ret;
> +		}
> +
> +		if (!baudrate_changed) {
> +			baudrate_changed = nxp_fw_change_baudrate(hdev, req->len);
> +			if (baudrate_changed) {
> +				serdev_device_set_baudrate(nxpdev->serdev,
> +								nxp_data->fw_dnld_sec_baudrate);
> +				serdev_device_set_flow_control(nxpdev->serdev, 1);
> +				nxpdev->current_baudrate = nxp_data->fw_dnld_sec_baudrate;
> +			}
> +			goto ret;
> +		}
> +	}
> +
> +	if (req->len == 0) {
> +		bt_dev_info(hdev, "FW Downloaded Successfully: %zu bytes", nxpdev->fw->size);
> +		clear_bit(BTNXPUART_FW_DOWNLOADING, &nxpdev->tx_state);
> +		wake_up_interruptible(&nxpdev->suspend_wait_q);
> +		goto ret;
> +	}
> +	if (req->error)
> +		bt_dev_err(hdev, "FW Download received err 0x%02x from chip. Resending FW chunk.",
> +			   req->error);
> +
> +	if (req->offset < nxpdev->fw_v3_offset_correction) {
> +		/* This scenario should ideally never occur.
> +		 * But if it ever does, FW is out of sync and
> +		 * needs a power cycle.
> +		 */
> +		bt_dev_err(hdev, "Something went wrong during FW download. Please power cycle and try again");
> +		goto ret;
> +	}
> +
> +	serdev_device_write_buf(nxpdev->serdev,
> +				nxpdev->fw->data + req->offset - nxpdev->fw_v3_offset_correction,
> +				req->len);
> +
> +ret:
> +	kfree_skb(skb);
> +	return 0;
> +}
> +
> +static int nxp_set_baudrate_cmd(struct hci_dev *hdev, void *data)
> +{
> +	struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
> +	u32 new_baudrate = __cpu_to_le32(nxpdev->new_baudrate);
> +	struct ps_data *psdata = nxpdev->psdata;
> +	u8 *pcmd = (u8 *)&new_baudrate;
> +	struct sk_buff *skb;
> +	u8 *status;
> +
> +	if (!psdata)
> +		return 0;
> +
> +	skb = nxp_drv_send_cmd(hdev, HCI_NXP_SET_OPER_SPEED, 4, pcmd);
> +	if (IS_ERR(skb)) {
> +		bt_dev_err(hdev, "Setting baudrate failed (%ld)", PTR_ERR(skb));
> +		return PTR_ERR(skb);
> +	}
> +
> +	status = skb_pull_data(skb, 1);
> +	if (status) {
> +		if (*status == 0) {
> +			serdev_device_set_baudrate(nxpdev->serdev, nxpdev->new_baudrate);
> +			nxpdev->current_baudrate = nxpdev->new_baudrate;
> +		}
> +		bt_dev_info(hdev, "Set baudrate response: status=%d, baudrate=%d",
> +					*status, nxpdev->new_baudrate);
> +	}
> +	kfree_skb(skb);
> +
> +	return 0;
> +}
> +
> +/* NXP protocol */
> +static void nxp_update_device_data(struct hci_dev *hdev,
> +								   char *label, char *value)
> +{
> +	struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
> +	struct btnxpuart_data *nxp_data = nxpdev->nxp_data;
> +	int ret = 0;
> +	u32 val;
> +
> +	if (!strncmp(label, FW_NAME_TAG, MAX_TAG_STR_LEN)) {
> +		snprintf(nxpdev->fw_name, MAX_FW_FILE_NAME_LEN, "%s",
> +				 value);
> +		return;
> +	}
> +
> +	ret = sscanf(value, "%u", &val);
> +	if (ret != 1) {
> +		bt_dev_err(hdev, "Error parsing value for %s", label);
> +		return;
> +	}
> +
> +	if (!strncmp(label, OPER_SPEED_TAG, MAX_TAG_STR_LEN))
> +		nxp_data->oper_speed = val;
> +	else if (!strncmp(label, FW_DL_PRI_BAUDRATE_TAG, MAX_TAG_STR_LEN))
> +		nxp_data->fw_dnld_pri_baudrate = val;
> +	else if (!strncmp(label, FW_DL_SEC_BAUDRATE_TAG, MAX_TAG_STR_LEN))
> +		nxp_data->fw_dnld_sec_baudrate = val;
> +	else if (!strncmp(label, FW_INIT_BAUDRATE, MAX_TAG_STR_LEN))
> +		nxp_data->fw_init_baudrate = val;
> +	else if (!strncmp(label, PS_INTERVAL_MS, MAX_TAG_STR_LEN))
> +		nxp_data->ps_interval_ms = val;
> +}
> +
> +static void nxp_parse_conf_file(struct hci_dev *hdev)
> +{
> +	struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
> +	char *dptr, *label, *value;
> +	bool valid_param = false;
> +	bool skipline = false;
> +	int param_index = 0;
> +	const char *sptr;
> +	int line_num = 1;
> +	char line[100];
> +	int ret = 0;
> +	int i, j;
> +
> +	ret = request_firmware(&nxpdev->fw_config, BT_FW_CONF_FILE, &hdev->dev);
> +	if (ret < 0) {
> +		bt_dev_info(hdev, "No NXP config file, using default settings");
> +		return;
> +	}
> +
> +	sptr = nxpdev->fw_config->data;
> +	j = 0;
> +	for (i = 0; i < nxpdev->fw_config->size; i++) {
> +		/* if current line is a comment, ignore */
> +		if (sptr[i] == '#') {
> +			skipline = true;
> +			continue;
> +		}
> +		/* keep ignoring the entire comment line */
> +		if (sptr[i] != '\n' && skipline)
> +			continue;
> +		/* ignore space, <CR> and comma */
> +		if (sptr[i] == ' ' || sptr[i] == '\r' || sptr[i] == ',')
> +			continue;
> +		/* handle '}' */
> +		if (sptr[i] == '}') {
> +			if (!valid_param) {
> +				bt_dev_err(hdev, "Unexpected '}' on line %d", line_num);
> +				goto ret;
> +			}
> +			valid_param = false;
> +			param_index++;
> +			continue;
> +		}
> +		/* handle new-line character */
> +		if (sptr[i] == '\n') {
> +			line_num++;
> +			if (skipline) {
> +				skipline = false;
> +				continue;
> +			}
> +			line[j] = '\0';
> +			/* ignore empty lines */
> +			if (strlen(line) == 0)
> +				continue;
> +
> +			dptr = line;
> +			label = strsep(&dptr, "=");
> +			value = strsep(&dptr, "=");
> +			if (label && value) {
> +				/* handle '{' */
> +				if (!strncmp(value, "{", MAX_TAG_STR_LEN) &&
> +					!strncmp(label, USER_CONFIG_TAG, MAX_TAG_STR_LEN)) {
> +					valid_param = true;
> +				} else if (valid_param) {
> +					nxp_update_device_data(hdev, label, value);
> +				}
> +			} else {
> +				bt_dev_err(hdev, "Invalid \"key\" = \"value\" pair at line: %d",
> +					   line_num - 1);
> +				goto ret;
> +			}
> +			j = 0;
> +		} else {
> +			line[j] = sptr[i];
> +			j++;
> +			if (j >= 100) {
> +				bt_dev_err(hdev, "Line too long: %d", line_num);
> +				goto ret;
> +			}
> +		}
> +	}
> +
> +ret:
> +	release_firmware(nxpdev->fw_config);
> +}
> +
> +static int nxp_setup(struct hci_dev *hdev)
> +{
> +	struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
> +	struct btnxpuart_data *nxp_data = nxpdev->nxp_data;
> +	int err = 0;
> +
> +	if (!nxpdev)
> +		return 0;
> +
> +	set_bit(BTNXPUART_FW_DOWNLOADING, &nxpdev->tx_state);
> +
> +	nxp_parse_conf_file(hdev);
> +	init_waitqueue_head(&nxpdev->suspend_wait_q);
> +
> +	if (!serdev_device_get_cts(nxpdev->serdev)) {
> +		bt_dev_info(hdev, "CTS high. Need FW Download");
> +		err = nxp_download_firmware(hdev);
> +		if (err < 0)
> +			return err;
> +	} else {
> +		bt_dev_info(hdev, "CTS low. FW already running.");
> +		clear_bit(BTNXPUART_FW_DOWNLOADING, &nxpdev->tx_state);
> +	}
> +
> +	serdev_device_set_flow_control(nxpdev->serdev, 1);
> +	serdev_device_set_baudrate(nxpdev->serdev, nxp_data->fw_init_baudrate);
> +	nxpdev->current_baudrate = nxp_data->fw_init_baudrate;
> +
> +	if (nxpdev->current_baudrate != nxp_data->oper_speed) {
> +		nxpdev->new_baudrate = nxp_data->oper_speed;
> +		hci_cmd_sync_queue(hdev, nxp_set_baudrate_cmd, NULL, NULL);
> +	}
> +
> +	if (!ps_init_work(hdev))
> +		ps_init_timer(hdev);
> +	ps_init(hdev);
> +
> +	return 0;
> +}
> +
> +static int nxp_enqueue(struct hci_dev *hdev, struct sk_buff *skb)
> +{
> +	struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
> +	struct ps_data *psdata = nxpdev->psdata;
> +	struct hci_command_hdr *hdr;
> +	u8 *param;
> +
> +	if (!nxpdev || !psdata) {
> +		kfree_skb(skb);
> +		goto ret;
> +	}
> +
> +	/* if vendor commands are received from user space (e.g. hcitool), update
> +	 * driver flags accordingly and ask driver to re-send the command to FW.
> +	 */
> +	if (bt_cb(skb)->pkt_type == HCI_COMMAND_PKT && !psdata->driver_sent_cmd) {
> +		hdr = (struct hci_command_hdr *)skb->data;
> +		param = skb->data + HCI_COMMAND_HDR_SIZE;
> +		switch (__le16_to_cpu(hdr->opcode)) {
> +		case HCI_NXP_AUTO_SLEEP_MODE:
> +			if (hdr->plen >= 1) {
> +				if (param[0] == BT_PS_ENABLE)
> +					psdata->ps_mode = PS_MODE_ENABLE;
> +				else if (param[0] == BT_PS_DISABLE)
> +					psdata->ps_mode = PS_MODE_DISABLE;
> +				hci_cmd_sync_queue(hdev, send_ps_cmd, NULL, NULL);
> +				kfree_skb(skb);
> +				goto ret;
> +			}
> +			break;
> +		case HCI_NXP_WAKEUP_METHOD:
> +			if (hdr->plen >= 4) {
> +				switch (param[2]) {
> +				case BT_CTRL_WAKEUP_METHOD_DSR:
> +					psdata->wakeupmode = WAKEUP_METHOD_DTR;
> +					break;
> +				case BT_CTRL_WAKEUP_METHOD_BREAK:
> +				default:
> +					psdata->wakeupmode = WAKEUP_METHOD_BREAK;
> +					break;
> +				}
> +				hci_cmd_sync_queue(hdev, send_wakeup_method_cmd, NULL, NULL);
> +				kfree_skb(skb);
> +				goto ret;
> +			}
> +			break;
> +		case HCI_NXP_SET_OPER_SPEED:
> +			if (hdr->plen == 4) {
> +				nxpdev->new_baudrate = *((u32 *)param);
> +				hci_cmd_sync_queue(hdev, nxp_set_baudrate_cmd, NULL, NULL);
> +				kfree_skb(skb);
> +				goto ret;
> +			}
> +		}
> +	}
> +
> +	/* Prepend skb with frame type */
> +	memcpy(skb_push(skb, 1), &hci_skb_pkt_type(skb), 1);
> +	skb_queue_tail(&nxpdev->txq, skb);
> +
> +	btnxpuart_tx_wakeup(nxpdev);
> +ret:
> +	return 0;
> +}
> +
> +static struct sk_buff *nxp_dequeue(void *data)
> +{
> +	struct btnxpuart_dev *nxpdev = (struct btnxpuart_dev *)data;
> +
> +	ps_wakeup(nxpdev);
> +	ps_start_timer(nxpdev);
> +	return skb_dequeue(&nxpdev->txq);
> +}
> +
> +/* btnxpuart based on serdev */
> +static void btnxpuart_tx_work(struct work_struct *work)
> +{
> +	struct btnxpuart_dev *nxpdev = container_of(work, struct btnxpuart_dev,
> +						   tx_work);
> +	struct serdev_device *serdev = nxpdev->serdev;
> +	struct hci_dev *hdev = nxpdev->hdev;
> +	struct sk_buff *skb;
> +	int len;
> +
> +	while ((skb = nxp_dequeue(nxpdev))) {
> +		len = serdev_device_write_buf(serdev, skb->data, skb->len);
> +		hdev->stat.byte_tx += len;
> +
> +		skb_pull(skb, len);
> +		if (skb->len > 0) {
> +			skb_queue_head(&nxpdev->txq, skb);
> +			break;
> +		}
> +
> +		switch (hci_skb_pkt_type(skb)) {
> +		case HCI_COMMAND_PKT:
> +			hdev->stat.cmd_tx++;
> +			break;
> +		case HCI_ACLDATA_PKT:
> +			hdev->stat.acl_tx++;
> +			break;
> +		case HCI_SCODATA_PKT:
> +			hdev->stat.sco_tx++;
> +			break;
> +		}
> +
> +		kfree_skb(skb);
> +	}
> +	clear_bit(BTNXPUART_TX_STATE_ACTIVE, &nxpdev->tx_state);
> +}
> +
> +static int btnxpuart_open(struct hci_dev *hdev)
> +{
> +	struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
> +	int err = 0;
> +
> +	err = serdev_device_open(nxpdev->serdev);
> +	if (err) {
> +		bt_dev_err(hdev, "Unable to open UART device %s",
> +			   dev_name(&nxpdev->serdev->dev));
> +	}
> +
> +	return err;
> +}
> +
> +static int btnxpuart_close(struct hci_dev *hdev)
> +{
> +	struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
> +
> +	if (!nxpdev)
> +		return 0;
> +
> +	serdev_device_close(nxpdev->serdev);
> +
> +	return 0;
> +}
> +
> +static int btnxpuart_flush(struct hci_dev *hdev)
> +{
> +	struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
> +
> +	if (!nxpdev)
> +		return 0;
> +
> +	/* Flush any pending characters */
> +	serdev_device_write_flush(nxpdev->serdev);
> +	skb_queue_purge(&nxpdev->txq);
> +
> +	cancel_work_sync(&nxpdev->tx_work);
> +
> +	kfree_skb(nxpdev->rx_skb);
> +	nxpdev->rx_skb = NULL;
> +
> +	return 0;
> +}
> +
> +static const struct h4_recv_pkt nxp_recv_pkts[] = {
> +	{ H4_RECV_ACL,          .recv = hci_recv_frame },
> +	{ H4_RECV_SCO,          .recv = hci_recv_frame },
> +	{ H4_RECV_EVENT,        .recv = hci_recv_frame },
> +	{ NXP_RECV_FW_REQ_V1,   .recv = nxp_recv_fw_req_v1 },
> +	{ NXP_RECV_CHIP_VER_V3, .recv = nxp_recv_chip_ver_v3 },
> +	{ NXP_RECV_FW_REQ_V3,   .recv = nxp_recv_fw_req_v3 },
> +};
> +
> +static int btnxpuart_receive_buf(struct serdev_device *serdev, const u8 *data,
> +								 size_t count)
> +{
> +	struct btnxpuart_dev *nxpdev = serdev_device_get_drvdata(serdev);
> +
> +	if (test_bit(BTNXPUART_FW_DOWNLOADING, &nxpdev->tx_state)) {
> +		if (*data != NXP_V1_FW_REQ_PKT && *data != NXP_V1_CHIP_VER_PKT &&
> +			*data != NXP_V3_FW_REQ_PKT && *data != NXP_V3_CHIP_VER_PKT) {
> +			/* Unknown bootloader signature, skip without returning error */
> +			return count;
> +		}
> +	}
> +
> +	ps_start_timer(nxpdev);
> +
> +	nxpdev->rx_skb = h4_recv_buf(nxpdev->hdev, nxpdev->rx_skb, data, count,
> +						nxp_recv_pkts, ARRAY_SIZE(nxp_recv_pkts));
> +	if (IS_ERR(nxpdev->rx_skb)) {
> +		int err = PTR_ERR(nxpdev->rx_skb);
> +
> +		bt_dev_err(nxpdev->hdev, "Frame reassembly failed (%d)", err);
> +		nxpdev->rx_skb = NULL;
> +		return err;
> +	}
> +	nxpdev->hdev->stat.byte_rx += count;
> +	return count;
> +}
> +
> +static void btnxpuart_write_wakeup(struct serdev_device *serdev)
> +{
> +	serdev_device_write_wakeup(serdev);
> +}
> +
> +static const struct serdev_device_ops btnxpuart_client_ops = {
> +	.receive_buf = btnxpuart_receive_buf,
> +	.write_wakeup = btnxpuart_write_wakeup,
> +};
> +
> +static int nxp_serdev_probe(struct serdev_device *serdev)
> +{
> +	struct hci_dev *hdev;
> +	struct btnxpuart_dev *nxpdev;
> +
> +	nxpdev = devm_kzalloc(&serdev->dev, sizeof(*nxpdev), GFP_KERNEL);
> +	if (!nxpdev)
> +		return -ENOMEM;
> +
> +	nxpdev->nxp_data = (struct btnxpuart_data *)device_get_match_data(&serdev->dev);
> +
> +	nxpdev->serdev = serdev;
> +	serdev_device_set_drvdata(serdev, nxpdev);
> +
> +	serdev_device_set_client_ops(serdev, &btnxpuart_client_ops);
> +
> +	INIT_WORK(&nxpdev->tx_work, btnxpuart_tx_work);
> +	skb_queue_head_init(&nxpdev->txq);
> +
> +	/* Initialize and register HCI device */
> +	hdev = hci_alloc_dev();
> +	if (!hdev) {
> +		dev_err(&serdev->dev, "Can't allocate HCI device\n");
> +		return -ENOMEM;
> +	}
> +
> +	nxpdev->hdev = hdev;
> +
> +	hdev->bus = HCI_UART;
> +	hci_set_drvdata(hdev, nxpdev);
> +
> +	hdev->manufacturer = 37;
> +	hdev->open  = btnxpuart_open;
> +	hdev->close = btnxpuart_close;
> +	hdev->flush = btnxpuart_flush;
> +	hdev->setup = nxp_setup;
> +	hdev->send  = nxp_enqueue;
> +	SET_HCIDEV_DEV(hdev, &serdev->dev);
> +
> +	if (hci_register_dev(hdev) < 0) {
> +		dev_err(&serdev->dev, "Can't register HCI device\n");
> +		hci_free_dev(hdev);
> +		return -ENODEV;
> +	}
> +
> +	return 0;
> +}
> +
> +static void nxp_serdev_remove(struct serdev_device *serdev)
> +{
> +	struct btnxpuart_dev *nxpdev = serdev_device_get_drvdata(serdev);
> +	struct btnxpuart_data *nxp_data = nxpdev->nxp_data;
> +	struct hci_dev *hdev = nxpdev->hdev;
> +
> +	/* Restore FW baudrate to fw_init_baudrate if changed.
> +	 * This will ensure FW baudrate is in sync with
> +	 * driver baudrate in case this driver is re-inserted.
> +	 */
> +	if (nxp_data->fw_init_baudrate != nxpdev->current_baudrate) {
> +		nxpdev->new_baudrate = nxp_data->fw_init_baudrate;
> +		nxp_set_baudrate_cmd(hdev, NULL);
> +	}
> +
> +	ps_cancel_timer(nxpdev);
> +	hci_unregister_dev(hdev);
> +	hci_free_dev(hdev);
> +}
> +
> +/* Following default values are as per Murata M.2 modules
> + * For modules from different vendor, if any of the device
> + * parameters are different, they can be over-written by
> + * config file /lib/firmware/nxp/bt_mod_para.conf
> + */
> +static struct btnxpuart_data w8987_data = {
> +	.fw_dnld_pri_baudrate = 115200,
> +	.fw_dnld_sec_baudrate = 3000000,
> +	.fw_init_baudrate = 115200,
> +	.oper_speed		= 3000000,
> +	.ps_interval_ms = PS_DEFAULT_TIMEOUT_PERIOD,
> +	.fw_name = FIRMWARE_W8987,
> +};
> +
> +static struct btnxpuart_data w8997_data = {
> +	.fw_dnld_pri_baudrate = 115200,
> +	.fw_dnld_sec_baudrate = 115200,
> +	.fw_init_baudrate = 115200,
> +	.oper_speed		= 3000000,
> +	.ps_interval_ms = PS_DEFAULT_TIMEOUT_PERIOD,
> +	.fw_name = FIRMWARE_W8997,
> +};
> +
> +static struct btnxpuart_data w9098_data = {
> +	.fw_dnld_pri_baudrate = 115200,
> +	.fw_dnld_sec_baudrate = 3000000,
> +	.fw_init_baudrate = 115200,
> +	.oper_speed		= 3000000,
> +	.ps_interval_ms = PS_DEFAULT_TIMEOUT_PERIOD,
> +	.fw_name = FIRMWARE_W9098,
> +};
> +
> +static struct btnxpuart_data iw416_data = {
> +	.fw_dnld_pri_baudrate = 115200,
> +	.fw_dnld_sec_baudrate = 3000000,
> +	.fw_init_baudrate = 115200,
> +	.oper_speed		= 3000000,
> +	.ps_interval_ms = PS_DEFAULT_TIMEOUT_PERIOD,
> +	.fw_name = FIRMWARE_IW416,
> +};
> +
> +static struct btnxpuart_data iw612_data = {
> +	.fw_dnld_pri_baudrate = 115200,
> +	.fw_dnld_sec_baudrate = 3000000,
> +	.fw_init_baudrate = 115200,
> +	.oper_speed		= 3000000,
> +	.ps_interval_ms = PS_DEFAULT_TIMEOUT_PERIOD,
> +	.fw_name = FIRMWARE_IW612,
> +};
> +
> +static const struct of_device_id nxpuart_of_match_table[] = {
> +	{ .compatible = "nxp,88w8987-bt", .data = &w8987_data },
> +	{ .compatible = "nxp,88w8997-bt", .data = &w8997_data },
> +	{ .compatible = "nxp,88w9098-bt", .data = &w9098_data },
> +	{ .compatible = "nxp,iw416-bt", .data = &iw416_data },
> +	{ .compatible = "nxp,iw612-bt", .data = &iw612_data },
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(of, nxpuart_of_match_table);
> +
> +static struct serdev_device_driver nxp_serdev_driver = {
> +	.probe = nxp_serdev_probe,
> +	.remove = nxp_serdev_remove,
> +	.driver = {
> +		.name = "btnxpuart",
> +		.of_match_table = of_match_ptr(nxpuart_of_match_table),
> +	},
> +};
> +
> +module_serdev_device_driver(nxp_serdev_driver);
> +
> +MODULE_AUTHOR("Neeraj Sanjay Kale <neeraj.sanjaykale@nxp.com>");
> +MODULE_DESCRIPTION("NXP Bluetooth Serial driver v1.0 ");
> +MODULE_LICENSE("GPL");
> 

^ permalink raw reply

* [PATCH v3 3/3] Bluetooth: NXP: Add protocol support for NXP Bluetooth chipsets
From: Neeraj Sanjay Kale @ 2023-02-13 14:54 UTC (permalink / raw)
  To: davem, edumazet, kuba, pabeni, robh+dt, krzysztof.kozlowski+dt,
	marcel, johan.hedberg, luiz.dentz, gregkh, jirislaby,
	alok.a.tiwari, hdanton, ilpo.jarvinen, leon
  Cc: netdev, devicetree, linux-kernel, linux-bluetooth, linux-serial,
	amitkumar.karwar, rohit.fule, sherry.sun, neeraj.sanjaykale
In-Reply-To: <20230213145432.1192911-1-neeraj.sanjaykale@nxp.com>

This adds a driver based on serdev driver for the NXP BT serial
protocol based on running H:4, which can enable the built-in
Bluetooth device inside a generic NXP BT chip.

This driver has Power Save feature that will put the chip into
sleep state whenever there is no activity for 2000ms, and will
be woken up when any activity is to be initiated over UART.

This driver enables the power save feature by default by sending
the vendor specific commands to the chip during setup.

During setup, the driver checks if a FW is already running on the
chip based on the CTS line, and downloads device specific FW file
into the chip over UART.

The driver contains certain device specific default parameters
related to FW filename, baudrate and timeouts which can be
overwritten by an optional user space config file. These parameters
may vary from one module vendor to another.

Signed-off-by: Neeraj Sanjay Kale <neeraj.sanjaykale@nxp.com>
---
v2: Removed conf file support and added static data for each chip
based on compatibility devices mentioned in DT bindings. Handled
potential memory leaks and null pointer dereference issues,
simplified FW download feature, handled byte-order and few cosmetic
changes. (Ilpo Järvinen, Alok Tiwari, Hillf Danton)
v3: Added conf file support necessary to support different vendor
modules, moved .h file contents to .c, cosmetic changes. (Luiz
Augusto von Dentz, Rob Herring, Leon Romanovsky)
---
 drivers/bluetooth/Kconfig     |   11 +
 drivers/bluetooth/Makefile    |    1 +
 drivers/bluetooth/btnxpuart.c | 1370 +++++++++++++++++++++++++++++++++
 3 files changed, 1382 insertions(+)
 create mode 100644 drivers/bluetooth/btnxpuart.c

diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig
index 5a1a7bec3c42..773b40d34b7b 100644
--- a/drivers/bluetooth/Kconfig
+++ b/drivers/bluetooth/Kconfig
@@ -465,4 +465,15 @@ config BT_VIRTIO
 	  Say Y here to compile support for HCI over Virtio into the
 	  kernel or say M to compile as a module.
 
+config BT_NXPUART
+	tristate "NXP protocol support"
+	depends on SERIAL_DEV_BUS
+	help
+	  NXP is serial driver required for NXP Bluetooth
+	  devices with UART interface.
+
+	  Say Y here to compile support for NXP Bluetooth UART device into
+	  the kernel, or say M here to compile as a module.
+
+
 endmenu
diff --git a/drivers/bluetooth/Makefile b/drivers/bluetooth/Makefile
index e0b261f24fc9..7a5967e9ac48 100644
--- a/drivers/bluetooth/Makefile
+++ b/drivers/bluetooth/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_BT_QCA)		+= btqca.o
 obj-$(CONFIG_BT_MTK)		+= btmtk.o
 
 obj-$(CONFIG_BT_VIRTIO)		+= virtio_bt.o
+obj-$(CONFIG_BT_NXPUART)	+= btnxpuart.o
 
 obj-$(CONFIG_BT_HCIUART_NOKIA)	+= hci_nokia.o
 
diff --git a/drivers/bluetooth/btnxpuart.c b/drivers/bluetooth/btnxpuart.c
new file mode 100644
index 000000000000..d774564d47ce
--- /dev/null
+++ b/drivers/bluetooth/btnxpuart.c
@@ -0,0 +1,1370 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ *  NXP Bluetooth driver
+ *  Copyright 2018-2023 NXP
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+
+#include <linux/serdev.h>
+#include <linux/of.h>
+#include <linux/skbuff.h>
+#include <asm/unaligned.h>
+#include <linux/firmware.h>
+#include <linux/string.h>
+#include <linux/crc8.h>
+
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
+
+#include "h4_recv.h"
+
+#define BTNXPUART_TX_STATE_ACTIVE	1
+#define BTNXPUART_FW_DOWNLOADING	2
+
+#define MAX_TAG_STR_LEN				20
+#define BT_FW_CONF_FILE				"nxp/bt_mod_para.conf"
+#define USER_CONFIG_TAG				"user_config"
+#define FW_NAME_TAG					"fw_name"
+#define OPER_SPEED_TAG				"oper_speed"
+#define FW_DL_PRI_BAUDRATE_TAG		"fw_dl_pri_speed"
+#define FW_DL_SEC_BAUDRATE_TAG		"fw_dl_sec_speed"
+#define FW_INIT_BAUDRATE			"fw_init_speed"
+#define PS_INTERVAL_MS				"ps_interval_ms"
+
+#define FIRMWARE_W8987	"nxp/sdiouart8987_combo_v0.bin"
+#define FIRMWARE_W8997	"nxp/uartuart8997_bt_v4.bin"
+#define FIRMWARE_W9098	"nxp/uartuart9098_bt_v1.bin"
+#define FIRMWARE_IW416	"nxp/sdiouartiw416_combo_v0.bin"
+#define FIRMWARE_IW612	"nxp/sduart_nw61x_v1.bin.se"
+
+#define MAX_FW_FILE_NAME_LEN    50
+
+/* Default ps timeout period in milli-second */
+#define PS_DEFAULT_TIMEOUT_PERIOD     2000
+
+/* wakeup methods */
+#define WAKEUP_METHOD_DTR       0
+#define WAKEUP_METHOD_BREAK     1
+#define WAKEUP_METHOD_EXT_BREAK 2
+#define WAKEUP_METHOD_RTS       3
+#define WAKEUP_METHOD_INVALID   0xff
+
+/* power save mode status */
+#define PS_MODE_DISABLE         0
+#define PS_MODE_ENABLE          1
+
+/* Power Save Commands to ps_work_func  */
+#define PS_CMD_EXIT_PS          1
+#define PS_CMD_ENTER_PS         2
+
+/* power save state */
+#define PS_STATE_AWAKE          0
+#define PS_STATE_SLEEP          1
+
+/* Bluetooth vendor command : Sleep mode */
+#define HCI_NXP_AUTO_SLEEP_MODE	0xfc23
+/* Bluetooth vendor command : Wakeup method */
+#define HCI_NXP_WAKEUP_METHOD	0xfc53
+/* Bluetooth vendor command : Set operational baudrate */
+#define HCI_NXP_SET_OPER_SPEED	0xfc09
+
+/* Bluetooth Power State : Vendor cmd params */
+#define BT_PS_ENABLE			0x02
+#define BT_PS_DISABLE			0x03
+
+/* Bluetooth Host Wakeup Methods */
+#define BT_HOST_WAKEUP_METHOD_NONE      0x00
+#define BT_HOST_WAKEUP_METHOD_DTR       0x01
+#define BT_HOST_WAKEUP_METHOD_BREAK     0x02
+#define BT_HOST_WAKEUP_METHOD_GPIO      0x03
+
+/* Bluetooth Chip Wakeup Methods */
+#define BT_CTRL_WAKEUP_METHOD_DSR       0x00
+#define BT_CTRL_WAKEUP_METHOD_BREAK     0x01
+#define BT_CTRL_WAKEUP_METHOD_GPIO      0x02
+#define BT_CTRL_WAKEUP_METHOD_EXT_BREAK 0x04
+#define BT_CTRL_WAKEUP_METHOD_RTS       0x05
+
+struct ps_data {
+	u8    ps_mode;
+	u8    cur_psmode;
+	u8    ps_state;
+	u8    ps_cmd;
+	u8    wakeupmode;
+	u8    cur_wakeupmode;
+	bool  driver_sent_cmd;
+	u8    timer_on;
+	u32   interval;
+	struct hci_dev *hdev;
+	struct work_struct work;
+	struct timer_list ps_timer;
+};
+
+struct btnxpuart_data {
+	u32 fw_dnld_pri_baudrate;
+	u32 fw_dnld_sec_baudrate;
+	u32 fw_init_baudrate;
+	u32 oper_speed;
+	u32 ps_interval_ms;
+	const u8 *fw_name;
+};
+
+struct btnxpuart_dev {
+	struct hci_dev *hdev;
+	struct serdev_device *serdev;
+
+	struct work_struct tx_work;
+	unsigned long tx_state;
+	struct sk_buff_head txq;
+	struct sk_buff *rx_skb;
+
+	const struct firmware *fw;
+	const struct firmware *fw_config;
+	u8 fw_name[MAX_FW_FILE_NAME_LEN];
+	u32 fw_dnld_v1_offset;
+	u32 fw_v1_sent_bytes;
+	u32 fw_v3_offset_correction;
+	wait_queue_head_t suspend_wait_q;
+
+	u32 new_baudrate;
+	u32 current_baudrate;
+
+	struct ps_data *psdata;
+	struct btnxpuart_data *nxp_data;
+};
+
+#define NXP_V1_FW_REQ_PKT      0xa5
+#define NXP_V1_CHIP_VER_PKT    0xaa
+#define NXP_V3_FW_REQ_PKT      0xa7
+#define NXP_V3_CHIP_VER_PKT    0xab
+
+#define NXP_ACK_V1             0x5a
+#define NXP_NAK_V1             0xbf
+#define NXP_ACK_V3             0x7a
+#define NXP_NAK_V3             0x7b
+#define NXP_CRC_ERROR_V3       0x7c
+
+#define HDR_LEN					16
+
+#define NXP_RECV_FW_REQ_V1 \
+	.type = NXP_V1_FW_REQ_PKT, \
+	.hlen = 4, \
+	.loff = 0, \
+	.lsize = 0, \
+	.maxlen = 4
+
+#define NXP_RECV_CHIP_VER_V3 \
+	.type = NXP_V3_CHIP_VER_PKT, \
+	.hlen = 4, \
+	.loff = 0, \
+	.lsize = 0, \
+	.maxlen = 4
+
+#define NXP_RECV_FW_REQ_V3 \
+	.type = NXP_V3_FW_REQ_PKT, \
+	.hlen = 9, \
+	.loff = 0, \
+	.lsize = 0, \
+	.maxlen = 9
+
+struct v1_data_req {
+	__le16 len;
+	__le16 len_comp;
+} __packed;
+
+struct v3_data_req {
+	__le16 len;
+	__le32 offset;
+	__le16 error;
+	u8 crc;
+} __packed;
+
+struct v3_start_ind {
+	__le16 chip_id;
+	u8 loader_ver;
+	u8 crc;
+} __packed;
+
+/* UART register addresses of BT chip */
+#define CLKDIVADDR       0x7f00008f
+#define UARTDIVADDR      0x7f000090
+#define UARTMCRADDR      0x7f000091
+#define UARTREINITADDR   0x7f000092
+#define UARTICRADDR      0x7f000093
+#define UARTFCRADDR      0x7f000094
+
+#define MCR   0x00000022
+#define INIT  0x00000001
+#define ICR   0x000000c7
+#define FCR   0x000000c7
+
+#define POLYNOMIAL8				0x07
+#define POLYNOMIAL32			0x04c11db7L
+
+struct uart_reg {
+	__le32 address;
+	__le32 value;
+} __packed;
+
+struct uart_config {
+	struct uart_reg clkdiv;
+	struct uart_reg uartdiv;
+	struct uart_reg mcr;
+	struct uart_reg re_init;
+	struct uart_reg icr;
+	struct uart_reg fcr;
+	__le32 crc;
+} __packed;
+
+struct nxp_bootloader_cmd {
+	__le32 header;
+	__le32 arg;
+	__le32 payload_len;
+	__le32 crc;
+} __packed;
+
+static u8 crc8_table[CRC8_TABLE_SIZE];
+static unsigned long crc32_table[256];
+
+/* Default Power Save configuration */
+int wakeupmode = WAKEUP_METHOD_BREAK;
+int ps_mode = PS_MODE_ENABLE;
+
+static struct sk_buff *nxp_drv_send_cmd(struct hci_dev *hdev, u16 opcode,
+										u32 plen,
+										void *param)
+{
+	struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
+	struct ps_data *psdata = nxpdev->psdata;
+	struct sk_buff *skb;
+
+	psdata->driver_sent_cmd = true;	/* set flag to prevent re-sending command in nxp_enqueue */
+	skb = __hci_cmd_sync(hdev, opcode, plen, param, HCI_CMD_TIMEOUT);
+	psdata->driver_sent_cmd = false;
+
+	return skb;
+}
+
+static void btnxpuart_tx_wakeup(struct btnxpuart_dev *nxpdev)
+{
+	if (schedule_work(&nxpdev->tx_work))
+		set_bit(BTNXPUART_TX_STATE_ACTIVE, &nxpdev->tx_state);
+}
+
+/* NXP Power Save Feature */
+static void ps_start_timer(struct btnxpuart_dev *nxpdev)
+{
+	struct ps_data *psdata = nxpdev->psdata;
+
+	if (!psdata)
+		return;
+
+	if (psdata->cur_psmode == PS_MODE_ENABLE) {
+		psdata->timer_on = 1;
+		mod_timer(&psdata->ps_timer, jiffies + (psdata->interval * HZ) / 1000);
+	}
+}
+
+static void ps_cancel_timer(struct btnxpuart_dev *nxpdev)
+{
+	struct ps_data *psdata = nxpdev->psdata;
+
+	if (!psdata)
+		return;
+
+	flush_work(&psdata->work);
+	if (psdata->timer_on)
+		del_timer_sync(&psdata->ps_timer);
+	kfree(psdata);
+}
+
+static void ps_control(struct hci_dev *hdev, u8 ps_state)
+{
+	struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
+	struct ps_data *psdata = nxpdev->psdata;
+
+	if (psdata->ps_state == ps_state)
+		return;
+
+	switch (psdata->cur_wakeupmode) {
+	case WAKEUP_METHOD_DTR:
+		if (ps_state == PS_STATE_AWAKE)
+			serdev_device_set_tiocm(nxpdev->serdev, TIOCM_DTR, 0);
+		else
+			serdev_device_set_tiocm(nxpdev->serdev, 0, TIOCM_DTR);
+		break;
+	case WAKEUP_METHOD_BREAK:
+	default:
+		bt_dev_info(hdev, "Set UART break: %s", ps_state == PS_STATE_AWAKE ? "off" : "on");
+		if (ps_state == PS_STATE_AWAKE)
+			serdev_device_break_ctl(nxpdev->serdev, 0);
+		else
+			serdev_device_break_ctl(nxpdev->serdev, -1);
+		break;
+	}
+	psdata->ps_state = ps_state;
+	if (ps_state == PS_STATE_AWAKE)
+		btnxpuart_tx_wakeup(nxpdev);
+}
+
+static void ps_work_func(struct work_struct *work)
+{
+	struct ps_data *data = container_of(work, struct ps_data, work);
+
+	if (data->ps_cmd == PS_CMD_ENTER_PS && data->cur_psmode == PS_MODE_ENABLE)
+		ps_control(data->hdev, PS_STATE_SLEEP);
+	else if (data->ps_cmd == PS_CMD_EXIT_PS)
+		ps_control(data->hdev, PS_STATE_AWAKE);
+}
+
+static void ps_timeout_func(struct timer_list *t)
+{
+	struct ps_data *data = from_timer(data, t, ps_timer);
+	struct hci_dev *hdev = data->hdev;
+	struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
+
+	data->timer_on = 0;
+	if (test_bit(BTNXPUART_TX_STATE_ACTIVE, &nxpdev->tx_state)) {
+		ps_start_timer(nxpdev);
+	} else {
+		data->ps_cmd = PS_CMD_ENTER_PS;
+		schedule_work(&data->work);
+	}
+}
+
+static int ps_init_work(struct hci_dev *hdev)
+{
+	struct ps_data *psdata = kzalloc(sizeof(*psdata), GFP_KERNEL);
+	struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
+	struct btnxpuart_data *nxp_data = nxpdev->nxp_data;
+
+	if (!psdata) {
+		bt_dev_err(hdev, "Can't allocate control structure for Power Save feature");
+		return -ENOMEM;
+	}
+	nxpdev->psdata = psdata;
+
+	psdata->interval = nxp_data->ps_interval_ms;
+	psdata->ps_state = PS_STATE_AWAKE;
+	psdata->ps_mode = ps_mode;
+	psdata->hdev = hdev;
+
+	switch (wakeupmode) {
+	case WAKEUP_METHOD_DTR:
+		psdata->wakeupmode = WAKEUP_METHOD_DTR;
+		break;
+	case WAKEUP_METHOD_BREAK:
+	default:
+		psdata->wakeupmode = WAKEUP_METHOD_BREAK;
+		break;
+	}
+	psdata->cur_psmode = PS_MODE_DISABLE;
+	psdata->cur_wakeupmode = WAKEUP_METHOD_INVALID;
+	INIT_WORK(&psdata->work, ps_work_func);
+
+	return 0;
+}
+
+static void ps_init_timer(struct hci_dev *hdev)
+{
+	struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
+	struct ps_data *psdata = nxpdev->psdata;
+
+	psdata->timer_on = 0;
+	timer_setup(&psdata->ps_timer, ps_timeout_func, 0);
+}
+
+static int ps_wakeup(struct btnxpuart_dev *nxpdev)
+{
+	struct ps_data *psdata = nxpdev->psdata;
+
+	if (psdata->ps_state == PS_STATE_AWAKE)
+		return 0;
+	psdata->ps_cmd = PS_CMD_EXIT_PS;
+	schedule_work(&psdata->work);
+
+	return 1;
+}
+
+static int send_ps_cmd(struct hci_dev *hdev, void *data)
+{
+	struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
+	struct ps_data *psdata = nxpdev->psdata;
+	u8 pcmd;
+	struct sk_buff *skb;
+	u8 *status;
+
+	if (psdata->ps_mode == PS_MODE_ENABLE)
+		pcmd = BT_PS_ENABLE;
+	else
+		pcmd = BT_PS_DISABLE;
+
+	skb = nxp_drv_send_cmd(hdev, HCI_NXP_AUTO_SLEEP_MODE, 1, &pcmd);
+	if (IS_ERR(skb)) {
+		bt_dev_err(hdev, "Setting Power Save mode failed (%ld)", PTR_ERR(skb));
+		return PTR_ERR(skb);
+	}
+
+	status = skb_pull_data(skb, 1);
+	if (status) {
+		if (!*status)
+			psdata->cur_psmode = psdata->ps_mode;
+		else
+			psdata->ps_mode = psdata->cur_psmode;
+		if (psdata->cur_psmode == PS_MODE_ENABLE)
+			ps_start_timer(nxpdev);
+		else
+			ps_wakeup(nxpdev);
+		bt_dev_info(hdev, "Power Save mode response: status=%d, ps_mode=%d",
+					*status, psdata->cur_psmode);
+	}
+	kfree_skb(skb);
+
+	return 0;
+}
+
+static int send_wakeup_method_cmd(struct hci_dev *hdev, void *data)
+{
+	struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
+	struct ps_data *psdata = nxpdev->psdata;
+	u8 pcmd[4];
+	struct sk_buff *skb;
+	u8 *status;
+
+	pcmd[0] = BT_HOST_WAKEUP_METHOD_NONE;
+	pcmd[1] = 0xff;
+	switch (psdata->wakeupmode) {
+	case WAKEUP_METHOD_DTR:
+		pcmd[2] = BT_CTRL_WAKEUP_METHOD_DSR;
+		break;
+	case WAKEUP_METHOD_BREAK:
+	default:
+		pcmd[2] = BT_CTRL_WAKEUP_METHOD_BREAK;
+		break;
+	}
+	pcmd[3] = 0xff;
+
+	skb = nxp_drv_send_cmd(hdev, HCI_NXP_WAKEUP_METHOD, 4, pcmd);
+	if (IS_ERR(skb)) {
+		bt_dev_err(hdev, "Setting wake-up method failed (%ld)", PTR_ERR(skb));
+		return PTR_ERR(skb);
+	}
+
+	status = skb_pull_data(skb, 1);
+	if (status) {
+		if (*status == 0)
+			psdata->cur_wakeupmode = psdata->wakeupmode;
+		else
+			psdata->wakeupmode = psdata->cur_wakeupmode;
+		bt_dev_info(hdev, "Set Wakeup Method response: status=%d, wakeupmode=%d",
+					*status, psdata->cur_wakeupmode);
+	}
+	kfree_skb(skb);
+
+	return 0;
+}
+
+static int ps_init(struct hci_dev *hdev)
+{
+	struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
+	struct ps_data *psdata = nxpdev->psdata;
+
+	serdev_device_set_tiocm(nxpdev->serdev, TIOCM_RTS, 0);
+
+	switch (psdata->wakeupmode) {
+	case WAKEUP_METHOD_DTR:
+		serdev_device_set_tiocm(nxpdev->serdev, 0, TIOCM_DTR);
+		serdev_device_set_tiocm(nxpdev->serdev, TIOCM_DTR, 0);
+		break;
+	case WAKEUP_METHOD_BREAK:
+	default:
+		serdev_device_break_ctl(nxpdev->serdev, -1);
+		usleep_range(5000, 10000);
+		serdev_device_break_ctl(nxpdev->serdev, 0);
+		usleep_range(5000, 10000);
+		break;
+	}
+	if (!test_bit(HCI_RUNNING, &hdev->flags)) {
+		bt_dev_err(hdev, "HCI_RUNNING is not set");
+		return -EBUSY;
+	}
+	if (psdata->cur_wakeupmode != psdata->wakeupmode)
+		hci_cmd_sync_queue(hdev, send_wakeup_method_cmd, NULL, NULL);
+	if (psdata->cur_psmode != psdata->ps_mode)
+		hci_cmd_sync_queue(hdev, send_ps_cmd, NULL, NULL);
+
+	return 0;
+}
+
+/* NXP Firmware Download Feature */
+static void nxp_fw_dnld_gen_crc32_table(void)
+{
+	int i, j;
+	unsigned long crc_accum;
+
+	for (i = 0; i < 256; i++) {
+		crc_accum = ((unsigned long)i << 24);
+		for (j = 0; j < 8; j++) {
+			if (crc_accum & 0x80000000L)
+				crc_accum = (crc_accum << 1) ^ POLYNOMIAL32;
+			else
+				crc_accum = (crc_accum << 1);
+		}
+		crc32_table[i] = crc_accum;
+	}
+}
+
+static unsigned long nxp_fw_dnld_update_crc(unsigned long crc_accum,
+									char *data_blk_ptr,
+									int data_blk_size)
+{
+	unsigned long i, j;
+
+	for (j = 0; j < data_blk_size; j++) {
+		i = ((unsigned long)(crc_accum >> 24) ^ *data_blk_ptr++) & 0xff;
+		crc_accum = (crc_accum << 8) ^ crc32_table[i];
+	}
+	return crc_accum;
+}
+
+static int nxp_download_firmware(struct hci_dev *hdev)
+{
+	struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
+	struct btnxpuart_data *nxp_data = nxpdev->nxp_data;
+	int err = 0;
+
+	nxpdev->fw_dnld_v1_offset = 0;
+	nxpdev->fw_v1_sent_bytes = 0;
+
+	crc8_populate_msb(crc8_table, POLYNOMIAL8);
+	nxp_fw_dnld_gen_crc32_table();
+
+	if (!strlen(nxpdev->fw_name))
+		snprintf(nxpdev->fw_name, MAX_FW_FILE_NAME_LEN, "%s",
+				 nxp_data->fw_name);
+
+	bt_dev_info(hdev, "Request Firmware: %s", nxpdev->fw_name);
+	err = request_firmware(&nxpdev->fw, nxpdev->fw_name, &hdev->dev);
+	if (err < 0) {
+		bt_dev_err(hdev, "Firmware file %s not found", nxpdev->fw_name);
+		clear_bit(BTNXPUART_FW_DOWNLOADING, &nxpdev->tx_state);
+		return err;
+	}
+
+	serdev_device_set_baudrate(nxpdev->serdev, nxp_data->fw_dnld_pri_baudrate);
+	serdev_device_set_flow_control(nxpdev->serdev, 0);
+	nxpdev->current_baudrate = nxp_data->fw_dnld_pri_baudrate;
+	nxpdev->fw_v3_offset_correction = 0;
+
+	/* Wait till FW is downloaded and CTS becomes low */
+	err = wait_event_interruptible_timeout(nxpdev->suspend_wait_q,
+							!test_bit(BTNXPUART_FW_DOWNLOADING,
+									  &nxpdev->tx_state),
+							msecs_to_jiffies(60000));
+	if (err == 0) {
+		bt_dev_err(hdev, "FW Download Timeout.");
+		return -ETIMEDOUT;
+	}
+
+	serdev_device_set_flow_control(nxpdev->serdev, 1);
+	err = serdev_device_wait_for_cts(nxpdev->serdev, 1, 60000);
+	if (err < 0) {
+		bt_dev_err(hdev, "CTS is still high. FW Download failed.");
+		return err;
+	}
+	bt_dev_info(hdev, "CTS is low");
+	release_firmware(nxpdev->fw);
+
+	/* Allow the downloaded FW to initialize */
+	usleep_range(1000000, 1200000);
+
+	return 0;
+}
+
+static int nxp_send_ack(u8 ack, struct hci_dev *hdev)
+{
+	struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
+	u8 ack_nak[2];
+
+	if (ack == NXP_ACK_V1 || ack == NXP_NAK_V1) {
+		ack_nak[0] = ack;
+		serdev_device_write_buf(nxpdev->serdev, ack_nak, 1);
+	} else if (ack == NXP_ACK_V3) {
+		ack_nak[0] = ack;
+		ack_nak[1] = crc8(crc8_table, ack_nak, 1, 0xff);
+		serdev_device_write_buf(nxpdev->serdev, ack_nak, 2);
+	}
+	return 0;
+}
+
+static bool nxp_fw_change_baudrate(struct hci_dev *hdev, u16 req_len)
+{
+	struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
+	struct nxp_bootloader_cmd nxp_cmd5;
+	struct uart_config uart_config;
+
+	if (req_len == sizeof(nxp_cmd5)) {
+		nxp_cmd5.header = __cpu_to_le32(5);
+		nxp_cmd5.arg = 0;
+		nxp_cmd5.payload_len = __cpu_to_le32(sizeof(uart_config));
+		nxp_cmd5.crc = swab32(nxp_fw_dnld_update_crc(0UL,
+									 (char *)&nxp_cmd5,
+									 sizeof(nxp_cmd5) - 4));
+
+		serdev_device_write_buf(nxpdev->serdev, (u8 *)&nxp_cmd5, req_len);
+		nxpdev->fw_v3_offset_correction += req_len;
+	} else if (req_len == sizeof(uart_config)) {
+		uart_config.clkdiv.address = __cpu_to_le32(CLKDIVADDR);
+		uart_config.clkdiv.value = __cpu_to_le32(0x00c00000);
+		uart_config.uartdiv.address = __cpu_to_le32(UARTDIVADDR);
+		uart_config.uartdiv.value = __cpu_to_le32(1);
+		uart_config.mcr.address = __cpu_to_le32(UARTMCRADDR);
+		uart_config.mcr.value = __cpu_to_le32(MCR);
+		uart_config.re_init.address = __cpu_to_le32(UARTREINITADDR);
+		uart_config.re_init.value = __cpu_to_le32(INIT);
+		uart_config.icr.address = __cpu_to_le32(UARTICRADDR);
+		uart_config.icr.value = __cpu_to_le32(ICR);
+		uart_config.fcr.address = __cpu_to_le32(UARTFCRADDR);
+		uart_config.fcr.value = __cpu_to_le32(FCR);
+		uart_config.crc = swab32(nxp_fw_dnld_update_crc(0UL,
+									(char *)&uart_config,
+									sizeof(uart_config) - 4));
+		serdev_device_write_buf(nxpdev->serdev, (u8 *)&uart_config, req_len);
+		serdev_device_wait_until_sent(nxpdev->serdev, 0);
+		nxpdev->fw_v3_offset_correction += req_len;
+		return true;
+	}
+	return false;
+}
+
+static bool nxp_fw_change_timeout(struct hci_dev *hdev, u16 req_len)
+{
+	struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
+	struct nxp_bootloader_cmd nxp_cmd7;
+
+	if (req_len != sizeof(nxp_cmd7))
+		return false;
+
+	nxp_cmd7.header = __cpu_to_le32(7);
+	nxp_cmd7.arg = __cpu_to_le32(0x70);
+	nxp_cmd7.payload_len = 0;
+	nxp_cmd7.crc = swab32(nxp_fw_dnld_update_crc(0UL,
+								(char *)&nxp_cmd7,
+								sizeof(nxp_cmd7) - 4));
+
+	serdev_device_write_buf(nxpdev->serdev, (u8 *)&nxp_cmd7, req_len);
+	serdev_device_wait_until_sent(nxpdev->serdev, 0);
+	nxpdev->fw_v3_offset_correction += req_len;
+	return true;
+}
+
+static u32 nxp_get_data_len(const u8 *buf)
+{
+	struct nxp_bootloader_cmd *hdr = (struct nxp_bootloader_cmd *)buf;
+
+	return __le32_to_cpu(hdr->payload_len);
+}
+
+/* for legacy chipsets with V1 bootloader */
+static int nxp_recv_fw_req_v1(struct hci_dev *hdev, struct sk_buff *skb)
+{
+	struct v1_data_req *req = skb_pull_data(skb, sizeof(struct v1_data_req));
+	struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
+	struct btnxpuart_data *nxp_data = nxpdev->nxp_data;
+	static bool timeout_changed;
+	static bool baudrate_changed;
+	u32 requested_len;
+	static u32 expected_len = HDR_LEN;
+
+	if (!test_bit(BTNXPUART_FW_DOWNLOADING, &nxpdev->tx_state))
+		goto ret;
+
+	if (!nxpdev->fw)
+		goto ret;
+
+	if (req && (req->len ^ req->len_comp) != 0xffff) {
+		bt_dev_info(hdev, "ERR: Send NAK");
+		nxp_send_ack(NXP_NAK_V1, hdev);
+		goto ret;
+	}
+	nxp_send_ack(NXP_ACK_V1, hdev);
+
+	if (nxp_data->fw_dnld_sec_baudrate != nxpdev->current_baudrate) {
+		if (!timeout_changed) {
+			timeout_changed = nxp_fw_change_timeout(hdev, req->len);
+			goto ret;
+		}
+		if (!baudrate_changed) {
+			baudrate_changed = nxp_fw_change_baudrate(hdev, req->len);
+			if (baudrate_changed) {
+				serdev_device_set_baudrate(nxpdev->serdev,
+								nxp_data->fw_dnld_sec_baudrate);
+				serdev_device_set_flow_control(nxpdev->serdev, 1);
+				nxpdev->current_baudrate = nxp_data->fw_dnld_sec_baudrate;
+			}
+			goto ret;
+		}
+	}
+
+	requested_len = req->len;
+	if (requested_len == 0) {
+		bt_dev_info(hdev, "FW Downloaded Successfully: %zu bytes", nxpdev->fw->size);
+		clear_bit(BTNXPUART_FW_DOWNLOADING, &nxpdev->tx_state);
+		wake_up_interruptible(&nxpdev->suspend_wait_q);
+		goto ret;
+	}
+	if (requested_len & 0x01) {
+		/* The CRC did not match at the other end.
+		 * Simply send the same bytes again.
+		 */
+		requested_len = nxpdev->fw_v1_sent_bytes;
+		bt_dev_err(hdev, "CRC error. Resend %d bytes of FW.", requested_len);
+	} else {
+		nxpdev->fw_dnld_v1_offset += nxpdev->fw_v1_sent_bytes;
+
+		/* The FW bin file is made up of many blocks of
+		 * 16 byte header and payload data chunks. If the
+		 * FW has requested a header, read the payload length
+		 * info from the header, before sending the header.
+		 * In the next iteration, the FW should request the
+		 * payload data chunk, which should be equal to the
+		 * payload length read from header. If there is a
+		 * mismatch, clearly the driver and FW are out of sync,
+		 * and we need to re-send the previous header again.
+		 */
+		if (requested_len == expected_len) {
+			if (requested_len == HDR_LEN)
+				expected_len = nxp_get_data_len(nxpdev->fw->data +
+									nxpdev->fw_dnld_v1_offset);
+			else
+				expected_len = HDR_LEN;
+		} else {
+			if (requested_len == HDR_LEN) {
+				/* FW download out of sync. Send previous chunk again */
+				nxpdev->fw_dnld_v1_offset -= nxpdev->fw_v1_sent_bytes;
+				expected_len = HDR_LEN;
+			}
+		}
+	}
+
+	if (nxpdev->fw_dnld_v1_offset + requested_len <= nxpdev->fw->size)
+		serdev_device_write_buf(nxpdev->serdev,
+				nxpdev->fw->data + nxpdev->fw_dnld_v1_offset,
+				requested_len);
+	nxpdev->fw_v1_sent_bytes = requested_len;
+
+ret:
+	kfree_skb(skb);
+	return 0;
+}
+
+static int nxp_recv_chip_ver_v3(struct hci_dev *hdev, struct sk_buff *skb)
+{
+	struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
+
+	if (test_bit(BTNXPUART_FW_DOWNLOADING, &nxpdev->tx_state))
+		nxp_send_ack(NXP_ACK_V3, hdev);
+	kfree_skb(skb);
+	return 0;
+}
+
+static int nxp_recv_fw_req_v3(struct hci_dev *hdev, struct sk_buff *skb)
+{
+	struct v3_data_req *req = skb_pull_data(skb, sizeof(struct v3_data_req));
+	struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
+	struct btnxpuart_data *nxp_data = nxpdev->nxp_data;
+	static bool timeout_changed;
+	static bool baudrate_changed;
+
+	if (!req || !nxpdev || !nxpdev->fw->data)
+		goto ret;
+
+	if (!test_bit(BTNXPUART_FW_DOWNLOADING, &nxpdev->tx_state))
+		goto ret;
+
+	nxp_send_ack(NXP_ACK_V3, hdev);
+
+	if (nxpdev->current_baudrate != nxp_data->fw_dnld_sec_baudrate) {
+		if (!timeout_changed) {
+			timeout_changed = nxp_fw_change_timeout(hdev, req->len);
+			goto ret;
+		}
+
+		if (!baudrate_changed) {
+			baudrate_changed = nxp_fw_change_baudrate(hdev, req->len);
+			if (baudrate_changed) {
+				serdev_device_set_baudrate(nxpdev->serdev,
+								nxp_data->fw_dnld_sec_baudrate);
+				serdev_device_set_flow_control(nxpdev->serdev, 1);
+				nxpdev->current_baudrate = nxp_data->fw_dnld_sec_baudrate;
+			}
+			goto ret;
+		}
+	}
+
+	if (req->len == 0) {
+		bt_dev_info(hdev, "FW Downloaded Successfully: %zu bytes", nxpdev->fw->size);
+		clear_bit(BTNXPUART_FW_DOWNLOADING, &nxpdev->tx_state);
+		wake_up_interruptible(&nxpdev->suspend_wait_q);
+		goto ret;
+	}
+	if (req->error)
+		bt_dev_err(hdev, "FW Download received err 0x%02x from chip. Resending FW chunk.",
+			   req->error);
+
+	if (req->offset < nxpdev->fw_v3_offset_correction) {
+		/* This scenario should ideally never occur.
+		 * But if it ever does, FW is out of sync and
+		 * needs a power cycle.
+		 */
+		bt_dev_err(hdev, "Something went wrong during FW download. Please power cycle and try again");
+		goto ret;
+	}
+
+	serdev_device_write_buf(nxpdev->serdev,
+				nxpdev->fw->data + req->offset - nxpdev->fw_v3_offset_correction,
+				req->len);
+
+ret:
+	kfree_skb(skb);
+	return 0;
+}
+
+static int nxp_set_baudrate_cmd(struct hci_dev *hdev, void *data)
+{
+	struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
+	u32 new_baudrate = __cpu_to_le32(nxpdev->new_baudrate);
+	struct ps_data *psdata = nxpdev->psdata;
+	u8 *pcmd = (u8 *)&new_baudrate;
+	struct sk_buff *skb;
+	u8 *status;
+
+	if (!psdata)
+		return 0;
+
+	skb = nxp_drv_send_cmd(hdev, HCI_NXP_SET_OPER_SPEED, 4, pcmd);
+	if (IS_ERR(skb)) {
+		bt_dev_err(hdev, "Setting baudrate failed (%ld)", PTR_ERR(skb));
+		return PTR_ERR(skb);
+	}
+
+	status = skb_pull_data(skb, 1);
+	if (status) {
+		if (*status == 0) {
+			serdev_device_set_baudrate(nxpdev->serdev, nxpdev->new_baudrate);
+			nxpdev->current_baudrate = nxpdev->new_baudrate;
+		}
+		bt_dev_info(hdev, "Set baudrate response: status=%d, baudrate=%d",
+					*status, nxpdev->new_baudrate);
+	}
+	kfree_skb(skb);
+
+	return 0;
+}
+
+/* NXP protocol */
+static void nxp_update_device_data(struct hci_dev *hdev,
+								   char *label, char *value)
+{
+	struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
+	struct btnxpuart_data *nxp_data = nxpdev->nxp_data;
+	int ret = 0;
+	u32 val;
+
+	if (!strncmp(label, FW_NAME_TAG, MAX_TAG_STR_LEN)) {
+		snprintf(nxpdev->fw_name, MAX_FW_FILE_NAME_LEN, "%s",
+				 value);
+		return;
+	}
+
+	ret = sscanf(value, "%u", &val);
+	if (ret != 1) {
+		bt_dev_err(hdev, "Error parsing value for %s", label);
+		return;
+	}
+
+	if (!strncmp(label, OPER_SPEED_TAG, MAX_TAG_STR_LEN))
+		nxp_data->oper_speed = val;
+	else if (!strncmp(label, FW_DL_PRI_BAUDRATE_TAG, MAX_TAG_STR_LEN))
+		nxp_data->fw_dnld_pri_baudrate = val;
+	else if (!strncmp(label, FW_DL_SEC_BAUDRATE_TAG, MAX_TAG_STR_LEN))
+		nxp_data->fw_dnld_sec_baudrate = val;
+	else if (!strncmp(label, FW_INIT_BAUDRATE, MAX_TAG_STR_LEN))
+		nxp_data->fw_init_baudrate = val;
+	else if (!strncmp(label, PS_INTERVAL_MS, MAX_TAG_STR_LEN))
+		nxp_data->ps_interval_ms = val;
+}
+
+static void nxp_parse_conf_file(struct hci_dev *hdev)
+{
+	struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
+	char *dptr, *label, *value;
+	bool valid_param = false;
+	bool skipline = false;
+	int param_index = 0;
+	const char *sptr;
+	int line_num = 1;
+	char line[100];
+	int ret = 0;
+	int i, j;
+
+	ret = request_firmware(&nxpdev->fw_config, BT_FW_CONF_FILE, &hdev->dev);
+	if (ret < 0) {
+		bt_dev_info(hdev, "No NXP config file, using default settings");
+		return;
+	}
+
+	sptr = nxpdev->fw_config->data;
+	j = 0;
+	for (i = 0; i < nxpdev->fw_config->size; i++) {
+		/* if current line is a comment, ignore */
+		if (sptr[i] == '#') {
+			skipline = true;
+			continue;
+		}
+		/* keep ignoring the entire comment line */
+		if (sptr[i] != '\n' && skipline)
+			continue;
+		/* ignore space, <CR> and comma */
+		if (sptr[i] == ' ' || sptr[i] == '\r' || sptr[i] == ',')
+			continue;
+		/* handle '}' */
+		if (sptr[i] == '}') {
+			if (!valid_param) {
+				bt_dev_err(hdev, "Unexpected '}' on line %d", line_num);
+				goto ret;
+			}
+			valid_param = false;
+			param_index++;
+			continue;
+		}
+		/* handle new-line character */
+		if (sptr[i] == '\n') {
+			line_num++;
+			if (skipline) {
+				skipline = false;
+				continue;
+			}
+			line[j] = '\0';
+			/* ignore empty lines */
+			if (strlen(line) == 0)
+				continue;
+
+			dptr = line;
+			label = strsep(&dptr, "=");
+			value = strsep(&dptr, "=");
+			if (label && value) {
+				/* handle '{' */
+				if (!strncmp(value, "{", MAX_TAG_STR_LEN) &&
+					!strncmp(label, USER_CONFIG_TAG, MAX_TAG_STR_LEN)) {
+					valid_param = true;
+				} else if (valid_param) {
+					nxp_update_device_data(hdev, label, value);
+				}
+			} else {
+				bt_dev_err(hdev, "Invalid \"key\" = \"value\" pair at line: %d",
+					   line_num - 1);
+				goto ret;
+			}
+			j = 0;
+		} else {
+			line[j] = sptr[i];
+			j++;
+			if (j >= 100) {
+				bt_dev_err(hdev, "Line too long: %d", line_num);
+				goto ret;
+			}
+		}
+	}
+
+ret:
+	release_firmware(nxpdev->fw_config);
+}
+
+static int nxp_setup(struct hci_dev *hdev)
+{
+	struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
+	struct btnxpuart_data *nxp_data = nxpdev->nxp_data;
+	int err = 0;
+
+	if (!nxpdev)
+		return 0;
+
+	set_bit(BTNXPUART_FW_DOWNLOADING, &nxpdev->tx_state);
+
+	nxp_parse_conf_file(hdev);
+	init_waitqueue_head(&nxpdev->suspend_wait_q);
+
+	if (!serdev_device_get_cts(nxpdev->serdev)) {
+		bt_dev_info(hdev, "CTS high. Need FW Download");
+		err = nxp_download_firmware(hdev);
+		if (err < 0)
+			return err;
+	} else {
+		bt_dev_info(hdev, "CTS low. FW already running.");
+		clear_bit(BTNXPUART_FW_DOWNLOADING, &nxpdev->tx_state);
+	}
+
+	serdev_device_set_flow_control(nxpdev->serdev, 1);
+	serdev_device_set_baudrate(nxpdev->serdev, nxp_data->fw_init_baudrate);
+	nxpdev->current_baudrate = nxp_data->fw_init_baudrate;
+
+	if (nxpdev->current_baudrate != nxp_data->oper_speed) {
+		nxpdev->new_baudrate = nxp_data->oper_speed;
+		hci_cmd_sync_queue(hdev, nxp_set_baudrate_cmd, NULL, NULL);
+	}
+
+	if (!ps_init_work(hdev))
+		ps_init_timer(hdev);
+	ps_init(hdev);
+
+	return 0;
+}
+
+static int nxp_enqueue(struct hci_dev *hdev, struct sk_buff *skb)
+{
+	struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
+	struct ps_data *psdata = nxpdev->psdata;
+	struct hci_command_hdr *hdr;
+	u8 *param;
+
+	if (!nxpdev || !psdata) {
+		kfree_skb(skb);
+		goto ret;
+	}
+
+	/* if vendor commands are received from user space (e.g. hcitool), update
+	 * driver flags accordingly and ask driver to re-send the command to FW.
+	 */
+	if (bt_cb(skb)->pkt_type == HCI_COMMAND_PKT && !psdata->driver_sent_cmd) {
+		hdr = (struct hci_command_hdr *)skb->data;
+		param = skb->data + HCI_COMMAND_HDR_SIZE;
+		switch (__le16_to_cpu(hdr->opcode)) {
+		case HCI_NXP_AUTO_SLEEP_MODE:
+			if (hdr->plen >= 1) {
+				if (param[0] == BT_PS_ENABLE)
+					psdata->ps_mode = PS_MODE_ENABLE;
+				else if (param[0] == BT_PS_DISABLE)
+					psdata->ps_mode = PS_MODE_DISABLE;
+				hci_cmd_sync_queue(hdev, send_ps_cmd, NULL, NULL);
+				kfree_skb(skb);
+				goto ret;
+			}
+			break;
+		case HCI_NXP_WAKEUP_METHOD:
+			if (hdr->plen >= 4) {
+				switch (param[2]) {
+				case BT_CTRL_WAKEUP_METHOD_DSR:
+					psdata->wakeupmode = WAKEUP_METHOD_DTR;
+					break;
+				case BT_CTRL_WAKEUP_METHOD_BREAK:
+				default:
+					psdata->wakeupmode = WAKEUP_METHOD_BREAK;
+					break;
+				}
+				hci_cmd_sync_queue(hdev, send_wakeup_method_cmd, NULL, NULL);
+				kfree_skb(skb);
+				goto ret;
+			}
+			break;
+		case HCI_NXP_SET_OPER_SPEED:
+			if (hdr->plen == 4) {
+				nxpdev->new_baudrate = *((u32 *)param);
+				hci_cmd_sync_queue(hdev, nxp_set_baudrate_cmd, NULL, NULL);
+				kfree_skb(skb);
+				goto ret;
+			}
+		}
+	}
+
+	/* Prepend skb with frame type */
+	memcpy(skb_push(skb, 1), &hci_skb_pkt_type(skb), 1);
+	skb_queue_tail(&nxpdev->txq, skb);
+
+	btnxpuart_tx_wakeup(nxpdev);
+ret:
+	return 0;
+}
+
+static struct sk_buff *nxp_dequeue(void *data)
+{
+	struct btnxpuart_dev *nxpdev = (struct btnxpuart_dev *)data;
+
+	ps_wakeup(nxpdev);
+	ps_start_timer(nxpdev);
+	return skb_dequeue(&nxpdev->txq);
+}
+
+/* btnxpuart based on serdev */
+static void btnxpuart_tx_work(struct work_struct *work)
+{
+	struct btnxpuart_dev *nxpdev = container_of(work, struct btnxpuart_dev,
+						   tx_work);
+	struct serdev_device *serdev = nxpdev->serdev;
+	struct hci_dev *hdev = nxpdev->hdev;
+	struct sk_buff *skb;
+	int len;
+
+	while ((skb = nxp_dequeue(nxpdev))) {
+		len = serdev_device_write_buf(serdev, skb->data, skb->len);
+		hdev->stat.byte_tx += len;
+
+		skb_pull(skb, len);
+		if (skb->len > 0) {
+			skb_queue_head(&nxpdev->txq, skb);
+			break;
+		}
+
+		switch (hci_skb_pkt_type(skb)) {
+		case HCI_COMMAND_PKT:
+			hdev->stat.cmd_tx++;
+			break;
+		case HCI_ACLDATA_PKT:
+			hdev->stat.acl_tx++;
+			break;
+		case HCI_SCODATA_PKT:
+			hdev->stat.sco_tx++;
+			break;
+		}
+
+		kfree_skb(skb);
+	}
+	clear_bit(BTNXPUART_TX_STATE_ACTIVE, &nxpdev->tx_state);
+}
+
+static int btnxpuart_open(struct hci_dev *hdev)
+{
+	struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
+	int err = 0;
+
+	err = serdev_device_open(nxpdev->serdev);
+	if (err) {
+		bt_dev_err(hdev, "Unable to open UART device %s",
+			   dev_name(&nxpdev->serdev->dev));
+	}
+
+	return err;
+}
+
+static int btnxpuart_close(struct hci_dev *hdev)
+{
+	struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
+
+	if (!nxpdev)
+		return 0;
+
+	serdev_device_close(nxpdev->serdev);
+
+	return 0;
+}
+
+static int btnxpuart_flush(struct hci_dev *hdev)
+{
+	struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
+
+	if (!nxpdev)
+		return 0;
+
+	/* Flush any pending characters */
+	serdev_device_write_flush(nxpdev->serdev);
+	skb_queue_purge(&nxpdev->txq);
+
+	cancel_work_sync(&nxpdev->tx_work);
+
+	kfree_skb(nxpdev->rx_skb);
+	nxpdev->rx_skb = NULL;
+
+	return 0;
+}
+
+static const struct h4_recv_pkt nxp_recv_pkts[] = {
+	{ H4_RECV_ACL,          .recv = hci_recv_frame },
+	{ H4_RECV_SCO,          .recv = hci_recv_frame },
+	{ H4_RECV_EVENT,        .recv = hci_recv_frame },
+	{ NXP_RECV_FW_REQ_V1,   .recv = nxp_recv_fw_req_v1 },
+	{ NXP_RECV_CHIP_VER_V3, .recv = nxp_recv_chip_ver_v3 },
+	{ NXP_RECV_FW_REQ_V3,   .recv = nxp_recv_fw_req_v3 },
+};
+
+static int btnxpuart_receive_buf(struct serdev_device *serdev, const u8 *data,
+								 size_t count)
+{
+	struct btnxpuart_dev *nxpdev = serdev_device_get_drvdata(serdev);
+
+	if (test_bit(BTNXPUART_FW_DOWNLOADING, &nxpdev->tx_state)) {
+		if (*data != NXP_V1_FW_REQ_PKT && *data != NXP_V1_CHIP_VER_PKT &&
+			*data != NXP_V3_FW_REQ_PKT && *data != NXP_V3_CHIP_VER_PKT) {
+			/* Unknown bootloader signature, skip without returning error */
+			return count;
+		}
+	}
+
+	ps_start_timer(nxpdev);
+
+	nxpdev->rx_skb = h4_recv_buf(nxpdev->hdev, nxpdev->rx_skb, data, count,
+						nxp_recv_pkts, ARRAY_SIZE(nxp_recv_pkts));
+	if (IS_ERR(nxpdev->rx_skb)) {
+		int err = PTR_ERR(nxpdev->rx_skb);
+
+		bt_dev_err(nxpdev->hdev, "Frame reassembly failed (%d)", err);
+		nxpdev->rx_skb = NULL;
+		return err;
+	}
+	nxpdev->hdev->stat.byte_rx += count;
+	return count;
+}
+
+static void btnxpuart_write_wakeup(struct serdev_device *serdev)
+{
+	serdev_device_write_wakeup(serdev);
+}
+
+static const struct serdev_device_ops btnxpuart_client_ops = {
+	.receive_buf = btnxpuart_receive_buf,
+	.write_wakeup = btnxpuart_write_wakeup,
+};
+
+static int nxp_serdev_probe(struct serdev_device *serdev)
+{
+	struct hci_dev *hdev;
+	struct btnxpuart_dev *nxpdev;
+
+	nxpdev = devm_kzalloc(&serdev->dev, sizeof(*nxpdev), GFP_KERNEL);
+	if (!nxpdev)
+		return -ENOMEM;
+
+	nxpdev->nxp_data = (struct btnxpuart_data *)device_get_match_data(&serdev->dev);
+
+	nxpdev->serdev = serdev;
+	serdev_device_set_drvdata(serdev, nxpdev);
+
+	serdev_device_set_client_ops(serdev, &btnxpuart_client_ops);
+
+	INIT_WORK(&nxpdev->tx_work, btnxpuart_tx_work);
+	skb_queue_head_init(&nxpdev->txq);
+
+	/* Initialize and register HCI device */
+	hdev = hci_alloc_dev();
+	if (!hdev) {
+		dev_err(&serdev->dev, "Can't allocate HCI device\n");
+		return -ENOMEM;
+	}
+
+	nxpdev->hdev = hdev;
+
+	hdev->bus = HCI_UART;
+	hci_set_drvdata(hdev, nxpdev);
+
+	hdev->manufacturer = 37;
+	hdev->open  = btnxpuart_open;
+	hdev->close = btnxpuart_close;
+	hdev->flush = btnxpuart_flush;
+	hdev->setup = nxp_setup;
+	hdev->send  = nxp_enqueue;
+	SET_HCIDEV_DEV(hdev, &serdev->dev);
+
+	if (hci_register_dev(hdev) < 0) {
+		dev_err(&serdev->dev, "Can't register HCI device\n");
+		hci_free_dev(hdev);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static void nxp_serdev_remove(struct serdev_device *serdev)
+{
+	struct btnxpuart_dev *nxpdev = serdev_device_get_drvdata(serdev);
+	struct btnxpuart_data *nxp_data = nxpdev->nxp_data;
+	struct hci_dev *hdev = nxpdev->hdev;
+
+	/* Restore FW baudrate to fw_init_baudrate if changed.
+	 * This will ensure FW baudrate is in sync with
+	 * driver baudrate in case this driver is re-inserted.
+	 */
+	if (nxp_data->fw_init_baudrate != nxpdev->current_baudrate) {
+		nxpdev->new_baudrate = nxp_data->fw_init_baudrate;
+		nxp_set_baudrate_cmd(hdev, NULL);
+	}
+
+	ps_cancel_timer(nxpdev);
+	hci_unregister_dev(hdev);
+	hci_free_dev(hdev);
+}
+
+/* Following default values are as per Murata M.2 modules
+ * For modules from different vendor, if any of the device
+ * parameters are different, they can be over-written by
+ * config file /lib/firmware/nxp/bt_mod_para.conf
+ */
+static struct btnxpuart_data w8987_data = {
+	.fw_dnld_pri_baudrate = 115200,
+	.fw_dnld_sec_baudrate = 3000000,
+	.fw_init_baudrate = 115200,
+	.oper_speed		= 3000000,
+	.ps_interval_ms = PS_DEFAULT_TIMEOUT_PERIOD,
+	.fw_name = FIRMWARE_W8987,
+};
+
+static struct btnxpuart_data w8997_data = {
+	.fw_dnld_pri_baudrate = 115200,
+	.fw_dnld_sec_baudrate = 115200,
+	.fw_init_baudrate = 115200,
+	.oper_speed		= 3000000,
+	.ps_interval_ms = PS_DEFAULT_TIMEOUT_PERIOD,
+	.fw_name = FIRMWARE_W8997,
+};
+
+static struct btnxpuart_data w9098_data = {
+	.fw_dnld_pri_baudrate = 115200,
+	.fw_dnld_sec_baudrate = 3000000,
+	.fw_init_baudrate = 115200,
+	.oper_speed		= 3000000,
+	.ps_interval_ms = PS_DEFAULT_TIMEOUT_PERIOD,
+	.fw_name = FIRMWARE_W9098,
+};
+
+static struct btnxpuart_data iw416_data = {
+	.fw_dnld_pri_baudrate = 115200,
+	.fw_dnld_sec_baudrate = 3000000,
+	.fw_init_baudrate = 115200,
+	.oper_speed		= 3000000,
+	.ps_interval_ms = PS_DEFAULT_TIMEOUT_PERIOD,
+	.fw_name = FIRMWARE_IW416,
+};
+
+static struct btnxpuart_data iw612_data = {
+	.fw_dnld_pri_baudrate = 115200,
+	.fw_dnld_sec_baudrate = 3000000,
+	.fw_init_baudrate = 115200,
+	.oper_speed		= 3000000,
+	.ps_interval_ms = PS_DEFAULT_TIMEOUT_PERIOD,
+	.fw_name = FIRMWARE_IW612,
+};
+
+static const struct of_device_id nxpuart_of_match_table[] = {
+	{ .compatible = "nxp,88w8987-bt", .data = &w8987_data },
+	{ .compatible = "nxp,88w8997-bt", .data = &w8997_data },
+	{ .compatible = "nxp,88w9098-bt", .data = &w9098_data },
+	{ .compatible = "nxp,iw416-bt", .data = &iw416_data },
+	{ .compatible = "nxp,iw612-bt", .data = &iw612_data },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, nxpuart_of_match_table);
+
+static struct serdev_device_driver nxp_serdev_driver = {
+	.probe = nxp_serdev_probe,
+	.remove = nxp_serdev_remove,
+	.driver = {
+		.name = "btnxpuart",
+		.of_match_table = of_match_ptr(nxpuart_of_match_table),
+	},
+};
+
+module_serdev_device_driver(nxp_serdev_driver);
+
+MODULE_AUTHOR("Neeraj Sanjay Kale <neeraj.sanjaykale@nxp.com>");
+MODULE_DESCRIPTION("NXP Bluetooth Serial driver v1.0 ");
+MODULE_LICENSE("GPL");
-- 
2.34.1


^ permalink raw reply related

* [PATCH v3 2/3] dt-bindings: net: bluetooth: Add NXP bluetooth support
From: Neeraj Sanjay Kale @ 2023-02-13 14:54 UTC (permalink / raw)
  To: davem, edumazet, kuba, pabeni, robh+dt, krzysztof.kozlowski+dt,
	marcel, johan.hedberg, luiz.dentz, gregkh, jirislaby,
	alok.a.tiwari, hdanton, ilpo.jarvinen, leon
  Cc: netdev, devicetree, linux-kernel, linux-bluetooth, linux-serial,
	amitkumar.karwar, rohit.fule, sherry.sun, neeraj.sanjaykale
In-Reply-To: <20230213145432.1192911-1-neeraj.sanjaykale@nxp.com>

Add binding document for NXP bluetooth chipsets attached
over UART.

Signed-off-by: Neeraj Sanjay Kale <neeraj.sanjaykale@nxp.com>
---
v2: Resolved dt_binding_check errors. (Rob Herring)
v2: Modified description, added specific compatibility devices, corrected indentations. (Krzysztof Kozlowski)
v3: Modified description, renamed file (Krzysztof Kozlowski)
---
 .../bindings/net/bluetooth/nxp,w8xxx-bt.yaml  | 44 +++++++++++++++++++
 MAINTAINERS                                   |  7 +++
 2 files changed, 51 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/net/bluetooth/nxp,w8xxx-bt.yaml

diff --git a/Documentation/devicetree/bindings/net/bluetooth/nxp,w8xxx-bt.yaml b/Documentation/devicetree/bindings/net/bluetooth/nxp,w8xxx-bt.yaml
new file mode 100644
index 000000000000..2685f6d5904f
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/bluetooth/nxp,w8xxx-bt.yaml
@@ -0,0 +1,44 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/bluetooth/nxp-bluetooth.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NXP Bluetooth chips
+
+description:
+  This binding describes UART-attached NXP bluetooth chips.
+  These chips are dual-radio chips supporting WiFi and Bluetooth,
+  except for iw612, which is a tri-radio chip supporting 15.4
+  as well.
+  The bluetooth works on standard H4 protocol over 4-wire UART.
+  The RTS and CTS lines are used during FW download.
+  To enable power save mode, the host asserts break signal
+  over UART-TX line to put the chip into power save state.
+  De-asserting break wakes-up the BT chip.
+
+maintainers:
+  - Neeraj Sanjay Kale <neeraj.sanjaykale@nxp.com>
+
+properties:
+  compatible:
+    enum:
+      - nxp,88w8987-bt
+      - nxp,88w8997-bt
+      - nxp,88w9098-bt
+      - nxp,iw416-bt
+      - nxp,iw612-bt
+
+required:
+  - compatible
+
+additionalProperties: false
+
+examples:
+  - |
+    uart2 {
+        uart-has-rtscts;
+        bluetooth {
+          compatible = "nxp,iw416-bt";
+        };
+    };
diff --git a/MAINTAINERS b/MAINTAINERS
index 32dd41574930..211fc667c0ec 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -22835,6 +22835,13 @@ L:	linux-mm@kvack.org
 S:	Maintained
 F:	mm/zswap.c
 
+NXP BLUETOOTH WIRELESS DRIVERS
+M:	Amitkumar Karwar <amitkumar.karwar@nxp.com>
+M:	Neeraj Kale <neeraj.sanjaykale@nxp.com>
+S:	Maintained
+F:	Documentation/devicetree/bindings/net/bluetooth/nxp-bluetooth.yaml
+F:	drivers/bluetooth/btnxpuart*
+
 THE REST
 M:	Linus Torvalds <torvalds@linux-foundation.org>
 L:	linux-kernel@vger.kernel.org
-- 
2.34.1


^ permalink raw reply related

* [PATCH v3 1/3] serdev: Add method to assert break signal over tty UART port
From: Neeraj Sanjay Kale @ 2023-02-13 14:54 UTC (permalink / raw)
  To: davem, edumazet, kuba, pabeni, robh+dt, krzysztof.kozlowski+dt,
	marcel, johan.hedberg, luiz.dentz, gregkh, jirislaby,
	alok.a.tiwari, hdanton, ilpo.jarvinen, leon
  Cc: netdev, devicetree, linux-kernel, linux-bluetooth, linux-serial,
	amitkumar.karwar, rohit.fule, sherry.sun, neeraj.sanjaykale
In-Reply-To: <20230213145432.1192911-1-neeraj.sanjaykale@nxp.com>

Adds serdev_device_break_ctl() and an implementation for ttyport.
This function simply calls the break_ctl in tty layer, which can
assert a break signal over UART-TX line, if the tty and the
underlying platform and UART peripheral supports this operation.

Signed-off-by: Neeraj Sanjay Kale <neeraj.sanjaykale@nxp.com>
---
v3: Add details to the commit message (Greg KH)
---
 drivers/tty/serdev/core.c           | 11 +++++++++++
 drivers/tty/serdev/serdev-ttyport.c | 12 ++++++++++++
 include/linux/serdev.h              |  6 ++++++
 3 files changed, 29 insertions(+)

diff --git a/drivers/tty/serdev/core.c b/drivers/tty/serdev/core.c
index 0180e1e4e75d..f2fdd6264e5d 100644
--- a/drivers/tty/serdev/core.c
+++ b/drivers/tty/serdev/core.c
@@ -405,6 +405,17 @@ int serdev_device_set_tiocm(struct serdev_device *serdev, int set, int clear)
 }
 EXPORT_SYMBOL_GPL(serdev_device_set_tiocm);
 
+int serdev_device_break_ctl(struct serdev_device *serdev, int break_state)
+{
+	struct serdev_controller *ctrl = serdev->ctrl;
+
+	if (!ctrl || !ctrl->ops->break_ctl)
+		return -EOPNOTSUPP;
+
+	return ctrl->ops->break_ctl(ctrl, break_state);
+}
+EXPORT_SYMBOL_GPL(serdev_device_break_ctl);
+
 static int serdev_drv_probe(struct device *dev)
 {
 	const struct serdev_device_driver *sdrv = to_serdev_device_driver(dev->driver);
diff --git a/drivers/tty/serdev/serdev-ttyport.c b/drivers/tty/serdev/serdev-ttyport.c
index d367803e2044..9888673744af 100644
--- a/drivers/tty/serdev/serdev-ttyport.c
+++ b/drivers/tty/serdev/serdev-ttyport.c
@@ -247,6 +247,17 @@ static int ttyport_set_tiocm(struct serdev_controller *ctrl, unsigned int set, u
 	return tty->ops->tiocmset(tty, set, clear);
 }
 
+static int ttyport_break_ctl(struct serdev_controller *ctrl, unsigned int break_state)
+{
+	struct serport *serport = serdev_controller_get_drvdata(ctrl);
+	struct tty_struct *tty = serport->tty;
+
+	if (!tty->ops->break_ctl)
+		return -EOPNOTSUPP;
+
+	return tty->ops->break_ctl(tty, break_state);
+}
+
 static const struct serdev_controller_ops ctrl_ops = {
 	.write_buf = ttyport_write_buf,
 	.write_flush = ttyport_write_flush,
@@ -259,6 +270,7 @@ static const struct serdev_controller_ops ctrl_ops = {
 	.wait_until_sent = ttyport_wait_until_sent,
 	.get_tiocm = ttyport_get_tiocm,
 	.set_tiocm = ttyport_set_tiocm,
+	.break_ctl = ttyport_break_ctl,
 };
 
 struct device *serdev_tty_port_register(struct tty_port *port,
diff --git a/include/linux/serdev.h b/include/linux/serdev.h
index 66f624fc618c..c065ef1c82f1 100644
--- a/include/linux/serdev.h
+++ b/include/linux/serdev.h
@@ -92,6 +92,7 @@ struct serdev_controller_ops {
 	void (*wait_until_sent)(struct serdev_controller *, long);
 	int (*get_tiocm)(struct serdev_controller *);
 	int (*set_tiocm)(struct serdev_controller *, unsigned int, unsigned int);
+	int (*break_ctl)(struct serdev_controller *ctrl, unsigned int break_state);
 };
 
 /**
@@ -202,6 +203,7 @@ int serdev_device_write_buf(struct serdev_device *, const unsigned char *, size_
 void serdev_device_wait_until_sent(struct serdev_device *, long);
 int serdev_device_get_tiocm(struct serdev_device *);
 int serdev_device_set_tiocm(struct serdev_device *, int, int);
+int serdev_device_break_ctl(struct serdev_device *serdev, int break_state);
 void serdev_device_write_wakeup(struct serdev_device *);
 int serdev_device_write(struct serdev_device *, const unsigned char *, size_t, long);
 void serdev_device_write_flush(struct serdev_device *);
@@ -255,6 +257,10 @@ static inline int serdev_device_set_tiocm(struct serdev_device *serdev, int set,
 {
 	return -ENOTSUPP;
 }
+static inline int serdev_device_break_ctl(struct serdev_device *serdev, int break_state)
+{
+	return -EOPNOTSUPP;
+}
 static inline int serdev_device_write(struct serdev_device *sdev, const unsigned char *buf,
 				      size_t count, unsigned long timeout)
 {
-- 
2.34.1


^ permalink raw reply related

* [PATCH v3 0/3] Add support for NXP bluetooth chipsets
From: Neeraj Sanjay Kale @ 2023-02-13 14:54 UTC (permalink / raw)
  To: davem, edumazet, kuba, pabeni, robh+dt, krzysztof.kozlowski+dt,
	marcel, johan.hedberg, luiz.dentz, gregkh, jirislaby,
	alok.a.tiwari, hdanton, ilpo.jarvinen, leon
  Cc: netdev, devicetree, linux-kernel, linux-bluetooth, linux-serial,
	amitkumar.karwar, rohit.fule, sherry.sun, neeraj.sanjaykale

This patch adds a driver for NXP bluetooth chipsets.

The driver is based on H4 protocol, and uses serdev APIs. It supports
host to chip power save feature, which is signalled by the host by
asserting break over UART TX lines, to put the chip into sleep state.

To support this feature, break_ctl has also been added to serdev-tty
along with a new serdev API serdev_device_break_ctl().

This driver is capable of downloading firmware into the chip over UART.

The document specifying device tree bindings for this driver is also
included in this patch series.

Neeraj Sanjay Kale (3):
  serdev: Add method to assert break signal over tty UART port
  dt-bindings: net: bluetooth: Add NXP bluetooth support
  Bluetooth: NXP: Add protocol support for NXP Bluetooth chipsets

 .../bindings/net/bluetooth/nxp,w8xxx-bt.yaml  |   44 +
 MAINTAINERS                                   |    7 +
 drivers/bluetooth/Kconfig                     |   11 +
 drivers/bluetooth/Makefile                    |    1 +
 drivers/bluetooth/btnxpuart.c                 | 1370 +++++++++++++++++
 drivers/tty/serdev/core.c                     |   11 +
 drivers/tty/serdev/serdev-ttyport.c           |   12 +
 include/linux/serdev.h                        |    6 +
 8 files changed, 1462 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/net/bluetooth/nxp,w8xxx-bt.yaml
 create mode 100644 drivers/bluetooth/btnxpuart.c

-- 
2.34.1


^ permalink raw reply

* RE: [PATCH v3 3/3] serial: 8250_em: Add serial_out() to struct serial8250_em_hw_info
From: Biju Das @ 2023-02-13 14:26 UTC (permalink / raw)
  To: Niklas Söderlund
  Cc: Jiri Slaby, Ilpo Järvinen, Geert Uytterhoeven, Magnus Damm,
	Greg Kroah-Hartman, linux-serial, Fabrizio Castro,
	linux-renesas-soc@vger.kernel.org
In-Reply-To: <Y+pEpwa3vFEh58Zc@oden.dyn.berto.se>

Hi Niklas,

Thanks for the feedback.

> Subject: Re: [PATCH v3 3/3] serial: 8250_em: Add serial_out() to struct
> serial8250_em_hw_info
> 
> Hi Biju,
> 
> On 2023-02-13 13:01:06 +0000, Biju Das wrote:
> > Please get files from here
> >
> 
> Thanks for the branch.
> 
> It boots and the serial console appears to be functioning as expected.
> Is there anything in particular you like me to test? I attach the full boot
> log in case it's useful for you.

Cool. It should be OK. Looks like RZ/V2M changes applies to EMMA mobile as well.

If you have cables, you could test {ttyS0, ttyS2, ttyS2} at {9600, 19200, 38400, 57600, 115200} bps
If it supports flow control, check that as well.

Eg:
stty -F /dev/ttyS0 115200
stty -F /dev/ttyS0 115200 crtscts

Open a teraterm and do below read/write testing

cat /dev/ttyS0 --> for reading
echo test > /dev/ttyS0 --> for writing

or Write a serial test program for read/write test on above baud rates.

If the cable is not available, you could also verify register settings
To check whether it matches with EMMA hardware manual.


dump() {

devmem2 0xA4040000  | grep Read
devmem2 0xA4040004  | grep Read
devmem2 0xA4040008  | grep Read
devmem2 0xA404000C  | grep Read

devmem2 0xA4040010  | grep Read
devmem2 0xA4040014  | grep Read
devmem2 0xA4040018  | grep Read
devmem2 0xA404001C  | grep Read

devmem2 0xA4040020  | grep Read
devmem2 0xA4040024  | grep Read  # DLAB(LCR[7]) 0x1B
devmem2 0xA4040028  | grep Read  # DLAB(LCR[7]) 0x1B
devmem2 0xA404002C  | grep Read

devmem2 0xA4040030  | grep Read
devmem2 0xA4040034  | grep Read
}

dump

Cheers,
Biju




> 
> [    0.000000] Booting Linux on physical CPU 0x0
> [    0.000000] Linux version 6.2.0-rc7-next-20230210-12179-g91bd68019b4b
> (neg@sleipner) (arm-linux-gnueabihf-gcc (GCC) 10.2.0, GNU ld (GNU Binutils)
> 2.35.1) #2 SMP Mon Feb 13 15:02:12 CET 2023
> [    0.000000] CPU: ARMv7 Processor [411fc092] revision 2 (ARMv7),
> cr=10c5387d
> [    0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing
> instruction cache
> [    0.000000] OF: fdt: Machine model: EMEV2 KZM9D Board
> [    0.000000] printk: debug: ignoring loglevel setting.
> [    0.000000] Memory policy: Data cache writealloc
> [    0.000000] cma: Failed to reserve 128 MiB
> [    0.000000] Zone ranges:
> [    0.000000]   Normal   [mem 0x0000000040000000-0x0000000047ffffff]
> [    0.000000]   HighMem  empty
> [    0.000000] Movable zone start for each node
> [    0.000000] Early memory node ranges
> [    0.000000]   node   0: [mem 0x0000000040000000-0x0000000047ffffff]
> [    0.000000] Initmem setup node 0 [mem 0x0000000040000000-
> 0x0000000047ffffff]
> [    0.000000] percpu: Embedded 14 pages/cpu s33620 r0 d23724 u57344
> [    0.000000] pcpu-alloc: s33620 r0 d23724 u57344 alloc=14*4096
> [    0.000000] pcpu-alloc: [0] 0 [0] 1
> [    0.000000] Built 1 zonelists, mobility grouping on.  Total pages: 32512
> [    0.000000] Kernel command line: ignore_loglevel rw root=/dev/nfs ip=on
> [    0.000000] Dentry cache hash table entries: 16384 (order: 4, 65536
> bytes, linear)
> [    0.000000] Inode-cache hash table entries: 8192 (order: 3, 32768 bytes,
> linear)
> [    0.000000] mem auto-init: stack:off, heap alloc:off, heap free:off
> [    0.000000] Memory: 116068K/131072K available (8192K kernel code, 1150K
> rwdata, 2596K rodata, 1024K init, 251K bss, 15004K reserved, 0K cma-
> reserved, 0K highmem)
> [    0.000000] trace event string verifier disabled
> [    0.000000] rcu: Hierarchical RCU implementation.
> [    0.000000] rcu: 	RCU event tracing is enabled.
> [    0.000000] rcu: 	RCU restricting CPUs from NR_CPUS=8 to
> nr_cpu_ids=2.
> [    0.000000] rcu: RCU calculated value of scheduler-enlistment delay is 10
> jiffies.
> [    0.000000] rcu: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=2
> [    0.000000] NR_IRQS: 16, nr_irqs: 16, preallocated irqs: 16
> [    0.000000] GIC: enabling workaround for broken byte access
> [    0.000000] rcu: srcu_init: Setting srcu_struct sizes based on
> contention.
> [    0.000000] timer_probe: no matching timers found
> [    0.000000] Console: colour dummy device 80x30
> [    0.000000] printk: console [tty0] enabled
> [    0.000000] sched_clock: 32 bits at 100 Hz, resolution 10000000ns, wraps
> every 21474836475000000ns
> [    0.000000] Calibrating delay loop (skipped) preset value.. 1066.00
> BogoMIPS (lpj=5330000)
> [    0.000000] pid_max: default: 32768 minimum: 301
> [    0.000000] Mount-cache hash table entries: 1024 (order: 0, 4096 bytes,
> linear)
> [    0.000000] Mountpoint-cache hash table entries: 1024 (order: 0, 4096
> bytes, linear)
> [    0.000000] CPU: Testing write buffer coherency: ok
> [    0.000000] CPU0: Spectre v2: using BPIALL workaround
> [    0.000000] CPU0: thread -1, cpu 0, socket 0, mpidr 80000000
> [    0.000000] Setting up static identity map for 0x40100000 - 0x40100060
> [    0.000000] rcu: Hierarchical SRCU implementation.
> [    0.000000] rcu: 	Max phase no-delay instances is 1000.
> [    0.000000] smp: Bringing up secondary CPUs ...
> [    0.000000] CPU1: thread -1, cpu 1, socket 0, mpidr 80000001
> [    0.000000] CPU1: Spectre v2: using BPIALL workaround
> [    0.000000] smp: Brought up 1 node, 2 CPUs
> [    0.000000] SMP: Total of 2 processors activated (2132.00 BogoMIPS).
> [    0.000000] CPU: All CPU(s) started in SVC mode.
> [    0.000000] devtmpfs: initialized
> [    0.000000] VFP support v0.3: implementor 41 architecture 3 part 30
> variant 9 rev 1
> [    0.000000] clocksource: jiffies: mask: 0xffffffff max_cycles:
> 0xffffffff, max_idle_ns: 19112604462750000 ns
> [    0.000000] futex hash table entries: 512 (order: 3, 32768 bytes, linear)
> [    0.000000] pinctrl core: initialized pinctrl subsystem
> [    0.000000] NET: Registered PF_NETLINK/PF_ROUTE protocol family
> [    0.000000] DMA: preallocated 256 KiB pool for atomic coherent
> allocations
> [    0.000000] thermal_sys: Registered thermal governor 'step_wise'
> [    0.000000] No ATAGs?
> [    0.000000] hw-breakpoint: found 5 (+1 reserved) breakpoint and 1
> watchpoint registers.
> [    0.000000] hw-breakpoint: maximum watchpoint size is 4 bytes.
> [    0.000000] sh-pfc e0140200.pinctrl: emev2_pfc support registered
> [    0.000000] SCSI subsystem initialized
> [    0.000000] libata version 3.00 loaded.
> [    0.000000] usbcore: registered new interface driver usbfs
> [    0.000000] usbcore: registered new interface driver hub
> [    0.000000] usbcore: registered new device driver usb
> [    0.000000] mc: Linux media interface: v0.10
> [    0.000000] videodev: Linux video capture interface: v2.00
> [    0.000000] pps_core: LinuxPPS API ver. 1 registered
> [    0.000000] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo
> Giometti <giometti@linux.it>
> [    0.000000] PTP clock support registered
> [    0.000000] em_sti e0180000.timer: used for clock events
> [    0.000000] em_sti e0180000.timer: used for oneshot clock events
> [    0.000000] em_sti e0180000.timer: used as clock source
> [    0.000000] clocksource: e0180000.timer: mask: 0xffffffffffff max_cycles:
> 0x1ef4687b1, max_idle_ns: 112843571739654 ns
> [    0.000000] Advanced Linux Sound Architecture Driver Initialized.
> [    0.000000] vgaarb: loaded
> [    0.890000] clocksource: Switched to clocksource e0180000.timer
> [    0.900000] Clockevents: could not switch to one-shot mode:
> [    0.900000] Clockevents: could not switch to one-shot mode: dummy_timer
> is not functional.
> [    0.900000]  dummy_timer is not functional.
> [    0.910000] NET: Registered PF_INET protocol family
> [    0.910000] IP idents hash table entries: 2048 (order: 2, 16384 bytes,
> linear)
> [    0.910000] tcp_listen_portaddr_hash hash table entries: 512 (order: 0,
> 4096 bytes, linear)
> [    0.910000] Table-perturb hash table entries: 65536 (order: 6, 262144
> bytes, linear)
> [    0.910000] TCP established hash table entries: 1024 (order: 0, 4096
> bytes, linear)
> [    0.910000] TCP bind hash table entries: 1024 (order: 2, 16384 bytes,
> linear)
> [    0.910000] TCP: Hash tables configured (established 1024 bind 1024)
> [    0.910000] UDP hash table entries: 256 (order: 1, 8192 bytes, linear)
> [    0.910000] UDP-Lite hash table entries: 256 (order: 1, 8192 bytes,
> linear)
> [    0.910000] NET: Registered PF_UNIX/PF_LOCAL protocol family
> [    0.910000] RPC: Registered named UNIX socket transport module.
> [    0.910000] RPC: Registered udp transport module.
> [    0.910000] RPC: Registered tcp transport module.
> [    0.910000] RPC: Registered tcp NFSv4.1 backchannel transport module.
> [    0.910000] PCI: CLS 0 bytes, default 64
> [    0.950000] hw perfevents: enabled with armv7_cortex_a9 PMU driver, 7
> counters available
> [    0.950000] workingset: timestamp_bits=30 max_order=15 bucket_order=0
> [    0.950000] NFS: Registering the id_resolver key type
> [    0.950000] Key type id_resolver registered
> [    0.950000] Key type id_legacy registered
> [    0.950000] nfs4filelayout_init: NFSv4 File Layout Driver Registering...
> [    0.950000] nfs4flexfilelayout_init: NFSv4 Flexfile Layout Driver
> Registering...
> [    0.960000] Block layer SCSI generic (bsg) driver version 0.4 loaded
> (major 246)
> [    0.960000] io scheduler mq-deadline registered
> [    0.960000] io scheduler kyber registered
> [    0.960000] io scheduler bfq registered
> [    0.970000] Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
> [    0.970000] e1020000.serial: ttyS0 at MMIO 0xe1020000 (irq = 37,
> base_baud = 796444) is a TI16750
> [    0.970000] e1030000.serial: ttyS1 at MMIO 0xe1030000 (irq = 38,
> base_baud = 7168000) is a TI16750
> [    0.970000] printk: console [ttyS1] enabled
> [    1.660000] e1040000.serial: ttyS2 at MMIO 0xe1040000 (irq = 39,
> base_baud = 14336000) is a TI16750
> [    1.670000] e1050000.serial: ttyS3 at MMIO 0xe1050000 (irq = 40,
> base_baud = 2389333) is a TI16750
> [    1.680000] SuperH (H)SCI(F) driver initialized
> [    1.700000] CAN device driver interface
> [    1.760000] smsc911x 20000000.ethernet eth0: MAC Address:
> 00:0a:a3:02:12:92
> [    1.770000] UDC core: g_ether: couldn't find an available UDC
> [    1.770000] i2c_dev: i2c /dev entries driver
> [    1.780000] em-i2c e0070000.i2c: Added i2c controller 0, irq 42
> [    1.790000] em-i2c e10a0000.i2c: Added i2c controller 1, irq 43
> [    1.800000] cpu cpu0: OPP table can't be empty
> [    1.800000] usbcore: registered new interface driver usbhid
> [    1.810000] usbhid: USB HID core driver
> [    1.820000] NET: Registered PF_INET6 protocol family
> [    1.820000] Segment Routing with IPv6
> [    1.830000] In-situ OAM (IOAM) with IPv6
> [    1.830000] sit: IPv6, IPv4 and MPLS over IPv4 tunneling driver
> [    1.840000] NET: Registered PF_PACKET protocol family
> [    1.840000] can: controller area network core
> [    1.850000] NET: Registered PF_CAN protocol family
> [    1.850000] can: raw protocol
> [    1.860000] can: broadcast manager protocol
> [    1.860000] can: netlink gateway - max_hops=1
> [    1.870000] Key type dns_resolver registered
> [    1.870000] Registering SWP/SWPB emulation handler
> [    1.900000] input: gpio_keys as /devices/platform/gpio_keys/input/input0
> [    1.960000] SMSC LAN8700 20000000.ethernet-ffffffff:01: attached PHY
> driver (mii_bus:phy_addr=20000000.ethernet-ffffffff:01, irq=POLL)
> [    2.000000] smsc911x 20000000.ethernet eth0: SMSC911x/921x identified at
> 0xc8920000, IRQ: 41
> [    4.080000] IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
> [    4.130000] Sending DHCP requests ., OK
> [    4.170000] IP-Config: Got DHCP answer from 10.0.1.1, my address is
> 10.0.1.2
> [    4.180000] IP-Config: Complete:
> [    4.180000]      device=eth0, hwaddr=00:0a:a3:02:12:92, ipaddr=10.0.1.2,
> mask=255.255.255.0, gw=10.0.1.1
> [    4.190000]      host=10.0.1.2, domain=dyn.berto.se, nis-domain=(none)
> [    4.200000]      bootserver=10.0.1.1, rootserver=10.0.1.1,
> rootpath=/srv/nfs4/arch,tcp,v3
> [    4.200000]      nameserver0=192.168.20.1
> [    4.210000] ALSA device list:
> [    4.210000]   No soundcards found.
> [    4.240000] VFS: Mounted root (nfs filesystem) on device 0:15.
> [    4.240000] devtmpfs: mounted
> [    4.250000] Freeing unused kernel image (initmem) memory: 1024K
> [    4.290000] Run /sbin/init as init process
> [    4.290000]   with arguments:
> [    4.290000]     /sbin/init
> [    4.300000]   with environment:
> [    4.300000]     HOME=/
> [    4.300000]     TERM=linux
> [    5.980000] systemd[1]: System time before build time, advancing clock.
> [    6.030000] systemd[1]: Failed to find module 'autofs4'
> [    6.160000] systemd[1]: systemd 252.5-1-arch running in system mode (+PAM
> +AUDIT -SELINUX -APPARMOR -IMA +SMACK +SECCOMP +GCRYPT +GNUTLS +OPENSSL +ACL
> +BLKID +CURL +ELFUTILS +FIDO2 +IDN2 -IDN +IPTC +KMOD +LIBCRYPTSETUP
> +LIBFDISK +PCRE2 -PWQUALITY +P11KIT -QRENCODE +TPM2 +BZIP2 +LZ4 +XZ +ZLIB
> +ZSTD +BPF_FRAMEWORK +XKBCOMMON +UTMP -SYSVINIT default-hierarchy=unified)
> [    6.190000] systemd[1]: Detected architecture arm.
> [    6.260000] systemd[1]: Hostname set to <arm>.
> [    6.510000] systemd[1]: bpf-lsm: BPF LSM hook not enabled in the kernel,
> BPF LSM not supported
> [    6.520000] memfd_create() without MFD_EXEC nor MFD_NOEXEC_SEAL, pid=1
> 'systemd'
> [    8.810000] systemd[1]: Queued start job for default target Graphical
> Interface.
> [    8.830000] systemd[1]: Created slice Slice /system/getty.
> [    8.870000] systemd[1]: Created slice Slice /system/modprobe.
> [    8.910000] systemd[1]: Created slice Slice /system/serial-getty.
> [    8.950000] systemd[1]: Created slice User and Session Slice.
> [    8.990000] systemd[1]: Started Dispatch Password Requests to Console
> Directory Watch.
> [    9.030000] systemd[1]: Started Forward Password Requests to Wall
> Directory Watch.
> [    9.070000] systemd[1]: Arbitrary Executable File Formats File System
> Automount Point was skipped because of an unmet condition check
> (ConditionPathExists=/proc/sys/fs/binfmt_misc).
> [    9.080000] systemd[1]: Reached target Local Encrypted Volumes.
> [    9.120000] systemd[1]: Reached target Local Integrity Protected Volumes.
> [    9.160000] systemd[1]: Reached target Network is Online.
> [    9.200000] systemd[1]: Reached target Path Units.
> [    9.240000] systemd[1]: Reached target Slice Units.
> [    9.280000] systemd[1]: Reached target Swaps.
> [    9.320000] systemd[1]: Reached target Local Verity Protected Volumes.
> [    9.360000] systemd[1]: Listening on Device-mapper event daemon FIFOs.
> [    9.420000] systemd[1]: Listening on Process Core Dump Socket.
> [    9.460000] systemd[1]: Journal Audit Socket was skipped because of an
> unmet condition check (ConditionSecurity=audit).
> [    9.470000] systemd[1]: Listening on Journal Socket (/dev/log).
> [    9.510000] systemd[1]: Listening on Journal Socket.
> [    9.550000] systemd[1]: Listening on udev Control Socket.
> [    9.590000] systemd[1]: Listening on udev Kernel Socket.
> [    9.630000] systemd[1]: Huge Pages File System was skipped because of an
> unmet condition check (ConditionPathExists=/sys/kernel/mm/hugepages).
> [    9.640000] systemd[1]: POSIX Message Queue File System was skipped
> because of an unmet condition check
> (ConditionPathExists=/proc/sys/fs/mqueue).
> [    9.710000] systemd[1]: Mounting /root/shared...
> [    9.750000] systemd[1]: Mounting Kernel Debug File System...
> [    9.790000] systemd[1]: Mounting Kernel Trace File System...
> [    9.850000] systemd[1]: Mounting Temporary Directory /tmp...
> [    9.900000] systemd[1]: Create List of Static Device Nodes was skipped
> because of an unmet condition check
> (ConditionFileNotEmpty=/lib/modules/6.2.0-rc7-next-20230210-12179-
> g91bd68019b4b/modules.devname).
> [    9.960000] systemd[1]: Starting Load Kernel Module configfs...
> [    9.990000] systemd[1]: Starting Load Kernel Module drm...
> [   10.040000] systemd[1]: Starting Load Kernel Module fuse...
> [   10.120000] systemd[1]: Load Kernel Modules was skipped because no
> trigger condition checks were met.
> [   10.210000] systemd[1]: Starting Remount Root and Kernel File Systems...
> [   10.250000] systemd[1]: Repartition Root Disk was skipped because no
> trigger condition checks were met.
> [   10.270000] systemd[1]: Starting Apply Kernel Variables...
> [   10.360000] systemd[1]: Starting Coldplug All udev Devices...
> [   10.440000] systemd[1]: Mounted Kernel Debug File System.
> [   10.480000] systemd[1]: Mounted Kernel Trace File System.
> [   10.510000] systemd[1]: Mounted Temporary Directory /tmp.
> [   10.560000] systemd[1]: modprobe@configfs.service: Deactivated
> successfully.
> [   10.570000] systemd[1]: Finished Load Kernel Module configfs.
> [   10.640000] systemd[1]: modprobe@drm.service: Deactivated successfully.
> [   10.660000] systemd[1]: Finished Load Kernel Module drm.
> [   10.680000] systemd[1]: modprobe@fuse.service: Deactivated successfully.
> [   10.690000] systemd[1]: Finished Load Kernel Module fuse.
> [   10.730000] systemd[1]: Finished Remount Root and Kernel File Systems.
> [   10.770000] systemd[1]: Finished Apply Kernel Variables.
> [   10.810000] systemd[1]: FUSE Control File System was skipped because of
> an unmet condition check (ConditionPathExists=/sys/fs/fuse/connections).
> [   10.880000] systemd[1]: Mounting Kernel Configuration File System...
> [   10.920000] systemd[1]: First Boot Wizard was skipped because of an unmet
> condition check (ConditionFirstBoot=yes).
> [   10.930000] systemd[1]: Rebuild Hardware Database was skipped because of
> an unmet condition check (ConditionNeedsUpdate=/etc).
> [   10.980000] systemd[1]: Starting Load/Save Random Seed...
> [   11.010000] systemd[1]: Create System Users was skipped because no
> trigger condition checks were met.
> [   11.030000] systemd[1]: Starting Create Static Device Nodes in /dev...
> [   11.100000] systemd[1]: Mounted Kernel Configuration File System.
> [   11.500000] systemd[1]: Reached target Host and Network Name Lookups.
> [   11.540000] systemd[1]: Listening on RPCbind Server Activation Socket.
> [   11.580000] systemd[1]: Reached target RPC Port Mapper.
> [   11.650000] systemd[1]: Starting NFS status monitor for NFSv2/3
> locking....
> [   11.830000] systemd[1]: Finished Coldplug All udev Devices.
> [   11.930000] systemd[1]: Starting RPC Bind...
> [   12.270000] systemd[1]: Finished Create Static Device Nodes in /dev.
> [   12.310000] systemd[1]: Reached target Preparation for Local File
> Systems.
> [   12.350000] systemd[1]: Virtual Machine and Container Storage
> (Compatibility) was skipped because of an unmet condition check
> (ConditionPathExists=/var/lib/machines.raw).
> [   12.370000] systemd[1]: Reached target Local File Systems.
> [   12.410000] systemd[1]: Entropy Daemon based on the HAVEGE algorithm was
> skipped because of an unmet condition check (ConditionKernelVersion=<5.6).
> [   12.430000] systemd[1]: Rebuild Dynamic Linker Cache was skipped because
> no trigger condition checks were met.
> [   12.490000] systemd[1]: Starting Notify NFS peers of a restart...
> [   12.540000] systemd[1]: Set Up Additional Binary Formats was skipped
> because no trigger condition checks were met.
> [   12.550000] systemd[1]: systemd-journald.service: unit configures an IP
> firewall, but the local system does not support BPF/cgroup firewalling.
> [   12.570000] systemd[1]: (This warning is only shown for the first unit
> using IP firewalling.)
> [   12.620000] systemd[1]: Starting Journal Service...
> [   12.690000] systemd[1]: Starting Rule-based Manager for Device Events and
> Files...
> [   12.750000] systemd[1]: Started RPC Bind.
> [   12.800000] systemd[1]: Started Notify NFS peers of a restart.
> [   12.870000] systemd[1]: Started NFS status monitor for NFSv2/3 locking..
> [   13.180000] systemd[1]: Started Journal Service.
> [   17.010000] systemd-journald[86]: Received client request to flush
> runtime journal.
> [   21.390000] random: dbus-daemon: uninitialized urandom read (12 bytes
> read)
> [   22.200000] random: dbus-daemon: uninitialized urandom read (12 bytes
> read)
> [   51.370000] random: crng init done
> 
> --
> Kind Regards,
> Niklas Söderlund

^ permalink raw reply

* Re: [PATCH v3 3/3] serial: 8250_em: Add serial_out() to struct serial8250_em_hw_info
From: Niklas Söderlund @ 2023-02-13 14:09 UTC (permalink / raw)
  To: Biju Das
  Cc: Jiri Slaby, Ilpo Järvinen, Geert Uytterhoeven, Magnus Damm,
	Greg Kroah-Hartman, linux-serial, Fabrizio Castro,
	linux-renesas-soc@vger.kernel.org
In-Reply-To: <OS0PR01MB592203B32464BE32BC55562886DD9@OS0PR01MB5922.jpnprd01.prod.outlook.com>

Hi Biju,

On 2023-02-13 13:01:06 +0000, Biju Das wrote:
> Please get files from here
> 
> https://gitlab.com/bijud/uart-fifo/-/commits/uart-fifo-testing

Thanks for the branch.

It boots and the serial console appears to be functioning as expected.  
Is there anything in particular you like me to test? I attach the full 
boot log in case it's useful for you.

[    0.000000] Booting Linux on physical CPU 0x0
[    0.000000] Linux version 6.2.0-rc7-next-20230210-12179-g91bd68019b4b (neg@sleipner) (arm-linux-gnueabihf-gcc (GCC) 10.2.0, GNU ld (GNU Binutils) 2.35.1) #2 SMP Mon Feb 13 15:02:12 CET 2023
[    0.000000] CPU: ARMv7 Processor [411fc092] revision 2 (ARMv7), cr=10c5387d
[    0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
[    0.000000] OF: fdt: Machine model: EMEV2 KZM9D Board
[    0.000000] printk: debug: ignoring loglevel setting.
[    0.000000] Memory policy: Data cache writealloc
[    0.000000] cma: Failed to reserve 128 MiB
[    0.000000] Zone ranges:
[    0.000000]   Normal   [mem 0x0000000040000000-0x0000000047ffffff]
[    0.000000]   HighMem  empty
[    0.000000] Movable zone start for each node
[    0.000000] Early memory node ranges
[    0.000000]   node   0: [mem 0x0000000040000000-0x0000000047ffffff]
[    0.000000] Initmem setup node 0 [mem 0x0000000040000000-0x0000000047ffffff]
[    0.000000] percpu: Embedded 14 pages/cpu s33620 r0 d23724 u57344
[    0.000000] pcpu-alloc: s33620 r0 d23724 u57344 alloc=14*4096
[    0.000000] pcpu-alloc: [0] 0 [0] 1 
[    0.000000] Built 1 zonelists, mobility grouping on.  Total pages: 32512
[    0.000000] Kernel command line: ignore_loglevel rw root=/dev/nfs ip=on
[    0.000000] Dentry cache hash table entries: 16384 (order: 4, 65536 bytes, linear)
[    0.000000] Inode-cache hash table entries: 8192 (order: 3, 32768 bytes, linear)
[    0.000000] mem auto-init: stack:off, heap alloc:off, heap free:off
[    0.000000] Memory: 116068K/131072K available (8192K kernel code, 1150K rwdata, 2596K rodata, 1024K init, 251K bss, 15004K reserved, 0K cma-reserved, 0K highmem)
[    0.000000] trace event string verifier disabled
[    0.000000] rcu: Hierarchical RCU implementation.
[    0.000000] rcu: 	RCU event tracing is enabled.
[    0.000000] rcu: 	RCU restricting CPUs from NR_CPUS=8 to nr_cpu_ids=2.
[    0.000000] rcu: RCU calculated value of scheduler-enlistment delay is 10 jiffies.
[    0.000000] rcu: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=2
[    0.000000] NR_IRQS: 16, nr_irqs: 16, preallocated irqs: 16
[    0.000000] GIC: enabling workaround for broken byte access
[    0.000000] rcu: srcu_init: Setting srcu_struct sizes based on contention.
[    0.000000] timer_probe: no matching timers found
[    0.000000] Console: colour dummy device 80x30
[    0.000000] printk: console [tty0] enabled
[    0.000000] sched_clock: 32 bits at 100 Hz, resolution 10000000ns, wraps every 21474836475000000ns
[    0.000000] Calibrating delay loop (skipped) preset value.. 1066.00 BogoMIPS (lpj=5330000)
[    0.000000] pid_max: default: 32768 minimum: 301
[    0.000000] Mount-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)
[    0.000000] Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)
[    0.000000] CPU: Testing write buffer coherency: ok
[    0.000000] CPU0: Spectre v2: using BPIALL workaround
[    0.000000] CPU0: thread -1, cpu 0, socket 0, mpidr 80000000
[    0.000000] Setting up static identity map for 0x40100000 - 0x40100060
[    0.000000] rcu: Hierarchical SRCU implementation.
[    0.000000] rcu: 	Max phase no-delay instances is 1000.
[    0.000000] smp: Bringing up secondary CPUs ...
[    0.000000] CPU1: thread -1, cpu 1, socket 0, mpidr 80000001
[    0.000000] CPU1: Spectre v2: using BPIALL workaround
[    0.000000] smp: Brought up 1 node, 2 CPUs
[    0.000000] SMP: Total of 2 processors activated (2132.00 BogoMIPS).
[    0.000000] CPU: All CPU(s) started in SVC mode.
[    0.000000] devtmpfs: initialized
[    0.000000] VFP support v0.3: implementor 41 architecture 3 part 30 variant 9 rev 1
[    0.000000] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
[    0.000000] futex hash table entries: 512 (order: 3, 32768 bytes, linear)
[    0.000000] pinctrl core: initialized pinctrl subsystem
[    0.000000] NET: Registered PF_NETLINK/PF_ROUTE protocol family
[    0.000000] DMA: preallocated 256 KiB pool for atomic coherent allocations
[    0.000000] thermal_sys: Registered thermal governor 'step_wise'
[    0.000000] No ATAGs?
[    0.000000] hw-breakpoint: found 5 (+1 reserved) breakpoint and 1 watchpoint registers.
[    0.000000] hw-breakpoint: maximum watchpoint size is 4 bytes.
[    0.000000] sh-pfc e0140200.pinctrl: emev2_pfc support registered
[    0.000000] SCSI subsystem initialized
[    0.000000] libata version 3.00 loaded.
[    0.000000] usbcore: registered new interface driver usbfs
[    0.000000] usbcore: registered new interface driver hub
[    0.000000] usbcore: registered new device driver usb
[    0.000000] mc: Linux media interface: v0.10
[    0.000000] videodev: Linux video capture interface: v2.00
[    0.000000] pps_core: LinuxPPS API ver. 1 registered
[    0.000000] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti <giometti@linux.it>
[    0.000000] PTP clock support registered
[    0.000000] em_sti e0180000.timer: used for clock events
[    0.000000] em_sti e0180000.timer: used for oneshot clock events
[    0.000000] em_sti e0180000.timer: used as clock source
[    0.000000] clocksource: e0180000.timer: mask: 0xffffffffffff max_cycles: 0x1ef4687b1, max_idle_ns: 112843571739654 ns
[    0.000000] Advanced Linux Sound Architecture Driver Initialized.
[    0.000000] vgaarb: loaded
[    0.890000] clocksource: Switched to clocksource e0180000.timer
[    0.900000] Clockevents: could not switch to one-shot mode:
[    0.900000] Clockevents: could not switch to one-shot mode: dummy_timer is not functional.
[    0.900000]  dummy_timer is not functional.
[    0.910000] NET: Registered PF_INET protocol family
[    0.910000] IP idents hash table entries: 2048 (order: 2, 16384 bytes, linear)
[    0.910000] tcp_listen_portaddr_hash hash table entries: 512 (order: 0, 4096 bytes, linear)
[    0.910000] Table-perturb hash table entries: 65536 (order: 6, 262144 bytes, linear)
[    0.910000] TCP established hash table entries: 1024 (order: 0, 4096 bytes, linear)
[    0.910000] TCP bind hash table entries: 1024 (order: 2, 16384 bytes, linear)
[    0.910000] TCP: Hash tables configured (established 1024 bind 1024)
[    0.910000] UDP hash table entries: 256 (order: 1, 8192 bytes, linear)
[    0.910000] UDP-Lite hash table entries: 256 (order: 1, 8192 bytes, linear)
[    0.910000] NET: Registered PF_UNIX/PF_LOCAL protocol family
[    0.910000] RPC: Registered named UNIX socket transport module.
[    0.910000] RPC: Registered udp transport module.
[    0.910000] RPC: Registered tcp transport module.
[    0.910000] RPC: Registered tcp NFSv4.1 backchannel transport module.
[    0.910000] PCI: CLS 0 bytes, default 64
[    0.950000] hw perfevents: enabled with armv7_cortex_a9 PMU driver, 7 counters available
[    0.950000] workingset: timestamp_bits=30 max_order=15 bucket_order=0
[    0.950000] NFS: Registering the id_resolver key type
[    0.950000] Key type id_resolver registered
[    0.950000] Key type id_legacy registered
[    0.950000] nfs4filelayout_init: NFSv4 File Layout Driver Registering...
[    0.950000] nfs4flexfilelayout_init: NFSv4 Flexfile Layout Driver Registering...
[    0.960000] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 246)
[    0.960000] io scheduler mq-deadline registered
[    0.960000] io scheduler kyber registered
[    0.960000] io scheduler bfq registered
[    0.970000] Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
[    0.970000] e1020000.serial: ttyS0 at MMIO 0xe1020000 (irq = 37, base_baud = 796444) is a TI16750
[    0.970000] e1030000.serial: ttyS1 at MMIO 0xe1030000 (irq = 38, base_baud = 7168000) is a TI16750
[    0.970000] printk: console [ttyS1] enabled
[    1.660000] e1040000.serial: ttyS2 at MMIO 0xe1040000 (irq = 39, base_baud = 14336000) is a TI16750
[    1.670000] e1050000.serial: ttyS3 at MMIO 0xe1050000 (irq = 40, base_baud = 2389333) is a TI16750
[    1.680000] SuperH (H)SCI(F) driver initialized
[    1.700000] CAN device driver interface
[    1.760000] smsc911x 20000000.ethernet eth0: MAC Address: 00:0a:a3:02:12:92
[    1.770000] UDC core: g_ether: couldn't find an available UDC
[    1.770000] i2c_dev: i2c /dev entries driver
[    1.780000] em-i2c e0070000.i2c: Added i2c controller 0, irq 42
[    1.790000] em-i2c e10a0000.i2c: Added i2c controller 1, irq 43
[    1.800000] cpu cpu0: OPP table can't be empty
[    1.800000] usbcore: registered new interface driver usbhid
[    1.810000] usbhid: USB HID core driver
[    1.820000] NET: Registered PF_INET6 protocol family
[    1.820000] Segment Routing with IPv6
[    1.830000] In-situ OAM (IOAM) with IPv6
[    1.830000] sit: IPv6, IPv4 and MPLS over IPv4 tunneling driver
[    1.840000] NET: Registered PF_PACKET protocol family
[    1.840000] can: controller area network core
[    1.850000] NET: Registered PF_CAN protocol family
[    1.850000] can: raw protocol
[    1.860000] can: broadcast manager protocol
[    1.860000] can: netlink gateway - max_hops=1
[    1.870000] Key type dns_resolver registered
[    1.870000] Registering SWP/SWPB emulation handler
[    1.900000] input: gpio_keys as /devices/platform/gpio_keys/input/input0
[    1.960000] SMSC LAN8700 20000000.ethernet-ffffffff:01: attached PHY driver (mii_bus:phy_addr=20000000.ethernet-ffffffff:01, irq=POLL)
[    2.000000] smsc911x 20000000.ethernet eth0: SMSC911x/921x identified at 0xc8920000, IRQ: 41
[    4.080000] IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
[    4.130000] Sending DHCP requests ., OK
[    4.170000] IP-Config: Got DHCP answer from 10.0.1.1, my address is 10.0.1.2
[    4.180000] IP-Config: Complete:
[    4.180000]      device=eth0, hwaddr=00:0a:a3:02:12:92, ipaddr=10.0.1.2, mask=255.255.255.0, gw=10.0.1.1
[    4.190000]      host=10.0.1.2, domain=dyn.berto.se, nis-domain=(none)
[    4.200000]      bootserver=10.0.1.1, rootserver=10.0.1.1, rootpath=/srv/nfs4/arch,tcp,v3
[    4.200000]      nameserver0=192.168.20.1
[    4.210000] ALSA device list:
[    4.210000]   No soundcards found.
[    4.240000] VFS: Mounted root (nfs filesystem) on device 0:15.
[    4.240000] devtmpfs: mounted
[    4.250000] Freeing unused kernel image (initmem) memory: 1024K
[    4.290000] Run /sbin/init as init process
[    4.290000]   with arguments:
[    4.290000]     /sbin/init
[    4.300000]   with environment:
[    4.300000]     HOME=/
[    4.300000]     TERM=linux
[    5.980000] systemd[1]: System time before build time, advancing clock.
[    6.030000] systemd[1]: Failed to find module 'autofs4'
[    6.160000] systemd[1]: systemd 252.5-1-arch running in system mode (+PAM +AUDIT -SELINUX -APPARMOR -IMA +SMACK +SECCOMP +GCRYPT +GNUTLS +OPENSSL +ACL +BLKID +CURL +ELFUTILS +FIDO2 +IDN2 -IDN +IPTC +KMOD +LIBCRYPTSETUP +LIBFDISK +PCRE2 -PWQUALITY +P11KIT -QRENCODE +TPM2 +BZIP2 +LZ4 +XZ +ZLIB +ZSTD +BPF_FRAMEWORK +XKBCOMMON +UTMP -SYSVINIT default-hierarchy=unified)
[    6.190000] systemd[1]: Detected architecture arm.
[    6.260000] systemd[1]: Hostname set to <arm>.
[    6.510000] systemd[1]: bpf-lsm: BPF LSM hook not enabled in the kernel, BPF LSM not supported
[    6.520000] memfd_create() without MFD_EXEC nor MFD_NOEXEC_SEAL, pid=1 'systemd'
[    8.810000] systemd[1]: Queued start job for default target Graphical Interface.
[    8.830000] systemd[1]: Created slice Slice /system/getty.
[    8.870000] systemd[1]: Created slice Slice /system/modprobe.
[    8.910000] systemd[1]: Created slice Slice /system/serial-getty.
[    8.950000] systemd[1]: Created slice User and Session Slice.
[    8.990000] systemd[1]: Started Dispatch Password Requests to Console Directory Watch.
[    9.030000] systemd[1]: Started Forward Password Requests to Wall Directory Watch.
[    9.070000] systemd[1]: Arbitrary Executable File Formats File System Automount Point was skipped because of an unmet condition check (ConditionPathExists=/proc/sys/fs/binfmt_misc).
[    9.080000] systemd[1]: Reached target Local Encrypted Volumes.
[    9.120000] systemd[1]: Reached target Local Integrity Protected Volumes.
[    9.160000] systemd[1]: Reached target Network is Online.
[    9.200000] systemd[1]: Reached target Path Units.
[    9.240000] systemd[1]: Reached target Slice Units.
[    9.280000] systemd[1]: Reached target Swaps.
[    9.320000] systemd[1]: Reached target Local Verity Protected Volumes.
[    9.360000] systemd[1]: Listening on Device-mapper event daemon FIFOs.
[    9.420000] systemd[1]: Listening on Process Core Dump Socket.
[    9.460000] systemd[1]: Journal Audit Socket was skipped because of an unmet condition check (ConditionSecurity=audit).
[    9.470000] systemd[1]: Listening on Journal Socket (/dev/log).
[    9.510000] systemd[1]: Listening on Journal Socket.
[    9.550000] systemd[1]: Listening on udev Control Socket.
[    9.590000] systemd[1]: Listening on udev Kernel Socket.
[    9.630000] systemd[1]: Huge Pages File System was skipped because of an unmet condition check (ConditionPathExists=/sys/kernel/mm/hugepages).
[    9.640000] systemd[1]: POSIX Message Queue File System was skipped because of an unmet condition check (ConditionPathExists=/proc/sys/fs/mqueue).
[    9.710000] systemd[1]: Mounting /root/shared...
[    9.750000] systemd[1]: Mounting Kernel Debug File System...
[    9.790000] systemd[1]: Mounting Kernel Trace File System...
[    9.850000] systemd[1]: Mounting Temporary Directory /tmp...
[    9.900000] systemd[1]: Create List of Static Device Nodes was skipped because of an unmet condition check (ConditionFileNotEmpty=/lib/modules/6.2.0-rc7-next-20230210-12179-g91bd68019b4b/modules.devname).
[    9.960000] systemd[1]: Starting Load Kernel Module configfs...
[    9.990000] systemd[1]: Starting Load Kernel Module drm...
[   10.040000] systemd[1]: Starting Load Kernel Module fuse...
[   10.120000] systemd[1]: Load Kernel Modules was skipped because no trigger condition checks were met.
[   10.210000] systemd[1]: Starting Remount Root and Kernel File Systems...
[   10.250000] systemd[1]: Repartition Root Disk was skipped because no trigger condition checks were met.
[   10.270000] systemd[1]: Starting Apply Kernel Variables...
[   10.360000] systemd[1]: Starting Coldplug All udev Devices...
[   10.440000] systemd[1]: Mounted Kernel Debug File System.
[   10.480000] systemd[1]: Mounted Kernel Trace File System.
[   10.510000] systemd[1]: Mounted Temporary Directory /tmp.
[   10.560000] systemd[1]: modprobe@configfs.service: Deactivated successfully.
[   10.570000] systemd[1]: Finished Load Kernel Module configfs.
[   10.640000] systemd[1]: modprobe@drm.service: Deactivated successfully.
[   10.660000] systemd[1]: Finished Load Kernel Module drm.
[   10.680000] systemd[1]: modprobe@fuse.service: Deactivated successfully.
[   10.690000] systemd[1]: Finished Load Kernel Module fuse.
[   10.730000] systemd[1]: Finished Remount Root and Kernel File Systems.
[   10.770000] systemd[1]: Finished Apply Kernel Variables.
[   10.810000] systemd[1]: FUSE Control File System was skipped because of an unmet condition check (ConditionPathExists=/sys/fs/fuse/connections).
[   10.880000] systemd[1]: Mounting Kernel Configuration File System...
[   10.920000] systemd[1]: First Boot Wizard was skipped because of an unmet condition check (ConditionFirstBoot=yes).
[   10.930000] systemd[1]: Rebuild Hardware Database was skipped because of an unmet condition check (ConditionNeedsUpdate=/etc).
[   10.980000] systemd[1]: Starting Load/Save Random Seed...
[   11.010000] systemd[1]: Create System Users was skipped because no trigger condition checks were met.
[   11.030000] systemd[1]: Starting Create Static Device Nodes in /dev...
[   11.100000] systemd[1]: Mounted Kernel Configuration File System.
[   11.500000] systemd[1]: Reached target Host and Network Name Lookups.
[   11.540000] systemd[1]: Listening on RPCbind Server Activation Socket.
[   11.580000] systemd[1]: Reached target RPC Port Mapper.
[   11.650000] systemd[1]: Starting NFS status monitor for NFSv2/3 locking....
[   11.830000] systemd[1]: Finished Coldplug All udev Devices.
[   11.930000] systemd[1]: Starting RPC Bind...
[   12.270000] systemd[1]: Finished Create Static Device Nodes in /dev.
[   12.310000] systemd[1]: Reached target Preparation for Local File Systems.
[   12.350000] systemd[1]: Virtual Machine and Container Storage (Compatibility) was skipped because of an unmet condition check (ConditionPathExists=/var/lib/machines.raw).
[   12.370000] systemd[1]: Reached target Local File Systems.
[   12.410000] systemd[1]: Entropy Daemon based on the HAVEGE algorithm was skipped because of an unmet condition check (ConditionKernelVersion=<5.6).
[   12.430000] systemd[1]: Rebuild Dynamic Linker Cache was skipped because no trigger condition checks were met.
[   12.490000] systemd[1]: Starting Notify NFS peers of a restart...
[   12.540000] systemd[1]: Set Up Additional Binary Formats was skipped because no trigger condition checks were met.
[   12.550000] systemd[1]: systemd-journald.service: unit configures an IP firewall, but the local system does not support BPF/cgroup firewalling.
[   12.570000] systemd[1]: (This warning is only shown for the first unit using IP firewalling.)
[   12.620000] systemd[1]: Starting Journal Service...
[   12.690000] systemd[1]: Starting Rule-based Manager for Device Events and Files...
[   12.750000] systemd[1]: Started RPC Bind.
[   12.800000] systemd[1]: Started Notify NFS peers of a restart.
[   12.870000] systemd[1]: Started NFS status monitor for NFSv2/3 locking..
[   13.180000] systemd[1]: Started Journal Service.
[   17.010000] systemd-journald[86]: Received client request to flush runtime journal.
[   21.390000] random: dbus-daemon: uninitialized urandom read (12 bytes read)
[   22.200000] random: dbus-daemon: uninitialized urandom read (12 bytes read)
[   51.370000] random: crng init done

-- 
Kind Regards,
Niklas Söderlund

^ permalink raw reply

* RE: [PATCH v3 3/3] serial: 8250_em: Add serial_out() to struct serial8250_em_hw_info
From: Biju Das @ 2023-02-13 13:01 UTC (permalink / raw)
  To: Niklas Söderlund
  Cc: Jiri Slaby, Ilpo Järvinen, Geert Uytterhoeven, Magnus Damm,
	Greg Kroah-Hartman, linux-serial, Fabrizio Castro,
	linux-renesas-soc@vger.kernel.org
In-Reply-To: <Y+oRDb8DzgUhu6U6@oden.dyn.berto.se>

Hi Niklas,

> -----Original Message-----
> From: Niklas Söderlund <niklas.soderlund@ragnatech.se>
> Sent: Monday, February 13, 2023 10:30 AM
> To: Biju Das <biju.das.jz@bp.renesas.com>
> Cc: Jiri Slaby <jirislaby@kernel.org>; Ilpo Järvinen
> <ilpo.jarvinen@linux.intel.com>; Geert Uytterhoeven
> <geert+renesas@glider.be>; Magnus Damm <magnus.damm@gmail.com>; Greg Kroah-
> Hartman <gregkh@linuxfoundation.org>; linux-serial <linux-
> serial@vger.kernel.org>; Fabrizio Castro <fabrizio.castro.jz@renesas.com>;
> linux-renesas-soc@vger.kernel.org
> Subject: Re: [PATCH v3 3/3] serial: 8250_em: Add serial_out() to struct
> serial8250_em_hw_info
> 
> Hi Biju,
> 
> On 2023-02-13 10:06:04 +0000, Biju Das wrote:
> > Hi Niklas,
> >
> > Thanks for testing.
> >
> > > -----Original Message-----
> > > From: Niklas Söderlund <niklas.soderlund@ragnatech.se>
> > > Sent: Monday, February 13, 2023 9:58 AM
> > > To: Biju Das <biju.das.jz@bp.renesas.com>
> > > Cc: Jiri Slaby <jirislaby@kernel.org>; Ilpo Järvinen
> > > <ilpo.jarvinen@linux.intel.com>; Geert Uytterhoeven
> > > <geert+renesas@glider.be>; Magnus Damm <magnus.damm@gmail.com>; Greg
> > > Kroah- Hartman <gregkh@linuxfoundation.org>; linux-serial <linux-
> > > serial@vger.kernel.org>; Fabrizio Castro
> > > <fabrizio.castro.jz@renesas.com>; linux-renesas-soc@vger.kernel.org
> > > Subject: Re: [PATCH v3 3/3] serial: 8250_em: Add serial_out() to
> > > struct serial8250_em_hw_info
> > >
> > > Hi Biju,
> > >
> > > On 2023-02-13 09:31:27 +0000, Biju Das wrote:
> > > > Adding Magnus and Niklas to test on EMMA mobile platform to check
> > > > the port type detected On that platform?
> > >
> > > I don't know what you want me to check, I don't know much about
> > > serial. I wired up the platform during the weekend, here is a boot
> > > log running on v6.1. If you want to to check / test something I'm
> > > happy to, but will need instructions.
> >
> > As per Geert the register layout is same as RZ/V2M, So The UART is
> > register compatible with standard 16750 chip.
> >
> > But below log shows that it is 16550A and using only 16-bytes fifo,
> > Eventhough it has 64-bytes fifo.
> >
> > [    1.020000] e1020000.serial: ttyS0 at MMIO 0xe1020000 (irq = 37,
> base_baud = 796444) is a 16550A
> > [    1.020000] e1030000.serial: ttyS1 at MMIO 0xe1030000 (irq = 38,
> base_baud = 7168000) is a 16550A
> > [    1.690000] printk: console [ttyS1] enabled
> > [    1.700000] e1040000.serial: ttyS2 at MMIO 0xe1040000 (irq = 39,
> base_baud = 14336000) is a 16550A
> > [    1.710000] e1050000.serial: ttyS3 at MMIO 0xe1050000 (irq = 40,
> base_baud = 2389333) is a 16550A
> >
> > So if you apply, this patch series, and add below changes it should
> > detect as 16750
> >
> > https://jpn01.safelinks.protection.outlook.com/?url=https%3A%2F%2Flore
> > .kernel.org%2Flinux-renesas-soc%2F8585f736-cf3b-b63c-753f-892d4051ada3
> > %40linux.intel.com%2FT%2F%23mce8d222e3670321e8a8e39faacc4d6dd061fdbd6&
> > data=05%7C01%7Cbiju.das.jz%40bp.renesas.com%7Cc1ababd7ffba4fa1f28608db
> > 0dad34ad%7C53d82571da1947e49cb4625a166a4a2a%7C0%7C0%7C6381188097859699
> > 13%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI
> > 6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=2NYFF9vLvkFSifCl4WYUfT1i
> > ad8oyUFegJgFclRdDOw%3D&reserved=0
> >
> > and for quick testing please do below change for emma mobile.
> >
> > + { .compatible = "renesas,em-uart", .data = &rzv2m_uart_hw_info },
> 
> 
> Could you provide a branch with the setup you like me to test?

Please get files from here

https://gitlab.com/bijud/uart-fifo/-/commits/uart-fifo-testing

Cheers,
Biju


> 
> >
> > Cheers,
> > Biju
> >
> >
> >
> > >
> > > [    0.000000] Booting Linux on physical CPU 0x0
> > > [    0.000000] Linux version 6.1.0 (neg@sleipner) (arm-linux-gnueabihf-
> gcc
> > > (GCC) 10.2.0, GNU ld (GNU Binutils) 2.35.1) #1 SMP Sun Feb 12
> > > 18:44:55 CET
> > > 2023
> > > [    0.000000] CPU: ARMv7 Processor [411fc092] revision 2 (ARMv7),
> > > cr=10c5387d
> > > [    0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing
> > > instruction cache
> > > [    0.000000] OF: fdt: Machine model: EMEV2 KZM9D Board
> > > [    0.000000] printk: debug: ignoring loglevel setting.
> > > [    0.000000] Memory policy: Data cache writealloc
> > > [    0.000000] cma: Failed to reserve 128 MiB
> > > [    0.000000] Zone ranges:
> > > [    0.000000]   Normal   [mem 0x0000000040000000-0x0000000047ffffff]
> > > [    0.000000]   HighMem  empty
> > > [    0.000000] Movable zone start for each node
> > > [    0.000000] Early memory node ranges
> > > [    0.000000]   node   0: [mem 0x0000000040000000-0x0000000047ffffff]
> > > [    0.000000] Initmem setup node 0 [mem 0x0000000040000000-
> > > 0x0000000047ffffff]
> > > [    0.000000] percpu: Embedded 13 pages/cpu s32468 r0 d20780 u53248
> > > [    0.000000] pcpu-alloc: s32468 r0 d20780 u53248 alloc=13*4096
> > > [    0.000000] pcpu-alloc: [0] 0 [0] 1
> > > [    0.000000] Built 1 zonelists, mobility grouping on.  Total pages:
> 32512
> > > [    0.000000] Kernel command line: ignore_loglevel rw root=/dev/nfs
> ip=on
> > > [    0.000000] Dentry cache hash table entries: 16384 (order: 4, 65536
> > > bytes, linear)
> > > [    0.000000] Inode-cache hash table entries: 8192 (order: 3, 32768
> bytes,
> > > linear)
> > > [    0.000000] mem auto-init: stack:off, heap alloc:off, heap free:off
> > > [    0.000000] Memory: 116072K/131072K available (8192K kernel code,
> 1152K
> > > rwdata, 2436K rodata, 1024K init, 259K bss, 15000K reserved, 0K cma-
> > > reserved, 0K highmem)
> > > [    0.000000] trace event string verifier disabled
> > > [    0.000000] rcu: Hierarchical RCU implementation.
> > > [    0.000000] rcu: 	RCU event tracing is enabled.
> > > [    0.000000] rcu: 	RCU restricting CPUs from NR_CPUS=8 to
> > > nr_cpu_ids=2.
> > > [    0.000000] rcu: RCU calculated value of scheduler-enlistment delay
> is 10
> > > jiffies.
> > > [    0.000000] rcu: Adjusting geometry for rcu_fanout_leaf=16,
> nr_cpu_ids=2
> > > [    0.000000] NR_IRQS: 16, nr_irqs: 16, preallocated irqs: 16
> > > [    0.000000] GIC: enabling workaround for broken byte access
> > > [    0.000000] rcu: srcu_init: Setting srcu_struct sizes based on
> > > contention.
> > > [    0.000000] timer_probe: no matching timers found
> > > [    0.000000] Console: colour dummy device 80x30
> > > [    0.000000] printk: console [tty0] enabled
> > > [    0.000000] sched_clock: 32 bits at 100 Hz, resolution 10000000ns,
> wraps
> > > every 21474836475000000ns
> > > [    0.000000] Calibrating delay loop (skipped) preset value.. 1066.00
> > > BogoMIPS (lpj=5330000)
> > > [    0.000000] pid_max: default: 32768 minimum: 301
> > > [    0.000000] Mount-cache hash table entries: 1024 (order: 0, 4096
> bytes,
> > > linear)
> > > [    0.000000] Mountpoint-cache hash table entries: 1024 (order: 0, 4096
> > > bytes, linear)
> > > [    0.000000] CPU: Testing write buffer coherency: ok
> > > [    0.000000] CPU0: Spectre v2: using BPIALL workaround
> > > [    0.000000] CPU0: thread -1, cpu 0, socket 0, mpidr 80000000
> > > [    0.000000] Setting up static identity map for 0x40100000 -
> 0x40100060
> > > [    0.000000] rcu: Hierarchical SRCU implementation.
> > > [    0.000000] rcu: 	Max phase no-delay instances is 1000.
> > > [    0.000000] smp: Bringing up secondary CPUs ...
> > > [    0.000000] CPU1: thread -1, cpu 1, socket 0, mpidr 80000001
> > > [    0.000000] CPU1: Spectre v2: using BPIALL workaround
> > > [    0.000000] smp: Brought up 1 node, 2 CPUs
> > > [    0.000000] SMP: Total of 2 processors activated (2132.00 BogoMIPS).
> > > [    0.000000] CPU: All CPU(s) started in SVC mode.
> > > [    0.000000] devtmpfs: initialized
> > > [    0.000000] VFP support v0.3: implementor 41 architecture 3 part 30
> > > variant 9 rev 1
> > > [    0.000000] clocksource: jiffies: mask: 0xffffffff max_cycles:
> > > 0xffffffff, max_idle_ns: 19112604462750000 ns
> > > [    0.000000] futex hash table entries: 512 (order: 3, 32768 bytes,
> linear)
> > > [    0.000000] pinctrl core: initialized pinctrl subsystem
> > > [    0.000000] NET: Registered PF_NETLINK/PF_ROUTE protocol family
> > > [    0.000000] DMA: preallocated 256 KiB pool for atomic coherent
> > > allocations
> > > [    0.000000] thermal_sys: Registered thermal governor 'step_wise'
> > > [    0.000000] No ATAGs?
> > > [    0.000000] hw-breakpoint: found 5 (+1 reserved) breakpoint and 1
> > > watchpoint registers.
> > > [    0.000000] hw-breakpoint: maximum watchpoint size is 4 bytes.
> > > [    0.000000] sh-pfc e0140200.pinctrl: emev2_pfc support registered
> > > [    0.000000] SCSI subsystem initialized
> > > [    0.000000] libata version 3.00 loaded.
> > > [    0.000000] usbcore: registered new interface driver usbfs
> > > [    0.000000] usbcore: registered new interface driver hub
> > > [    0.000000] usbcore: registered new device driver usb
> > > [    0.000000] mc: Linux media interface: v0.10
> > > [    0.000000] videodev: Linux video capture interface: v2.00
> > > [    0.000000] pps_core: LinuxPPS API ver. 1 registered
> > > [    0.000000] pps_core: Software ver. 5.3.6 - Copyright 2005-2007
> Rodolfo
> > > Giometti <giometti@linux.it>
> > > [    0.000000] PTP clock support registered
> > > [    0.000000] em_sti e0180000.timer: used for clock events
> > > [    0.000000] em_sti e0180000.timer: used for oneshot clock events
> > > [    0.000000] em_sti e0180000.timer: used as clock source
> > > [    0.000000] clocksource: e0180000.timer: mask: 0xffffffffffff
> max_cycles:
> > > 0x1ef4687b1, max_idle_ns: 112843571739654 ns
> > > [    0.000000] Advanced Linux Sound Architecture Driver Initialized.
> > > [    0.000000] vgaarb: loaded
> > > [    0.940000] clocksource: Switched to clocksource e0180000.timer
> > > [    0.950000] Clockevents: could not switch to one-shot mode:
> > > [    0.950000] Clockevents: could not switch to one-shot mode:
> dummy_timer
> > > is not functional.
> > > [    0.950000]  dummy_timer is not functional.
> > > [    0.960000] NET: Registered PF_INET protocol family
> > > [    0.960000] IP idents hash table entries: 2048 (order: 2, 16384
> bytes,
> > > linear)
> > > [    0.960000] tcp_listen_portaddr_hash hash table entries: 512 (order:
> 0,
> > > 4096 bytes, linear)
> > > [    0.960000] Table-perturb hash table entries: 65536 (order: 6, 262144
> > > bytes, linear)
> > > [    0.960000] TCP established hash table entries: 1024 (order: 0, 4096
> > > bytes, linear)
> > > [    0.960000] TCP bind hash table entries: 1024 (order: 2, 16384 bytes,
> > > linear)
> > > [    0.960000] TCP: Hash tables configured (established 1024 bind 1024)
> > > [    0.960000] UDP hash table entries: 256 (order: 1, 8192 bytes,
> linear)
> > > [    0.960000] UDP-Lite hash table entries: 256 (order: 1, 8192 bytes,
> > > linear)
> > > [    0.960000] NET: Registered PF_UNIX/PF_LOCAL protocol family
> > > [    0.960000] RPC: Registered named UNIX socket transport module.
> > > [    0.960000] RPC: Registered udp transport module.
> > > [    0.960000] RPC: Registered tcp transport module.
> > > [    0.960000] RPC: Registered tcp NFSv4.1 backchannel transport module.
> > > [    0.960000] PCI: CLS 0 bytes, default 64
> > > [    1.000000] hw perfevents: enabled with armv7_cortex_a9 PMU driver, 7
> > > counters available
> > > [    1.000000] workingset: timestamp_bits=30 max_order=15 bucket_order=0
> > > [    1.000000] NFS: Registering the id_resolver key type
> > > [    1.000000] Key type id_resolver registered
> > > [    1.000000] Key type id_legacy registered
> > > [    1.000000] nfs4filelayout_init: NFSv4 File Layout Driver
> Registering...
> > > [    1.000000] nfs4flexfilelayout_init: NFSv4 Flexfile Layout Driver
> > > Registering...
> > > [    1.000000] Block layer SCSI generic (bsg) driver version 0.4 loaded
> > > (major 246)
> > > [    1.000000] io scheduler mq-deadline registered
> > > [    1.000000] io scheduler kyber registered
> > > [    1.010000] Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
> > > [    1.020000] e1020000.serial: ttyS0 at MMIO 0xe1020000 (irq = 37,
> > > base_baud = 796444) is a 16550A
> > > [    1.020000] e1030000.serial: ttyS1 at MMIO 0xe1030000 (irq = 38,
> > > base_baud = 7168000) is a 16550A
> > > [    1.690000] printk: console [ttyS1] enabled
> > > [    1.700000] e1040000.serial: ttyS2 at MMIO 0xe1040000 (irq = 39,
> > > base_baud = 14336000) is a 16550A
> > > [    1.710000] e1050000.serial: ttyS3 at MMIO 0xe1050000 (irq = 40,
> > > base_baud = 2389333) is a 16550A
> > > [    1.720000] SuperH (H)SCI(F) driver initialized
> > > [    1.730000] CAN device driver interface
> > > [    1.800000] smsc911x 20000000.ethernet eth0: MAC Address:
> > > 00:0a:a3:02:12:92
> > > [    1.810000] UDC core: g_ether: couldn't find an available UDC
> > > [    1.810000] i2c_dev: i2c /dev entries driver
> > > [    1.820000] em-i2c e0070000.i2c: Added i2c controller 0, irq 42
> > > [    1.830000] em-i2c e10a0000.i2c: Added i2c controller 1, irq 43
> > > [    1.830000] cpu cpu0: OPP table can't be empty
> > > [    1.840000] usbcore: registered new interface driver usbhid
> > > [    1.850000] usbhid: USB HID core driver
> > > [    1.850000] NET: Registered PF_INET6 protocol family
> > > [    1.860000] Segment Routing with IPv6
> > > [    1.870000] In-situ OAM (IOAM) with IPv6
> > > [    1.870000] sit: IPv6, IPv4 and MPLS over IPv4 tunneling driver
> > > [    1.880000] NET: Registered PF_PACKET protocol family
> > > [    1.880000] can: controller area network core
> > > [    1.890000] NET: Registered PF_CAN protocol family
> > > [    1.890000] can: raw protocol
> > > [    1.900000] can: broadcast manager protocol
> > > [    1.900000] can: netlink gateway - max_hops=1
> > > [    1.900000] Key type dns_resolver registered
> > > [    1.910000] Registering SWP/SWPB emulation handler
> > > [    1.920000] input: gpio_keys as
> /devices/platform/gpio_keys/input/input0
> > > [    1.980000] SMSC LAN8700 20000000.ethernet-ffffffff:01: attached PHY
> > > driver (mii_bus:phy_addr=20000000.ethernet-ffffffff:01, irq=POLL)
> > > [    2.020000] smsc911x 20000000.ethernet eth0: SMSC911x/921x identified
> at
> > > 0xc8920000, IRQ: 41
> > > [    4.160000] IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
> > > [    4.210000] Sending DHCP requests ., OK
> > > [    4.250000] IP-Config: Got DHCP answer from 10.0.1.1, my address is
> > > 10.0.1.2
> > > [    4.260000] IP-Config: Complete:
> > > [    4.260000]      device=eth0, hwaddr=00:0a:a3:02:12:92,
> ipaddr=10.0.1.2,
> > > mask=255.255.255.0, gw=10.0.1.1
> > > [    4.270000]      host=10.0.1.2, domain=dyn.berto.se, nis-
> domain=(none)
> > > [    4.280000]      bootserver=10.0.1.1, rootserver=10.0.1.1,
> > > rootpath=/srv/nfs4/arch,tcp,v3
> > > [    4.280000]      nameserver0=192.168.20.1
> > > [    4.290000] ALSA device list:
> > > [    4.290000]   No soundcards found.
> > > [    4.320000] VFS: Mounted root (nfs filesystem) on device 0:15.
> > > [    4.320000] devtmpfs: mounted
> > > [    4.330000] Freeing unused kernel image (initmem) memory: 1024K
> > > [    4.390000] Run /sbin/init as init process
> > > [    4.390000]   with arguments:
> > > [    4.390000]     /sbin/init
> > > [    4.400000]   with environment:
> > > [    4.400000]     HOME=/
> > > [    4.400000]     TERM=linux
> > > [    6.040000] systemd[1]: System time before build time, advancing
> clock.
> > > [    6.100000] systemd[1]: Failed to find module 'autofs4'
> > > [    6.220000] systemd[1]: systemd 252.5-1-arch running in system mode
> (+PAM
> > > +AUDIT -SELINUX -APPARMOR -IMA +SMACK +SECCOMP +GCRYPT +GNUTLS
> > > ++OPENSSL +ACL BLKID +CURL +ELFUTILS +FIDO2 +IDN2 -IDN +IPTC +KMOD
> > > ++LIBCRYPTSETUP LIBFDISK +PCRE2 -PWQUALITY +P11KIT -QRENCODE +TPM2
> > > ++BZIP2 +LZ4 +XZ +ZLIB ZSTD +BPF_FRAMEWORK +XKBCOMMON +UTMP
> > > +-SYSVINIT default-hierarchy=unified)
> > > [    6.240000] systemd[1]: Detected architecture arm.
> > > [    6.290000] systemd[1]: Hostname set to <arm>.
> > > [    6.520000] systemd[1]: bpf-lsm: BPF LSM hook not enabled in the
> kernel,
> > > BPF LSM not supported
> > > [    8.710000] systemd[1]: Queued start job for default target Graphical
> > > Interface.
> > > [    8.730000] systemd[1]: Created slice Slice /system/getty.
> > > [    8.770000] systemd[1]: Created slice Slice /system/modprobe.
> > > [    8.810000] systemd[1]: Created slice Slice /system/serial-getty.
> > > [    8.850000] systemd[1]: Created slice User and Session Slice.
> > > [    8.890000] systemd[1]: Started Dispatch Password Requests to Console
> > > Directory Watch.
> > > [    8.930000] systemd[1]: Started Forward Password Requests to Wall
> > > Directory Watch.
> > > [    8.970000] systemd[1]: Arbitrary Executable File Formats File System
> > > Automount Point was skipped because of an unmet condition check
> > > (ConditionPathExists=/proc/sys/fs/binfmt_misc).
> > > [    8.980000] systemd[1]: Reached target Local Encrypted Volumes.
> > > [    9.020000] systemd[1]: Reached target Local Integrity Protected
> Volumes.
> > > [    9.060000] systemd[1]: Reached target Network is Online.
> > > [    9.100000] systemd[1]: Reached target Path Units.
> > > [    9.130000] systemd[1]: Reached target Slice Units.
> > > [    9.170000] systemd[1]: Reached target Swaps.
> > > [    9.200000] systemd[1]: Reached target Local Verity Protected
> Volumes.
> > > [    9.240000] systemd[1]: Listening on Device-mapper event daemon
> FIFOs.
> > > [    9.300000] systemd[1]: Listening on Process Core Dump Socket.
> > > [    9.340000] systemd[1]: Journal Audit Socket was skipped because of
> an
> > > unmet condition check (ConditionSecurity=audit).
> > > [    9.350000] systemd[1]: Listening on Journal Socket (/dev/log).
> > > [    9.390000] systemd[1]: Listening on Journal Socket.
> > > [    9.430000] systemd[1]: Listening on udev Control Socket.
> > > [    9.470000] systemd[1]: Listening on udev Kernel Socket.
> > > [    9.510000] systemd[1]: Huge Pages File System was skipped because of
> an
> > > unmet condition check (ConditionPathExists=/sys/kernel/mm/hugepages).
> > > [    9.520000] systemd[1]: POSIX Message Queue File System was skipped
> > > because of an unmet condition check
> > > (ConditionPathExists=/proc/sys/fs/mqueue).
> > > [    9.590000] systemd[1]: Mounting /root/shared...
> > > [    9.620000] systemd[1]: Mounting Kernel Debug File System...
> > > [    9.680000] systemd[1]: Mounting Kernel Trace File System...
> > > [    9.780000] systemd[1]: Mounting Temporary Directory /tmp...
> > > [    9.820000] systemd[1]: Create List of Static Device Nodes was
> skipped
> > > because of an unmet condition check
> > > (ConditionFileNotEmpty=/lib/modules/6.1.0/modules.devname).
> > > [    9.850000] systemd[1]: Starting Load Kernel Module configfs...
> > > [    9.960000] systemd[1]: Starting Load Kernel Module drm...
> > > [   10.010000] systemd[1]: Starting Load Kernel Module fuse...
> > > [   10.070000] systemd[1]: Load Kernel Modules was skipped because no
> > > trigger condition checks were met.
> > > [   10.120000] systemd[1]: Starting Remount Root and Kernel File
> Systems...
> > > [   10.190000] systemd[1]: Repartition Root Disk was skipped because no
> > > trigger condition checks were met.
> > > [   10.250000] systemd[1]: Starting Apply Kernel Variables...
> > > [   10.310000] systemd[1]: Starting Coldplug All udev Devices...
> > > [   10.390000] systemd[1]: Mounted Kernel Debug File System.
> > > [   10.410000] systemd[1]: Mounted Kernel Trace File System.
> > > [   10.450000] systemd[1]: Mounted Temporary Directory /tmp.
> > > [   10.490000] systemd[1]: modprobe@configfs.service: Deactivated
> > > successfully.
> > > [   10.520000] systemd[1]: Finished Load Kernel Module configfs.
> > > [   10.550000] systemd[1]: modprobe@drm.service: Deactivated
> successfully.
> > > [   10.550000] systemd[1]: Finished Load Kernel Module drm.
> > > [   10.600000] systemd[1]: modprobe@fuse.service: Deactivated
> successfully.
> > > [   10.610000] systemd[1]: Finished Load Kernel Module fuse.
> > > [   10.650000] systemd[1]: Finished Remount Root and Kernel File
> Systems.
> > > [   10.670000] systemd[1]: Finished Apply Kernel Variables.
> > > [   10.890000] systemd[1]: Reached target Host and Network Name Lookups.
> > > [   10.940000] systemd[1]: Listening on RPCbind Server Activation
> Socket.
> > > [   10.990000] systemd[1]: Reached target RPC Port Mapper.
> > > [   11.030000] systemd[1]: FUSE Control File System was skipped because
> of
> > > an unmet condition check (ConditionPathExists=/sys/fs/fuse/connections).
> > > [   11.090000] systemd[1]: Mounting Kernel Configuration File System...
> > > [   11.130000] systemd[1]: Starting NFS status monitor for NFSv2/3
> > > locking....
> > > [   11.180000] systemd[1]: First Boot Wizard was skipped because of an
> unmet
> > > condition check (ConditionFirstBoot=yes).
> > > [   11.210000] systemd[1]: Rebuild Hardware Database was skipped because
> of
> > > an unmet condition check (ConditionNeedsUpdate=/etc).
> > > [   11.290000] systemd[1]: Starting Load/Save Random Seed...
> > > [   11.330000] systemd[1]: Create System Users was skipped because no
> > > trigger condition checks were met.
> > > [   11.380000] systemd[1]: Starting Create Static Device Nodes in
> /dev...
> > > [   11.500000] systemd[1]: Finished Coldplug All udev Devices.
> > > [   11.540000] systemd[1]: Mounted Kernel Configuration File System.
> > > [   11.620000] systemd[1]: Starting RPC Bind...
> > > [   12.160000] systemd[1]: Finished Create Static Device Nodes in /dev.
> > > [   12.200000] systemd[1]: Started RPC Bind.
> > > [   12.240000] systemd[1]: Reached target Preparation for Local File
> > > Systems.
> > > [   12.290000] systemd[1]: Virtual Machine and Container Storage
> > > (Compatibility) was skipped because of an unmet condition check
> > > (ConditionPathExists=/var/lib/machines.raw).
> > > [   12.310000] systemd[1]: Reached target Local File Systems.
> > > [   12.350000] systemd[1]: Entropy Daemon based on the HAVEGE algorithm
> was
> > > skipped because of an unmet condition check
> (ConditionKernelVersion=<5.6).
> > > [   12.360000] systemd[1]: Rebuild Dynamic Linker Cache was skipped
> because
> > > no trigger condition checks were met.
> > > [   12.420000] systemd[1]: Starting Notify NFS peers of a restart...
> > > [   12.460000] systemd[1]: Set Up Additional Binary Formats was skipped
> > > because no trigger condition checks were met.
> > > [   12.480000] systemd[1]: systemd-journald.service: unit configures an
> IP
> > > firewall, but the local system does not support BPF/cgroup firewalling.
> > > [   12.490000] systemd[1]: (This warning is only shown for the first
> unit
> > > using IP firewalling.)
> > > [   12.570000] systemd[1]: Starting Journal Service...
> > > [   12.620000] systemd[1]: Starting Rule-based Manager for Device Events
> and
> > > Files...
> > > [   12.700000] systemd[1]: Started NFS status monitor for NFSv2/3
> locking..
> > > [   12.740000] systemd[1]: Started Notify NFS peers of a restart.
> > > [   12.990000] systemd[1]: Started Journal Service.
> > > [   16.860000] systemd-journald[87]: Received client request to flush
> > > runtime journal.
> > > [   21.360000] random: dbus-daemon: uninitialized urandom read (12 bytes
> > > read)
> > > [   22.190000] random: dbus-daemon: uninitialized urandom read (12 bytes
> > > read)
> > > [   39.150000] random: crng init done
> > >
> > > --
> > > Kind Regards,
> > > Niklas Söderlund
> 
> --
> Kind Regards,
> Niklas Söderlund

^ permalink raw reply

* RE: [PATCH v3 3/3] serial: 8250_em: Add serial_out() to struct serial8250_em_hw_info
From: Biju Das @ 2023-02-13 12:18 UTC (permalink / raw)
  To: Ilpo Järvinen
  Cc: Jiri Slaby, Geert Uytterhoeven, Magnus Damm,
	Niklas Söderlund, Greg Kroah-Hartman, linux-serial,
	Fabrizio Castro, linux-renesas-soc@vger.kernel.org
In-Reply-To: <c2e6e9c4-9342-45df-401e-8dffa881e8@linux.intel.com>

Hi Ilpo Järvinen,

Thanks for feedback.

> -----Original Message-----
> From: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
> Sent: Monday, February 13, 2023 12:05 PM
> To: Biju Das <biju.das.jz@bp.renesas.com>
> Cc: Jiri Slaby <jirislaby@kernel.org>; Geert Uytterhoeven
> <geert+renesas@glider.be>; Magnus Damm <magnus.damm@gmail.com>; Niklas
> Söderlund <niklas.soderlund@ragnatech.se>; Greg Kroah-Hartman
> <gregkh@linuxfoundation.org>; linux-serial <linux-serial@vger.kernel.org>;
> Fabrizio Castro <fabrizio.castro.jz@renesas.com>; linux-renesas-
> soc@vger.kernel.org
> Subject: RE: [PATCH v3 3/3] serial: 8250_em: Add serial_out() to struct
> serial8250_em_hw_info
> 
> On Mon, 13 Feb 2023, Biju Das wrote:
> 
> > Hi Ilpo,
> >
> > Thanks for the feedback.
> >
> > > Subject: RE: [PATCH v3 3/3] serial: 8250_em: Add serial_out() to
> > > struct serial8250_em_hw_info
> > >
> > > On Mon, 13 Feb 2023, Biju Das wrote:
> > >
> > > > Hi Jiri Slaby,
> > > >
> > > > Thanks for the feedback.
> > > >
> > > > > Subject: Re: [PATCH v3 3/3] serial: 8250_em: Add serial_out() to
> > > > > struct serial8250_em_hw_info
> > > > >
> > > > > On 13. 02. 23, 10:31, Biju Das wrote:
> > > > > > So looks like similar to other macros, UART_FCR_EM (0x3) is
> > > > > > sensible
> > > one.
> > > > > >
> > > > > > UART_FCR_RO_OFFSET (9)
> > > > > > UART_FCR_RO_EM (UART_FCR_EM + UART_FCR_RO_OFFSET)
> > > > > >
> > > > > >
> > > > > > static unsigned int serial8250_em_serial_in(struct uart_port
> > > > > > *p, int
> > > > > > offset) case UART_FCR_RO_EM:
> > > > > > 	return readl(p->membase + (offset - UART_FCR_RO_OFFSET <<
> > > > > > 2));
> > > > >
> > > > >
> > > > > Please send a complete patch as a reply. I am completely lost now.
> > > >
> > > > Please find the complete patc.
> > > >
> > > >
> > > > From e597ae60eb170c1f1b650e1e533bf4e12c09f822 Mon Sep 17 00:00:00
> > > > 2001
> > > > From: Biju Das <biju.das.jz@bp.renesas.com>
> > > > Date: Tue, 7 Feb 2023 15:07:13 +0000
> > > > Subject: [PATCH] serial: 8250_em: Add serial_out() to struct
> > > > serial8250_em_hw_info
> > > >
> > > > As per RZ/V2M hardware manual(Rev.1.30 Jun, 2022), UART IP has a
> > > > restriction as mentioned below.
> > > >
> > > > 40.6.1 Point for Caution when Changing the Register Settings:
> > > >
> > > > When changing the settings of the following registers, a PRESETn
> > > > master reset or FIFO reset + SW reset (FCR[2],FCR[1], HCR0[7])
> > > > must be input to re-initialize them.
> > > >
> > > > Target Registers: FCR, LCR, MCR, DLL, DLM, HCR0.
> > > >
> > > > This patch adds serial_out() to struct serial8250_em_hw_info to
> > > > handle this difference between emma mobile and rz/v2m.
> > > >
> > > > DLL/DLM register can be updated only by setting LCR[7]. So the
> > > > updation of LCR[7] will perform reset for DLL/DLM register changes.
> > > >
> > > > Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
> > > > ---
> > > >  drivers/tty/serial/8250/8250_em.c | 70
> > > > ++++++++++++++++++++++++++++++-
> > > >  1 file changed, 69 insertions(+), 1 deletion(-)
> > > >
> > > > diff --git a/drivers/tty/serial/8250/8250_em.c
> > > > b/drivers/tty/serial/8250/8250_em.c
> > > > index 69cd3b611501..c1c64f48ee7e 100644
> > > > --- a/drivers/tty/serial/8250/8250_em.c
> > > > +++ b/drivers/tty/serial/8250/8250_em.c
> > > > @@ -17,12 +17,23 @@
> > > >
> > > >  #include "8250.h"
> > > >
> > > > +#define UART_FCR_EM 3
> > > >  #define UART_DLL_EM 9
> > > >  #define UART_DLM_EM 10
> > > > +#define UART_HCR0_EM 11
> > > > +
> > > > +#define UART_FCR_R_EM	(UART_FCR_EM + UART_HCR0_EM)
> > >
> > > It's easy to lose track of all this, IMHO this would be simple:
> > >
> > > /*
> > >  * A high value for UART_FCR_EM avoids overlapping with existing
> > > UART_*
> > >  * register defines. UART_FCR_EM_HW is the real HW register offset.
> > >  */
> > > #define UART_FCR_EM 12
> >
> > I will change it to #define UART_FCR_EM 14
> >
> > And will add the below unused HW status registers in the driver.
> >
> > #define UART_HCR2_EM 12 (@30)
> > #define UART_HCR3_EM 13 (@34)
> >
> > Is it ok?
> 
> It's okay, that number is pseudo one anyway so the actual number doesn't
> matter. One could just as well pick some large number such as 0x10003 or so
> if the collision with real regs is a concern.

OK will use 0x10003, as pseudo offset.

Cheers,
Biju

^ permalink raw reply

* Re: [PATCH v5 1/1] tty: n_gsm: add keep alive support
From: m.brock @ 2023-02-13 11:10 UTC (permalink / raw)
  To: D. Starke; +Cc: linux-serial, gregkh, jirislaby, ilpo.jarvinen, linux-kernel
In-Reply-To: <20230213094327.3428-1-daniel.starke@siemens.com>

D. Starke schreef op 2023-02-13 10:43:
> From: Daniel Starke <daniel.starke@siemens.com>
> +	u32 keep_alive;		/* Control channel keep-alive in ms */
[...]
> +		if (dlci && !dlci->dead)
> +			mod_timer(&gsm->ka_timer, jiffies + gsm->keep_alive * HZ / 100);

keep-alive is in ms? or in 10ms?

Maarten


^ permalink raw reply

* RE: [PATCH v3 3/3] serial: 8250_em: Add serial_out() to struct serial8250_em_hw_info
From: Ilpo Järvinen @ 2023-02-13 12:05 UTC (permalink / raw)
  To: Biju Das
  Cc: Jiri Slaby, Geert Uytterhoeven, Magnus Damm,
	Niklas Söderlund, Greg Kroah-Hartman, linux-serial,
	Fabrizio Castro, linux-renesas-soc@vger.kernel.org
In-Reply-To: <OS0PR01MB59227AE1C2A89B75DFBF8F8286DD9@OS0PR01MB5922.jpnprd01.prod.outlook.com>

On Mon, 13 Feb 2023, Biju Das wrote:

> Hi Ilpo,
> 
> Thanks for the feedback.
> 
> > Subject: RE: [PATCH v3 3/3] serial: 8250_em: Add serial_out() to struct
> > serial8250_em_hw_info
> > 
> > On Mon, 13 Feb 2023, Biju Das wrote:
> > 
> > > Hi Jiri Slaby,
> > >
> > > Thanks for the feedback.
> > >
> > > > Subject: Re: [PATCH v3 3/3] serial: 8250_em: Add serial_out() to
> > > > struct serial8250_em_hw_info
> > > >
> > > > On 13. 02. 23, 10:31, Biju Das wrote:
> > > > > So looks like similar to other macros, UART_FCR_EM (0x3) is sensible
> > one.
> > > > >
> > > > > UART_FCR_RO_OFFSET (9)
> > > > > UART_FCR_RO_EM (UART_FCR_EM + UART_FCR_RO_OFFSET)
> > > > >
> > > > >
> > > > > static unsigned int serial8250_em_serial_in(struct uart_port *p,
> > > > > int
> > > > > offset) case UART_FCR_RO_EM:
> > > > > 	return readl(p->membase + (offset - UART_FCR_RO_OFFSET << 2));
> > > >
> > > >
> > > > Please send a complete patch as a reply. I am completely lost now.
> > >
> > > Please find the complete patc.
> > >
> > >
> > > From e597ae60eb170c1f1b650e1e533bf4e12c09f822 Mon Sep 17 00:00:00 2001
> > > From: Biju Das <biju.das.jz@bp.renesas.com>
> > > Date: Tue, 7 Feb 2023 15:07:13 +0000
> > > Subject: [PATCH] serial: 8250_em: Add serial_out() to struct
> > > serial8250_em_hw_info
> > >
> > > As per RZ/V2M hardware manual(Rev.1.30 Jun, 2022), UART IP has a
> > > restriction as mentioned below.
> > >
> > > 40.6.1 Point for Caution when Changing the Register Settings:
> > >
> > > When changing the settings of the following registers, a PRESETn
> > > master reset or FIFO reset + SW reset (FCR[2],FCR[1], HCR0[7]) must be
> > > input to re-initialize them.
> > >
> > > Target Registers: FCR, LCR, MCR, DLL, DLM, HCR0.
> > >
> > > This patch adds serial_out() to struct serial8250_em_hw_info to handle
> > > this difference between emma mobile and rz/v2m.
> > >
> > > DLL/DLM register can be updated only by setting LCR[7]. So the
> > > updation of LCR[7] will perform reset for DLL/DLM register changes.
> > >
> > > Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
> > > ---
> > >  drivers/tty/serial/8250/8250_em.c | 70
> > > ++++++++++++++++++++++++++++++-
> > >  1 file changed, 69 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/drivers/tty/serial/8250/8250_em.c
> > > b/drivers/tty/serial/8250/8250_em.c
> > > index 69cd3b611501..c1c64f48ee7e 100644
> > > --- a/drivers/tty/serial/8250/8250_em.c
> > > +++ b/drivers/tty/serial/8250/8250_em.c
> > > @@ -17,12 +17,23 @@
> > >
> > >  #include "8250.h"
> > >
> > > +#define UART_FCR_EM 3
> > >  #define UART_DLL_EM 9
> > >  #define UART_DLM_EM 10
> > > +#define UART_HCR0_EM 11
> > > +
> > > +#define UART_FCR_R_EM	(UART_FCR_EM + UART_HCR0_EM)
> > 
> > It's easy to lose track of all this, IMHO this would be simple:
> > 
> > /*
> >  * A high value for UART_FCR_EM avoids overlapping with existing UART_*
> >  * register defines. UART_FCR_EM_HW is the real HW register offset.
> >  */
> > #define UART_FCR_EM 12
> 
> I will change it to #define UART_FCR_EM 14 
> 
> And will add the below unused HW status registers in the driver.
> 
> #define UART_HCR2_EM 12 (@30)
> #define UART_HCR3_EM 13 (@34)
> 
> Is it ok?

It's okay, that number is pseudo one anyway so the actual number doesn't 
matter. One could just as well pick some large number such as 0x10003 or
so if the collision with real regs is a concern.

-- 
 i.


^ permalink raw reply

* RE: [PATCH v3 3/3] serial: 8250_em: Add serial_out() to struct serial8250_em_hw_info
From: Biju Das @ 2023-02-13 11:40 UTC (permalink / raw)
  To: Ilpo Järvinen
  Cc: Jiri Slaby, Geert Uytterhoeven, Magnus Damm,
	Niklas Söderlund, Greg Kroah-Hartman, linux-serial,
	Fabrizio Castro, linux-renesas-soc@vger.kernel.org
In-Reply-To: <4cfed9ad-bf89-7b1-40cd-7def4c64f1@linux.intel.com>

Hi Ilpo,

Thanks for the feedback.

> Subject: RE: [PATCH v3 3/3] serial: 8250_em: Add serial_out() to struct
> serial8250_em_hw_info
> 
> On Mon, 13 Feb 2023, Biju Das wrote:
> 
> > Hi Jiri Slaby,
> >
> > Thanks for the feedback.
> >
> > > Subject: Re: [PATCH v3 3/3] serial: 8250_em: Add serial_out() to
> > > struct serial8250_em_hw_info
> > >
> > > On 13. 02. 23, 10:31, Biju Das wrote:
> > > > So looks like similar to other macros, UART_FCR_EM (0x3) is sensible
> one.
> > > >
> > > > UART_FCR_RO_OFFSET (9)
> > > > UART_FCR_RO_EM (UART_FCR_EM + UART_FCR_RO_OFFSET)
> > > >
> > > >
> > > > static unsigned int serial8250_em_serial_in(struct uart_port *p,
> > > > int
> > > > offset) case UART_FCR_RO_EM:
> > > > 	return readl(p->membase + (offset - UART_FCR_RO_OFFSET << 2));
> > >
> > >
> > > Please send a complete patch as a reply. I am completely lost now.
> >
> > Please find the complete patc.
> >
> >
> > From e597ae60eb170c1f1b650e1e533bf4e12c09f822 Mon Sep 17 00:00:00 2001
> > From: Biju Das <biju.das.jz@bp.renesas.com>
> > Date: Tue, 7 Feb 2023 15:07:13 +0000
> > Subject: [PATCH] serial: 8250_em: Add serial_out() to struct
> > serial8250_em_hw_info
> >
> > As per RZ/V2M hardware manual(Rev.1.30 Jun, 2022), UART IP has a
> > restriction as mentioned below.
> >
> > 40.6.1 Point for Caution when Changing the Register Settings:
> >
> > When changing the settings of the following registers, a PRESETn
> > master reset or FIFO reset + SW reset (FCR[2],FCR[1], HCR0[7]) must be
> > input to re-initialize them.
> >
> > Target Registers: FCR, LCR, MCR, DLL, DLM, HCR0.
> >
> > This patch adds serial_out() to struct serial8250_em_hw_info to handle
> > this difference between emma mobile and rz/v2m.
> >
> > DLL/DLM register can be updated only by setting LCR[7]. So the
> > updation of LCR[7] will perform reset for DLL/DLM register changes.
> >
> > Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
> > ---
> >  drivers/tty/serial/8250/8250_em.c | 70
> > ++++++++++++++++++++++++++++++-
> >  1 file changed, 69 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/tty/serial/8250/8250_em.c
> > b/drivers/tty/serial/8250/8250_em.c
> > index 69cd3b611501..c1c64f48ee7e 100644
> > --- a/drivers/tty/serial/8250/8250_em.c
> > +++ b/drivers/tty/serial/8250/8250_em.c
> > @@ -17,12 +17,23 @@
> >
> >  #include "8250.h"
> >
> > +#define UART_FCR_EM 3
> >  #define UART_DLL_EM 9
> >  #define UART_DLM_EM 10
> > +#define UART_HCR0_EM 11
> > +
> > +#define UART_FCR_R_EM	(UART_FCR_EM + UART_HCR0_EM)
> 
> It's easy to lose track of all this, IMHO this would be simple:
> 
> /*
>  * A high value for UART_FCR_EM avoids overlapping with existing UART_*
>  * register defines. UART_FCR_EM_HW is the real HW register offset.
>  */
> #define UART_FCR_EM 12

I will change it to #define UART_FCR_EM 14 

And will add the below unused HW status registers in the driver.

#define UART_HCR2_EM 12 (@30)
#define UART_HCR3_EM 13 (@34)

Is it ok?

Cheers,
Biju

> #define UART_FCR_EM_HW 3
> 
> Then use UART_FCR_EM consistently within the function you add for RZ so
> you'd need provide both _in/_out with UART_FCR_EM. (You'll have both
> UART_FCR and UART_FCR_EM cases in _out but that seems fine, IMHO).
> 
> To me that would look the cleanest workaround to the overlapping defines.
> 
> --
>  i.
> 
> 
> > +#define UART_HCR0_EM_SW_RESET	BIT(7) /* SW Reset */
> >
> >  struct serial8250_em_hw_info {
> >  	unsigned int type;
> >  	upf_t flags;
> > +	void (*serial_out)(struct uart_port *p, int off, int value);
> >  };
> >
> >  struct serial8250_em_priv {
> > @@ -46,6 +57,7 @@ static void serial8250_em_serial_out(struct uart_port
> *p, int offset, int value)
> >  		fallthrough;
> >  	case UART_DLL_EM: /* DLL @ 0x24 (+9) */
> >  	case UART_DLM_EM: /* DLM @ 0x28 (+9) */
> > +	case UART_HCR0_EM: /* HCR0 @ 0x2c */
> >  		writel(value, p->membase + (offset << 2));
> >  	}
> >  }
> > @@ -55,20 +67,74 @@ static unsigned int serial8250_em_serial_in(struct
> uart_port *p, int offset)
> >  	switch (offset) {
> >  	case UART_RX: /* RX @ 0x00 */
> >  		return readb(p->membase);
> > +	case UART_LCR: /* LCR @ 0x10 (+1) */
> >  	case UART_MCR: /* MCR @ 0x14 (+1) */
> >  	case UART_LSR: /* LSR @ 0x18 (+1) */
> >  	case UART_MSR: /* MSR @ 0x1c (+1) */
> >  	case UART_SCR: /* SCR @ 0x20 (+1) */
> >  		return readl(p->membase + ((offset + 1) << 2));
> > +	case UART_FCR_R_EM:
> > +		return readl(p->membase + (UART_FCR_EM << 2));
> >  	case UART_IER: /* IER @ 0x04 */
> >  	case UART_IIR: /* IIR @ 0x08 */
> >  	case UART_DLL_EM: /* DLL @ 0x24 (+9) */
> >  	case UART_DLM_EM: /* DLM @ 0x28 (+9) */
> > +	case UART_HCR0_EM: /* HCR0 @ 0x2c */
> >  		return readl(p->membase + (offset << 2));
> >  	}
> >  	return 0;
> >  }
> >
> > +static void serial8250_rzv2m_reg_update(struct uart_port *p, int off, int
> value)
> > +{
> > +	unsigned int ier, fcr, lcr, mcr, hcr0;
> > +
> > +	ier = serial8250_em_serial_in(p, UART_IER);
> > +	fcr = serial8250_em_serial_in(p, UART_FCR_R_EM);
> > +	lcr = serial8250_em_serial_in(p, UART_LCR);
> > +	mcr = serial8250_em_serial_in(p, UART_MCR);
> > +	hcr0 = serial8250_em_serial_in(p, UART_HCR0_EM);
> > +
> > +	serial8250_em_serial_out(p, UART_FCR, fcr | UART_FCR_CLEAR_RCVR |
> > +				 UART_FCR_CLEAR_XMIT);
> > +	serial8250_em_serial_out(p, UART_HCR0_EM, hcr0 |
> UART_HCR0_EM_SW_RESET);
> > +	serial8250_em_serial_out(p, UART_HCR0_EM, hcr0 &
> ~UART_HCR0_EM_SW_RESET);
> > +
> > +	switch (off) {
> > +	case UART_FCR:
> > +		fcr = value;
> > +		break;
> > +	case UART_LCR:
> > +		lcr = value;
> > +		break;
> > +	case UART_MCR:
> > +		mcr = value;
> > +	}
> > +
> > +	serial8250_em_serial_out(p, UART_IER, ier);
> > +	serial8250_em_serial_out(p, UART_FCR, fcr);
> > +	serial8250_em_serial_out(p, UART_MCR, mcr);
> > +	serial8250_em_serial_out(p, UART_LCR, lcr);
> > +	serial8250_em_serial_out(p, UART_HCR0_EM, hcr0);
> > +}
> > +
> > +static void serial8250_em_rzv2m_serial_out(struct uart_port *p, int
> offset, int value)
> > +{
> > +	switch (offset) {
> > +	case UART_TX:
> > +	case UART_SCR:
> > +	case UART_IER:
> > +	case UART_DLL_EM:
> > +	case UART_DLM_EM:
> > +		serial8250_em_serial_out(p, offset, value);
> > +		break;
> > +	case UART_FCR:
> > +	case UART_LCR:
> > +	case UART_MCR:
> > +		serial8250_rzv2m_reg_update(p, offset, value);
> > +	}
> > +}
> > +
> >  static int serial8250_em_serial_dl_read(struct uart_8250_port *up)
> >  {
> >  	return serial_in(up, UART_DLL_EM) | serial_in(up, UART_DLM_EM) << 8;
> > @@ -120,7 +186,7 @@ static int serial8250_em_probe(struct platform_device
> *pdev)
> >
> >  	up.port.iotype = UPIO_MEM32;
> >  	up.port.serial_in = serial8250_em_serial_in;
> > -	up.port.serial_out = serial8250_em_serial_out;
> > +	up.port.serial_out = info->serial_out;
> >  	up.dl_read = serial8250_em_serial_dl_read;
> >  	up.dl_write = serial8250_em_serial_dl_write;
> >
> > @@ -144,11 +210,13 @@ static int serial8250_em_remove(struct
> platform_device *pdev)
> >  static const struct serial8250_em_hw_info emma_mobile_uart_hw_info = {
> >  	.type = PORT_UNKNOWN,
> >  	.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT | UPF_IOREMAP,
> > +	.serial_out = serial8250_em_serial_out,
> >  };
> >
> >  static const struct serial8250_em_hw_info rzv2m_uart_hw_info = {
> >  	.type = PORT_16750,
> >  	.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT | UPF_IOREMAP |
> UPF_FIXED_TYPE,
> > +	.serial_out = serial8250_em_rzv2m_serial_out,
> >  };
> >
> >  static const struct of_device_id serial8250_em_dt_ids[] = {
> >

^ permalink raw reply

* RE: [PATCH v5 1/1] tty: n_gsm: add keep alive support
From: Starke, Daniel @ 2023-02-13 11:32 UTC (permalink / raw)
  To: m.brock@vanmierlo.com
  Cc: linux-serial@vger.kernel.org, gregkh@linuxfoundation.org,
	jirislaby@kernel.org, ilpo.jarvinen@linux.intel.com,
	linux-kernel@vger.kernel.org
In-Reply-To: <aec7575cd784ae4fe9e9f2c1e08107a9@vanmierlo.com>

> > From: Daniel Starke <daniel.starke@siemens.com>
> > +	u32 keep_alive;		/* Control channel keep-alive in ms */
> [...]
> > +		if (dlci && !dlci->dead)
> > +			mod_timer(&gsm->ka_timer, jiffies + gsm->keep_alive * HZ / 100);
> 
> keep-alive is in ms? or in 10ms?

Good found. The comment is wrong. It is in 10ms as also written in the
comment for "keep_alive" within gsmmux.h to be in line with t1 and t2.
I will correct this for v6 of the patch.

Best regards,
Daniel Starke

^ permalink raw reply

* RE: [PATCH v3 3/3] serial: 8250_em: Add serial_out() to struct serial8250_em_hw_info
From: Ilpo Järvinen @ 2023-02-13 11:31 UTC (permalink / raw)
  To: Biju Das
  Cc: Jiri Slaby, Geert Uytterhoeven, Magnus Damm,
	Niklas Söderlund, Greg Kroah-Hartman, linux-serial,
	Fabrizio Castro, linux-renesas-soc@vger.kernel.org
In-Reply-To: <OS0PR01MB5922139BA73BBBE2556161DA86DD9@OS0PR01MB5922.jpnprd01.prod.outlook.com>

On Mon, 13 Feb 2023, Biju Das wrote:

> Hi Jiri Slaby,
> 
> Thanks for the feedback.
> 
> > Subject: Re: [PATCH v3 3/3] serial: 8250_em: Add serial_out() to struct
> > serial8250_em_hw_info
> > 
> > On 13. 02. 23, 10:31, Biju Das wrote:
> > > So looks like similar to other macros, UART_FCR_EM (0x3) is sensible one.
> > >
> > > UART_FCR_RO_OFFSET (9)
> > > UART_FCR_RO_EM (UART_FCR_EM + UART_FCR_RO_OFFSET)
> > >
> > >
> > > static unsigned int serial8250_em_serial_in(struct uart_port *p, int
> > > offset) case UART_FCR_RO_EM:
> > > 	return readl(p->membase + (offset - UART_FCR_RO_OFFSET << 2));
> > 
> > 
> > Please send a complete patch as a reply. I am completely lost now.
> 
> Please find the complete patc.
> 
> 
> From e597ae60eb170c1f1b650e1e533bf4e12c09f822 Mon Sep 17 00:00:00 2001
> From: Biju Das <biju.das.jz@bp.renesas.com>
> Date: Tue, 7 Feb 2023 15:07:13 +0000
> Subject: [PATCH] serial: 8250_em: Add serial_out() to struct
>  serial8250_em_hw_info
> 
> As per RZ/V2M hardware manual(Rev.1.30 Jun, 2022), UART IP has a
> restriction as mentioned below.
> 
> 40.6.1 Point for Caution when Changing the Register Settings:
> 
> When changing the settings of the following registers, a PRESETn master
> reset or FIFO reset + SW reset (FCR[2],FCR[1], HCR0[7]) must be input to
> re-initialize them.
> 
> Target Registers: FCR, LCR, MCR, DLL, DLM, HCR0.
> 
> This patch adds serial_out() to struct serial8250_em_hw_info to
> handle this difference between emma mobile and rz/v2m.
> 
> DLL/DLM register can be updated only by setting LCR[7]. So the
> updation of LCR[7] will perform reset for DLL/DLM register changes.
> 
> Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
> ---
>  drivers/tty/serial/8250/8250_em.c | 70 ++++++++++++++++++++++++++++++-
>  1 file changed, 69 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/tty/serial/8250/8250_em.c b/drivers/tty/serial/8250/8250_em.c
> index 69cd3b611501..c1c64f48ee7e 100644
> --- a/drivers/tty/serial/8250/8250_em.c
> +++ b/drivers/tty/serial/8250/8250_em.c
> @@ -17,12 +17,23 @@
>  
>  #include "8250.h"
>  
> +#define UART_FCR_EM 3
>  #define UART_DLL_EM 9
>  #define UART_DLM_EM 10
> +#define UART_HCR0_EM 11
> +
> +#define UART_FCR_R_EM	(UART_FCR_EM + UART_HCR0_EM)

It's easy to lose track of all this, IMHO this would be simple:

/*
 * A high value for UART_FCR_EM avoids overlapping with existing UART_* 
 * register defines. UART_FCR_EM_HW is the real HW register offset.
 */
#define UART_FCR_EM 12
#define UART_FCR_EM_HW 3

Then use UART_FCR_EM consistently within the function you add for RZ so 
you'd need provide both _in/_out with UART_FCR_EM. (You'll have both 
UART_FCR and UART_FCR_EM cases in _out but that seems fine, IMHO).

To me that would look the cleanest workaround to the overlapping defines.

-- 
 i.


> +#define UART_HCR0_EM_SW_RESET	BIT(7) /* SW Reset */
>  
>  struct serial8250_em_hw_info {
>  	unsigned int type;
>  	upf_t flags;
> +	void (*serial_out)(struct uart_port *p, int off, int value);
>  };
>  
>  struct serial8250_em_priv {
> @@ -46,6 +57,7 @@ static void serial8250_em_serial_out(struct uart_port *p, int offset, int value)
>  		fallthrough;
>  	case UART_DLL_EM: /* DLL @ 0x24 (+9) */
>  	case UART_DLM_EM: /* DLM @ 0x28 (+9) */
> +	case UART_HCR0_EM: /* HCR0 @ 0x2c */
>  		writel(value, p->membase + (offset << 2));
>  	}
>  }
> @@ -55,20 +67,74 @@ static unsigned int serial8250_em_serial_in(struct uart_port *p, int offset)
>  	switch (offset) {
>  	case UART_RX: /* RX @ 0x00 */
>  		return readb(p->membase);
> +	case UART_LCR: /* LCR @ 0x10 (+1) */
>  	case UART_MCR: /* MCR @ 0x14 (+1) */
>  	case UART_LSR: /* LSR @ 0x18 (+1) */
>  	case UART_MSR: /* MSR @ 0x1c (+1) */
>  	case UART_SCR: /* SCR @ 0x20 (+1) */
>  		return readl(p->membase + ((offset + 1) << 2));
> +	case UART_FCR_R_EM:
> +		return readl(p->membase + (UART_FCR_EM << 2));
>  	case UART_IER: /* IER @ 0x04 */
>  	case UART_IIR: /* IIR @ 0x08 */
>  	case UART_DLL_EM: /* DLL @ 0x24 (+9) */
>  	case UART_DLM_EM: /* DLM @ 0x28 (+9) */
> +	case UART_HCR0_EM: /* HCR0 @ 0x2c */
>  		return readl(p->membase + (offset << 2));
>  	}
>  	return 0;
>  }
>  
> +static void serial8250_rzv2m_reg_update(struct uart_port *p, int off, int value)
> +{
> +	unsigned int ier, fcr, lcr, mcr, hcr0;
> +
> +	ier = serial8250_em_serial_in(p, UART_IER);
> +	fcr = serial8250_em_serial_in(p, UART_FCR_R_EM);
> +	lcr = serial8250_em_serial_in(p, UART_LCR);
> +	mcr = serial8250_em_serial_in(p, UART_MCR);
> +	hcr0 = serial8250_em_serial_in(p, UART_HCR0_EM);
> +
> +	serial8250_em_serial_out(p, UART_FCR, fcr | UART_FCR_CLEAR_RCVR |
> +				 UART_FCR_CLEAR_XMIT);
> +	serial8250_em_serial_out(p, UART_HCR0_EM, hcr0 | UART_HCR0_EM_SW_RESET);
> +	serial8250_em_serial_out(p, UART_HCR0_EM, hcr0 & ~UART_HCR0_EM_SW_RESET);
> +
> +	switch (off) {
> +	case UART_FCR:
> +		fcr = value;
> +		break;
> +	case UART_LCR:
> +		lcr = value;
> +		break;
> +	case UART_MCR:
> +		mcr = value;
> +	}
> +
> +	serial8250_em_serial_out(p, UART_IER, ier);
> +	serial8250_em_serial_out(p, UART_FCR, fcr);
> +	serial8250_em_serial_out(p, UART_MCR, mcr);
> +	serial8250_em_serial_out(p, UART_LCR, lcr);
> +	serial8250_em_serial_out(p, UART_HCR0_EM, hcr0);
> +}
> +
> +static void serial8250_em_rzv2m_serial_out(struct uart_port *p, int offset, int value)
> +{
> +	switch (offset) {
> +	case UART_TX:
> +	case UART_SCR:
> +	case UART_IER:
> +	case UART_DLL_EM:
> +	case UART_DLM_EM:
> +		serial8250_em_serial_out(p, offset, value);
> +		break;
> +	case UART_FCR:
> +	case UART_LCR:
> +	case UART_MCR:
> +		serial8250_rzv2m_reg_update(p, offset, value);
> +	}
> +}
> +
>  static int serial8250_em_serial_dl_read(struct uart_8250_port *up)
>  {
>  	return serial_in(up, UART_DLL_EM) | serial_in(up, UART_DLM_EM) << 8;
> @@ -120,7 +186,7 @@ static int serial8250_em_probe(struct platform_device *pdev)
>  
>  	up.port.iotype = UPIO_MEM32;
>  	up.port.serial_in = serial8250_em_serial_in;
> -	up.port.serial_out = serial8250_em_serial_out;
> +	up.port.serial_out = info->serial_out;
>  	up.dl_read = serial8250_em_serial_dl_read;
>  	up.dl_write = serial8250_em_serial_dl_write;
>  
> @@ -144,11 +210,13 @@ static int serial8250_em_remove(struct platform_device *pdev)
>  static const struct serial8250_em_hw_info emma_mobile_uart_hw_info = {
>  	.type = PORT_UNKNOWN,
>  	.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT | UPF_IOREMAP,
> +	.serial_out = serial8250_em_serial_out,
>  };
>  
>  static const struct serial8250_em_hw_info rzv2m_uart_hw_info = {
>  	.type = PORT_16750,
>  	.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT | UPF_IOREMAP | UPF_FIXED_TYPE,
> +	.serial_out = serial8250_em_rzv2m_serial_out,
>  };
>  
>  static const struct of_device_id serial8250_em_dt_ids[] = {
> 

^ permalink raw reply

* Re: [Linux-stm32] [PATCH v3 6/6] ARM: dts: stm32: add ETZPC as a system bus for STM32MP13x boards
From: Ahmad Fatoum @ 2023-02-13 11:27 UTC (permalink / raw)
  To: Gatien CHEVALLIER, Oleksii_Moisieiev, gregkh, herbert, davem,
	robh+dt, krzysztof.kozlowski+dt, alexandre.torgue, vkoul, jic23,
	olivier.moysan, arnaud.pouliquen, mchehab, fabrice.gasnier,
	ulf.hansson, edumazet, kuba, pabeni
  Cc: devicetree, alsa-devel, linux-iio, netdev, linux-usb, linux-mmc,
	linux-kernel, linux-spi, linux-i2c, dmaengine, linux-crypto,
	linux-serial, linux-phy, linux-stm32, linux-arm-kernel,
	linux-media, Pengutronix Kernel Team
In-Reply-To: <837908e8-8ace-5c2e-f9fb-8b50054426f2@foss.st.com>

Hello Gatien,

On 13.02.23 11:54, Gatien CHEVALLIER wrote:
> On 2/9/23 09:10, Ahmad Fatoum wrote:
>> On 09.02.23 08:46, Ahmad Fatoum wrote:
>>> Hello Gatien,
>>>
>>> On 27.01.23 17:40, Gatien Chevallier wrote:
>>>> The STM32 System Bus is an internal bus on which devices are connected.
>>>> ETZPC is a peripheral overseeing the firewall bus that configures
>>>> and control access to the peripherals connected on it.
>>>>
>>>> For more information on which peripheral is securable, please read
>>>> the STM32MP13 reference manual.
>>>
>>> Diff is way too big. Please split up the alphabetic reordering into its
>>> own commit, so actual functional changes are apparent.
>>
>> Ah, I see now that you are moving securable peripherals into a new bus.
>> I share Uwe's confusion of considering the ETZPC as bus.
>>
>> Does this configuration even change dynamically? Why can't you implement
>> this binding in the bootloader and have Linux only see a DT where unavailable
>> nodes are status = "disabled"; secure-status = "okay"?
>>
>> For inspiration, see barebox' device tree fixups when devices are disabled
>> per fuse:
>>
>>    https://elixir.bootlin.com/barebox/v2023.01.0/source/drivers/base/featctrl.c#L122
>>
>> Cheers,
>> Ahmad
> 
> This configuration can change dynamically. The binding will be implemented in the bootloader, where the ETZPC is already implemented as a bus in our downstream.
> 
> I find the mentionned example valid.
> 
> Now, why is it a bus? :D
> 
> It is the result of the discussion on the previous submission by Benjamin (Sorry for the lack of link but I saw that you participated on these threads)+ we need the bus mechanism to control whether a subnode should be probed or not. You can see it as a firewall bus.
> 
> The ETZPC relies on the ARM TrustZone extension to the AHB bus and propagation through bridges to the APB bus. Therefore, I find it relevant to consider it as a bus, what is your opinion?
> 
> This patchset is a first step to the implementation of an API to control accesses dynamically.

I still don't get what's dynamic about this. Either:

  - Configuration _can_ change while Linux is running: You'll need to do
    way more than what your current bus provides to somwhow synchronize state
    with the secure monitor; otherwise a newly secured device will cause the driver
    to trigger data aborts that you'll have to handle and unbind the driver.
    (like if a USB drive is yanked out).

  - Configuration _can't_ change while Linux is running: You can have the bootloader
    fixup the device tree and Linux need not care at all about devices that the
    ETZPC is securing.

My understanding is that the latter is your use case, so I don't see why we
even need the normal world to be aware of the partitioning.

Cheers,
Ahmad

> 
>>
>>>
>>> Thanks,
>>> Ahmad
>>>
>>>>
>>>> Signed-off-by: Gatien Chevallier <gatien.chevallier@foss.st.com>
>>>> ---
>>>>
>>>> No changes in V2.
>>>>
>>>> Changes in V3:
>>>>     -Use appriopriate node name: bus
>>>>
>>>>   arch/arm/boot/dts/stm32mp131.dtsi  | 407 +++++++++++++++--------------
>>>>   arch/arm/boot/dts/stm32mp133.dtsi  |  51 ++--
>>>>   arch/arm/boot/dts/stm32mp13xc.dtsi |  19 +-
>>>>   arch/arm/boot/dts/stm32mp13xf.dtsi |  18 +-
>>>>   4 files changed, 258 insertions(+), 237 deletions(-)
>>>>
>>>> diff --git a/arch/arm/boot/dts/stm32mp131.dtsi b/arch/arm/boot/dts/stm32mp131.dtsi
>>>> index accc3824f7e9..24462a647101 100644
>>>> --- a/arch/arm/boot/dts/stm32mp131.dtsi
>>>> +++ b/arch/arm/boot/dts/stm32mp131.dtsi
>>>> @@ -253,148 +253,6 @@ dmamux1: dma-router@48002000 {
>>>>               dma-channels = <16>;
>>>>           };
>>>>   -        adc_2: adc@48004000 {
>>>> -            compatible = "st,stm32mp13-adc-core";
>>>> -            reg = <0x48004000 0x400>;
>>>> -            interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
>>>> -            clocks = <&rcc ADC2>, <&rcc ADC2_K>;
>>>> -            clock-names = "bus", "adc";
>>>> -            interrupt-controller;
>>>> -            #interrupt-cells = <1>;
>>>> -            #address-cells = <1>;
>>>> -            #size-cells = <0>;
>>>> -            status = "disabled";
>>>> -
>>>> -            adc2: adc@0 {
>>>> -                compatible = "st,stm32mp13-adc";
>>>> -                #io-channel-cells = <1>;
>>>> -                #address-cells = <1>;
>>>> -                #size-cells = <0>;
>>>> -                reg = <0x0>;
>>>> -                interrupt-parent = <&adc_2>;
>>>> -                interrupts = <0>;
>>>> -                dmas = <&dmamux1 10 0x400 0x80000001>;
>>>> -                dma-names = "rx";
>>>> -                status = "disabled";
>>>> -
>>>> -                channel@13 {
>>>> -                    reg = <13>;
>>>> -                    label = "vrefint";
>>>> -                };
>>>> -                channel@14 {
>>>> -                    reg = <14>;
>>>> -                    label = "vddcore";
>>>> -                };
>>>> -                channel@16 {
>>>> -                    reg = <16>;
>>>> -                    label = "vddcpu";
>>>> -                };
>>>> -                channel@17 {
>>>> -                    reg = <17>;
>>>> -                    label = "vddq_ddr";
>>>> -                };
>>>> -            };
>>>> -        };
>>>> -
>>>> -        usbotg_hs: usb@49000000 {
>>>> -            compatible = "st,stm32mp15-hsotg", "snps,dwc2";
>>>> -            reg = <0x49000000 0x40000>;
>>>> -            clocks = <&rcc USBO_K>;
>>>> -            clock-names = "otg";
>>>> -            resets = <&rcc USBO_R>;
>>>> -            reset-names = "dwc2";
>>>> -            interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
>>>> -            g-rx-fifo-size = <512>;
>>>> -            g-np-tx-fifo-size = <32>;
>>>> -            g-tx-fifo-size = <256 16 16 16 16 16 16 16>;
>>>> -            dr_mode = "otg";
>>>> -            otg-rev = <0x200>;
>>>> -            usb33d-supply = <&usb33>;
>>>> -            status = "disabled";
>>>> -        };
>>>> -
>>>> -        spi4: spi@4c002000 {
>>>> -            compatible = "st,stm32h7-spi";
>>>> -            reg = <0x4c002000 0x400>;
>>>> -            interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
>>>> -            clocks = <&rcc SPI4_K>;
>>>> -            resets = <&rcc SPI4_R>;
>>>> -            #address-cells = <1>;
>>>> -            #size-cells = <0>;
>>>> -            dmas = <&dmamux1 83 0x400 0x01>,
>>>> -                   <&dmamux1 84 0x400 0x01>;
>>>> -            dma-names = "rx", "tx";
>>>> -            status = "disabled";
>>>> -        };
>>>> -
>>>> -        spi5: spi@4c003000 {
>>>> -            compatible = "st,stm32h7-spi";
>>>> -            reg = <0x4c003000 0x400>;
>>>> -            interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
>>>> -            clocks = <&rcc SPI5_K>;
>>>> -            resets = <&rcc SPI5_R>;
>>>> -            #address-cells = <1>;
>>>> -            #size-cells = <0>;
>>>> -            dmas = <&dmamux1 85 0x400 0x01>,
>>>> -                   <&dmamux1 86 0x400 0x01>;
>>>> -            dma-names = "rx", "tx";
>>>> -            status = "disabled";
>>>> -        };
>>>> -
>>>> -        i2c3: i2c@4c004000 {
>>>> -            compatible = "st,stm32mp13-i2c";
>>>> -            reg = <0x4c004000 0x400>;
>>>> -            interrupt-names = "event", "error";
>>>> -            interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>,
>>>> -                     <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
>>>> -            clocks = <&rcc I2C3_K>;
>>>> -            resets = <&rcc I2C3_R>;
>>>> -            #address-cells = <1>;
>>>> -            #size-cells = <0>;
>>>> -            dmas = <&dmamux1 73 0x400 0x1>,
>>>> -                   <&dmamux1 74 0x400 0x1>;
>>>> -            dma-names = "rx", "tx";
>>>> -            st,syscfg-fmp = <&syscfg 0x4 0x4>;
>>>> -            i2c-analog-filter;
>>>> -            status = "disabled";
>>>> -        };
>>>> -
>>>> -        i2c4: i2c@4c005000 {
>>>> -            compatible = "st,stm32mp13-i2c";
>>>> -            reg = <0x4c005000 0x400>;
>>>> -            interrupt-names = "event", "error";
>>>> -            interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>,
>>>> -                     <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
>>>> -            clocks = <&rcc I2C4_K>;
>>>> -            resets = <&rcc I2C4_R>;
>>>> -            #address-cells = <1>;
>>>> -            #size-cells = <0>;
>>>> -            dmas = <&dmamux1 75 0x400 0x1>,
>>>> -                   <&dmamux1 76 0x400 0x1>;
>>>> -            dma-names = "rx", "tx";
>>>> -            st,syscfg-fmp = <&syscfg 0x4 0x8>;
>>>> -            i2c-analog-filter;
>>>> -            status = "disabled";
>>>> -        };
>>>> -
>>>> -        i2c5: i2c@4c006000 {
>>>> -            compatible = "st,stm32mp13-i2c";
>>>> -            reg = <0x4c006000 0x400>;
>>>> -            interrupt-names = "event", "error";
>>>> -            interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>,
>>>> -                     <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>;
>>>> -            clocks = <&rcc I2C5_K>;
>>>> -            resets = <&rcc I2C5_R>;
>>>> -            #address-cells = <1>;
>>>> -            #size-cells = <0>;
>>>> -            dmas = <&dmamux1 115 0x400 0x1>,
>>>> -                   <&dmamux1 116 0x400 0x1>;
>>>> -            dma-names = "rx", "tx";
>>>> -            st,syscfg-fmp = <&syscfg 0x4 0x10>;
>>>> -            i2c-analog-filter;
>>>> -            status = "disabled";
>>>> -        };
>>>> -
>>>>           rcc: rcc@50000000 {
>>>>               compatible = "st,stm32mp13-rcc", "syscon";
>>>>               reg = <0x50000000 0x1000>;
>>>> @@ -431,34 +289,6 @@ mdma: dma-controller@58000000 {
>>>>               dma-requests = <48>;
>>>>           };
>>>>   -        sdmmc1: mmc@58005000 {
>>>> -            compatible = "st,stm32-sdmmc2", "arm,pl18x", "arm,primecell";
>>>> -            arm,primecell-periphid = <0x20253180>;
>>>> -            reg = <0x58005000 0x1000>, <0x58006000 0x1000>;
>>>> -            interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
>>>> -            clocks = <&rcc SDMMC1_K>;
>>>> -            clock-names = "apb_pclk";
>>>> -            resets = <&rcc SDMMC1_R>;
>>>> -            cap-sd-highspeed;
>>>> -            cap-mmc-highspeed;
>>>> -            max-frequency = <130000000>;
>>>> -            status = "disabled";
>>>> -        };
>>>> -
>>>> -        sdmmc2: mmc@58007000 {
>>>> -            compatible = "st,stm32-sdmmc2", "arm,pl18x", "arm,primecell";
>>>> -            arm,primecell-periphid = <0x20253180>;
>>>> -            reg = <0x58007000 0x1000>, <0x58008000 0x1000>;
>>>> -            interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
>>>> -            clocks = <&rcc SDMMC2_K>;
>>>> -            clock-names = "apb_pclk";
>>>> -            resets = <&rcc SDMMC2_R>;
>>>> -            cap-sd-highspeed;
>>>> -            cap-mmc-highspeed;
>>>> -            max-frequency = <130000000>;
>>>> -            status = "disabled";
>>>> -        };
>>>> -
>>>>           usbh_ohci: usb@5800c000 {
>>>>               compatible = "generic-ohci";
>>>>               reg = <0x5800c000 0x1000>;
>>>> @@ -486,29 +316,6 @@ iwdg2: watchdog@5a002000 {
>>>>               status = "disabled";
>>>>           };
>>>>   -        usbphyc: usbphyc@5a006000 {
>>>> -            #address-cells = <1>;
>>>> -            #size-cells = <0>;
>>>> -            #clock-cells = <0>;
>>>> -            compatible = "st,stm32mp1-usbphyc";
>>>> -            reg = <0x5a006000 0x1000>;
>>>> -            clocks = <&rcc USBPHY_K>;
>>>> -            resets = <&rcc USBPHY_R>;
>>>> -            vdda1v1-supply = <&reg11>;
>>>> -            vdda1v8-supply = <&reg18>;
>>>> -            status = "disabled";
>>>> -
>>>> -            usbphyc_port0: usb-phy@0 {
>>>> -                #phy-cells = <0>;
>>>> -                reg = <0>;
>>>> -            };
>>>> -
>>>> -            usbphyc_port1: usb-phy@1 {
>>>> -                #phy-cells = <1>;
>>>> -                reg = <1>;
>>>> -            };
>>>> -        };
>>>> -
>>>>           rtc: rtc@5c004000 {
>>>>               compatible = "st,stm32mp1-rtc";
>>>>               reg = <0x5c004000 0x400>;
>>>> @@ -536,6 +343,220 @@ ts_cal2: calib@5e {
>>>>               };
>>>>           };
>>>>   +        etzpc: bus@5c007000 {
>>>> +            compatible = "st,stm32mp13-sys-bus";
>>>> +            reg = <0x5c007000 0x400>;
>>>> +            #address-cells = <1>;
>>>> +            #size-cells = <1>;
>>>> +            feature-domain-controller;
>>>> +            #feature-domain-cells = <1>;
>>>> +            ranges;
>>>> +
>>>> +            adc_2: adc@48004000 {
>>>> +                compatible = "st,stm32mp13-adc-core";
>>>> +                reg = <0x48004000 0x400>;
>>>> +                interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
>>>> +                clocks = <&rcc ADC2>, <&rcc ADC2_K>;
>>>> +                clock-names = "bus", "adc";
>>>> +                interrupt-controller;
>>>> +                #interrupt-cells = <1>;
>>>> +                #address-cells = <1>;
>>>> +                #size-cells = <0>;
>>>> +                feature-domains = <&etzpc 33>;
>>>> +                status = "disabled";
>>>> +
>>>> +                adc2: adc@0 {
>>>> +                    compatible = "st,stm32mp13-adc";
>>>> +                    #io-channel-cells = <1>;
>>>> +                    #address-cells = <1>;
>>>> +                    #size-cells = <0>;
>>>> +                    reg = <0x0>;
>>>> +                    interrupt-parent = <&adc_2>;
>>>> +                    interrupts = <0>;
>>>> +                    dmas = <&dmamux1 10 0x400 0x80000001>;
>>>> +                    dma-names = "rx";
>>>> +                    status = "disabled";
>>>> +
>>>> +                    channel@13 {
>>>> +                        reg = <13>;
>>>> +                        label = "vrefint";
>>>> +                    };
>>>> +                    channel@14 {
>>>> +                        reg = <14>;
>>>> +                        label = "vddcore";
>>>> +                    };
>>>> +                    channel@16 {
>>>> +                        reg = <16>;
>>>> +                        label = "vddcpu";
>>>> +                    };
>>>> +                    channel@17 {
>>>> +                        reg = <17>;
>>>> +                        label = "vddq_ddr";
>>>> +                    };
>>>> +                };
>>>> +            };
>>>> +
>>>> +            usbotg_hs: usb@49000000 {
>>>> +                compatible = "st,stm32mp15-hsotg", "snps,dwc2";
>>>> +                reg = <0x49000000 0x40000>;
>>>> +                clocks = <&rcc USBO_K>;
>>>> +                clock-names = "otg";
>>>> +                resets = <&rcc USBO_R>;
>>>> +                reset-names = "dwc2";
>>>> +                interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
>>>> +                g-rx-fifo-size = <512>;
>>>> +                g-np-tx-fifo-size = <32>;
>>>> +                g-tx-fifo-size = <256 16 16 16 16 16 16 16>;
>>>> +                dr_mode = "otg";
>>>> +                otg-rev = <0x200>;
>>>> +                usb33d-supply = <&usb33>;
>>>> +                feature-domains = <&etzpc 34>;
>>>> +                status = "disabled";
>>>> +            };
>>>> +
>>>> +            spi4: spi@4c002000 {
>>>> +                compatible = "st,stm32h7-spi";
>>>> +                reg = <0x4c002000 0x400>;
>>>> +                interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
>>>> +                clocks = <&rcc SPI4_K>;
>>>> +                resets = <&rcc SPI4_R>;
>>>> +                #address-cells = <1>;
>>>> +                #size-cells = <0>;
>>>> +                dmas = <&dmamux1 83 0x400 0x01>,
>>>> +                       <&dmamux1 84 0x400 0x01>;
>>>> +                dma-names = "rx", "tx";
>>>> +                feature-domains = <&etzpc 18>;
>>>> +                status = "disabled";
>>>> +            };
>>>> +
>>>> +            spi5: spi@4c003000 {
>>>> +                compatible = "st,stm32h7-spi";
>>>> +                reg = <0x4c003000 0x400>;
>>>> +                interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
>>>> +                clocks = <&rcc SPI5_K>;
>>>> +                resets = <&rcc SPI5_R>;
>>>> +                #address-cells = <1>;
>>>> +                #size-cells = <0>;
>>>> +                dmas = <&dmamux1 85 0x400 0x01>,
>>>> +                       <&dmamux1 86 0x400 0x01>;
>>>> +                dma-names = "rx", "tx";
>>>> +                feature-domains = <&etzpc 19>;
>>>> +                status = "disabled";
>>>> +            };
>>>> +
>>>> +            i2c3: i2c@4c004000 {
>>>> +                compatible = "st,stm32mp13-i2c";
>>>> +                reg = <0x4c004000 0x400>;
>>>> +                interrupt-names = "event", "error";
>>>> +                interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>,
>>>> +                         <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
>>>> +                clocks = <&rcc I2C3_K>;
>>>> +                resets = <&rcc I2C3_R>;
>>>> +                #address-cells = <1>;
>>>> +                #size-cells = <0>;
>>>> +                dmas = <&dmamux1 73 0x400 0x1>,
>>>> +                       <&dmamux1 74 0x400 0x1>;
>>>> +                dma-names = "rx", "tx";
>>>> +                st,syscfg-fmp = <&syscfg 0x4 0x4>;
>>>> +                i2c-analog-filter;
>>>> +                feature-domains = <&etzpc 20>;
>>>> +                status = "disabled";
>>>> +            };
>>>> +
>>>> +            i2c4: i2c@4c005000 {
>>>> +                compatible = "st,stm32mp13-i2c";
>>>> +                reg = <0x4c005000 0x400>;
>>>> +                interrupt-names = "event", "error";
>>>> +                interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>,
>>>> +                         <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
>>>> +                clocks = <&rcc I2C4_K>;
>>>> +                resets = <&rcc I2C4_R>;
>>>> +                #address-cells = <1>;
>>>> +                #size-cells = <0>;
>>>> +                dmas = <&dmamux1 75 0x400 0x1>,
>>>> +                       <&dmamux1 76 0x400 0x1>;
>>>> +                dma-names = "rx", "tx";
>>>> +                st,syscfg-fmp = <&syscfg 0x4 0x8>;
>>>> +                i2c-analog-filter;
>>>> +                feature-domains = <&etzpc 21>;
>>>> +                status = "disabled";
>>>> +            };
>>>> +
>>>> +            i2c5: i2c@4c006000 {
>>>> +                compatible = "st,stm32mp13-i2c";
>>>> +                reg = <0x4c006000 0x400>;
>>>> +                interrupt-names = "event", "error";
>>>> +                interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>,
>>>> +                         <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>;
>>>> +                clocks = <&rcc I2C5_K>;
>>>> +                resets = <&rcc I2C5_R>;
>>>> +                #address-cells = <1>;
>>>> +                #size-cells = <0>;
>>>> +                dmas = <&dmamux1 115 0x400 0x1>,
>>>> +                       <&dmamux1 116 0x400 0x1>;
>>>> +                dma-names = "rx", "tx";
>>>> +                st,syscfg-fmp = <&syscfg 0x4 0x10>;
>>>> +                i2c-analog-filter;
>>>> +                feature-domains = <&etzpc 22>;
>>>> +                status = "disabled";
>>>> +            };
>>>> +
>>>> +            sdmmc1: mmc@58005000 {
>>>> +                compatible = "st,stm32-sdmmc2", "arm,pl18x", "arm,primecell";
>>>> +                arm,primecell-periphid = <0x20253180>;
>>>> +                reg = <0x58005000 0x1000>, <0x58006000 0x1000>;
>>>> +                interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
>>>> +                clocks = <&rcc SDMMC1_K>;
>>>> +                clock-names = "apb_pclk";
>>>> +                resets = <&rcc SDMMC1_R>;
>>>> +                cap-sd-highspeed;
>>>> +                cap-mmc-highspeed;
>>>> +                max-frequency = <130000000>;
>>>> +                feature-domains = <&etzpc 50>;
>>>> +                status = "disabled";
>>>> +            };
>>>> +
>>>> +            sdmmc2: mmc@58007000 {
>>>> +                compatible = "st,stm32-sdmmc2", "arm,pl18x", "arm,primecell";
>>>> +                arm,primecell-periphid = <0x20253180>;
>>>> +                reg = <0x58007000 0x1000>, <0x58008000 0x1000>;
>>>> +                interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
>>>> +                clocks = <&rcc SDMMC2_K>;
>>>> +                clock-names = "apb_pclk";
>>>> +                resets = <&rcc SDMMC2_R>;
>>>> +                cap-sd-highspeed;
>>>> +                cap-mmc-highspeed;
>>>> +                max-frequency = <130000000>;
>>>> +                feature-domains = <&etzpc 51>;
>>>> +                status = "disabled";
>>>> +            };
>>>> +
>>>> +            usbphyc: usbphyc@5a006000 {
>>>> +                #address-cells = <1>;
>>>> +                #size-cells = <0>;
>>>> +                #clock-cells = <0>;
>>>> +                compatible = "st,stm32mp1-usbphyc";
>>>> +                reg = <0x5a006000 0x1000>;
>>>> +                clocks = <&rcc USBPHY_K>;
>>>> +                resets = <&rcc USBPHY_R>;
>>>> +                vdda1v1-supply = <&reg11>;
>>>> +                vdda1v8-supply = <&reg18>;
>>>> +                feature-domains = <&etzpc 5>;
>>>> +                status = "disabled";
>>>> +
>>>> +                usbphyc_port0: usb-phy@0 {
>>>> +                    #phy-cells = <0>;
>>>> +                    reg = <0>;
>>>> +                };
>>>> +
>>>> +                usbphyc_port1: usb-phy@1 {
>>>> +                    #phy-cells = <1>;
>>>> +                    reg = <1>;
>>>> +                };
>>>> +            };
>>>> +
>>>> +        };
>>>> +
>>>>           /*
>>>>            * Break node order to solve dependency probe issue between
>>>>            * pinctrl and exti.
>>>> diff --git a/arch/arm/boot/dts/stm32mp133.dtsi b/arch/arm/boot/dts/stm32mp133.dtsi
>>>> index df451c3c2a26..be6061552683 100644
>>>> --- a/arch/arm/boot/dts/stm32mp133.dtsi
>>>> +++ b/arch/arm/boot/dts/stm32mp133.dtsi
>>>> @@ -33,35 +33,38 @@ m_can2: can@4400f000 {
>>>>               bosch,mram-cfg = <0x1400 0 0 32 0 0 2 2>;
>>>>               status = "disabled";
>>>>           };
>>>> +    };
>>>> +};
>>>>   -        adc_1: adc@48003000 {
>>>> -            compatible = "st,stm32mp13-adc-core";
>>>> -            reg = <0x48003000 0x400>;
>>>> -            interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
>>>> -            clocks = <&rcc ADC1>, <&rcc ADC1_K>;
>>>> -            clock-names = "bus", "adc";
>>>> -            interrupt-controller;
>>>> -            #interrupt-cells = <1>;
>>>> +&etzpc {
>>>> +    adc_1: adc@48003000 {
>>>> +        compatible = "st,stm32mp13-adc-core";
>>>> +        reg = <0x48003000 0x400>;
>>>> +        interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
>>>> +        clocks = <&rcc ADC1>, <&rcc ADC1_K>;
>>>> +        clock-names = "bus", "adc";
>>>> +        interrupt-controller;
>>>> +        #interrupt-cells = <1>;
>>>> +        #address-cells = <1>;
>>>> +        #size-cells = <0>;
>>>> +        feature-domains = <&etzpc 32>;
>>>> +        status = "disabled";
>>>> +
>>>> +        adc1: adc@0 {
>>>> +            compatible = "st,stm32mp13-adc";
>>>> +            #io-channel-cells = <1>;
>>>>               #address-cells = <1>;
>>>>               #size-cells = <0>;
>>>> +            reg = <0x0>;
>>>> +            interrupt-parent = <&adc_1>;
>>>> +            interrupts = <0>;
>>>> +            dmas = <&dmamux1 9 0x400 0x80000001>;
>>>> +            dma-names = "rx";
>>>>               status = "disabled";
>>>>   -            adc1: adc@0 {
>>>> -                compatible = "st,stm32mp13-adc";
>>>> -                #io-channel-cells = <1>;
>>>> -                #address-cells = <1>;
>>>> -                #size-cells = <0>;
>>>> -                reg = <0x0>;
>>>> -                interrupt-parent = <&adc_1>;
>>>> -                interrupts = <0>;
>>>> -                dmas = <&dmamux1 9 0x400 0x80000001>;
>>>> -                dma-names = "rx";
>>>> -                status = "disabled";
>>>> -
>>>> -                channel@18 {
>>>> -                    reg = <18>;
>>>> -                    label = "vrefint";
>>>> -                };
>>>> +            channel@18 {
>>>> +                reg = <18>;
>>>> +                label = "vrefint";
>>>>               };
>>>>           };
>>>>       };
>>>> diff --git a/arch/arm/boot/dts/stm32mp13xc.dtsi b/arch/arm/boot/dts/stm32mp13xc.dtsi
>>>> index 4d00e7592882..a1a7a40c2a3e 100644
>>>> --- a/arch/arm/boot/dts/stm32mp13xc.dtsi
>>>> +++ b/arch/arm/boot/dts/stm32mp13xc.dtsi
>>>> @@ -4,15 +4,14 @@
>>>>    * Author: Alexandre Torgue <alexandre.torgue@foss.st.com> for STMicroelectronics.
>>>>    */
>>>>   -/ {
>>>> -    soc {
>>>> -        cryp: crypto@54002000 {
>>>> -            compatible = "st,stm32mp1-cryp";
>>>> -            reg = <0x54002000 0x400>;
>>>> -            interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
>>>> -            clocks = <&rcc CRYP1>;
>>>> -            resets = <&rcc CRYP1_R>;
>>>> -            status = "disabled";
>>>> -        };
>>>> +&etzpc {
>>>> +    cryp: crypto@54002000 {
>>>> +        compatible = "st,stm32mp1-cryp";
>>>> +        reg = <0x54002000 0x400>;
>>>> +        interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
>>>> +        clocks = <&rcc CRYP1>;
>>>> +        resets = <&rcc CRYP1_R>;
>>>> +        feature-domains = <&etzpc 42>;
>>>> +        status = "disabled";
>>>>       };
>>>>   };
>>>> diff --git a/arch/arm/boot/dts/stm32mp13xf.dtsi b/arch/arm/boot/dts/stm32mp13xf.dtsi
>>>> index 4d00e7592882..b9fb071a1471 100644
>>>> --- a/arch/arm/boot/dts/stm32mp13xf.dtsi
>>>> +++ b/arch/arm/boot/dts/stm32mp13xf.dtsi
>>>> @@ -4,15 +4,13 @@
>>>>    * Author: Alexandre Torgue <alexandre.torgue@foss.st.com> for STMicroelectronics.
>>>>    */
>>>>   -/ {
>>>> -    soc {
>>>> -        cryp: crypto@54002000 {
>>>> -            compatible = "st,stm32mp1-cryp";
>>>> -            reg = <0x54002000 0x400>;
>>>> -            interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
>>>> -            clocks = <&rcc CRYP1>;
>>>> -            resets = <&rcc CRYP1_R>;
>>>> -            status = "disabled";
>>>> -        };
>>>> +&etzpc {
>>>> +    cryp: crypto@54002000 {
>>>> +        compatible = "st,stm32mp1-cryp";
>>>> +        reg = <0x54002000 0x400>;
>>>> +        interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
>>>> +        clocks = <&rcc CRYP1>;
>>>> +        resets = <&rcc CRYP1_R>;
>>>> +        status = "disabled";
>>>>       };
>>>>   };
>>>
>>
> 
> Regarding the patch itself, I can separate it in two patches.
> 1)Introduce ETZPC
> 2)Move peripherals under ETZPC
> 
> Best regards,
> Gatien
> 

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


^ permalink raw reply

* RE: [PATCH v3 3/3] serial: 8250_em: Add serial_out() to struct serial8250_em_hw_info
From: Biju Das @ 2023-02-13 11:12 UTC (permalink / raw)
  To: Jiri Slaby, Ilpo Järvinen, Geert Uytterhoeven, Magnus Damm,
	Niklas Söderlund
  Cc: Greg Kroah-Hartman, linux-serial, Fabrizio Castro,
	linux-renesas-soc@vger.kernel.org
In-Reply-To: <283b2e79-e992-dc35-2a79-feccc93103fb@kernel.org>

Hi Jiri Slaby,

Thanks for the feedback.

> Subject: Re: [PATCH v3 3/3] serial: 8250_em: Add serial_out() to struct
> serial8250_em_hw_info
> 
> On 13. 02. 23, 10:31, Biju Das wrote:
> > So looks like similar to other macros, UART_FCR_EM (0x3) is sensible one.
> >
> > UART_FCR_RO_OFFSET (9)
> > UART_FCR_RO_EM (UART_FCR_EM + UART_FCR_RO_OFFSET)
> >
> >
> > static unsigned int serial8250_em_serial_in(struct uart_port *p, int
> > offset) case UART_FCR_RO_EM:
> > 	return readl(p->membase + (offset - UART_FCR_RO_OFFSET << 2));
> 
> 
> Please send a complete patch as a reply. I am completely lost now.

Please find the complete patc.


From e597ae60eb170c1f1b650e1e533bf4e12c09f822 Mon Sep 17 00:00:00 2001
From: Biju Das <biju.das.jz@bp.renesas.com>
Date: Tue, 7 Feb 2023 15:07:13 +0000
Subject: [PATCH] serial: 8250_em: Add serial_out() to struct
 serial8250_em_hw_info

As per RZ/V2M hardware manual(Rev.1.30 Jun, 2022), UART IP has a
restriction as mentioned below.

40.6.1 Point for Caution when Changing the Register Settings:

When changing the settings of the following registers, a PRESETn master
reset or FIFO reset + SW reset (FCR[2],FCR[1], HCR0[7]) must be input to
re-initialize them.

Target Registers: FCR, LCR, MCR, DLL, DLM, HCR0.

This patch adds serial_out() to struct serial8250_em_hw_info to
handle this difference between emma mobile and rz/v2m.

DLL/DLM register can be updated only by setting LCR[7]. So the
updation of LCR[7] will perform reset for DLL/DLM register changes.

Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
---
 drivers/tty/serial/8250/8250_em.c | 70 ++++++++++++++++++++++++++++++-
 1 file changed, 69 insertions(+), 1 deletion(-)

diff --git a/drivers/tty/serial/8250/8250_em.c b/drivers/tty/serial/8250/8250_em.c
index 69cd3b611501..c1c64f48ee7e 100644
--- a/drivers/tty/serial/8250/8250_em.c
+++ b/drivers/tty/serial/8250/8250_em.c
@@ -17,12 +17,23 @@
 
 #include "8250.h"
 
+#define UART_FCR_EM 3
 #define UART_DLL_EM 9
 #define UART_DLM_EM 10
+#define UART_HCR0_EM 11
+
+/*
+ * Add UART_FCR_R_EM(14) to avoid overlapping with existing register defines
+ * for reading the FCR value.
+ */
+#define UART_FCR_R_EM	(UART_FCR_EM + UART_HCR0_EM)
+
+#define UART_HCR0_EM_SW_RESET	BIT(7) /* SW Reset */
 
 struct serial8250_em_hw_info {
 	unsigned int type;
 	upf_t flags;
+	void (*serial_out)(struct uart_port *p, int off, int value);
 };
 
 struct serial8250_em_priv {
@@ -46,6 +57,7 @@ static void serial8250_em_serial_out(struct uart_port *p, int offset, int value)
 		fallthrough;
 	case UART_DLL_EM: /* DLL @ 0x24 (+9) */
 	case UART_DLM_EM: /* DLM @ 0x28 (+9) */
+	case UART_HCR0_EM: /* HCR0 @ 0x2c */
 		writel(value, p->membase + (offset << 2));
 	}
 }
@@ -55,20 +67,74 @@ static unsigned int serial8250_em_serial_in(struct uart_port *p, int offset)
 	switch (offset) {
 	case UART_RX: /* RX @ 0x00 */
 		return readb(p->membase);
+	case UART_LCR: /* LCR @ 0x10 (+1) */
 	case UART_MCR: /* MCR @ 0x14 (+1) */
 	case UART_LSR: /* LSR @ 0x18 (+1) */
 	case UART_MSR: /* MSR @ 0x1c (+1) */
 	case UART_SCR: /* SCR @ 0x20 (+1) */
 		return readl(p->membase + ((offset + 1) << 2));
+	case UART_FCR_R_EM:
+		return readl(p->membase + (UART_FCR_EM << 2));
 	case UART_IER: /* IER @ 0x04 */
 	case UART_IIR: /* IIR @ 0x08 */
 	case UART_DLL_EM: /* DLL @ 0x24 (+9) */
 	case UART_DLM_EM: /* DLM @ 0x28 (+9) */
+	case UART_HCR0_EM: /* HCR0 @ 0x2c */
 		return readl(p->membase + (offset << 2));
 	}
 	return 0;
 }
 
+static void serial8250_rzv2m_reg_update(struct uart_port *p, int off, int value)
+{
+	unsigned int ier, fcr, lcr, mcr, hcr0;
+
+	ier = serial8250_em_serial_in(p, UART_IER);
+	fcr = serial8250_em_serial_in(p, UART_FCR_R_EM);
+	lcr = serial8250_em_serial_in(p, UART_LCR);
+	mcr = serial8250_em_serial_in(p, UART_MCR);
+	hcr0 = serial8250_em_serial_in(p, UART_HCR0_EM);
+
+	serial8250_em_serial_out(p, UART_FCR, fcr | UART_FCR_CLEAR_RCVR |
+				 UART_FCR_CLEAR_XMIT);
+	serial8250_em_serial_out(p, UART_HCR0_EM, hcr0 | UART_HCR0_EM_SW_RESET);
+	serial8250_em_serial_out(p, UART_HCR0_EM, hcr0 & ~UART_HCR0_EM_SW_RESET);
+
+	switch (off) {
+	case UART_FCR:
+		fcr = value;
+		break;
+	case UART_LCR:
+		lcr = value;
+		break;
+	case UART_MCR:
+		mcr = value;
+	}
+
+	serial8250_em_serial_out(p, UART_IER, ier);
+	serial8250_em_serial_out(p, UART_FCR, fcr);
+	serial8250_em_serial_out(p, UART_MCR, mcr);
+	serial8250_em_serial_out(p, UART_LCR, lcr);
+	serial8250_em_serial_out(p, UART_HCR0_EM, hcr0);
+}
+
+static void serial8250_em_rzv2m_serial_out(struct uart_port *p, int offset, int value)
+{
+	switch (offset) {
+	case UART_TX:
+	case UART_SCR:
+	case UART_IER:
+	case UART_DLL_EM:
+	case UART_DLM_EM:
+		serial8250_em_serial_out(p, offset, value);
+		break;
+	case UART_FCR:
+	case UART_LCR:
+	case UART_MCR:
+		serial8250_rzv2m_reg_update(p, offset, value);
+	}
+}
+
 static int serial8250_em_serial_dl_read(struct uart_8250_port *up)
 {
 	return serial_in(up, UART_DLL_EM) | serial_in(up, UART_DLM_EM) << 8;
@@ -120,7 +186,7 @@ static int serial8250_em_probe(struct platform_device *pdev)
 
 	up.port.iotype = UPIO_MEM32;
 	up.port.serial_in = serial8250_em_serial_in;
-	up.port.serial_out = serial8250_em_serial_out;
+	up.port.serial_out = info->serial_out;
 	up.dl_read = serial8250_em_serial_dl_read;
 	up.dl_write = serial8250_em_serial_dl_write;
 
@@ -144,11 +210,13 @@ static int serial8250_em_remove(struct platform_device *pdev)
 static const struct serial8250_em_hw_info emma_mobile_uart_hw_info = {
 	.type = PORT_UNKNOWN,
 	.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT | UPF_IOREMAP,
+	.serial_out = serial8250_em_serial_out,
 };
 
 static const struct serial8250_em_hw_info rzv2m_uart_hw_info = {
 	.type = PORT_16750,
 	.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT | UPF_IOREMAP | UPF_FIXED_TYPE,
+	.serial_out = serial8250_em_rzv2m_serial_out,
 };
 
 static const struct of_device_id serial8250_em_dt_ids[] = {
-- 
2.25.1

^ permalink raw reply related

* Re: [Linux-stm32] [PATCH v3 6/6] ARM: dts: stm32: add ETZPC as a system bus for STM32MP13x boards
From: Gatien CHEVALLIER @ 2023-02-13 10:54 UTC (permalink / raw)
  To: Ahmad Fatoum, Oleksii_Moisieiev, gregkh, herbert, davem, robh+dt,
	krzysztof.kozlowski+dt, alexandre.torgue, vkoul, jic23,
	olivier.moysan, arnaud.pouliquen, mchehab, fabrice.gasnier,
	ulf.hansson, edumazet, kuba, pabeni
  Cc: devicetree, alsa-devel, linux-iio, netdev, linux-usb, linux-mmc,
	linux-kernel, linux-spi, linux-i2c, dmaengine, linux-crypto,
	linux-serial, linux-phy, linux-stm32, linux-arm-kernel,
	linux-media
In-Reply-To: <64ac012e-e471-9093-b253-4798bbfa8cb4@pengutronix.de>

Hi Ahmad, Uwe,

On 2/9/23 09:10, Ahmad Fatoum wrote:
> On 09.02.23 08:46, Ahmad Fatoum wrote:
>> Hello Gatien,
>>
>> On 27.01.23 17:40, Gatien Chevallier wrote:
>>> The STM32 System Bus is an internal bus on which devices are connected.
>>> ETZPC is a peripheral overseeing the firewall bus that configures
>>> and control access to the peripherals connected on it.
>>>
>>> For more information on which peripheral is securable, please read
>>> the STM32MP13 reference manual.
>>
>> Diff is way too big. Please split up the alphabetic reordering into its
>> own commit, so actual functional changes are apparent.
> 
> Ah, I see now that you are moving securable peripherals into a new bus.
> I share Uwe's confusion of considering the ETZPC as bus.
> 
> Does this configuration even change dynamically? Why can't you implement
> this binding in the bootloader and have Linux only see a DT where unavailable
> nodes are status = "disabled"; secure-status = "okay"?
> 
> For inspiration, see barebox' device tree fixups when devices are disabled
> per fuse:
> 
>    https://elixir.bootlin.com/barebox/v2023.01.0/source/drivers/base/featctrl.c#L122
> 
> Cheers,
> Ahmad

This configuration can change dynamically. The binding will be 
implemented in the bootloader, where the ETZPC is already implemented as 
a bus in our downstream.

I find the mentionned example valid.

Now, why is it a bus? :D

It is the result of the discussion on the previous submission by 
Benjamin (Sorry for the lack of link but I saw that you participated on 
these threads)+ we need the bus mechanism to control whether a subnode 
should be probed or not. You can see it as a firewall bus.

The ETZPC relies on the ARM TrustZone extension to the AHB bus and 
propagation through bridges to the APB bus. Therefore, I find it 
relevant to consider it as a bus, what is your opinion?

This patchset is a first step to the implementation of an API to control 
accesses dynamically.

> 
>>
>> Thanks,
>> Ahmad
>>
>>>
>>> Signed-off-by: Gatien Chevallier <gatien.chevallier@foss.st.com>
>>> ---
>>>
>>> No changes in V2.
>>>
>>> Changes in V3:
>>> 	-Use appriopriate node name: bus
>>>
>>>   arch/arm/boot/dts/stm32mp131.dtsi  | 407 +++++++++++++++--------------
>>>   arch/arm/boot/dts/stm32mp133.dtsi  |  51 ++--
>>>   arch/arm/boot/dts/stm32mp13xc.dtsi |  19 +-
>>>   arch/arm/boot/dts/stm32mp13xf.dtsi |  18 +-
>>>   4 files changed, 258 insertions(+), 237 deletions(-)
>>>
>>> diff --git a/arch/arm/boot/dts/stm32mp131.dtsi b/arch/arm/boot/dts/stm32mp131.dtsi
>>> index accc3824f7e9..24462a647101 100644
>>> --- a/arch/arm/boot/dts/stm32mp131.dtsi
>>> +++ b/arch/arm/boot/dts/stm32mp131.dtsi
>>> @@ -253,148 +253,6 @@ dmamux1: dma-router@48002000 {
>>>   			dma-channels = <16>;
>>>   		};
>>>   
>>> -		adc_2: adc@48004000 {
>>> -			compatible = "st,stm32mp13-adc-core";
>>> -			reg = <0x48004000 0x400>;
>>> -			interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
>>> -			clocks = <&rcc ADC2>, <&rcc ADC2_K>;
>>> -			clock-names = "bus", "adc";
>>> -			interrupt-controller;
>>> -			#interrupt-cells = <1>;
>>> -			#address-cells = <1>;
>>> -			#size-cells = <0>;
>>> -			status = "disabled";
>>> -
>>> -			adc2: adc@0 {
>>> -				compatible = "st,stm32mp13-adc";
>>> -				#io-channel-cells = <1>;
>>> -				#address-cells = <1>;
>>> -				#size-cells = <0>;
>>> -				reg = <0x0>;
>>> -				interrupt-parent = <&adc_2>;
>>> -				interrupts = <0>;
>>> -				dmas = <&dmamux1 10 0x400 0x80000001>;
>>> -				dma-names = "rx";
>>> -				status = "disabled";
>>> -
>>> -				channel@13 {
>>> -					reg = <13>;
>>> -					label = "vrefint";
>>> -				};
>>> -				channel@14 {
>>> -					reg = <14>;
>>> -					label = "vddcore";
>>> -				};
>>> -				channel@16 {
>>> -					reg = <16>;
>>> -					label = "vddcpu";
>>> -				};
>>> -				channel@17 {
>>> -					reg = <17>;
>>> -					label = "vddq_ddr";
>>> -				};
>>> -			};
>>> -		};
>>> -
>>> -		usbotg_hs: usb@49000000 {
>>> -			compatible = "st,stm32mp15-hsotg", "snps,dwc2";
>>> -			reg = <0x49000000 0x40000>;
>>> -			clocks = <&rcc USBO_K>;
>>> -			clock-names = "otg";
>>> -			resets = <&rcc USBO_R>;
>>> -			reset-names = "dwc2";
>>> -			interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
>>> -			g-rx-fifo-size = <512>;
>>> -			g-np-tx-fifo-size = <32>;
>>> -			g-tx-fifo-size = <256 16 16 16 16 16 16 16>;
>>> -			dr_mode = "otg";
>>> -			otg-rev = <0x200>;
>>> -			usb33d-supply = <&usb33>;
>>> -			status = "disabled";
>>> -		};
>>> -
>>> -		spi4: spi@4c002000 {
>>> -			compatible = "st,stm32h7-spi";
>>> -			reg = <0x4c002000 0x400>;
>>> -			interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
>>> -			clocks = <&rcc SPI4_K>;
>>> -			resets = <&rcc SPI4_R>;
>>> -			#address-cells = <1>;
>>> -			#size-cells = <0>;
>>> -			dmas = <&dmamux1 83 0x400 0x01>,
>>> -			       <&dmamux1 84 0x400 0x01>;
>>> -			dma-names = "rx", "tx";
>>> -			status = "disabled";
>>> -		};
>>> -
>>> -		spi5: spi@4c003000 {
>>> -			compatible = "st,stm32h7-spi";
>>> -			reg = <0x4c003000 0x400>;
>>> -			interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
>>> -			clocks = <&rcc SPI5_K>;
>>> -			resets = <&rcc SPI5_R>;
>>> -			#address-cells = <1>;
>>> -			#size-cells = <0>;
>>> -			dmas = <&dmamux1 85 0x400 0x01>,
>>> -			       <&dmamux1 86 0x400 0x01>;
>>> -			dma-names = "rx", "tx";
>>> -			status = "disabled";
>>> -		};
>>> -
>>> -		i2c3: i2c@4c004000 {
>>> -			compatible = "st,stm32mp13-i2c";
>>> -			reg = <0x4c004000 0x400>;
>>> -			interrupt-names = "event", "error";
>>> -			interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>,
>>> -				     <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
>>> -			clocks = <&rcc I2C3_K>;
>>> -			resets = <&rcc I2C3_R>;
>>> -			#address-cells = <1>;
>>> -			#size-cells = <0>;
>>> -			dmas = <&dmamux1 73 0x400 0x1>,
>>> -			       <&dmamux1 74 0x400 0x1>;
>>> -			dma-names = "rx", "tx";
>>> -			st,syscfg-fmp = <&syscfg 0x4 0x4>;
>>> -			i2c-analog-filter;
>>> -			status = "disabled";
>>> -		};
>>> -
>>> -		i2c4: i2c@4c005000 {
>>> -			compatible = "st,stm32mp13-i2c";
>>> -			reg = <0x4c005000 0x400>;
>>> -			interrupt-names = "event", "error";
>>> -			interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>,
>>> -				     <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
>>> -			clocks = <&rcc I2C4_K>;
>>> -			resets = <&rcc I2C4_R>;
>>> -			#address-cells = <1>;
>>> -			#size-cells = <0>;
>>> -			dmas = <&dmamux1 75 0x400 0x1>,
>>> -			       <&dmamux1 76 0x400 0x1>;
>>> -			dma-names = "rx", "tx";
>>> -			st,syscfg-fmp = <&syscfg 0x4 0x8>;
>>> -			i2c-analog-filter;
>>> -			status = "disabled";
>>> -		};
>>> -
>>> -		i2c5: i2c@4c006000 {
>>> -			compatible = "st,stm32mp13-i2c";
>>> -			reg = <0x4c006000 0x400>;
>>> -			interrupt-names = "event", "error";
>>> -			interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>,
>>> -				     <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>;
>>> -			clocks = <&rcc I2C5_K>;
>>> -			resets = <&rcc I2C5_R>;
>>> -			#address-cells = <1>;
>>> -			#size-cells = <0>;
>>> -			dmas = <&dmamux1 115 0x400 0x1>,
>>> -			       <&dmamux1 116 0x400 0x1>;
>>> -			dma-names = "rx", "tx";
>>> -			st,syscfg-fmp = <&syscfg 0x4 0x10>;
>>> -			i2c-analog-filter;
>>> -			status = "disabled";
>>> -		};
>>> -
>>>   		rcc: rcc@50000000 {
>>>   			compatible = "st,stm32mp13-rcc", "syscon";
>>>   			reg = <0x50000000 0x1000>;
>>> @@ -431,34 +289,6 @@ mdma: dma-controller@58000000 {
>>>   			dma-requests = <48>;
>>>   		};
>>>   
>>> -		sdmmc1: mmc@58005000 {
>>> -			compatible = "st,stm32-sdmmc2", "arm,pl18x", "arm,primecell";
>>> -			arm,primecell-periphid = <0x20253180>;
>>> -			reg = <0x58005000 0x1000>, <0x58006000 0x1000>;
>>> -			interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
>>> -			clocks = <&rcc SDMMC1_K>;
>>> -			clock-names = "apb_pclk";
>>> -			resets = <&rcc SDMMC1_R>;
>>> -			cap-sd-highspeed;
>>> -			cap-mmc-highspeed;
>>> -			max-frequency = <130000000>;
>>> -			status = "disabled";
>>> -		};
>>> -
>>> -		sdmmc2: mmc@58007000 {
>>> -			compatible = "st,stm32-sdmmc2", "arm,pl18x", "arm,primecell";
>>> -			arm,primecell-periphid = <0x20253180>;
>>> -			reg = <0x58007000 0x1000>, <0x58008000 0x1000>;
>>> -			interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
>>> -			clocks = <&rcc SDMMC2_K>;
>>> -			clock-names = "apb_pclk";
>>> -			resets = <&rcc SDMMC2_R>;
>>> -			cap-sd-highspeed;
>>> -			cap-mmc-highspeed;
>>> -			max-frequency = <130000000>;
>>> -			status = "disabled";
>>> -		};
>>> -
>>>   		usbh_ohci: usb@5800c000 {
>>>   			compatible = "generic-ohci";
>>>   			reg = <0x5800c000 0x1000>;
>>> @@ -486,29 +316,6 @@ iwdg2: watchdog@5a002000 {
>>>   			status = "disabled";
>>>   		};
>>>   
>>> -		usbphyc: usbphyc@5a006000 {
>>> -			#address-cells = <1>;
>>> -			#size-cells = <0>;
>>> -			#clock-cells = <0>;
>>> -			compatible = "st,stm32mp1-usbphyc";
>>> -			reg = <0x5a006000 0x1000>;
>>> -			clocks = <&rcc USBPHY_K>;
>>> -			resets = <&rcc USBPHY_R>;
>>> -			vdda1v1-supply = <&reg11>;
>>> -			vdda1v8-supply = <&reg18>;
>>> -			status = "disabled";
>>> -
>>> -			usbphyc_port0: usb-phy@0 {
>>> -				#phy-cells = <0>;
>>> -				reg = <0>;
>>> -			};
>>> -
>>> -			usbphyc_port1: usb-phy@1 {
>>> -				#phy-cells = <1>;
>>> -				reg = <1>;
>>> -			};
>>> -		};
>>> -
>>>   		rtc: rtc@5c004000 {
>>>   			compatible = "st,stm32mp1-rtc";
>>>   			reg = <0x5c004000 0x400>;
>>> @@ -536,6 +343,220 @@ ts_cal2: calib@5e {
>>>   			};
>>>   		};
>>>   
>>> +		etzpc: bus@5c007000 {
>>> +			compatible = "st,stm32mp13-sys-bus";
>>> +			reg = <0x5c007000 0x400>;
>>> +			#address-cells = <1>;
>>> +			#size-cells = <1>;
>>> +			feature-domain-controller;
>>> +			#feature-domain-cells = <1>;
>>> +			ranges;
>>> +
>>> +			adc_2: adc@48004000 {
>>> +				compatible = "st,stm32mp13-adc-core";
>>> +				reg = <0x48004000 0x400>;
>>> +				interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
>>> +				clocks = <&rcc ADC2>, <&rcc ADC2_K>;
>>> +				clock-names = "bus", "adc";
>>> +				interrupt-controller;
>>> +				#interrupt-cells = <1>;
>>> +				#address-cells = <1>;
>>> +				#size-cells = <0>;
>>> +				feature-domains = <&etzpc 33>;
>>> +				status = "disabled";
>>> +
>>> +				adc2: adc@0 {
>>> +					compatible = "st,stm32mp13-adc";
>>> +					#io-channel-cells = <1>;
>>> +					#address-cells = <1>;
>>> +					#size-cells = <0>;
>>> +					reg = <0x0>;
>>> +					interrupt-parent = <&adc_2>;
>>> +					interrupts = <0>;
>>> +					dmas = <&dmamux1 10 0x400 0x80000001>;
>>> +					dma-names = "rx";
>>> +					status = "disabled";
>>> +
>>> +					channel@13 {
>>> +						reg = <13>;
>>> +						label = "vrefint";
>>> +					};
>>> +					channel@14 {
>>> +						reg = <14>;
>>> +						label = "vddcore";
>>> +					};
>>> +					channel@16 {
>>> +						reg = <16>;
>>> +						label = "vddcpu";
>>> +					};
>>> +					channel@17 {
>>> +						reg = <17>;
>>> +						label = "vddq_ddr";
>>> +					};
>>> +				};
>>> +			};
>>> +
>>> +			usbotg_hs: usb@49000000 {
>>> +				compatible = "st,stm32mp15-hsotg", "snps,dwc2";
>>> +				reg = <0x49000000 0x40000>;
>>> +				clocks = <&rcc USBO_K>;
>>> +				clock-names = "otg";
>>> +				resets = <&rcc USBO_R>;
>>> +				reset-names = "dwc2";
>>> +				interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
>>> +				g-rx-fifo-size = <512>;
>>> +				g-np-tx-fifo-size = <32>;
>>> +				g-tx-fifo-size = <256 16 16 16 16 16 16 16>;
>>> +				dr_mode = "otg";
>>> +				otg-rev = <0x200>;
>>> +				usb33d-supply = <&usb33>;
>>> +				feature-domains = <&etzpc 34>;
>>> +				status = "disabled";
>>> +			};
>>> +
>>> +			spi4: spi@4c002000 {
>>> +				compatible = "st,stm32h7-spi";
>>> +				reg = <0x4c002000 0x400>;
>>> +				interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
>>> +				clocks = <&rcc SPI4_K>;
>>> +				resets = <&rcc SPI4_R>;
>>> +				#address-cells = <1>;
>>> +				#size-cells = <0>;
>>> +				dmas = <&dmamux1 83 0x400 0x01>,
>>> +				       <&dmamux1 84 0x400 0x01>;
>>> +				dma-names = "rx", "tx";
>>> +				feature-domains = <&etzpc 18>;
>>> +				status = "disabled";
>>> +			};
>>> +
>>> +			spi5: spi@4c003000 {
>>> +				compatible = "st,stm32h7-spi";
>>> +				reg = <0x4c003000 0x400>;
>>> +				interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
>>> +				clocks = <&rcc SPI5_K>;
>>> +				resets = <&rcc SPI5_R>;
>>> +				#address-cells = <1>;
>>> +				#size-cells = <0>;
>>> +				dmas = <&dmamux1 85 0x400 0x01>,
>>> +				       <&dmamux1 86 0x400 0x01>;
>>> +				dma-names = "rx", "tx";
>>> +				feature-domains = <&etzpc 19>;
>>> +				status = "disabled";
>>> +			};
>>> +
>>> +			i2c3: i2c@4c004000 {
>>> +				compatible = "st,stm32mp13-i2c";
>>> +				reg = <0x4c004000 0x400>;
>>> +				interrupt-names = "event", "error";
>>> +				interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>,
>>> +					     <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
>>> +				clocks = <&rcc I2C3_K>;
>>> +				resets = <&rcc I2C3_R>;
>>> +				#address-cells = <1>;
>>> +				#size-cells = <0>;
>>> +				dmas = <&dmamux1 73 0x400 0x1>,
>>> +				       <&dmamux1 74 0x400 0x1>;
>>> +				dma-names = "rx", "tx";
>>> +				st,syscfg-fmp = <&syscfg 0x4 0x4>;
>>> +				i2c-analog-filter;
>>> +				feature-domains = <&etzpc 20>;
>>> +				status = "disabled";
>>> +			};
>>> +
>>> +			i2c4: i2c@4c005000 {
>>> +				compatible = "st,stm32mp13-i2c";
>>> +				reg = <0x4c005000 0x400>;
>>> +				interrupt-names = "event", "error";
>>> +				interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>,
>>> +					     <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
>>> +				clocks = <&rcc I2C4_K>;
>>> +				resets = <&rcc I2C4_R>;
>>> +				#address-cells = <1>;
>>> +				#size-cells = <0>;
>>> +				dmas = <&dmamux1 75 0x400 0x1>,
>>> +				       <&dmamux1 76 0x400 0x1>;
>>> +				dma-names = "rx", "tx";
>>> +				st,syscfg-fmp = <&syscfg 0x4 0x8>;
>>> +				i2c-analog-filter;
>>> +				feature-domains = <&etzpc 21>;
>>> +				status = "disabled";
>>> +			};
>>> +
>>> +			i2c5: i2c@4c006000 {
>>> +				compatible = "st,stm32mp13-i2c";
>>> +				reg = <0x4c006000 0x400>;
>>> +				interrupt-names = "event", "error";
>>> +				interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>,
>>> +					     <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>;
>>> +				clocks = <&rcc I2C5_K>;
>>> +				resets = <&rcc I2C5_R>;
>>> +				#address-cells = <1>;
>>> +				#size-cells = <0>;
>>> +				dmas = <&dmamux1 115 0x400 0x1>,
>>> +				       <&dmamux1 116 0x400 0x1>;
>>> +				dma-names = "rx", "tx";
>>> +				st,syscfg-fmp = <&syscfg 0x4 0x10>;
>>> +				i2c-analog-filter;
>>> +				feature-domains = <&etzpc 22>;
>>> +				status = "disabled";
>>> +			};
>>> +
>>> +			sdmmc1: mmc@58005000 {
>>> +				compatible = "st,stm32-sdmmc2", "arm,pl18x", "arm,primecell";
>>> +				arm,primecell-periphid = <0x20253180>;
>>> +				reg = <0x58005000 0x1000>, <0x58006000 0x1000>;
>>> +				interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
>>> +				clocks = <&rcc SDMMC1_K>;
>>> +				clock-names = "apb_pclk";
>>> +				resets = <&rcc SDMMC1_R>;
>>> +				cap-sd-highspeed;
>>> +				cap-mmc-highspeed;
>>> +				max-frequency = <130000000>;
>>> +				feature-domains = <&etzpc 50>;
>>> +				status = "disabled";
>>> +			};
>>> +
>>> +			sdmmc2: mmc@58007000 {
>>> +				compatible = "st,stm32-sdmmc2", "arm,pl18x", "arm,primecell";
>>> +				arm,primecell-periphid = <0x20253180>;
>>> +				reg = <0x58007000 0x1000>, <0x58008000 0x1000>;
>>> +				interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
>>> +				clocks = <&rcc SDMMC2_K>;
>>> +				clock-names = "apb_pclk";
>>> +				resets = <&rcc SDMMC2_R>;
>>> +				cap-sd-highspeed;
>>> +				cap-mmc-highspeed;
>>> +				max-frequency = <130000000>;
>>> +				feature-domains = <&etzpc 51>;
>>> +				status = "disabled";
>>> +			};
>>> +
>>> +			usbphyc: usbphyc@5a006000 {
>>> +				#address-cells = <1>;
>>> +				#size-cells = <0>;
>>> +				#clock-cells = <0>;
>>> +				compatible = "st,stm32mp1-usbphyc";
>>> +				reg = <0x5a006000 0x1000>;
>>> +				clocks = <&rcc USBPHY_K>;
>>> +				resets = <&rcc USBPHY_R>;
>>> +				vdda1v1-supply = <&reg11>;
>>> +				vdda1v8-supply = <&reg18>;
>>> +				feature-domains = <&etzpc 5>;
>>> +				status = "disabled";
>>> +
>>> +				usbphyc_port0: usb-phy@0 {
>>> +					#phy-cells = <0>;
>>> +					reg = <0>;
>>> +				};
>>> +
>>> +				usbphyc_port1: usb-phy@1 {
>>> +					#phy-cells = <1>;
>>> +					reg = <1>;
>>> +				};
>>> +			};
>>> +
>>> +		};
>>> +
>>>   		/*
>>>   		 * Break node order to solve dependency probe issue between
>>>   		 * pinctrl and exti.
>>> diff --git a/arch/arm/boot/dts/stm32mp133.dtsi b/arch/arm/boot/dts/stm32mp133.dtsi
>>> index df451c3c2a26..be6061552683 100644
>>> --- a/arch/arm/boot/dts/stm32mp133.dtsi
>>> +++ b/arch/arm/boot/dts/stm32mp133.dtsi
>>> @@ -33,35 +33,38 @@ m_can2: can@4400f000 {
>>>   			bosch,mram-cfg = <0x1400 0 0 32 0 0 2 2>;
>>>   			status = "disabled";
>>>   		};
>>> +	};
>>> +};
>>>   
>>> -		adc_1: adc@48003000 {
>>> -			compatible = "st,stm32mp13-adc-core";
>>> -			reg = <0x48003000 0x400>;
>>> -			interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
>>> -			clocks = <&rcc ADC1>, <&rcc ADC1_K>;
>>> -			clock-names = "bus", "adc";
>>> -			interrupt-controller;
>>> -			#interrupt-cells = <1>;
>>> +&etzpc {
>>> +	adc_1: adc@48003000 {
>>> +		compatible = "st,stm32mp13-adc-core";
>>> +		reg = <0x48003000 0x400>;
>>> +		interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
>>> +		clocks = <&rcc ADC1>, <&rcc ADC1_K>;
>>> +		clock-names = "bus", "adc";
>>> +		interrupt-controller;
>>> +		#interrupt-cells = <1>;
>>> +		#address-cells = <1>;
>>> +		#size-cells = <0>;
>>> +		feature-domains = <&etzpc 32>;
>>> +		status = "disabled";
>>> +
>>> +		adc1: adc@0 {
>>> +			compatible = "st,stm32mp13-adc";
>>> +			#io-channel-cells = <1>;
>>>   			#address-cells = <1>;
>>>   			#size-cells = <0>;
>>> +			reg = <0x0>;
>>> +			interrupt-parent = <&adc_1>;
>>> +			interrupts = <0>;
>>> +			dmas = <&dmamux1 9 0x400 0x80000001>;
>>> +			dma-names = "rx";
>>>   			status = "disabled";
>>>   
>>> -			adc1: adc@0 {
>>> -				compatible = "st,stm32mp13-adc";
>>> -				#io-channel-cells = <1>;
>>> -				#address-cells = <1>;
>>> -				#size-cells = <0>;
>>> -				reg = <0x0>;
>>> -				interrupt-parent = <&adc_1>;
>>> -				interrupts = <0>;
>>> -				dmas = <&dmamux1 9 0x400 0x80000001>;
>>> -				dma-names = "rx";
>>> -				status = "disabled";
>>> -
>>> -				channel@18 {
>>> -					reg = <18>;
>>> -					label = "vrefint";
>>> -				};
>>> +			channel@18 {
>>> +				reg = <18>;
>>> +				label = "vrefint";
>>>   			};
>>>   		};
>>>   	};
>>> diff --git a/arch/arm/boot/dts/stm32mp13xc.dtsi b/arch/arm/boot/dts/stm32mp13xc.dtsi
>>> index 4d00e7592882..a1a7a40c2a3e 100644
>>> --- a/arch/arm/boot/dts/stm32mp13xc.dtsi
>>> +++ b/arch/arm/boot/dts/stm32mp13xc.dtsi
>>> @@ -4,15 +4,14 @@
>>>    * Author: Alexandre Torgue <alexandre.torgue@foss.st.com> for STMicroelectronics.
>>>    */
>>>   
>>> -/ {
>>> -	soc {
>>> -		cryp: crypto@54002000 {
>>> -			compatible = "st,stm32mp1-cryp";
>>> -			reg = <0x54002000 0x400>;
>>> -			interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
>>> -			clocks = <&rcc CRYP1>;
>>> -			resets = <&rcc CRYP1_R>;
>>> -			status = "disabled";
>>> -		};
>>> +&etzpc {
>>> +	cryp: crypto@54002000 {
>>> +		compatible = "st,stm32mp1-cryp";
>>> +		reg = <0x54002000 0x400>;
>>> +		interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
>>> +		clocks = <&rcc CRYP1>;
>>> +		resets = <&rcc CRYP1_R>;
>>> +		feature-domains = <&etzpc 42>;
>>> +		status = "disabled";
>>>   	};
>>>   };
>>> diff --git a/arch/arm/boot/dts/stm32mp13xf.dtsi b/arch/arm/boot/dts/stm32mp13xf.dtsi
>>> index 4d00e7592882..b9fb071a1471 100644
>>> --- a/arch/arm/boot/dts/stm32mp13xf.dtsi
>>> +++ b/arch/arm/boot/dts/stm32mp13xf.dtsi
>>> @@ -4,15 +4,13 @@
>>>    * Author: Alexandre Torgue <alexandre.torgue@foss.st.com> for STMicroelectronics.
>>>    */
>>>   
>>> -/ {
>>> -	soc {
>>> -		cryp: crypto@54002000 {
>>> -			compatible = "st,stm32mp1-cryp";
>>> -			reg = <0x54002000 0x400>;
>>> -			interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
>>> -			clocks = <&rcc CRYP1>;
>>> -			resets = <&rcc CRYP1_R>;
>>> -			status = "disabled";
>>> -		};
>>> +&etzpc {
>>> +	cryp: crypto@54002000 {
>>> +		compatible = "st,stm32mp1-cryp";
>>> +		reg = <0x54002000 0x400>;
>>> +		interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
>>> +		clocks = <&rcc CRYP1>;
>>> +		resets = <&rcc CRYP1_R>;
>>> +		status = "disabled";
>>>   	};
>>>   };
>>
> 

Regarding the patch itself, I can separate it in two patches.
1)Introduce ETZPC
2)Move peripherals under ETZPC

Best regards,
Gatien

^ permalink raw reply

* Re: [PATCH v3 3/3] serial: 8250_em: Add serial_out() to struct serial8250_em_hw_info
From: Niklas Söderlund @ 2023-02-13 10:29 UTC (permalink / raw)
  To: Biju Das
  Cc: Jiri Slaby, Ilpo Järvinen, Geert Uytterhoeven, Magnus Damm,
	Greg Kroah-Hartman, linux-serial, Fabrizio Castro,
	linux-renesas-soc@vger.kernel.org
In-Reply-To: <OS0PR01MB5922EFD04CDA5EE790CE2B0086DD9@OS0PR01MB5922.jpnprd01.prod.outlook.com>

Hi Biju,

On 2023-02-13 10:06:04 +0000, Biju Das wrote:
> Hi Niklas,
> 
> Thanks for testing.
> 
> > -----Original Message-----
> > From: Niklas Söderlund <niklas.soderlund@ragnatech.se>
> > Sent: Monday, February 13, 2023 9:58 AM
> > To: Biju Das <biju.das.jz@bp.renesas.com>
> > Cc: Jiri Slaby <jirislaby@kernel.org>; Ilpo Järvinen
> > <ilpo.jarvinen@linux.intel.com>; Geert Uytterhoeven
> > <geert+renesas@glider.be>; Magnus Damm <magnus.damm@gmail.com>; Greg Kroah-
> > Hartman <gregkh@linuxfoundation.org>; linux-serial <linux-
> > serial@vger.kernel.org>; Fabrizio Castro <fabrizio.castro.jz@renesas.com>;
> > linux-renesas-soc@vger.kernel.org
> > Subject: Re: [PATCH v3 3/3] serial: 8250_em: Add serial_out() to struct
> > serial8250_em_hw_info
> > 
> > Hi Biju,
> > 
> > On 2023-02-13 09:31:27 +0000, Biju Das wrote:
> > > Adding Magnus and Niklas to test on EMMA mobile platform to check the
> > > port type detected On that platform?
> > 
> > I don't know what you want me to check, I don't know much about serial. I
> > wired up the platform during the weekend, here is a boot log running on
> > v6.1. If you want to to check / test something I'm happy to, but will need
> > instructions.
> 
> As per Geert the register layout is same as RZ/V2M,
> So The UART is register compatible with standard 16750 chip.
> 
> But below log shows that it is 16550A and using only 16-bytes fifo,
> Eventhough it has 64-bytes fifo.
> 
> [    1.020000] e1020000.serial: ttyS0 at MMIO 0xe1020000 (irq = 37, base_baud = 796444) is a 16550A
> [    1.020000] e1030000.serial: ttyS1 at MMIO 0xe1030000 (irq = 38, base_baud = 7168000) is a 16550A
> [    1.690000] printk: console [ttyS1] enabled
> [    1.700000] e1040000.serial: ttyS2 at MMIO 0xe1040000 (irq = 39, base_baud = 14336000) is a 16550A
> [    1.710000] e1050000.serial: ttyS3 at MMIO 0xe1050000 (irq = 40, base_baud = 2389333) is a 16550A
> 
> So if you apply, this patch series, and add below changes it should detect as 16750
> 
> https://lore.kernel.org/linux-renesas-soc/8585f736-cf3b-b63c-753f-892d4051ada3@linux.intel.com/T/#mce8d222e3670321e8a8e39faacc4d6dd061fdbd6
> 
> and for quick testing please do below change for emma mobile.
> 
> + { .compatible = "renesas,em-uart", .data = &rzv2m_uart_hw_info },


Could you provide a branch with the setup you like me to test?

> 
> Cheers,
> Biju
> 
> 
> 
> > 
> > [    0.000000] Booting Linux on physical CPU 0x0
> > [    0.000000] Linux version 6.1.0 (neg@sleipner) (arm-linux-gnueabihf-gcc
> > (GCC) 10.2.0, GNU ld (GNU Binutils) 2.35.1) #1 SMP Sun Feb 12 18:44:55 CET
> > 2023
> > [    0.000000] CPU: ARMv7 Processor [411fc092] revision 2 (ARMv7),
> > cr=10c5387d
> > [    0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing
> > instruction cache
> > [    0.000000] OF: fdt: Machine model: EMEV2 KZM9D Board
> > [    0.000000] printk: debug: ignoring loglevel setting.
> > [    0.000000] Memory policy: Data cache writealloc
> > [    0.000000] cma: Failed to reserve 128 MiB
> > [    0.000000] Zone ranges:
> > [    0.000000]   Normal   [mem 0x0000000040000000-0x0000000047ffffff]
> > [    0.000000]   HighMem  empty
> > [    0.000000] Movable zone start for each node
> > [    0.000000] Early memory node ranges
> > [    0.000000]   node   0: [mem 0x0000000040000000-0x0000000047ffffff]
> > [    0.000000] Initmem setup node 0 [mem 0x0000000040000000-
> > 0x0000000047ffffff]
> > [    0.000000] percpu: Embedded 13 pages/cpu s32468 r0 d20780 u53248
> > [    0.000000] pcpu-alloc: s32468 r0 d20780 u53248 alloc=13*4096
> > [    0.000000] pcpu-alloc: [0] 0 [0] 1
> > [    0.000000] Built 1 zonelists, mobility grouping on.  Total pages: 32512
> > [    0.000000] Kernel command line: ignore_loglevel rw root=/dev/nfs ip=on
> > [    0.000000] Dentry cache hash table entries: 16384 (order: 4, 65536
> > bytes, linear)
> > [    0.000000] Inode-cache hash table entries: 8192 (order: 3, 32768 bytes,
> > linear)
> > [    0.000000] mem auto-init: stack:off, heap alloc:off, heap free:off
> > [    0.000000] Memory: 116072K/131072K available (8192K kernel code, 1152K
> > rwdata, 2436K rodata, 1024K init, 259K bss, 15000K reserved, 0K cma-
> > reserved, 0K highmem)
> > [    0.000000] trace event string verifier disabled
> > [    0.000000] rcu: Hierarchical RCU implementation.
> > [    0.000000] rcu: 	RCU event tracing is enabled.
> > [    0.000000] rcu: 	RCU restricting CPUs from NR_CPUS=8 to
> > nr_cpu_ids=2.
> > [    0.000000] rcu: RCU calculated value of scheduler-enlistment delay is 10
> > jiffies.
> > [    0.000000] rcu: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=2
> > [    0.000000] NR_IRQS: 16, nr_irqs: 16, preallocated irqs: 16
> > [    0.000000] GIC: enabling workaround for broken byte access
> > [    0.000000] rcu: srcu_init: Setting srcu_struct sizes based on
> > contention.
> > [    0.000000] timer_probe: no matching timers found
> > [    0.000000] Console: colour dummy device 80x30
> > [    0.000000] printk: console [tty0] enabled
> > [    0.000000] sched_clock: 32 bits at 100 Hz, resolution 10000000ns, wraps
> > every 21474836475000000ns
> > [    0.000000] Calibrating delay loop (skipped) preset value.. 1066.00
> > BogoMIPS (lpj=5330000)
> > [    0.000000] pid_max: default: 32768 minimum: 301
> > [    0.000000] Mount-cache hash table entries: 1024 (order: 0, 4096 bytes,
> > linear)
> > [    0.000000] Mountpoint-cache hash table entries: 1024 (order: 0, 4096
> > bytes, linear)
> > [    0.000000] CPU: Testing write buffer coherency: ok
> > [    0.000000] CPU0: Spectre v2: using BPIALL workaround
> > [    0.000000] CPU0: thread -1, cpu 0, socket 0, mpidr 80000000
> > [    0.000000] Setting up static identity map for 0x40100000 - 0x40100060
> > [    0.000000] rcu: Hierarchical SRCU implementation.
> > [    0.000000] rcu: 	Max phase no-delay instances is 1000.
> > [    0.000000] smp: Bringing up secondary CPUs ...
> > [    0.000000] CPU1: thread -1, cpu 1, socket 0, mpidr 80000001
> > [    0.000000] CPU1: Spectre v2: using BPIALL workaround
> > [    0.000000] smp: Brought up 1 node, 2 CPUs
> > [    0.000000] SMP: Total of 2 processors activated (2132.00 BogoMIPS).
> > [    0.000000] CPU: All CPU(s) started in SVC mode.
> > [    0.000000] devtmpfs: initialized
> > [    0.000000] VFP support v0.3: implementor 41 architecture 3 part 30
> > variant 9 rev 1
> > [    0.000000] clocksource: jiffies: mask: 0xffffffff max_cycles:
> > 0xffffffff, max_idle_ns: 19112604462750000 ns
> > [    0.000000] futex hash table entries: 512 (order: 3, 32768 bytes, linear)
> > [    0.000000] pinctrl core: initialized pinctrl subsystem
> > [    0.000000] NET: Registered PF_NETLINK/PF_ROUTE protocol family
> > [    0.000000] DMA: preallocated 256 KiB pool for atomic coherent
> > allocations
> > [    0.000000] thermal_sys: Registered thermal governor 'step_wise'
> > [    0.000000] No ATAGs?
> > [    0.000000] hw-breakpoint: found 5 (+1 reserved) breakpoint and 1
> > watchpoint registers.
> > [    0.000000] hw-breakpoint: maximum watchpoint size is 4 bytes.
> > [    0.000000] sh-pfc e0140200.pinctrl: emev2_pfc support registered
> > [    0.000000] SCSI subsystem initialized
> > [    0.000000] libata version 3.00 loaded.
> > [    0.000000] usbcore: registered new interface driver usbfs
> > [    0.000000] usbcore: registered new interface driver hub
> > [    0.000000] usbcore: registered new device driver usb
> > [    0.000000] mc: Linux media interface: v0.10
> > [    0.000000] videodev: Linux video capture interface: v2.00
> > [    0.000000] pps_core: LinuxPPS API ver. 1 registered
> > [    0.000000] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo
> > Giometti <giometti@linux.it>
> > [    0.000000] PTP clock support registered
> > [    0.000000] em_sti e0180000.timer: used for clock events
> > [    0.000000] em_sti e0180000.timer: used for oneshot clock events
> > [    0.000000] em_sti e0180000.timer: used as clock source
> > [    0.000000] clocksource: e0180000.timer: mask: 0xffffffffffff max_cycles:
> > 0x1ef4687b1, max_idle_ns: 112843571739654 ns
> > [    0.000000] Advanced Linux Sound Architecture Driver Initialized.
> > [    0.000000] vgaarb: loaded
> > [    0.940000] clocksource: Switched to clocksource e0180000.timer
> > [    0.950000] Clockevents: could not switch to one-shot mode:
> > [    0.950000] Clockevents: could not switch to one-shot mode: dummy_timer
> > is not functional.
> > [    0.950000]  dummy_timer is not functional.
> > [    0.960000] NET: Registered PF_INET protocol family
> > [    0.960000] IP idents hash table entries: 2048 (order: 2, 16384 bytes,
> > linear)
> > [    0.960000] tcp_listen_portaddr_hash hash table entries: 512 (order: 0,
> > 4096 bytes, linear)
> > [    0.960000] Table-perturb hash table entries: 65536 (order: 6, 262144
> > bytes, linear)
> > [    0.960000] TCP established hash table entries: 1024 (order: 0, 4096
> > bytes, linear)
> > [    0.960000] TCP bind hash table entries: 1024 (order: 2, 16384 bytes,
> > linear)
> > [    0.960000] TCP: Hash tables configured (established 1024 bind 1024)
> > [    0.960000] UDP hash table entries: 256 (order: 1, 8192 bytes, linear)
> > [    0.960000] UDP-Lite hash table entries: 256 (order: 1, 8192 bytes,
> > linear)
> > [    0.960000] NET: Registered PF_UNIX/PF_LOCAL protocol family
> > [    0.960000] RPC: Registered named UNIX socket transport module.
> > [    0.960000] RPC: Registered udp transport module.
> > [    0.960000] RPC: Registered tcp transport module.
> > [    0.960000] RPC: Registered tcp NFSv4.1 backchannel transport module.
> > [    0.960000] PCI: CLS 0 bytes, default 64
> > [    1.000000] hw perfevents: enabled with armv7_cortex_a9 PMU driver, 7
> > counters available
> > [    1.000000] workingset: timestamp_bits=30 max_order=15 bucket_order=0
> > [    1.000000] NFS: Registering the id_resolver key type
> > [    1.000000] Key type id_resolver registered
> > [    1.000000] Key type id_legacy registered
> > [    1.000000] nfs4filelayout_init: NFSv4 File Layout Driver Registering...
> > [    1.000000] nfs4flexfilelayout_init: NFSv4 Flexfile Layout Driver
> > Registering...
> > [    1.000000] Block layer SCSI generic (bsg) driver version 0.4 loaded
> > (major 246)
> > [    1.000000] io scheduler mq-deadline registered
> > [    1.000000] io scheduler kyber registered
> > [    1.010000] Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
> > [    1.020000] e1020000.serial: ttyS0 at MMIO 0xe1020000 (irq = 37,
> > base_baud = 796444) is a 16550A
> > [    1.020000] e1030000.serial: ttyS1 at MMIO 0xe1030000 (irq = 38,
> > base_baud = 7168000) is a 16550A
> > [    1.690000] printk: console [ttyS1] enabled
> > [    1.700000] e1040000.serial: ttyS2 at MMIO 0xe1040000 (irq = 39,
> > base_baud = 14336000) is a 16550A
> > [    1.710000] e1050000.serial: ttyS3 at MMIO 0xe1050000 (irq = 40,
> > base_baud = 2389333) is a 16550A
> > [    1.720000] SuperH (H)SCI(F) driver initialized
> > [    1.730000] CAN device driver interface
> > [    1.800000] smsc911x 20000000.ethernet eth0: MAC Address:
> > 00:0a:a3:02:12:92
> > [    1.810000] UDC core: g_ether: couldn't find an available UDC
> > [    1.810000] i2c_dev: i2c /dev entries driver
> > [    1.820000] em-i2c e0070000.i2c: Added i2c controller 0, irq 42
> > [    1.830000] em-i2c e10a0000.i2c: Added i2c controller 1, irq 43
> > [    1.830000] cpu cpu0: OPP table can't be empty
> > [    1.840000] usbcore: registered new interface driver usbhid
> > [    1.850000] usbhid: USB HID core driver
> > [    1.850000] NET: Registered PF_INET6 protocol family
> > [    1.860000] Segment Routing with IPv6
> > [    1.870000] In-situ OAM (IOAM) with IPv6
> > [    1.870000] sit: IPv6, IPv4 and MPLS over IPv4 tunneling driver
> > [    1.880000] NET: Registered PF_PACKET protocol family
> > [    1.880000] can: controller area network core
> > [    1.890000] NET: Registered PF_CAN protocol family
> > [    1.890000] can: raw protocol
> > [    1.900000] can: broadcast manager protocol
> > [    1.900000] can: netlink gateway - max_hops=1
> > [    1.900000] Key type dns_resolver registered
> > [    1.910000] Registering SWP/SWPB emulation handler
> > [    1.920000] input: gpio_keys as /devices/platform/gpio_keys/input/input0
> > [    1.980000] SMSC LAN8700 20000000.ethernet-ffffffff:01: attached PHY
> > driver (mii_bus:phy_addr=20000000.ethernet-ffffffff:01, irq=POLL)
> > [    2.020000] smsc911x 20000000.ethernet eth0: SMSC911x/921x identified at
> > 0xc8920000, IRQ: 41
> > [    4.160000] IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
> > [    4.210000] Sending DHCP requests ., OK
> > [    4.250000] IP-Config: Got DHCP answer from 10.0.1.1, my address is
> > 10.0.1.2
> > [    4.260000] IP-Config: Complete:
> > [    4.260000]      device=eth0, hwaddr=00:0a:a3:02:12:92, ipaddr=10.0.1.2,
> > mask=255.255.255.0, gw=10.0.1.1
> > [    4.270000]      host=10.0.1.2, domain=dyn.berto.se, nis-domain=(none)
> > [    4.280000]      bootserver=10.0.1.1, rootserver=10.0.1.1,
> > rootpath=/srv/nfs4/arch,tcp,v3
> > [    4.280000]      nameserver0=192.168.20.1
> > [    4.290000] ALSA device list:
> > [    4.290000]   No soundcards found.
> > [    4.320000] VFS: Mounted root (nfs filesystem) on device 0:15.
> > [    4.320000] devtmpfs: mounted
> > [    4.330000] Freeing unused kernel image (initmem) memory: 1024K
> > [    4.390000] Run /sbin/init as init process
> > [    4.390000]   with arguments:
> > [    4.390000]     /sbin/init
> > [    4.400000]   with environment:
> > [    4.400000]     HOME=/
> > [    4.400000]     TERM=linux
> > [    6.040000] systemd[1]: System time before build time, advancing clock.
> > [    6.100000] systemd[1]: Failed to find module 'autofs4'
> > [    6.220000] systemd[1]: systemd 252.5-1-arch running in system mode (+PAM
> > +AUDIT -SELINUX -APPARMOR -IMA +SMACK +SECCOMP +GCRYPT +GNUTLS +OPENSSL +ACL
> > +BLKID +CURL +ELFUTILS +FIDO2 +IDN2 -IDN +IPTC +KMOD +LIBCRYPTSETUP
> > +LIBFDISK +PCRE2 -PWQUALITY +P11KIT -QRENCODE +TPM2 +BZIP2 +LZ4 +XZ +ZLIB
> > +ZSTD +BPF_FRAMEWORK +XKBCOMMON +UTMP -SYSVINIT default-hierarchy=unified)
> > [    6.240000] systemd[1]: Detected architecture arm.
> > [    6.290000] systemd[1]: Hostname set to <arm>.
> > [    6.520000] systemd[1]: bpf-lsm: BPF LSM hook not enabled in the kernel,
> > BPF LSM not supported
> > [    8.710000] systemd[1]: Queued start job for default target Graphical
> > Interface.
> > [    8.730000] systemd[1]: Created slice Slice /system/getty.
> > [    8.770000] systemd[1]: Created slice Slice /system/modprobe.
> > [    8.810000] systemd[1]: Created slice Slice /system/serial-getty.
> > [    8.850000] systemd[1]: Created slice User and Session Slice.
> > [    8.890000] systemd[1]: Started Dispatch Password Requests to Console
> > Directory Watch.
> > [    8.930000] systemd[1]: Started Forward Password Requests to Wall
> > Directory Watch.
> > [    8.970000] systemd[1]: Arbitrary Executable File Formats File System
> > Automount Point was skipped because of an unmet condition check
> > (ConditionPathExists=/proc/sys/fs/binfmt_misc).
> > [    8.980000] systemd[1]: Reached target Local Encrypted Volumes.
> > [    9.020000] systemd[1]: Reached target Local Integrity Protected Volumes.
> > [    9.060000] systemd[1]: Reached target Network is Online.
> > [    9.100000] systemd[1]: Reached target Path Units.
> > [    9.130000] systemd[1]: Reached target Slice Units.
> > [    9.170000] systemd[1]: Reached target Swaps.
> > [    9.200000] systemd[1]: Reached target Local Verity Protected Volumes.
> > [    9.240000] systemd[1]: Listening on Device-mapper event daemon FIFOs.
> > [    9.300000] systemd[1]: Listening on Process Core Dump Socket.
> > [    9.340000] systemd[1]: Journal Audit Socket was skipped because of an
> > unmet condition check (ConditionSecurity=audit).
> > [    9.350000] systemd[1]: Listening on Journal Socket (/dev/log).
> > [    9.390000] systemd[1]: Listening on Journal Socket.
> > [    9.430000] systemd[1]: Listening on udev Control Socket.
> > [    9.470000] systemd[1]: Listening on udev Kernel Socket.
> > [    9.510000] systemd[1]: Huge Pages File System was skipped because of an
> > unmet condition check (ConditionPathExists=/sys/kernel/mm/hugepages).
> > [    9.520000] systemd[1]: POSIX Message Queue File System was skipped
> > because of an unmet condition check
> > (ConditionPathExists=/proc/sys/fs/mqueue).
> > [    9.590000] systemd[1]: Mounting /root/shared...
> > [    9.620000] systemd[1]: Mounting Kernel Debug File System...
> > [    9.680000] systemd[1]: Mounting Kernel Trace File System...
> > [    9.780000] systemd[1]: Mounting Temporary Directory /tmp...
> > [    9.820000] systemd[1]: Create List of Static Device Nodes was skipped
> > because of an unmet condition check
> > (ConditionFileNotEmpty=/lib/modules/6.1.0/modules.devname).
> > [    9.850000] systemd[1]: Starting Load Kernel Module configfs...
> > [    9.960000] systemd[1]: Starting Load Kernel Module drm...
> > [   10.010000] systemd[1]: Starting Load Kernel Module fuse...
> > [   10.070000] systemd[1]: Load Kernel Modules was skipped because no
> > trigger condition checks were met.
> > [   10.120000] systemd[1]: Starting Remount Root and Kernel File Systems...
> > [   10.190000] systemd[1]: Repartition Root Disk was skipped because no
> > trigger condition checks were met.
> > [   10.250000] systemd[1]: Starting Apply Kernel Variables...
> > [   10.310000] systemd[1]: Starting Coldplug All udev Devices...
> > [   10.390000] systemd[1]: Mounted Kernel Debug File System.
> > [   10.410000] systemd[1]: Mounted Kernel Trace File System.
> > [   10.450000] systemd[1]: Mounted Temporary Directory /tmp.
> > [   10.490000] systemd[1]: modprobe@configfs.service: Deactivated
> > successfully.
> > [   10.520000] systemd[1]: Finished Load Kernel Module configfs.
> > [   10.550000] systemd[1]: modprobe@drm.service: Deactivated successfully.
> > [   10.550000] systemd[1]: Finished Load Kernel Module drm.
> > [   10.600000] systemd[1]: modprobe@fuse.service: Deactivated successfully.
> > [   10.610000] systemd[1]: Finished Load Kernel Module fuse.
> > [   10.650000] systemd[1]: Finished Remount Root and Kernel File Systems.
> > [   10.670000] systemd[1]: Finished Apply Kernel Variables.
> > [   10.890000] systemd[1]: Reached target Host and Network Name Lookups.
> > [   10.940000] systemd[1]: Listening on RPCbind Server Activation Socket.
> > [   10.990000] systemd[1]: Reached target RPC Port Mapper.
> > [   11.030000] systemd[1]: FUSE Control File System was skipped because of
> > an unmet condition check (ConditionPathExists=/sys/fs/fuse/connections).
> > [   11.090000] systemd[1]: Mounting Kernel Configuration File System...
> > [   11.130000] systemd[1]: Starting NFS status monitor for NFSv2/3
> > locking....
> > [   11.180000] systemd[1]: First Boot Wizard was skipped because of an unmet
> > condition check (ConditionFirstBoot=yes).
> > [   11.210000] systemd[1]: Rebuild Hardware Database was skipped because of
> > an unmet condition check (ConditionNeedsUpdate=/etc).
> > [   11.290000] systemd[1]: Starting Load/Save Random Seed...
> > [   11.330000] systemd[1]: Create System Users was skipped because no
> > trigger condition checks were met.
> > [   11.380000] systemd[1]: Starting Create Static Device Nodes in /dev...
> > [   11.500000] systemd[1]: Finished Coldplug All udev Devices.
> > [   11.540000] systemd[1]: Mounted Kernel Configuration File System.
> > [   11.620000] systemd[1]: Starting RPC Bind...
> > [   12.160000] systemd[1]: Finished Create Static Device Nodes in /dev.
> > [   12.200000] systemd[1]: Started RPC Bind.
> > [   12.240000] systemd[1]: Reached target Preparation for Local File
> > Systems.
> > [   12.290000] systemd[1]: Virtual Machine and Container Storage
> > (Compatibility) was skipped because of an unmet condition check
> > (ConditionPathExists=/var/lib/machines.raw).
> > [   12.310000] systemd[1]: Reached target Local File Systems.
> > [   12.350000] systemd[1]: Entropy Daemon based on the HAVEGE algorithm was
> > skipped because of an unmet condition check (ConditionKernelVersion=<5.6).
> > [   12.360000] systemd[1]: Rebuild Dynamic Linker Cache was skipped because
> > no trigger condition checks were met.
> > [   12.420000] systemd[1]: Starting Notify NFS peers of a restart...
> > [   12.460000] systemd[1]: Set Up Additional Binary Formats was skipped
> > because no trigger condition checks were met.
> > [   12.480000] systemd[1]: systemd-journald.service: unit configures an IP
> > firewall, but the local system does not support BPF/cgroup firewalling.
> > [   12.490000] systemd[1]: (This warning is only shown for the first unit
> > using IP firewalling.)
> > [   12.570000] systemd[1]: Starting Journal Service...
> > [   12.620000] systemd[1]: Starting Rule-based Manager for Device Events and
> > Files...
> > [   12.700000] systemd[1]: Started NFS status monitor for NFSv2/3 locking..
> > [   12.740000] systemd[1]: Started Notify NFS peers of a restart.
> > [   12.990000] systemd[1]: Started Journal Service.
> > [   16.860000] systemd-journald[87]: Received client request to flush
> > runtime journal.
> > [   21.360000] random: dbus-daemon: uninitialized urandom read (12 bytes
> > read)
> > [   22.190000] random: dbus-daemon: uninitialized urandom read (12 bytes
> > read)
> > [   39.150000] random: crng init done
> > 
> > --
> > Kind Regards,
> > Niklas Söderlund

-- 
Kind Regards,
Niklas Söderlund

^ permalink raw reply

* RE: [PATCH v3 3/3] serial: 8250_em: Add serial_out() to struct serial8250_em_hw_info
From: Biju Das @ 2023-02-13 10:06 UTC (permalink / raw)
  To: Niklas Söderlund
  Cc: Jiri Slaby, Ilpo Järvinen, Geert Uytterhoeven, Magnus Damm,
	Greg Kroah-Hartman, linux-serial, Fabrizio Castro,
	linux-renesas-soc@vger.kernel.org
In-Reply-To: <Y+oJkcP2e5a9H7fr@oden.dyn.berto.se>

Hi Niklas,

Thanks for testing.

> -----Original Message-----
> From: Niklas Söderlund <niklas.soderlund@ragnatech.se>
> Sent: Monday, February 13, 2023 9:58 AM
> To: Biju Das <biju.das.jz@bp.renesas.com>
> Cc: Jiri Slaby <jirislaby@kernel.org>; Ilpo Järvinen
> <ilpo.jarvinen@linux.intel.com>; Geert Uytterhoeven
> <geert+renesas@glider.be>; Magnus Damm <magnus.damm@gmail.com>; Greg Kroah-
> Hartman <gregkh@linuxfoundation.org>; linux-serial <linux-
> serial@vger.kernel.org>; Fabrizio Castro <fabrizio.castro.jz@renesas.com>;
> linux-renesas-soc@vger.kernel.org
> Subject: Re: [PATCH v3 3/3] serial: 8250_em: Add serial_out() to struct
> serial8250_em_hw_info
> 
> Hi Biju,
> 
> On 2023-02-13 09:31:27 +0000, Biju Das wrote:
> > Adding Magnus and Niklas to test on EMMA mobile platform to check the
> > port type detected On that platform?
> 
> I don't know what you want me to check, I don't know much about serial. I
> wired up the platform during the weekend, here is a boot log running on
> v6.1. If you want to to check / test something I'm happy to, but will need
> instructions.

As per Geert the register layout is same as RZ/V2M,
So The UART is register compatible with standard 16750 chip.

But below log shows that it is 16550A and using only 16-bytes fifo,
Eventhough it has 64-bytes fifo.

[    1.020000] e1020000.serial: ttyS0 at MMIO 0xe1020000 (irq = 37, base_baud = 796444) is a 16550A
[    1.020000] e1030000.serial: ttyS1 at MMIO 0xe1030000 (irq = 38, base_baud = 7168000) is a 16550A
[    1.690000] printk: console [ttyS1] enabled
[    1.700000] e1040000.serial: ttyS2 at MMIO 0xe1040000 (irq = 39, base_baud = 14336000) is a 16550A
[    1.710000] e1050000.serial: ttyS3 at MMIO 0xe1050000 (irq = 40, base_baud = 2389333) is a 16550A

So if you apply, this patch series, and add below changes it should detect as 16750

https://lore.kernel.org/linux-renesas-soc/8585f736-cf3b-b63c-753f-892d4051ada3@linux.intel.com/T/#mce8d222e3670321e8a8e39faacc4d6dd061fdbd6

and for quick testing please do below change for emma mobile.

+ { .compatible = "renesas,em-uart", .data = &rzv2m_uart_hw_info },

Cheers,
Biju



> 
> [    0.000000] Booting Linux on physical CPU 0x0
> [    0.000000] Linux version 6.1.0 (neg@sleipner) (arm-linux-gnueabihf-gcc
> (GCC) 10.2.0, GNU ld (GNU Binutils) 2.35.1) #1 SMP Sun Feb 12 18:44:55 CET
> 2023
> [    0.000000] CPU: ARMv7 Processor [411fc092] revision 2 (ARMv7),
> cr=10c5387d
> [    0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing
> instruction cache
> [    0.000000] OF: fdt: Machine model: EMEV2 KZM9D Board
> [    0.000000] printk: debug: ignoring loglevel setting.
> [    0.000000] Memory policy: Data cache writealloc
> [    0.000000] cma: Failed to reserve 128 MiB
> [    0.000000] Zone ranges:
> [    0.000000]   Normal   [mem 0x0000000040000000-0x0000000047ffffff]
> [    0.000000]   HighMem  empty
> [    0.000000] Movable zone start for each node
> [    0.000000] Early memory node ranges
> [    0.000000]   node   0: [mem 0x0000000040000000-0x0000000047ffffff]
> [    0.000000] Initmem setup node 0 [mem 0x0000000040000000-
> 0x0000000047ffffff]
> [    0.000000] percpu: Embedded 13 pages/cpu s32468 r0 d20780 u53248
> [    0.000000] pcpu-alloc: s32468 r0 d20780 u53248 alloc=13*4096
> [    0.000000] pcpu-alloc: [0] 0 [0] 1
> [    0.000000] Built 1 zonelists, mobility grouping on.  Total pages: 32512
> [    0.000000] Kernel command line: ignore_loglevel rw root=/dev/nfs ip=on
> [    0.000000] Dentry cache hash table entries: 16384 (order: 4, 65536
> bytes, linear)
> [    0.000000] Inode-cache hash table entries: 8192 (order: 3, 32768 bytes,
> linear)
> [    0.000000] mem auto-init: stack:off, heap alloc:off, heap free:off
> [    0.000000] Memory: 116072K/131072K available (8192K kernel code, 1152K
> rwdata, 2436K rodata, 1024K init, 259K bss, 15000K reserved, 0K cma-
> reserved, 0K highmem)
> [    0.000000] trace event string verifier disabled
> [    0.000000] rcu: Hierarchical RCU implementation.
> [    0.000000] rcu: 	RCU event tracing is enabled.
> [    0.000000] rcu: 	RCU restricting CPUs from NR_CPUS=8 to
> nr_cpu_ids=2.
> [    0.000000] rcu: RCU calculated value of scheduler-enlistment delay is 10
> jiffies.
> [    0.000000] rcu: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=2
> [    0.000000] NR_IRQS: 16, nr_irqs: 16, preallocated irqs: 16
> [    0.000000] GIC: enabling workaround for broken byte access
> [    0.000000] rcu: srcu_init: Setting srcu_struct sizes based on
> contention.
> [    0.000000] timer_probe: no matching timers found
> [    0.000000] Console: colour dummy device 80x30
> [    0.000000] printk: console [tty0] enabled
> [    0.000000] sched_clock: 32 bits at 100 Hz, resolution 10000000ns, wraps
> every 21474836475000000ns
> [    0.000000] Calibrating delay loop (skipped) preset value.. 1066.00
> BogoMIPS (lpj=5330000)
> [    0.000000] pid_max: default: 32768 minimum: 301
> [    0.000000] Mount-cache hash table entries: 1024 (order: 0, 4096 bytes,
> linear)
> [    0.000000] Mountpoint-cache hash table entries: 1024 (order: 0, 4096
> bytes, linear)
> [    0.000000] CPU: Testing write buffer coherency: ok
> [    0.000000] CPU0: Spectre v2: using BPIALL workaround
> [    0.000000] CPU0: thread -1, cpu 0, socket 0, mpidr 80000000
> [    0.000000] Setting up static identity map for 0x40100000 - 0x40100060
> [    0.000000] rcu: Hierarchical SRCU implementation.
> [    0.000000] rcu: 	Max phase no-delay instances is 1000.
> [    0.000000] smp: Bringing up secondary CPUs ...
> [    0.000000] CPU1: thread -1, cpu 1, socket 0, mpidr 80000001
> [    0.000000] CPU1: Spectre v2: using BPIALL workaround
> [    0.000000] smp: Brought up 1 node, 2 CPUs
> [    0.000000] SMP: Total of 2 processors activated (2132.00 BogoMIPS).
> [    0.000000] CPU: All CPU(s) started in SVC mode.
> [    0.000000] devtmpfs: initialized
> [    0.000000] VFP support v0.3: implementor 41 architecture 3 part 30
> variant 9 rev 1
> [    0.000000] clocksource: jiffies: mask: 0xffffffff max_cycles:
> 0xffffffff, max_idle_ns: 19112604462750000 ns
> [    0.000000] futex hash table entries: 512 (order: 3, 32768 bytes, linear)
> [    0.000000] pinctrl core: initialized pinctrl subsystem
> [    0.000000] NET: Registered PF_NETLINK/PF_ROUTE protocol family
> [    0.000000] DMA: preallocated 256 KiB pool for atomic coherent
> allocations
> [    0.000000] thermal_sys: Registered thermal governor 'step_wise'
> [    0.000000] No ATAGs?
> [    0.000000] hw-breakpoint: found 5 (+1 reserved) breakpoint and 1
> watchpoint registers.
> [    0.000000] hw-breakpoint: maximum watchpoint size is 4 bytes.
> [    0.000000] sh-pfc e0140200.pinctrl: emev2_pfc support registered
> [    0.000000] SCSI subsystem initialized
> [    0.000000] libata version 3.00 loaded.
> [    0.000000] usbcore: registered new interface driver usbfs
> [    0.000000] usbcore: registered new interface driver hub
> [    0.000000] usbcore: registered new device driver usb
> [    0.000000] mc: Linux media interface: v0.10
> [    0.000000] videodev: Linux video capture interface: v2.00
> [    0.000000] pps_core: LinuxPPS API ver. 1 registered
> [    0.000000] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo
> Giometti <giometti@linux.it>
> [    0.000000] PTP clock support registered
> [    0.000000] em_sti e0180000.timer: used for clock events
> [    0.000000] em_sti e0180000.timer: used for oneshot clock events
> [    0.000000] em_sti e0180000.timer: used as clock source
> [    0.000000] clocksource: e0180000.timer: mask: 0xffffffffffff max_cycles:
> 0x1ef4687b1, max_idle_ns: 112843571739654 ns
> [    0.000000] Advanced Linux Sound Architecture Driver Initialized.
> [    0.000000] vgaarb: loaded
> [    0.940000] clocksource: Switched to clocksource e0180000.timer
> [    0.950000] Clockevents: could not switch to one-shot mode:
> [    0.950000] Clockevents: could not switch to one-shot mode: dummy_timer
> is not functional.
> [    0.950000]  dummy_timer is not functional.
> [    0.960000] NET: Registered PF_INET protocol family
> [    0.960000] IP idents hash table entries: 2048 (order: 2, 16384 bytes,
> linear)
> [    0.960000] tcp_listen_portaddr_hash hash table entries: 512 (order: 0,
> 4096 bytes, linear)
> [    0.960000] Table-perturb hash table entries: 65536 (order: 6, 262144
> bytes, linear)
> [    0.960000] TCP established hash table entries: 1024 (order: 0, 4096
> bytes, linear)
> [    0.960000] TCP bind hash table entries: 1024 (order: 2, 16384 bytes,
> linear)
> [    0.960000] TCP: Hash tables configured (established 1024 bind 1024)
> [    0.960000] UDP hash table entries: 256 (order: 1, 8192 bytes, linear)
> [    0.960000] UDP-Lite hash table entries: 256 (order: 1, 8192 bytes,
> linear)
> [    0.960000] NET: Registered PF_UNIX/PF_LOCAL protocol family
> [    0.960000] RPC: Registered named UNIX socket transport module.
> [    0.960000] RPC: Registered udp transport module.
> [    0.960000] RPC: Registered tcp transport module.
> [    0.960000] RPC: Registered tcp NFSv4.1 backchannel transport module.
> [    0.960000] PCI: CLS 0 bytes, default 64
> [    1.000000] hw perfevents: enabled with armv7_cortex_a9 PMU driver, 7
> counters available
> [    1.000000] workingset: timestamp_bits=30 max_order=15 bucket_order=0
> [    1.000000] NFS: Registering the id_resolver key type
> [    1.000000] Key type id_resolver registered
> [    1.000000] Key type id_legacy registered
> [    1.000000] nfs4filelayout_init: NFSv4 File Layout Driver Registering...
> [    1.000000] nfs4flexfilelayout_init: NFSv4 Flexfile Layout Driver
> Registering...
> [    1.000000] Block layer SCSI generic (bsg) driver version 0.4 loaded
> (major 246)
> [    1.000000] io scheduler mq-deadline registered
> [    1.000000] io scheduler kyber registered
> [    1.010000] Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
> [    1.020000] e1020000.serial: ttyS0 at MMIO 0xe1020000 (irq = 37,
> base_baud = 796444) is a 16550A
> [    1.020000] e1030000.serial: ttyS1 at MMIO 0xe1030000 (irq = 38,
> base_baud = 7168000) is a 16550A
> [    1.690000] printk: console [ttyS1] enabled
> [    1.700000] e1040000.serial: ttyS2 at MMIO 0xe1040000 (irq = 39,
> base_baud = 14336000) is a 16550A
> [    1.710000] e1050000.serial: ttyS3 at MMIO 0xe1050000 (irq = 40,
> base_baud = 2389333) is a 16550A
> [    1.720000] SuperH (H)SCI(F) driver initialized
> [    1.730000] CAN device driver interface
> [    1.800000] smsc911x 20000000.ethernet eth0: MAC Address:
> 00:0a:a3:02:12:92
> [    1.810000] UDC core: g_ether: couldn't find an available UDC
> [    1.810000] i2c_dev: i2c /dev entries driver
> [    1.820000] em-i2c e0070000.i2c: Added i2c controller 0, irq 42
> [    1.830000] em-i2c e10a0000.i2c: Added i2c controller 1, irq 43
> [    1.830000] cpu cpu0: OPP table can't be empty
> [    1.840000] usbcore: registered new interface driver usbhid
> [    1.850000] usbhid: USB HID core driver
> [    1.850000] NET: Registered PF_INET6 protocol family
> [    1.860000] Segment Routing with IPv6
> [    1.870000] In-situ OAM (IOAM) with IPv6
> [    1.870000] sit: IPv6, IPv4 and MPLS over IPv4 tunneling driver
> [    1.880000] NET: Registered PF_PACKET protocol family
> [    1.880000] can: controller area network core
> [    1.890000] NET: Registered PF_CAN protocol family
> [    1.890000] can: raw protocol
> [    1.900000] can: broadcast manager protocol
> [    1.900000] can: netlink gateway - max_hops=1
> [    1.900000] Key type dns_resolver registered
> [    1.910000] Registering SWP/SWPB emulation handler
> [    1.920000] input: gpio_keys as /devices/platform/gpio_keys/input/input0
> [    1.980000] SMSC LAN8700 20000000.ethernet-ffffffff:01: attached PHY
> driver (mii_bus:phy_addr=20000000.ethernet-ffffffff:01, irq=POLL)
> [    2.020000] smsc911x 20000000.ethernet eth0: SMSC911x/921x identified at
> 0xc8920000, IRQ: 41
> [    4.160000] IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
> [    4.210000] Sending DHCP requests ., OK
> [    4.250000] IP-Config: Got DHCP answer from 10.0.1.1, my address is
> 10.0.1.2
> [    4.260000] IP-Config: Complete:
> [    4.260000]      device=eth0, hwaddr=00:0a:a3:02:12:92, ipaddr=10.0.1.2,
> mask=255.255.255.0, gw=10.0.1.1
> [    4.270000]      host=10.0.1.2, domain=dyn.berto.se, nis-domain=(none)
> [    4.280000]      bootserver=10.0.1.1, rootserver=10.0.1.1,
> rootpath=/srv/nfs4/arch,tcp,v3
> [    4.280000]      nameserver0=192.168.20.1
> [    4.290000] ALSA device list:
> [    4.290000]   No soundcards found.
> [    4.320000] VFS: Mounted root (nfs filesystem) on device 0:15.
> [    4.320000] devtmpfs: mounted
> [    4.330000] Freeing unused kernel image (initmem) memory: 1024K
> [    4.390000] Run /sbin/init as init process
> [    4.390000]   with arguments:
> [    4.390000]     /sbin/init
> [    4.400000]   with environment:
> [    4.400000]     HOME=/
> [    4.400000]     TERM=linux
> [    6.040000] systemd[1]: System time before build time, advancing clock.
> [    6.100000] systemd[1]: Failed to find module 'autofs4'
> [    6.220000] systemd[1]: systemd 252.5-1-arch running in system mode (+PAM
> +AUDIT -SELINUX -APPARMOR -IMA +SMACK +SECCOMP +GCRYPT +GNUTLS +OPENSSL +ACL
> +BLKID +CURL +ELFUTILS +FIDO2 +IDN2 -IDN +IPTC +KMOD +LIBCRYPTSETUP
> +LIBFDISK +PCRE2 -PWQUALITY +P11KIT -QRENCODE +TPM2 +BZIP2 +LZ4 +XZ +ZLIB
> +ZSTD +BPF_FRAMEWORK +XKBCOMMON +UTMP -SYSVINIT default-hierarchy=unified)
> [    6.240000] systemd[1]: Detected architecture arm.
> [    6.290000] systemd[1]: Hostname set to <arm>.
> [    6.520000] systemd[1]: bpf-lsm: BPF LSM hook not enabled in the kernel,
> BPF LSM not supported
> [    8.710000] systemd[1]: Queued start job for default target Graphical
> Interface.
> [    8.730000] systemd[1]: Created slice Slice /system/getty.
> [    8.770000] systemd[1]: Created slice Slice /system/modprobe.
> [    8.810000] systemd[1]: Created slice Slice /system/serial-getty.
> [    8.850000] systemd[1]: Created slice User and Session Slice.
> [    8.890000] systemd[1]: Started Dispatch Password Requests to Console
> Directory Watch.
> [    8.930000] systemd[1]: Started Forward Password Requests to Wall
> Directory Watch.
> [    8.970000] systemd[1]: Arbitrary Executable File Formats File System
> Automount Point was skipped because of an unmet condition check
> (ConditionPathExists=/proc/sys/fs/binfmt_misc).
> [    8.980000] systemd[1]: Reached target Local Encrypted Volumes.
> [    9.020000] systemd[1]: Reached target Local Integrity Protected Volumes.
> [    9.060000] systemd[1]: Reached target Network is Online.
> [    9.100000] systemd[1]: Reached target Path Units.
> [    9.130000] systemd[1]: Reached target Slice Units.
> [    9.170000] systemd[1]: Reached target Swaps.
> [    9.200000] systemd[1]: Reached target Local Verity Protected Volumes.
> [    9.240000] systemd[1]: Listening on Device-mapper event daemon FIFOs.
> [    9.300000] systemd[1]: Listening on Process Core Dump Socket.
> [    9.340000] systemd[1]: Journal Audit Socket was skipped because of an
> unmet condition check (ConditionSecurity=audit).
> [    9.350000] systemd[1]: Listening on Journal Socket (/dev/log).
> [    9.390000] systemd[1]: Listening on Journal Socket.
> [    9.430000] systemd[1]: Listening on udev Control Socket.
> [    9.470000] systemd[1]: Listening on udev Kernel Socket.
> [    9.510000] systemd[1]: Huge Pages File System was skipped because of an
> unmet condition check (ConditionPathExists=/sys/kernel/mm/hugepages).
> [    9.520000] systemd[1]: POSIX Message Queue File System was skipped
> because of an unmet condition check
> (ConditionPathExists=/proc/sys/fs/mqueue).
> [    9.590000] systemd[1]: Mounting /root/shared...
> [    9.620000] systemd[1]: Mounting Kernel Debug File System...
> [    9.680000] systemd[1]: Mounting Kernel Trace File System...
> [    9.780000] systemd[1]: Mounting Temporary Directory /tmp...
> [    9.820000] systemd[1]: Create List of Static Device Nodes was skipped
> because of an unmet condition check
> (ConditionFileNotEmpty=/lib/modules/6.1.0/modules.devname).
> [    9.850000] systemd[1]: Starting Load Kernel Module configfs...
> [    9.960000] systemd[1]: Starting Load Kernel Module drm...
> [   10.010000] systemd[1]: Starting Load Kernel Module fuse...
> [   10.070000] systemd[1]: Load Kernel Modules was skipped because no
> trigger condition checks were met.
> [   10.120000] systemd[1]: Starting Remount Root and Kernel File Systems...
> [   10.190000] systemd[1]: Repartition Root Disk was skipped because no
> trigger condition checks were met.
> [   10.250000] systemd[1]: Starting Apply Kernel Variables...
> [   10.310000] systemd[1]: Starting Coldplug All udev Devices...
> [   10.390000] systemd[1]: Mounted Kernel Debug File System.
> [   10.410000] systemd[1]: Mounted Kernel Trace File System.
> [   10.450000] systemd[1]: Mounted Temporary Directory /tmp.
> [   10.490000] systemd[1]: modprobe@configfs.service: Deactivated
> successfully.
> [   10.520000] systemd[1]: Finished Load Kernel Module configfs.
> [   10.550000] systemd[1]: modprobe@drm.service: Deactivated successfully.
> [   10.550000] systemd[1]: Finished Load Kernel Module drm.
> [   10.600000] systemd[1]: modprobe@fuse.service: Deactivated successfully.
> [   10.610000] systemd[1]: Finished Load Kernel Module fuse.
> [   10.650000] systemd[1]: Finished Remount Root and Kernel File Systems.
> [   10.670000] systemd[1]: Finished Apply Kernel Variables.
> [   10.890000] systemd[1]: Reached target Host and Network Name Lookups.
> [   10.940000] systemd[1]: Listening on RPCbind Server Activation Socket.
> [   10.990000] systemd[1]: Reached target RPC Port Mapper.
> [   11.030000] systemd[1]: FUSE Control File System was skipped because of
> an unmet condition check (ConditionPathExists=/sys/fs/fuse/connections).
> [   11.090000] systemd[1]: Mounting Kernel Configuration File System...
> [   11.130000] systemd[1]: Starting NFS status monitor for NFSv2/3
> locking....
> [   11.180000] systemd[1]: First Boot Wizard was skipped because of an unmet
> condition check (ConditionFirstBoot=yes).
> [   11.210000] systemd[1]: Rebuild Hardware Database was skipped because of
> an unmet condition check (ConditionNeedsUpdate=/etc).
> [   11.290000] systemd[1]: Starting Load/Save Random Seed...
> [   11.330000] systemd[1]: Create System Users was skipped because no
> trigger condition checks were met.
> [   11.380000] systemd[1]: Starting Create Static Device Nodes in /dev...
> [   11.500000] systemd[1]: Finished Coldplug All udev Devices.
> [   11.540000] systemd[1]: Mounted Kernel Configuration File System.
> [   11.620000] systemd[1]: Starting RPC Bind...
> [   12.160000] systemd[1]: Finished Create Static Device Nodes in /dev.
> [   12.200000] systemd[1]: Started RPC Bind.
> [   12.240000] systemd[1]: Reached target Preparation for Local File
> Systems.
> [   12.290000] systemd[1]: Virtual Machine and Container Storage
> (Compatibility) was skipped because of an unmet condition check
> (ConditionPathExists=/var/lib/machines.raw).
> [   12.310000] systemd[1]: Reached target Local File Systems.
> [   12.350000] systemd[1]: Entropy Daemon based on the HAVEGE algorithm was
> skipped because of an unmet condition check (ConditionKernelVersion=<5.6).
> [   12.360000] systemd[1]: Rebuild Dynamic Linker Cache was skipped because
> no trigger condition checks were met.
> [   12.420000] systemd[1]: Starting Notify NFS peers of a restart...
> [   12.460000] systemd[1]: Set Up Additional Binary Formats was skipped
> because no trigger condition checks were met.
> [   12.480000] systemd[1]: systemd-journald.service: unit configures an IP
> firewall, but the local system does not support BPF/cgroup firewalling.
> [   12.490000] systemd[1]: (This warning is only shown for the first unit
> using IP firewalling.)
> [   12.570000] systemd[1]: Starting Journal Service...
> [   12.620000] systemd[1]: Starting Rule-based Manager for Device Events and
> Files...
> [   12.700000] systemd[1]: Started NFS status monitor for NFSv2/3 locking..
> [   12.740000] systemd[1]: Started Notify NFS peers of a restart.
> [   12.990000] systemd[1]: Started Journal Service.
> [   16.860000] systemd-journald[87]: Received client request to flush
> runtime journal.
> [   21.360000] random: dbus-daemon: uninitialized urandom read (12 bytes
> read)
> [   22.190000] random: dbus-daemon: uninitialized urandom read (12 bytes
> read)
> [   39.150000] random: crng init done
> 
> --
> Kind Regards,
> Niklas Söderlund

^ permalink raw reply

* Re: [PATCH v3 3/3] serial: 8250_em: Add serial_out() to struct serial8250_em_hw_info
From: Niklas Söderlund @ 2023-02-13  9:57 UTC (permalink / raw)
  To: Biju Das
  Cc: Jiri Slaby, Ilpo Järvinen, Geert Uytterhoeven, Magnus Damm,
	Greg Kroah-Hartman, linux-serial, Fabrizio Castro,
	linux-renesas-soc@vger.kernel.org
In-Reply-To: <OS0PR01MB592210E15CD943F1987316F086DD9@OS0PR01MB5922.jpnprd01.prod.outlook.com>

Hi Biju,

On 2023-02-13 09:31:27 +0000, Biju Das wrote:
> Adding Magnus and Niklas to test on EMMA mobile platform to check the 
> port type detected
> On that platform?

I don't know what you want me to check, I don't know much about serial. I 
wired up the platform during the weekend, here is a boot log running on 
v6.1. If you want to to check / test something I'm happy to, but will need 
instructions.

[    0.000000] Booting Linux on physical CPU 0x0
[    0.000000] Linux version 6.1.0 (neg@sleipner) (arm-linux-gnueabihf-gcc (GCC) 10.2.0, GNU ld (GNU Binutils) 2.35.1) #1 SMP Sun Feb 12 18:44:55 CET 2023
[    0.000000] CPU: ARMv7 Processor [411fc092] revision 2 (ARMv7), cr=10c5387d
[    0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
[    0.000000] OF: fdt: Machine model: EMEV2 KZM9D Board
[    0.000000] printk: debug: ignoring loglevel setting.
[    0.000000] Memory policy: Data cache writealloc
[    0.000000] cma: Failed to reserve 128 MiB
[    0.000000] Zone ranges:
[    0.000000]   Normal   [mem 0x0000000040000000-0x0000000047ffffff]
[    0.000000]   HighMem  empty
[    0.000000] Movable zone start for each node
[    0.000000] Early memory node ranges
[    0.000000]   node   0: [mem 0x0000000040000000-0x0000000047ffffff]
[    0.000000] Initmem setup node 0 [mem 0x0000000040000000-0x0000000047ffffff]
[    0.000000] percpu: Embedded 13 pages/cpu s32468 r0 d20780 u53248
[    0.000000] pcpu-alloc: s32468 r0 d20780 u53248 alloc=13*4096
[    0.000000] pcpu-alloc: [0] 0 [0] 1 
[    0.000000] Built 1 zonelists, mobility grouping on.  Total pages: 32512
[    0.000000] Kernel command line: ignore_loglevel rw root=/dev/nfs ip=on
[    0.000000] Dentry cache hash table entries: 16384 (order: 4, 65536 bytes, linear)
[    0.000000] Inode-cache hash table entries: 8192 (order: 3, 32768 bytes, linear)
[    0.000000] mem auto-init: stack:off, heap alloc:off, heap free:off
[    0.000000] Memory: 116072K/131072K available (8192K kernel code, 1152K rwdata, 2436K rodata, 1024K init, 259K bss, 15000K reserved, 0K cma-reserved, 0K highmem)
[    0.000000] trace event string verifier disabled
[    0.000000] rcu: Hierarchical RCU implementation.
[    0.000000] rcu: 	RCU event tracing is enabled.
[    0.000000] rcu: 	RCU restricting CPUs from NR_CPUS=8 to nr_cpu_ids=2.
[    0.000000] rcu: RCU calculated value of scheduler-enlistment delay is 10 jiffies.
[    0.000000] rcu: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=2
[    0.000000] NR_IRQS: 16, nr_irqs: 16, preallocated irqs: 16
[    0.000000] GIC: enabling workaround for broken byte access
[    0.000000] rcu: srcu_init: Setting srcu_struct sizes based on contention.
[    0.000000] timer_probe: no matching timers found
[    0.000000] Console: colour dummy device 80x30
[    0.000000] printk: console [tty0] enabled
[    0.000000] sched_clock: 32 bits at 100 Hz, resolution 10000000ns, wraps every 21474836475000000ns
[    0.000000] Calibrating delay loop (skipped) preset value.. 1066.00 BogoMIPS (lpj=5330000)
[    0.000000] pid_max: default: 32768 minimum: 301
[    0.000000] Mount-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)
[    0.000000] Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)
[    0.000000] CPU: Testing write buffer coherency: ok
[    0.000000] CPU0: Spectre v2: using BPIALL workaround
[    0.000000] CPU0: thread -1, cpu 0, socket 0, mpidr 80000000
[    0.000000] Setting up static identity map for 0x40100000 - 0x40100060
[    0.000000] rcu: Hierarchical SRCU implementation.
[    0.000000] rcu: 	Max phase no-delay instances is 1000.
[    0.000000] smp: Bringing up secondary CPUs ...
[    0.000000] CPU1: thread -1, cpu 1, socket 0, mpidr 80000001
[    0.000000] CPU1: Spectre v2: using BPIALL workaround
[    0.000000] smp: Brought up 1 node, 2 CPUs
[    0.000000] SMP: Total of 2 processors activated (2132.00 BogoMIPS).
[    0.000000] CPU: All CPU(s) started in SVC mode.
[    0.000000] devtmpfs: initialized
[    0.000000] VFP support v0.3: implementor 41 architecture 3 part 30 variant 9 rev 1
[    0.000000] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
[    0.000000] futex hash table entries: 512 (order: 3, 32768 bytes, linear)
[    0.000000] pinctrl core: initialized pinctrl subsystem
[    0.000000] NET: Registered PF_NETLINK/PF_ROUTE protocol family
[    0.000000] DMA: preallocated 256 KiB pool for atomic coherent allocations
[    0.000000] thermal_sys: Registered thermal governor 'step_wise'
[    0.000000] No ATAGs?
[    0.000000] hw-breakpoint: found 5 (+1 reserved) breakpoint and 1 watchpoint registers.
[    0.000000] hw-breakpoint: maximum watchpoint size is 4 bytes.
[    0.000000] sh-pfc e0140200.pinctrl: emev2_pfc support registered
[    0.000000] SCSI subsystem initialized
[    0.000000] libata version 3.00 loaded.
[    0.000000] usbcore: registered new interface driver usbfs
[    0.000000] usbcore: registered new interface driver hub
[    0.000000] usbcore: registered new device driver usb
[    0.000000] mc: Linux media interface: v0.10
[    0.000000] videodev: Linux video capture interface: v2.00
[    0.000000] pps_core: LinuxPPS API ver. 1 registered
[    0.000000] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti <giometti@linux.it>
[    0.000000] PTP clock support registered
[    0.000000] em_sti e0180000.timer: used for clock events
[    0.000000] em_sti e0180000.timer: used for oneshot clock events
[    0.000000] em_sti e0180000.timer: used as clock source
[    0.000000] clocksource: e0180000.timer: mask: 0xffffffffffff max_cycles: 0x1ef4687b1, max_idle_ns: 112843571739654 ns
[    0.000000] Advanced Linux Sound Architecture Driver Initialized.
[    0.000000] vgaarb: loaded
[    0.940000] clocksource: Switched to clocksource e0180000.timer
[    0.950000] Clockevents: could not switch to one-shot mode:
[    0.950000] Clockevents: could not switch to one-shot mode: dummy_timer is not functional.
[    0.950000]  dummy_timer is not functional.
[    0.960000] NET: Registered PF_INET protocol family
[    0.960000] IP idents hash table entries: 2048 (order: 2, 16384 bytes, linear)
[    0.960000] tcp_listen_portaddr_hash hash table entries: 512 (order: 0, 4096 bytes, linear)
[    0.960000] Table-perturb hash table entries: 65536 (order: 6, 262144 bytes, linear)
[    0.960000] TCP established hash table entries: 1024 (order: 0, 4096 bytes, linear)
[    0.960000] TCP bind hash table entries: 1024 (order: 2, 16384 bytes, linear)
[    0.960000] TCP: Hash tables configured (established 1024 bind 1024)
[    0.960000] UDP hash table entries: 256 (order: 1, 8192 bytes, linear)
[    0.960000] UDP-Lite hash table entries: 256 (order: 1, 8192 bytes, linear)
[    0.960000] NET: Registered PF_UNIX/PF_LOCAL protocol family
[    0.960000] RPC: Registered named UNIX socket transport module.
[    0.960000] RPC: Registered udp transport module.
[    0.960000] RPC: Registered tcp transport module.
[    0.960000] RPC: Registered tcp NFSv4.1 backchannel transport module.
[    0.960000] PCI: CLS 0 bytes, default 64
[    1.000000] hw perfevents: enabled with armv7_cortex_a9 PMU driver, 7 counters available
[    1.000000] workingset: timestamp_bits=30 max_order=15 bucket_order=0
[    1.000000] NFS: Registering the id_resolver key type
[    1.000000] Key type id_resolver registered
[    1.000000] Key type id_legacy registered
[    1.000000] nfs4filelayout_init: NFSv4 File Layout Driver Registering...
[    1.000000] nfs4flexfilelayout_init: NFSv4 Flexfile Layout Driver Registering...
[    1.000000] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 246)
[    1.000000] io scheduler mq-deadline registered
[    1.000000] io scheduler kyber registered
[    1.010000] Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
[    1.020000] e1020000.serial: ttyS0 at MMIO 0xe1020000 (irq = 37, base_baud = 796444) is a 16550A
[    1.020000] e1030000.serial: ttyS1 at MMIO 0xe1030000 (irq = 38, base_baud = 7168000) is a 16550A
[    1.690000] printk: console [ttyS1] enabled
[    1.700000] e1040000.serial: ttyS2 at MMIO 0xe1040000 (irq = 39, base_baud = 14336000) is a 16550A
[    1.710000] e1050000.serial: ttyS3 at MMIO 0xe1050000 (irq = 40, base_baud = 2389333) is a 16550A
[    1.720000] SuperH (H)SCI(F) driver initialized
[    1.730000] CAN device driver interface
[    1.800000] smsc911x 20000000.ethernet eth0: MAC Address: 00:0a:a3:02:12:92
[    1.810000] UDC core: g_ether: couldn't find an available UDC
[    1.810000] i2c_dev: i2c /dev entries driver
[    1.820000] em-i2c e0070000.i2c: Added i2c controller 0, irq 42
[    1.830000] em-i2c e10a0000.i2c: Added i2c controller 1, irq 43
[    1.830000] cpu cpu0: OPP table can't be empty
[    1.840000] usbcore: registered new interface driver usbhid
[    1.850000] usbhid: USB HID core driver
[    1.850000] NET: Registered PF_INET6 protocol family
[    1.860000] Segment Routing with IPv6
[    1.870000] In-situ OAM (IOAM) with IPv6
[    1.870000] sit: IPv6, IPv4 and MPLS over IPv4 tunneling driver
[    1.880000] NET: Registered PF_PACKET protocol family
[    1.880000] can: controller area network core
[    1.890000] NET: Registered PF_CAN protocol family
[    1.890000] can: raw protocol
[    1.900000] can: broadcast manager protocol
[    1.900000] can: netlink gateway - max_hops=1
[    1.900000] Key type dns_resolver registered
[    1.910000] Registering SWP/SWPB emulation handler
[    1.920000] input: gpio_keys as /devices/platform/gpio_keys/input/input0
[    1.980000] SMSC LAN8700 20000000.ethernet-ffffffff:01: attached PHY driver (mii_bus:phy_addr=20000000.ethernet-ffffffff:01, irq=POLL)
[    2.020000] smsc911x 20000000.ethernet eth0: SMSC911x/921x identified at 0xc8920000, IRQ: 41
[    4.160000] IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
[    4.210000] Sending DHCP requests ., OK
[    4.250000] IP-Config: Got DHCP answer from 10.0.1.1, my address is 10.0.1.2
[    4.260000] IP-Config: Complete:
[    4.260000]      device=eth0, hwaddr=00:0a:a3:02:12:92, ipaddr=10.0.1.2, mask=255.255.255.0, gw=10.0.1.1
[    4.270000]      host=10.0.1.2, domain=dyn.berto.se, nis-domain=(none)
[    4.280000]      bootserver=10.0.1.1, rootserver=10.0.1.1, rootpath=/srv/nfs4/arch,tcp,v3
[    4.280000]      nameserver0=192.168.20.1
[    4.290000] ALSA device list:
[    4.290000]   No soundcards found.
[    4.320000] VFS: Mounted root (nfs filesystem) on device 0:15.
[    4.320000] devtmpfs: mounted
[    4.330000] Freeing unused kernel image (initmem) memory: 1024K
[    4.390000] Run /sbin/init as init process
[    4.390000]   with arguments:
[    4.390000]     /sbin/init
[    4.400000]   with environment:
[    4.400000]     HOME=/
[    4.400000]     TERM=linux
[    6.040000] systemd[1]: System time before build time, advancing clock.
[    6.100000] systemd[1]: Failed to find module 'autofs4'
[    6.220000] systemd[1]: systemd 252.5-1-arch running in system mode (+PAM +AUDIT -SELINUX -APPARMOR -IMA +SMACK +SECCOMP +GCRYPT +GNUTLS +OPENSSL +ACL +BLKID +CURL +ELFUTILS +FIDO2 +IDN2 -IDN +IPTC +KMOD +LIBCRYPTSETUP +LIBFDISK +PCRE2 -PWQUALITY +P11KIT -QRENCODE +TPM2 +BZIP2 +LZ4 +XZ +ZLIB +ZSTD +BPF_FRAMEWORK +XKBCOMMON +UTMP -SYSVINIT default-hierarchy=unified)
[    6.240000] systemd[1]: Detected architecture arm.
[    6.290000] systemd[1]: Hostname set to <arm>.
[    6.520000] systemd[1]: bpf-lsm: BPF LSM hook not enabled in the kernel, BPF LSM not supported
[    8.710000] systemd[1]: Queued start job for default target Graphical Interface.
[    8.730000] systemd[1]: Created slice Slice /system/getty.
[    8.770000] systemd[1]: Created slice Slice /system/modprobe.
[    8.810000] systemd[1]: Created slice Slice /system/serial-getty.
[    8.850000] systemd[1]: Created slice User and Session Slice.
[    8.890000] systemd[1]: Started Dispatch Password Requests to Console Directory Watch.
[    8.930000] systemd[1]: Started Forward Password Requests to Wall Directory Watch.
[    8.970000] systemd[1]: Arbitrary Executable File Formats File System Automount Point was skipped because of an unmet condition check (ConditionPathExists=/proc/sys/fs/binfmt_misc).
[    8.980000] systemd[1]: Reached target Local Encrypted Volumes.
[    9.020000] systemd[1]: Reached target Local Integrity Protected Volumes.
[    9.060000] systemd[1]: Reached target Network is Online.
[    9.100000] systemd[1]: Reached target Path Units.
[    9.130000] systemd[1]: Reached target Slice Units.
[    9.170000] systemd[1]: Reached target Swaps.
[    9.200000] systemd[1]: Reached target Local Verity Protected Volumes.
[    9.240000] systemd[1]: Listening on Device-mapper event daemon FIFOs.
[    9.300000] systemd[1]: Listening on Process Core Dump Socket.
[    9.340000] systemd[1]: Journal Audit Socket was skipped because of an unmet condition check (ConditionSecurity=audit).
[    9.350000] systemd[1]: Listening on Journal Socket (/dev/log).
[    9.390000] systemd[1]: Listening on Journal Socket.
[    9.430000] systemd[1]: Listening on udev Control Socket.
[    9.470000] systemd[1]: Listening on udev Kernel Socket.
[    9.510000] systemd[1]: Huge Pages File System was skipped because of an unmet condition check (ConditionPathExists=/sys/kernel/mm/hugepages).
[    9.520000] systemd[1]: POSIX Message Queue File System was skipped because of an unmet condition check (ConditionPathExists=/proc/sys/fs/mqueue).
[    9.590000] systemd[1]: Mounting /root/shared...
[    9.620000] systemd[1]: Mounting Kernel Debug File System...
[    9.680000] systemd[1]: Mounting Kernel Trace File System...
[    9.780000] systemd[1]: Mounting Temporary Directory /tmp...
[    9.820000] systemd[1]: Create List of Static Device Nodes was skipped because of an unmet condition check (ConditionFileNotEmpty=/lib/modules/6.1.0/modules.devname).
[    9.850000] systemd[1]: Starting Load Kernel Module configfs...
[    9.960000] systemd[1]: Starting Load Kernel Module drm...
[   10.010000] systemd[1]: Starting Load Kernel Module fuse...
[   10.070000] systemd[1]: Load Kernel Modules was skipped because no trigger condition checks were met.
[   10.120000] systemd[1]: Starting Remount Root and Kernel File Systems...
[   10.190000] systemd[1]: Repartition Root Disk was skipped because no trigger condition checks were met.
[   10.250000] systemd[1]: Starting Apply Kernel Variables...
[   10.310000] systemd[1]: Starting Coldplug All udev Devices...
[   10.390000] systemd[1]: Mounted Kernel Debug File System.
[   10.410000] systemd[1]: Mounted Kernel Trace File System.
[   10.450000] systemd[1]: Mounted Temporary Directory /tmp.
[   10.490000] systemd[1]: modprobe@configfs.service: Deactivated successfully.
[   10.520000] systemd[1]: Finished Load Kernel Module configfs.
[   10.550000] systemd[1]: modprobe@drm.service: Deactivated successfully.
[   10.550000] systemd[1]: Finished Load Kernel Module drm.
[   10.600000] systemd[1]: modprobe@fuse.service: Deactivated successfully.
[   10.610000] systemd[1]: Finished Load Kernel Module fuse.
[   10.650000] systemd[1]: Finished Remount Root and Kernel File Systems.
[   10.670000] systemd[1]: Finished Apply Kernel Variables.
[   10.890000] systemd[1]: Reached target Host and Network Name Lookups.
[   10.940000] systemd[1]: Listening on RPCbind Server Activation Socket.
[   10.990000] systemd[1]: Reached target RPC Port Mapper.
[   11.030000] systemd[1]: FUSE Control File System was skipped because of an unmet condition check (ConditionPathExists=/sys/fs/fuse/connections).
[   11.090000] systemd[1]: Mounting Kernel Configuration File System...
[   11.130000] systemd[1]: Starting NFS status monitor for NFSv2/3 locking....
[   11.180000] systemd[1]: First Boot Wizard was skipped because of an unmet condition check (ConditionFirstBoot=yes).
[   11.210000] systemd[1]: Rebuild Hardware Database was skipped because of an unmet condition check (ConditionNeedsUpdate=/etc).
[   11.290000] systemd[1]: Starting Load/Save Random Seed...
[   11.330000] systemd[1]: Create System Users was skipped because no trigger condition checks were met.
[   11.380000] systemd[1]: Starting Create Static Device Nodes in /dev...
[   11.500000] systemd[1]: Finished Coldplug All udev Devices.
[   11.540000] systemd[1]: Mounted Kernel Configuration File System.
[   11.620000] systemd[1]: Starting RPC Bind...
[   12.160000] systemd[1]: Finished Create Static Device Nodes in /dev.
[   12.200000] systemd[1]: Started RPC Bind.
[   12.240000] systemd[1]: Reached target Preparation for Local File Systems.
[   12.290000] systemd[1]: Virtual Machine and Container Storage (Compatibility) was skipped because of an unmet condition check (ConditionPathExists=/var/lib/machines.raw).
[   12.310000] systemd[1]: Reached target Local File Systems.
[   12.350000] systemd[1]: Entropy Daemon based on the HAVEGE algorithm was skipped because of an unmet condition check (ConditionKernelVersion=<5.6).
[   12.360000] systemd[1]: Rebuild Dynamic Linker Cache was skipped because no trigger condition checks were met.
[   12.420000] systemd[1]: Starting Notify NFS peers of a restart...
[   12.460000] systemd[1]: Set Up Additional Binary Formats was skipped because no trigger condition checks were met.
[   12.480000] systemd[1]: systemd-journald.service: unit configures an IP firewall, but the local system does not support BPF/cgroup firewalling.
[   12.490000] systemd[1]: (This warning is only shown for the first unit using IP firewalling.)
[   12.570000] systemd[1]: Starting Journal Service...
[   12.620000] systemd[1]: Starting Rule-based Manager for Device Events and Files...
[   12.700000] systemd[1]: Started NFS status monitor for NFSv2/3 locking..
[   12.740000] systemd[1]: Started Notify NFS peers of a restart.
[   12.990000] systemd[1]: Started Journal Service.
[   16.860000] systemd-journald[87]: Received client request to flush runtime journal.
[   21.360000] random: dbus-daemon: uninitialized urandom read (12 bytes read)
[   22.190000] random: dbus-daemon: uninitialized urandom read (12 bytes read)
[   39.150000] random: crng init done

-- 
Kind Regards,
Niklas Söderlund

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox