cregit-Linux how code gets into the kernel

Release 4.7 drivers/mfd/lpc_sch.c

Directory: drivers/mfd
/*
 *  lpc_sch.c - LPC interface for Intel Poulsbo SCH
 *
 *  LPC bridge function of the Intel SCH contains many other
 *  functional units, such as Interrupt controllers, Timers,
 *  Power Management, System Management, GPIO, RTC, and LPC
 *  Configuration Registers.
 *
 *  Copyright (c) 2010 CompuLab Ltd
 *  Copyright (c) 2014 Intel Corp.
 *  Author: Denis Turischev <denis@compulab.co.il>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License 2 as published
 *  by the Free Software Foundation.
 *
 *  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.
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/acpi.h>
#include <linux/pci.h>
#include <linux/mfd/core.h>


#define SMBASE		0x40

#define SMBUS_IO_SIZE	64


#define GPIOBASE	0x44

#define GPIO_IO_SIZE	64

#define GPIO_IO_SIZE_CENTERTON	128

/* Intel Quark X1000 GPIO IRQ Number */

#define GPIO_IRQ_QUARK_X1000	9


#define WDTBASE		0x84

#define WDT_IO_SIZE	64


enum sch_chipsets {
	
LPC_SCH = 0,		/* Intel Poulsbo SCH */
	
LPC_ITC,		/* Intel Tunnel Creek */
	
LPC_CENTERTON,		/* Intel Centerton */
	
LPC_QUARK_X1000,	/* Intel Quark X1000 */
};


struct lpc_sch_info {
	
unsigned int io_size_smbus;
	
unsigned int io_size_gpio;
	
unsigned int io_size_wdt;
	
int irq_gpio;
};


static struct lpc_sch_info sch_chipset_info[] = {
	[LPC_SCH] = {
		.io_size_smbus = SMBUS_IO_SIZE,
		.io_size_gpio = GPIO_IO_SIZE,
		.irq_gpio = -1,
        },
	[LPC_ITC] = {
		.io_size_smbus = SMBUS_IO_SIZE,
		.io_size_gpio = GPIO_IO_SIZE,
		.io_size_wdt = WDT_IO_SIZE,
		.irq_gpio = -1,
        },
	[LPC_CENTERTON] = {
		.io_size_smbus = SMBUS_IO_SIZE,
		.io_size_gpio = GPIO_IO_SIZE_CENTERTON,
		.io_size_wdt = WDT_IO_SIZE,
		.irq_gpio = -1,
        },
	[LPC_QUARK_X1000] = {
		.io_size_gpio = GPIO_IO_SIZE,
		.irq_gpio = GPIO_IRQ_QUARK_X1000,
		.io_size_wdt = WDT_IO_SIZE,
        },
};


static const struct pci_device_id lpc_sch_ids[] = {
	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_SCH_LPC), LPC_SCH },
	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ITC_LPC), LPC_ITC },
	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_CENTERTON_ILB), LPC_CENTERTON },
	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_QUARK_X1000_ILB), LPC_QUARK_X1000 },
	{ 0, }
};
MODULE_DEVICE_TABLE(pci, lpc_sch_ids);


#define LPC_NO_RESOURCE		1

#define LPC_SKIP_RESOURCE	2


static int lpc_sch_get_io(struct pci_dev *pdev, int where, const char *name, struct resource *res, int size) { unsigned int base_addr_cfg; unsigned short base_addr; if (size == 0) return LPC_NO_RESOURCE; pci_read_config_dword(pdev, where, &base_addr_cfg); base_addr = 0; if (!(base_addr_cfg & (1 << 31))) dev_warn(&pdev->dev, "Decode of the %s I/O range disabled\n", name); else base_addr = (unsigned short)base_addr_cfg; if (base_addr == 0) { dev_warn(&pdev->dev, "I/O space for %s uninitialized\n", name); return LPC_SKIP_RESOURCE; } res->start = base_addr; res->end = base_addr + size - 1; res->flags = IORESOURCE_IO; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
denis turischevdenis turischev8258.57%133.33%
andy shevchenkoandy shevchenko4935.00%133.33%
darren hartdarren hart96.43%133.33%
Total140100.00%3100.00%


static int lpc_sch_populate_cell(struct pci_dev *pdev, int where, const char *name, int size, int irq, int id, struct mfd_cell *cell) { struct resource *res; int ret; res = devm_kcalloc(&pdev->dev, 2, sizeof(*res), GFP_KERNEL); if (!res) return -ENOMEM; ret = lpc_sch_get_io(pdev, where, name, res, size); if (ret) return ret; memset(cell, 0, sizeof(*cell)); cell->name = name; cell->resources = res; cell->num_resources = 1; cell->ignore_resource_conflicts = true; cell->id = id; /* Check if we need to add an IRQ resource */ if (irq < 0) return 0; res++; res->start = irq; res->end = irq; res->flags = IORESOURCE_IRQ; cell->num_resources++; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
andy shevchenkoandy shevchenko14382.18%240.00%
denis turischevdenis turischev2413.79%120.00%
seth heasleyseth heasley42.30%120.00%
darren hartdarren hart31.72%120.00%
Total174100.00%5100.00%


static int lpc_sch_probe(struct pci_dev *dev, const struct pci_device_id *id) { struct mfd_cell lpc_sch_cells[3]; struct lpc_sch_info *info = &sch_chipset_info[id->driver_data]; unsigned int cells = 0; int ret; ret = lpc_sch_populate_cell(dev, SMBASE, "isch_smbus", info->io_size_smbus, -1, id->device, &lpc_sch_cells[cells]); if (ret < 0) return ret; if (ret == 0) cells++; ret = lpc_sch_populate_cell(dev, GPIOBASE, "sch_gpio", info->io_size_gpio, info->irq_gpio, id->device, &lpc_sch_cells[cells]); if (ret < 0) return ret; if (ret == 0) cells++; ret = lpc_sch_populate_cell(dev, WDTBASE, "ie6xx_wdt", info->io_size_wdt, -1, id->device, &lpc_sch_cells[cells]); if (ret < 0) return ret; if (ret == 0) cells++; if (cells == 0) { dev_err(&dev->dev, "All decode registers disabled.\n"); return -ENODEV; } return mfd_add_devices(&dev->dev, 0, lpc_sch_cells, cells, NULL, 0, NULL); }

Contributors

PersonTokensPropCommitsCommitProp
andy shevchenkoandy shevchenko14664.04%337.50%
alexander steinalexander stein4218.42%112.50%
darren hartdarren hart3414.91%112.50%
seth heasleyseth heasley20.88%112.50%
mark brownmark brown20.88%112.50%
denis turischevdenis turischev20.88%112.50%
Total228100.00%8100.00%


static void lpc_sch_remove(struct pci_dev *dev) { mfd_remove_devices(&dev->dev); }

Contributors

PersonTokensPropCommitsCommitProp
denis turischevdenis turischev19100.00%1100.00%
Total19100.00%1100.00%

static struct pci_driver lpc_sch_driver = { .name = "lpc_sch", .id_table = lpc_sch_ids, .probe = lpc_sch_probe, .remove = lpc_sch_remove, }; module_pci_driver(lpc_sch_driver); MODULE_AUTHOR("Denis Turischev <denis@compulab.co.il>"); MODULE_DESCRIPTION("LPC interface for Intel Poulsbo SCH"); MODULE_LICENSE("GPL");

Overall Contributors

PersonTokensPropCommitsCommitProp
andy shevchenkoandy shevchenko47754.45%428.57%
denis turischevdenis turischev25328.88%214.29%
alexander steinalexander stein586.62%17.14%
darren hartdarren hart505.71%17.14%
seth heasleyseth heasley161.83%17.14%
johannes thumshirnjohannes thumshirn70.80%17.14%
jingoo hanjingoo han60.68%17.14%
ong boon leongong boon leong50.57%17.14%
mark brownmark brown20.23%17.14%
axel linaxel lin20.23%17.14%
Total876100.00%14100.00%
Directory: drivers/mfd
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
{% endraw %}