drivers/usb/typec/tcpm/fusb302.c

Source file repositories/reference/linux-study-clean/drivers/usb/typec/tcpm/fusb302.c

File Facts

System
Linux kernel
Corpus path
drivers/usb/typec/tcpm/fusb302.c
Extension
.c
Size
49802 bytes
Lines
1869
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 fusb302_chip {
	struct device *dev;
	struct i2c_client *i2c_client;
	struct tcpm_port *tcpm_port;
	struct tcpc_dev tcpc_dev;

	struct regulator *vbus;

	spinlock_t irq_lock;
	struct work_struct irq_work;
	bool irq_suspended;
	bool irq_while_suspended;
	struct gpio_desc *gpio_int_n;
	int gpio_int_n_irq;
	struct extcon_dev *extcon;

	struct workqueue_struct *wq;
	struct delayed_work bc_lvl_handler;

	/* lock for sharing chip states */
	struct mutex lock;

	/* chip status */
	enum toggling_mode toggling_mode;
	enum src_current_status src_current_status;
	bool intr_togdone;
	bool intr_bc_lvl;
	bool intr_comp_chng;

	/* port status */
	bool vconn_on;
	bool vbus_on;
	bool charge_on;
	bool pd_rx_on;
	bool vbus_present;
	enum typec_cc_polarity cc_polarity;
	enum typec_cc_status cc1;
	enum typec_cc_status cc2;
	u32 snk_pdo[PDO_MAX_OBJECTS];

#ifdef CONFIG_DEBUG_FS
	struct dentry *dentry;
	/* lock for log buffer access */
	struct mutex logbuffer_lock;
	int logbuffer_head;
	int logbuffer_tail;
	u8 *logbuffer[LOG_BUFFER_ENTRIES];
#endif
};

/*
 * Logging
 */

#ifdef CONFIG_DEBUG_FS
static bool fusb302_log_full(struct fusb302_chip *chip)
{
	return chip->logbuffer_tail ==
		(chip->logbuffer_head + 1) % LOG_BUFFER_ENTRIES;
}

__printf(2, 0)
static void _fusb302_log(struct fusb302_chip *chip, const char *fmt,
			 va_list args)
{
	char tmpbuffer[LOG_BUFFER_ENTRY_SIZE];
	u64 ts_nsec = local_clock();
	unsigned long rem_nsec;

	if (!chip->logbuffer[chip->logbuffer_head]) {
		chip->logbuffer[chip->logbuffer_head] =
				kzalloc(LOG_BUFFER_ENTRY_SIZE, GFP_KERNEL);
		if (!chip->logbuffer[chip->logbuffer_head])
			return;
	}

	vsnprintf(tmpbuffer, sizeof(tmpbuffer), fmt, args);

	mutex_lock(&chip->logbuffer_lock);

	if (fusb302_log_full(chip)) {
		chip->logbuffer_head = max(chip->logbuffer_head - 1, 0);
		strscpy(tmpbuffer, "overflow", sizeof(tmpbuffer));
	}

	if (chip->logbuffer_head < 0 ||
	    chip->logbuffer_head >= LOG_BUFFER_ENTRIES) {
		dev_warn(chip->dev,
			 "Bad log buffer index %d\n", chip->logbuffer_head);
		goto abort;

Annotation

Implementation Notes