static int __init it87_gpio_init()

in gpio-it87.c [272:395]


static int __init it87_gpio_init(void)
{
	int rc = 0, i;
	u16 chip_type;
	u8 chip_rev, gpio_ba_reg;
	char *labels, **labels_table;

	struct it87_gpio *it87_gpio = &it87_gpio_chip;

	rc = superio_enter();
	if (rc)
		return rc;

	chip_type = superio_inw(CHIPID);
	chip_rev  = superio_inb(CHIPREV) & 0x0f;
	superio_exit();

	it87_gpio->chip = it87_template_chip;

	switch (chip_type) {
	case IT8613_ID:
		gpio_ba_reg = 0x62;
		it87_gpio->io_size = 8;  /* it8613 only needs 6, use 8 for alignment */
		it87_gpio->output_base = 0xc8;
		it87_gpio->simple_base = 0xc0;
		it87_gpio->simple_size = 6;
		it87_gpio->chip.ngpio = 64;  /* has 48, use 64 for convenient calc */
		break;
	case IT8620_ID:
	case IT8628_ID:
		gpio_ba_reg = 0x62;
		it87_gpio->io_size = 11;
		it87_gpio->output_base = 0xc8;
		it87_gpio->simple_size = 0;
		it87_gpio->chip.ngpio = 64;
		break;
	case IT8718_ID:
	case IT8728_ID:
	case IT8732_ID:
	case IT8772_ID:
	case IT8786_ID:
		gpio_ba_reg = 0x62;
		it87_gpio->io_size = 8;
		it87_gpio->output_base = 0xc8;
		it87_gpio->simple_base = 0xc0;
		it87_gpio->simple_size = 5;
		it87_gpio->chip.ngpio = 64;
		break;
	case IT8761_ID:
		gpio_ba_reg = 0x60;
		it87_gpio->io_size = 4;
		it87_gpio->output_base = 0xf0;
		it87_gpio->simple_size = 0;
		it87_gpio->chip.ngpio = 16;
		break;
	case NO_DEV_ID:
		pr_err("no device\n");
		return -ENODEV;
	default:
		pr_err("Unknown Chip found, Chip %04x Revision %x\n",
		       chip_type, chip_rev);
		return -ENODEV;
	}

	rc = superio_enter();
	if (rc)
		return rc;

	superio_select(GPIO);

	/* fetch GPIO base address */
	it87_gpio->io_base = superio_inw(gpio_ba_reg);

	superio_exit();

	pr_info("Found Chip IT%04x rev %x. %u GPIO lines starting at %04xh\n",
		chip_type, chip_rev, it87_gpio->chip.ngpio,
		it87_gpio->io_base);

	if (!request_region(it87_gpio->io_base, it87_gpio->io_size,
							KBUILD_MODNAME))
		return -EBUSY;

	/* Set up aliases for the GPIO connection.
	 *
	 * ITE documentation for recent chips such as the IT8728F
	 * refers to the GPIO lines as GPxy, with a coordinates system
	 * where x is the GPIO group (starting from 1) and y is the
	 * bit within the group.
	 *
	 * By creating these aliases, we make it easier to understand
	 * to which GPIO pin we're referring to.
	 */
	labels = kcalloc(it87_gpio->chip.ngpio, sizeof("it87_gpXY"),
								GFP_KERNEL);
	labels_table = kcalloc(it87_gpio->chip.ngpio, sizeof(const char *),
								GFP_KERNEL);

	if (!labels || !labels_table) {
		rc = -ENOMEM;
		goto labels_free;
	}

	for (i = 0; i < it87_gpio->chip.ngpio; i++) {
		char *label = &labels[i * sizeof("it87_gpXY")];

		sprintf(label, "it87_gp%u%u", 1+(i/8), i%8);
		labels_table[i] = label;
	}

	it87_gpio->chip.names = (const char *const*)labels_table;

	rc = gpiochip_add_data(&it87_gpio->chip, it87_gpio);
	if (rc)
		goto labels_free;

	return 0;

labels_free:
	kfree(labels_table);
	kfree(labels);
	release_region(it87_gpio->io_base, it87_gpio->io_size);
	return rc;
}