drivers/tty/serial/8250/8250_men_mcb.c

Source file repositories/reference/linux-study-clean/drivers/tty/serial/8250/8250_men_mcb.c

File Facts

System
Linux kernel
Corpus path
drivers/tty/serial/8250/8250_men_mcb.c
Extension
.c
Size
6629 bytes
Lines
268
Domain
Driver Families
Bucket
drivers/tty
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 serial_8250_men_mcb_data {
	int num_ports;
	int line[MEN_Z025_MAX_UARTS];
	unsigned int offset[MEN_Z025_MAX_UARTS];
};

/*
 * The Z125 16550-compatible UART has no fixed base clock assigned
 * So, depending on the board we're on, we need to adjust the
 * parameter in order to really set the correct baudrate, and
 * do so if possible without user interaction
 */
static u32 men_lookup_uartclk(struct mcb_device *mdev)
{
	/* use default value if board is not available below */
	u32 clkval = 1041666;

	dev_info(&mdev->dev, "%s on board %s\n",
		dev_name(&mdev->dev),
		mdev->bus->name);
	if  (strncmp(mdev->bus->name, "F075", 4) == 0)
		clkval = 1041666;
	else if (strncmp(mdev->bus->name, "F216", 4) == 0)
		clkval = 1843200;
	else if (strncmp(mdev->bus->name, "F210", 4) == 0)
		clkval = 115200;
	else if (strstr(mdev->bus->name, "215"))
		clkval = 1843200;
	else
		dev_info(&mdev->dev,
			 "board not detected, using default uartclk\n");

	clkval = clkval  << 4;

	return clkval;
}

static int read_uarts_available_from_register(struct resource *mem_res,
					      u8 *uarts_available)
{
	void __iomem *mem;
	int reg_value;

	if (!request_mem_region(mem_res->start + MEN_Z025_REGISTER_OFFSET,
				MEM_UART_REGISTER_SIZE,  KBUILD_MODNAME)) {
		return -EBUSY;
	}

	mem = ioremap(mem_res->start + MEN_Z025_REGISTER_OFFSET,
		      MEM_UART_REGISTER_SIZE);
	if (!mem) {
		release_mem_region(mem_res->start + MEN_Z025_REGISTER_OFFSET,
				   MEM_UART_REGISTER_SIZE);
		return -ENOMEM;
	}

	reg_value = MEN_READ_REGISTER(mem);

	iounmap(mem);

	release_mem_region(mem_res->start + MEN_Z025_REGISTER_OFFSET,
			   MEM_UART_REGISTER_SIZE);

	*uarts_available = reg_value >> 4;

	return 0;
}

static int read_serial_data(struct mcb_device *mdev,
			    struct resource *mem_res,
			    struct serial_8250_men_mcb_data *serial_data)
{
	u8 uarts_available;
	int count = 0;
	int mask;
	int res;
	int i;

	res = read_uarts_available_from_register(mem_res, &uarts_available);
	if (res < 0)
		return res;

	for (i = 0; i < MEN_Z025_MAX_UARTS; i++) {
		mask = 0x1 << i;
		switch (uarts_available & mask) {
		case MEN_UART1_MASK:
			serial_data->offset[count] = MEN_UART1_OFFSET;
			count++;
			break;
		case MEN_UART2_MASK:

Annotation

Implementation Notes