^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * EHCI HCD (Host Controller Driver) for USB.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Bus Glue for Xilinx EHCI core on the of_platform bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (c) 2009 Xilinx, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Based on "ehci-ppc-of.c" by Valentine Barshak <vbarshak@ru.mvista.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * and "ehci-ppc-soc.c" by Stefan Roese <sr@denx.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * and "ohci-ppc-of.c" by Sylvain Munaut <tnt@246tNt.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/of_platform.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/of_address.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/of_irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * ehci_xilinx_port_handed_over - hand the port out if failed to enable it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * @hcd: Pointer to the usb_hcd device to which the host controller bound
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * @portnum:Port number to which the device is attached.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * This function is used as a place to tell the user that the Xilinx USB host
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * controller does support LS devices. And in an HS only configuration, it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * does not support FS devices either. It is hoped that this can help a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * confused user.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * There are cases when the host controller fails to enable the port due to,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * for example, insufficient power that can be supplied to the device from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * the USB bus. In those cases, the messages printed here are not helpful.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) static int ehci_xilinx_port_handed_over(struct usb_hcd *hcd, int portnum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) dev_warn(hcd->self.controller, "port %d cannot be enabled\n", portnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) if (hcd->has_tt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) dev_warn(hcd->self.controller,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) "Maybe you have connected a low speed device?\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) dev_warn(hcd->self.controller,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) "We do not support low speed devices\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) dev_warn(hcd->self.controller,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) "Maybe your device is not a high speed device?\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) dev_warn(hcd->self.controller,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) "The USB host controller does not support full speed "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) "nor low speed devices\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) dev_warn(hcd->self.controller,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) "You can reconfigure the host controller to have "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) "full speed support\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) static const struct hc_driver ehci_xilinx_of_hc_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) .description = hcd_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) .product_desc = "OF EHCI",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) .hcd_priv_size = sizeof(struct ehci_hcd),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * generic hardware linkage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) .irq = ehci_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) .flags = HCD_MEMORY | HCD_DMA | HCD_USB2 | HCD_BH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * basic lifecycle operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) .reset = ehci_setup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) .start = ehci_run,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) .stop = ehci_stop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) .shutdown = ehci_shutdown,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * managing i/o requests and associated device resources
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) .urb_enqueue = ehci_urb_enqueue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) .urb_dequeue = ehci_urb_dequeue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) .endpoint_disable = ehci_endpoint_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) .endpoint_reset = ehci_endpoint_reset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) * scheduling support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) .get_frame_number = ehci_get_frame,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) * root hub support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) .hub_status_data = ehci_hub_status_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) .hub_control = ehci_hub_control,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) .bus_suspend = ehci_bus_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) .bus_resume = ehci_bus_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) .relinquish_port = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) .port_handed_over = ehci_xilinx_port_handed_over,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) * ehci_hcd_xilinx_of_probe - Probe method for the USB host controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) * @op: pointer to the platform_device bound to the host controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) * This function requests resources and sets up appropriate properties for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * host controller. Because the Xilinx USB host controller can be configured
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) * as HS only or HS/FS only, it checks the configuration in the device tree
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) * entry, and sets an appropriate value for hcd->has_tt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) static int ehci_hcd_xilinx_of_probe(struct platform_device *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) struct device_node *dn = op->dev.of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) struct usb_hcd *hcd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) struct ehci_hcd *ehci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) struct resource res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) int rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) int *value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) if (usb_disabled())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) dev_dbg(&op->dev, "initializing XILINX-OF USB Controller\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) rv = of_address_to_resource(dn, 0, &res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) if (rv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) hcd = usb_create_hcd(&ehci_xilinx_of_hc_driver, &op->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) "XILINX-OF USB");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) if (!hcd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) hcd->rsrc_start = res.start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) hcd->rsrc_len = resource_size(&res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) irq = irq_of_parse_and_map(dn, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) if (!irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) dev_err(&op->dev, "%s: irq_of_parse_and_map failed\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) __FILE__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) rv = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) goto err_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) hcd->regs = devm_ioremap_resource(&op->dev, &res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) if (IS_ERR(hcd->regs)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) rv = PTR_ERR(hcd->regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) goto err_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) ehci = hcd_to_ehci(hcd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) /* This core always has big-endian register interface and uses
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) * big-endian memory descriptors.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) ehci->big_endian_mmio = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) ehci->big_endian_desc = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) /* Check whether the FS support option is selected in the hardware.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) value = (int *)of_get_property(dn, "xlnx,support-usb-fs", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) if (value && (*value == 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) ehci_dbg(ehci, "USB host controller supports FS devices\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) hcd->has_tt = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) ehci_dbg(ehci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) "USB host controller is HS only\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) hcd->has_tt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) /* Debug registers are at the first 0x100 region
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) ehci->caps = hcd->regs + 0x100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) rv = usb_add_hcd(hcd, irq, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) if (rv == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) device_wakeup_enable(hcd->self.controller);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) err_irq:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) usb_put_hcd(hcd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) * ehci_hcd_xilinx_of_remove - shutdown hcd and release resources
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) * @op: pointer to platform_device structure that is to be removed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) * Remove the hcd structure, and release resources that has been requested
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) * during probe.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) static int ehci_hcd_xilinx_of_remove(struct platform_device *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) struct usb_hcd *hcd = platform_get_drvdata(op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) dev_dbg(&op->dev, "stopping XILINX-OF USB Controller\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) usb_remove_hcd(hcd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) usb_put_hcd(hcd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) static const struct of_device_id ehci_hcd_xilinx_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) {.compatible = "xlnx,xps-usb-host-1.00.a",},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) {},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) MODULE_DEVICE_TABLE(of, ehci_hcd_xilinx_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) static struct platform_driver ehci_hcd_xilinx_of_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) .probe = ehci_hcd_xilinx_of_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) .remove = ehci_hcd_xilinx_of_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) .shutdown = usb_hcd_platform_shutdown,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) .name = "xilinx-of-ehci",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) .of_match_table = ehci_hcd_xilinx_of_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) };