drivers/usb/serial/f81534.c

Source file repositories/reference/linux-study-clean/drivers/usb/serial/f81534.c

File Facts

System
Linux kernel
Corpus path
drivers/usb/serial/f81534.c
Extension
.c
Size
40453 bytes
Lines
1576
Domain
Driver Families
Bucket
drivers/usb
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct f81534_serial_private {
	u8 conf_data[F81534_DEF_CONF_SIZE];
	int tty_idx[F81534_NUM_PORT];
	u8 setting_idx;
	int opened_port;
	struct mutex urb_mutex;
};

struct f81534_port_private {
	struct mutex mcr_mutex;
	struct mutex lcr_mutex;
	struct work_struct lsr_work;
	struct usb_serial_port *port;
	unsigned long tx_empty;
	spinlock_t msr_lock;
	u32 baud_base;
	u8 shadow_mcr;
	u8 shadow_lcr;
	u8 shadow_msr;
	u8 shadow_clk;
	u8 phy_num;
};

struct f81534_pin_data {
	const u16 reg_addr;
	const u8 reg_mask;
};

struct f81534_port_out_pin {
	struct f81534_pin_data pin[3];
};

/* Pin output value for M2/M1/M0(SD) */
static const struct f81534_port_out_pin f81534_port_out_pins[] = {
	 { { { 0x2ae8, BIT(7) }, { 0x2a90, BIT(5) }, { 0x2a90, BIT(4) } } },
	 { { { 0x2ae8, BIT(6) }, { 0x2ae8, BIT(0) }, { 0x2ae8, BIT(3) } } },
	 { { { 0x2a90, BIT(0) }, { 0x2ae8, BIT(2) }, { 0x2a80, BIT(6) } } },
	 { { { 0x2a90, BIT(3) }, { 0x2a90, BIT(2) }, { 0x2a90, BIT(1) } } },
};

static u32 const baudrate_table[] = { 115200, 921600, 1152000, 1500000 };
static u8 const clock_table[] = { F81534_CLK_1_846_MHZ, F81534_CLK_14_77_MHZ,
				F81534_CLK_18_46_MHZ, F81534_CLK_24_MHZ };

static int f81534_logic_to_phy_port(struct usb_serial *serial,
					struct usb_serial_port *port)
{
	struct f81534_serial_private *serial_priv =
			usb_get_serial_data(port->serial);
	int count = 0;
	int i;

	for (i = 0; i < F81534_NUM_PORT; ++i) {
		if (serial_priv->conf_data[i] & F81534_PORT_UNAVAILABLE)
			continue;

		if (port->port_number == count)
			return i;

		++count;
	}

	return -ENODEV;
}

static int f81534_set_register(struct usb_serial *serial, u16 reg, u8 data)
{
	struct usb_interface *interface = serial->interface;
	struct usb_device *dev = serial->dev;
	size_t count = F81534_USB_MAX_RETRY;
	int status;
	u8 *tmp;

	tmp = kmalloc(sizeof(u8), GFP_KERNEL);
	if (!tmp)
		return -ENOMEM;

	*tmp = data;

	/*
	 * Our device maybe not reply when heavily loading, We'll retry for
	 * F81534_USB_MAX_RETRY times.
	 */
	while (count--) {
		status = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
					 F81534_SET_GET_REGISTER,
					 USB_TYPE_VENDOR | USB_DIR_OUT,
					 reg, 0, tmp, sizeof(u8),
					 F81534_USB_TIMEOUT);
		if (status == sizeof(u8)) {

Annotation

Implementation Notes