/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #define XR_USB_SERIAL_IOC_MAGIC 'v' #define XR_USB_SERIAL_GET_REG _IOWR(XR_USB_SERIAL_IOC_MAGIC, 1, int) #define XR_USB_SERIAL_SET_REG _IOWR(XR_USB_SERIAL_IOC_MAGIC, 2, int) #define XR_USB_SERIAL_SET_ADDRESS_MATCH _IO(XR_USB_SERIAL_IOC_MAGIC, 3) #define XR_USB_SERIAL_SET_PRECISE_FLAGS _IO(XR_USB_SERIAL_IOC_MAGIC, 4) #define XR_USB_SERIAL_TEST_MODE _IO(XR_USB_SERIAL_IOC_MAGIC, 5) #define XR_USB_SERIAL_LOOPBACK _IO(XR_USB_SERIAL_IOC_MAGIC, 6) #define XR_USB_SERIAL_SET_GPIO_MODE_REG _IO(XR_USB_SERIAL_IOC_MAGIC, 9) #define XR_USB_SERIAL_GET_GPIO_MODE_REG _IO(XR_USB_SERIAL_IOC_MAGIC, 10) #define XRIOC_SET_ANY_BAUD_RATE _IO(XR_USB_SERIAL_IOC_MAGIC, 11) #define XRIOC_SET_PRECISE_FLAGS _IO(XR_USB_SERIAL_IOC_MAGIC, 12) #define VZ_ADDRESS_UNICAST_S 0 #define VZ_ADDRESS_BROADCAST_S 8 #define VZ_ADDRESS_MATCH(U, B) (0x8000000 | ((B) << VZ_ADDRESS_BROADCAST_S) | ((U) << VZ_ADDRESS_UNICAST_S)) #define VZ_ADDRESS_MATCH_DISABLE 0 #define XR_USB_SERIAL_SET_GPIO7 _IOW(XR_USB_SERIAL_IOC_MAGIC, 13, int) /* POG422 fork 1D: blocking wait for SLV-IN (GPIO1/CD) edge via USB interrupt */ #define POG422_GPIO1_STATUS_BIT 0x0002 struct xr_pog422_gpio1_event { __u64 timestamp_ns; __u16 gpio_state; __u16 gpio_int; __u8 slv_in_active; __u8 _pad[3]; }; #define XR_USB_SERIAL_WAIT_GPIO1 _IOR(XR_USB_SERIAL_IOC_MAGIC, 14, struct xr_pog422_gpio1_event) #define XR_USB_SERIAL_GET_GPIO1_EVENT _IOR(XR_USB_SERIAL_IOC_MAGIC, 15, struct xr_pog422_gpio1_event) /* POG422 fork 1H: RX path diagnostics (driver flip-buffer insert count) */ struct xr_pog422_rx_stats { __u64 chars_inserted; __u64 urbs_completed; __u32 have_extra_byte; __u32 preciseflags; }; #define XR_USB_SERIAL_GET_RX_STATS _IOR(XR_USB_SERIAL_IOC_MAGIC, 16, struct xr_pog422_rx_stats) #define XR_USB_SERIAL_RESET_RX_STATS _IO(XR_USB_SERIAL_IOC_MAGIC, 17) /* POG422 fork 1I: DTtty — driver-side RX ring (bypass kernel tty flip for capture) */ #ifndef POG422_DTTTY_RX_SIZE #define POG422_DTTTY_RX_SIZE 8192u #endif struct xr_pog422_dttty_avail { __u32 avail; __u64 total_written; __u32 overruns; __u8 dttty_rx; __u8 _pad[3]; }; struct xr_pog422_dttty_read { __u64 user_buf; __u32 max_len; __u32 out_len; __u32 avail; __u64 total_written; __u32 overruns; }; #define XR_USB_SERIAL_SET_DTTTY_RX _IOW(XR_USB_SERIAL_IOC_MAGIC, 21, int) #define XR_USB_SERIAL_GET_DTTTY_RX_AVAIL _IOR(XR_USB_SERIAL_IOC_MAGIC, 22, struct xr_pog422_dttty_avail) #define XR_USB_SERIAL_READ_DTTTY_RX _IOWR(XR_USB_SERIAL_IOC_MAGIC, 23, struct xr_pog422_dttty_read) #define XR_USB_SERIAL_FLUSH_DTTTY_RX _IO(XR_USB_SERIAL_IOC_MAGIC, 24) /* POG422 fork 1J: kernel-side wide-mode TX burst (data+RAMCTL interleave on USB URB) */ #ifndef POG422_INJECT_FRAME_MAX /* Must cover Transfer Master Config 0x09 (~1170 B). Was 256 — rejected MTC with EINVAL. */ #define POG422_INJECT_FRAME_MAX 2048u #endif struct xr_pog422_inject_tx { __u64 user_frame; __u32 frame_len; __u32 timeout_ms; __u32 tx_ns; __u32 drain_wait_ns; /* out: wire-time usleep before wide off (does not extend DE) */ __u32 post_margin_us; /* in: 0=default 400us; 0xFFFFFFFE=manual DE (C owns GPIO7) */ /* 1S+ TX path diagnostics (out) — sample around USB bulk; not used for DE hold */ __u32 tx_fifo_before; /* TX_FIFO_COUNT @ 0x041 before bulk */ __u32 tx_fifo_after_bulk; /* immediately after usb_*_msg, before wire wait */ __u32 tx_fifo_after_drain; /* after wire wait */ __u32 usb_actual; /* bytes accepted by usb_*_msg (expect frame_len*2) */ }; #ifndef POG422_INJECT_POST_MANUAL_DE #define POG422_INJECT_POST_MANUAL_DE 0xFFFFFFFEu #endif #define XR_USB_SERIAL_INJECT_TX _IOWR(XR_USB_SERIAL_IOC_MAGIC, 25, struct xr_pog422_inject_tx) /* * EG 2.2.1.7: wait for USB interrupt IN (Table-8) when GPIO5 RS485_EN_ACT sense * falls (shifter idle), then confirm TX_FIFO empty. Manual GPIO7 DE is separate. * XR21B1422 has no Tx-empty USB IRQ and no LSR — reason codes describe EN_ACT+FIFO. */ #define POG422_TX_EMPTY_REASON_NONE 0u #define POG422_TX_EMPTY_REASON_ALREADY_IDLE 1u #define POG422_TX_EMPTY_REASON_EN_ACT_FALL 2u #define POG422_TX_EMPTY_REASON_TIMEOUT_OK 3u /* FIFO+EN_ACT idle after timeout poll */ #define POG422_TX_EMPTY_REASON_SPURIOUS 4u /* INT without FIFO empty */ struct xr_pog422_tx_empty { __u32 timeout_ms; /* in: max wait (0 = default 500) */ __u32 tx_fifo; /* out: last TX_FIFO_COUNT sample */ __u32 wait_ns; /* out: time spent waiting */ __u8 reason; /* out: POG422_TX_EMPTY_REASON_* */ __u8 temt; /* out: 1 if EN_ACT idle + FIFO empty */ __u8 thre; /* out: 1 if FIFO empty observed */ __u8 _pad; }; #define XR_USB_SERIAL_WAIT_TX_EMPTY _IOWR(XR_USB_SERIAL_IOC_MAGIC, 26, struct xr_pog422_tx_empty) /* * EG 2.2.1.6 HW debug: drain Table-8 USB interrupt edge history (GPIO1+GPIO5). * Only populated when the driver is built with -DPOG422_HW_DEBUG=1; otherwise EOPNOTSUPP. * GPIO5 edges exist only on this USB INT path — no other source. */ #ifndef POG422_HWDBG_EDGE_MAX #define POG422_HWDBG_EDGE_MAX 256u #endif #define POG422_HWDBG_F_GPIO1 0x01u #define POG422_HWDBG_F_GPIO5 0x02u #define POG422_HWDBG_F_GPIO5_FELL 0x04u #define POG422_HWDBG_F_SLV_IN 0x08u struct xr_pog422_hwdbg_edge { __u64 timestamp_ns; __u16 gpio_state; __u16 gpio_int; __u8 flags; __u8 _pad[3]; }; struct xr_pog422_hwdbg_drain { __u64 user_buf; /* in: userspace array of xr_pog422_hwdbg_edge */ __u32 max_out; /* in: capacity */ __u32 out_n; /* out: edges copied */ __u32 dropped; /* out: edges lost to ring overflow since last drain */ __u32 hw_debug; /* out: 1 if driver compiled with POG422_HW_DEBUG */ }; #define XR_USB_SERIAL_DRAIN_HWDBG _IOWR(XR_USB_SERIAL_IOC_MAGIC, 27, struct xr_pog422_hwdbg_drain) /* * EG 2.2.1.15: always-on wide RX tee — parallel to DTtty (data-only). * Storage mirrors USB wide layout: packed [data][flags] pairs. * Flags bits 0x02..0x08 = BREAK/FRAME/OVERRUN; bit 0x10 = cached SLV-IN/HS. * Bit 0: 9th data bit when UART is in 9-bit wide mode (EG 2.2.1.16+ CS5); * parity-*error* when left in 8-bit wide mode (misleading for MARK). */ #ifndef POG422_WIDE_RX_SIZE #define POG422_WIDE_RX_SIZE 8192u /* pairs */ #endif #ifndef POG422_RAMCTL_HS #define POG422_RAMCTL_HS 0x10u #endif struct xr_pog422_wide_rx_avail { __u32 avail; /* bytes available (2 × pairs) */ __u64 total_written; /* pairs pushed since enable/flush */ __u32 overruns; __u8 wide_rx; __u8 _pad[3]; }; struct xr_pog422_wide_rx_read { __u64 user_buf; __u32 max_len; /* byte capacity (even) */ __u32 out_len; /* bytes copied */ __u32 avail; __u64 total_written; __u32 overruns; }; #define XR_USB_SERIAL_SET_WIDE_RX _IOW(XR_USB_SERIAL_IOC_MAGIC, 28, int) #define XR_USB_SERIAL_GET_WIDE_RX_AVAIL _IOR(XR_USB_SERIAL_IOC_MAGIC, 29, struct xr_pog422_wide_rx_avail) #define XR_USB_SERIAL_READ_WIDE_RX _IOWR(XR_USB_SERIAL_IOC_MAGIC, 30, struct xr_pog422_wide_rx_read) #define XR_USB_SERIAL_FLUSH_WIDE_RX _IO(XR_USB_SERIAL_IOC_MAGIC, 31) /* * EG 3.0.1.6: runtime-gated HS/RX timing ring (independent of POG422_HW_DEBUG). * Disabled by default — one branch when off. Host URB receipt times, not copper. */ #ifndef POG422_TIMING_RING_MAX #define POG422_TIMING_RING_MAX 256u #endif #define POG422_TIMING_EV_GPIO_INT 1u /* Table-8 USB INT (GPIO1 and/or GPIO5) */ #define POG422_TIMING_EV_RX_URB 2u /* bulk/int data RX URB completion */ #define POG422_TIMING_F_GPIO1 0x01u #define POG422_TIMING_F_GPIO5 0x02u #define POG422_TIMING_F_GPIO5_FELL 0x04u #define POG422_TIMING_F_SLV_IN 0x08u struct xr_pog422_timing_event { __u64 timestamp_ns; __u32 type; /* POG422_TIMING_EV_* */ __u16 gpio_state; __u16 gpio_int; __u8 flags; /* POG422_TIMING_F_* */ __u8 _pad; __u16 nbytes; /* RX_URB: urb->actual_length */ __u64 rx_chars; /* cumulative chars_inserted after event (RX) */ }; struct xr_pog422_timing_status { __u8 enabled; __u8 _pad[3]; __u32 count; __u32 dropped; __u64 total_pushed; }; struct xr_pog422_timing_drain { __u64 user_buf; /* in: array of xr_pog422_timing_event */ __u32 max_out; __u32 out_n; __u32 dropped; /* overflow since last drain/reset/enable */ __u8 enabled; __u8 _pad[3]; }; #define XR_USB_SERIAL_SET_TIMING_TRACE _IOW(XR_USB_SERIAL_IOC_MAGIC, 18, int) #define XR_USB_SERIAL_GET_TIMING_STATUS _IOR(XR_USB_SERIAL_IOC_MAGIC, 19, struct xr_pog422_timing_status) #define XR_USB_SERIAL_RESET_TIMING_TRACE _IO(XR_USB_SERIAL_IOC_MAGIC, 20) #define XR_USB_SERIAL_DRAIN_TIMING_TRACE _IOWR(XR_USB_SERIAL_IOC_MAGIC, 32, struct xr_pog422_timing_drain)