Path: blob/master/drivers/i2c/busses/i2c-mv64xxx.c
15111 views
/*1* Driver for the i2c controller on the Marvell line of host bridges2* (e.g, gt642[46]0, mv643[46]0, mv644[46]0, and Orion SoC family).3*4* Author: Mark A. Greer <[email protected]>5*6* 2005 (c) MontaVista, Software, Inc. This file is licensed under7* the terms of the GNU General Public License version 2. This program8* is licensed "as is" without any warranty of any kind, whether express9* or implied.10*/11#include <linux/kernel.h>12#include <linux/slab.h>13#include <linux/module.h>14#include <linux/spinlock.h>15#include <linux/i2c.h>16#include <linux/interrupt.h>17#include <linux/mv643xx_i2c.h>18#include <linux/platform_device.h>19#include <linux/io.h>2021/* Register defines */22#define MV64XXX_I2C_REG_SLAVE_ADDR 0x0023#define MV64XXX_I2C_REG_DATA 0x0424#define MV64XXX_I2C_REG_CONTROL 0x0825#define MV64XXX_I2C_REG_STATUS 0x0c26#define MV64XXX_I2C_REG_BAUD 0x0c27#define MV64XXX_I2C_REG_EXT_SLAVE_ADDR 0x1028#define MV64XXX_I2C_REG_SOFT_RESET 0x1c2930#define MV64XXX_I2C_REG_CONTROL_ACK 0x0000000431#define MV64XXX_I2C_REG_CONTROL_IFLG 0x0000000832#define MV64XXX_I2C_REG_CONTROL_STOP 0x0000001033#define MV64XXX_I2C_REG_CONTROL_START 0x0000002034#define MV64XXX_I2C_REG_CONTROL_TWSIEN 0x0000004035#define MV64XXX_I2C_REG_CONTROL_INTEN 0x000000803637/* Ctlr status values */38#define MV64XXX_I2C_STATUS_BUS_ERR 0x0039#define MV64XXX_I2C_STATUS_MAST_START 0x0840#define MV64XXX_I2C_STATUS_MAST_REPEAT_START 0x1041#define MV64XXX_I2C_STATUS_MAST_WR_ADDR_ACK 0x1842#define MV64XXX_I2C_STATUS_MAST_WR_ADDR_NO_ACK 0x2043#define MV64XXX_I2C_STATUS_MAST_WR_ACK 0x2844#define MV64XXX_I2C_STATUS_MAST_WR_NO_ACK 0x3045#define MV64XXX_I2C_STATUS_MAST_LOST_ARB 0x3846#define MV64XXX_I2C_STATUS_MAST_RD_ADDR_ACK 0x4047#define MV64XXX_I2C_STATUS_MAST_RD_ADDR_NO_ACK 0x4848#define MV64XXX_I2C_STATUS_MAST_RD_DATA_ACK 0x5049#define MV64XXX_I2C_STATUS_MAST_RD_DATA_NO_ACK 0x5850#define MV64XXX_I2C_STATUS_MAST_WR_ADDR_2_ACK 0xd051#define MV64XXX_I2C_STATUS_MAST_WR_ADDR_2_NO_ACK 0xd852#define MV64XXX_I2C_STATUS_MAST_RD_ADDR_2_ACK 0xe053#define MV64XXX_I2C_STATUS_MAST_RD_ADDR_2_NO_ACK 0xe854#define MV64XXX_I2C_STATUS_NO_STATUS 0xf85556/* Driver states */57enum {58MV64XXX_I2C_STATE_INVALID,59MV64XXX_I2C_STATE_IDLE,60MV64XXX_I2C_STATE_WAITING_FOR_START_COND,61MV64XXX_I2C_STATE_WAITING_FOR_RESTART,62MV64XXX_I2C_STATE_WAITING_FOR_ADDR_1_ACK,63MV64XXX_I2C_STATE_WAITING_FOR_ADDR_2_ACK,64MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_ACK,65MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_DATA,66};6768/* Driver actions */69enum {70MV64XXX_I2C_ACTION_INVALID,71MV64XXX_I2C_ACTION_CONTINUE,72MV64XXX_I2C_ACTION_SEND_START,73MV64XXX_I2C_ACTION_SEND_RESTART,74MV64XXX_I2C_ACTION_SEND_ADDR_1,75MV64XXX_I2C_ACTION_SEND_ADDR_2,76MV64XXX_I2C_ACTION_SEND_DATA,77MV64XXX_I2C_ACTION_RCV_DATA,78MV64XXX_I2C_ACTION_RCV_DATA_STOP,79MV64XXX_I2C_ACTION_SEND_STOP,80};8182struct mv64xxx_i2c_data {83int irq;84u32 state;85u32 action;86u32 aborting;87u32 cntl_bits;88void __iomem *reg_base;89u32 reg_base_p;90u32 reg_size;91u32 addr1;92u32 addr2;93u32 bytes_left;94u32 byte_posn;95u32 send_stop;96u32 block;97int rc;98u32 freq_m;99u32 freq_n;100wait_queue_head_t waitq;101spinlock_t lock;102struct i2c_msg *msg;103struct i2c_adapter adapter;104};105106/*107*****************************************************************************108*109* Finite State Machine & Interrupt Routines110*111*****************************************************************************112*/113114/* Reset hardware and initialize FSM */115static void116mv64xxx_i2c_hw_init(struct mv64xxx_i2c_data *drv_data)117{118writel(0, drv_data->reg_base + MV64XXX_I2C_REG_SOFT_RESET);119writel((((drv_data->freq_m & 0xf) << 3) | (drv_data->freq_n & 0x7)),120drv_data->reg_base + MV64XXX_I2C_REG_BAUD);121writel(0, drv_data->reg_base + MV64XXX_I2C_REG_SLAVE_ADDR);122writel(0, drv_data->reg_base + MV64XXX_I2C_REG_EXT_SLAVE_ADDR);123writel(MV64XXX_I2C_REG_CONTROL_TWSIEN | MV64XXX_I2C_REG_CONTROL_STOP,124drv_data->reg_base + MV64XXX_I2C_REG_CONTROL);125drv_data->state = MV64XXX_I2C_STATE_IDLE;126}127128static void129mv64xxx_i2c_fsm(struct mv64xxx_i2c_data *drv_data, u32 status)130{131/*132* If state is idle, then this is likely the remnants of an old133* operation that driver has given up on or the user has killed.134* If so, issue the stop condition and go to idle.135*/136if (drv_data->state == MV64XXX_I2C_STATE_IDLE) {137drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP;138return;139}140141/* The status from the ctlr [mostly] tells us what to do next */142switch (status) {143/* Start condition interrupt */144case MV64XXX_I2C_STATUS_MAST_START: /* 0x08 */145case MV64XXX_I2C_STATUS_MAST_REPEAT_START: /* 0x10 */146drv_data->action = MV64XXX_I2C_ACTION_SEND_ADDR_1;147drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_ADDR_1_ACK;148break;149150/* Performing a write */151case MV64XXX_I2C_STATUS_MAST_WR_ADDR_ACK: /* 0x18 */152if (drv_data->msg->flags & I2C_M_TEN) {153drv_data->action = MV64XXX_I2C_ACTION_SEND_ADDR_2;154drv_data->state =155MV64XXX_I2C_STATE_WAITING_FOR_ADDR_2_ACK;156break;157}158/* FALLTHRU */159case MV64XXX_I2C_STATUS_MAST_WR_ADDR_2_ACK: /* 0xd0 */160case MV64XXX_I2C_STATUS_MAST_WR_ACK: /* 0x28 */161if ((drv_data->bytes_left == 0)162|| (drv_data->aborting163&& (drv_data->byte_posn != 0))) {164if (drv_data->send_stop) {165drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP;166drv_data->state = MV64XXX_I2C_STATE_IDLE;167} else {168drv_data->action =169MV64XXX_I2C_ACTION_SEND_RESTART;170drv_data->state =171MV64XXX_I2C_STATE_WAITING_FOR_RESTART;172}173} else {174drv_data->action = MV64XXX_I2C_ACTION_SEND_DATA;175drv_data->state =176MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_ACK;177drv_data->bytes_left--;178}179break;180181/* Performing a read */182case MV64XXX_I2C_STATUS_MAST_RD_ADDR_ACK: /* 40 */183if (drv_data->msg->flags & I2C_M_TEN) {184drv_data->action = MV64XXX_I2C_ACTION_SEND_ADDR_2;185drv_data->state =186MV64XXX_I2C_STATE_WAITING_FOR_ADDR_2_ACK;187break;188}189/* FALLTHRU */190case MV64XXX_I2C_STATUS_MAST_RD_ADDR_2_ACK: /* 0xe0 */191if (drv_data->bytes_left == 0) {192drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP;193drv_data->state = MV64XXX_I2C_STATE_IDLE;194break;195}196/* FALLTHRU */197case MV64XXX_I2C_STATUS_MAST_RD_DATA_ACK: /* 0x50 */198if (status != MV64XXX_I2C_STATUS_MAST_RD_DATA_ACK)199drv_data->action = MV64XXX_I2C_ACTION_CONTINUE;200else {201drv_data->action = MV64XXX_I2C_ACTION_RCV_DATA;202drv_data->bytes_left--;203}204drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_DATA;205206if ((drv_data->bytes_left == 1) || drv_data->aborting)207drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_ACK;208break;209210case MV64XXX_I2C_STATUS_MAST_RD_DATA_NO_ACK: /* 0x58 */211drv_data->action = MV64XXX_I2C_ACTION_RCV_DATA_STOP;212drv_data->state = MV64XXX_I2C_STATE_IDLE;213break;214215case MV64XXX_I2C_STATUS_MAST_WR_ADDR_NO_ACK: /* 0x20 */216case MV64XXX_I2C_STATUS_MAST_WR_NO_ACK: /* 30 */217case MV64XXX_I2C_STATUS_MAST_RD_ADDR_NO_ACK: /* 48 */218/* Doesn't seem to be a device at other end */219drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP;220drv_data->state = MV64XXX_I2C_STATE_IDLE;221drv_data->rc = -ENODEV;222break;223224default:225dev_err(&drv_data->adapter.dev,226"mv64xxx_i2c_fsm: Ctlr Error -- state: 0x%x, "227"status: 0x%x, addr: 0x%x, flags: 0x%x\n",228drv_data->state, status, drv_data->msg->addr,229drv_data->msg->flags);230drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP;231mv64xxx_i2c_hw_init(drv_data);232drv_data->rc = -EIO;233}234}235236static void237mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data)238{239switch(drv_data->action) {240case MV64XXX_I2C_ACTION_SEND_RESTART:241drv_data->cntl_bits |= MV64XXX_I2C_REG_CONTROL_START;242drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_INTEN;243writel(drv_data->cntl_bits,244drv_data->reg_base + MV64XXX_I2C_REG_CONTROL);245drv_data->block = 0;246wake_up_interruptible(&drv_data->waitq);247break;248249case MV64XXX_I2C_ACTION_CONTINUE:250writel(drv_data->cntl_bits,251drv_data->reg_base + MV64XXX_I2C_REG_CONTROL);252break;253254case MV64XXX_I2C_ACTION_SEND_START:255writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_START,256drv_data->reg_base + MV64XXX_I2C_REG_CONTROL);257break;258259case MV64XXX_I2C_ACTION_SEND_ADDR_1:260writel(drv_data->addr1,261drv_data->reg_base + MV64XXX_I2C_REG_DATA);262writel(drv_data->cntl_bits,263drv_data->reg_base + MV64XXX_I2C_REG_CONTROL);264break;265266case MV64XXX_I2C_ACTION_SEND_ADDR_2:267writel(drv_data->addr2,268drv_data->reg_base + MV64XXX_I2C_REG_DATA);269writel(drv_data->cntl_bits,270drv_data->reg_base + MV64XXX_I2C_REG_CONTROL);271break;272273case MV64XXX_I2C_ACTION_SEND_DATA:274writel(drv_data->msg->buf[drv_data->byte_posn++],275drv_data->reg_base + MV64XXX_I2C_REG_DATA);276writel(drv_data->cntl_bits,277drv_data->reg_base + MV64XXX_I2C_REG_CONTROL);278break;279280case MV64XXX_I2C_ACTION_RCV_DATA:281drv_data->msg->buf[drv_data->byte_posn++] =282readl(drv_data->reg_base + MV64XXX_I2C_REG_DATA);283writel(drv_data->cntl_bits,284drv_data->reg_base + MV64XXX_I2C_REG_CONTROL);285break;286287case MV64XXX_I2C_ACTION_RCV_DATA_STOP:288drv_data->msg->buf[drv_data->byte_posn++] =289readl(drv_data->reg_base + MV64XXX_I2C_REG_DATA);290drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_INTEN;291writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_STOP,292drv_data->reg_base + MV64XXX_I2C_REG_CONTROL);293drv_data->block = 0;294wake_up_interruptible(&drv_data->waitq);295break;296297case MV64XXX_I2C_ACTION_INVALID:298default:299dev_err(&drv_data->adapter.dev,300"mv64xxx_i2c_do_action: Invalid action: %d\n",301drv_data->action);302drv_data->rc = -EIO;303/* FALLTHRU */304case MV64XXX_I2C_ACTION_SEND_STOP:305drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_INTEN;306writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_STOP,307drv_data->reg_base + MV64XXX_I2C_REG_CONTROL);308drv_data->block = 0;309wake_up_interruptible(&drv_data->waitq);310break;311}312}313314static irqreturn_t315mv64xxx_i2c_intr(int irq, void *dev_id)316{317struct mv64xxx_i2c_data *drv_data = dev_id;318unsigned long flags;319u32 status;320irqreturn_t rc = IRQ_NONE;321322spin_lock_irqsave(&drv_data->lock, flags);323while (readl(drv_data->reg_base + MV64XXX_I2C_REG_CONTROL) &324MV64XXX_I2C_REG_CONTROL_IFLG) {325status = readl(drv_data->reg_base + MV64XXX_I2C_REG_STATUS);326mv64xxx_i2c_fsm(drv_data, status);327mv64xxx_i2c_do_action(drv_data);328rc = IRQ_HANDLED;329}330spin_unlock_irqrestore(&drv_data->lock, flags);331332return rc;333}334335/*336*****************************************************************************337*338* I2C Msg Execution Routines339*340*****************************************************************************341*/342static void343mv64xxx_i2c_prepare_for_io(struct mv64xxx_i2c_data *drv_data,344struct i2c_msg *msg)345{346u32 dir = 0;347348drv_data->msg = msg;349drv_data->byte_posn = 0;350drv_data->bytes_left = msg->len;351drv_data->aborting = 0;352drv_data->rc = 0;353drv_data->cntl_bits = MV64XXX_I2C_REG_CONTROL_ACK |354MV64XXX_I2C_REG_CONTROL_INTEN | MV64XXX_I2C_REG_CONTROL_TWSIEN;355356if (msg->flags & I2C_M_RD)357dir = 1;358359if (msg->flags & I2C_M_TEN) {360drv_data->addr1 = 0xf0 | (((u32)msg->addr & 0x300) >> 7) | dir;361drv_data->addr2 = (u32)msg->addr & 0xff;362} else {363drv_data->addr1 = ((u32)msg->addr & 0x7f) << 1 | dir;364drv_data->addr2 = 0;365}366}367368static void369mv64xxx_i2c_wait_for_completion(struct mv64xxx_i2c_data *drv_data)370{371long time_left;372unsigned long flags;373char abort = 0;374375time_left = wait_event_interruptible_timeout(drv_data->waitq,376!drv_data->block, drv_data->adapter.timeout);377378spin_lock_irqsave(&drv_data->lock, flags);379if (!time_left) { /* Timed out */380drv_data->rc = -ETIMEDOUT;381abort = 1;382} else if (time_left < 0) { /* Interrupted/Error */383drv_data->rc = time_left; /* errno value */384abort = 1;385}386387if (abort && drv_data->block) {388drv_data->aborting = 1;389spin_unlock_irqrestore(&drv_data->lock, flags);390391time_left = wait_event_timeout(drv_data->waitq,392!drv_data->block, drv_data->adapter.timeout);393394if ((time_left <= 0) && drv_data->block) {395drv_data->state = MV64XXX_I2C_STATE_IDLE;396dev_err(&drv_data->adapter.dev,397"mv64xxx: I2C bus locked, block: %d, "398"time_left: %d\n", drv_data->block,399(int)time_left);400mv64xxx_i2c_hw_init(drv_data);401}402} else403spin_unlock_irqrestore(&drv_data->lock, flags);404}405406static int407mv64xxx_i2c_execute_msg(struct mv64xxx_i2c_data *drv_data, struct i2c_msg *msg,408int is_first, int is_last)409{410unsigned long flags;411412spin_lock_irqsave(&drv_data->lock, flags);413mv64xxx_i2c_prepare_for_io(drv_data, msg);414415if (unlikely(msg->flags & I2C_M_NOSTART)) { /* Skip start/addr phases */416if (drv_data->msg->flags & I2C_M_RD) {417/* No action to do, wait for slave to send a byte */418drv_data->action = MV64XXX_I2C_ACTION_CONTINUE;419drv_data->state =420MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_DATA;421} else {422drv_data->action = MV64XXX_I2C_ACTION_SEND_DATA;423drv_data->state =424MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_ACK;425drv_data->bytes_left--;426}427} else {428if (is_first) {429drv_data->action = MV64XXX_I2C_ACTION_SEND_START;430drv_data->state =431MV64XXX_I2C_STATE_WAITING_FOR_START_COND;432} else {433drv_data->action = MV64XXX_I2C_ACTION_SEND_ADDR_1;434drv_data->state =435MV64XXX_I2C_STATE_WAITING_FOR_ADDR_1_ACK;436}437}438439drv_data->send_stop = is_last;440drv_data->block = 1;441mv64xxx_i2c_do_action(drv_data);442spin_unlock_irqrestore(&drv_data->lock, flags);443444mv64xxx_i2c_wait_for_completion(drv_data);445return drv_data->rc;446}447448/*449*****************************************************************************450*451* I2C Core Support Routines (Interface to higher level I2C code)452*453*****************************************************************************454*/455static u32456mv64xxx_i2c_functionality(struct i2c_adapter *adap)457{458return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR | I2C_FUNC_SMBUS_EMUL;459}460461static int462mv64xxx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)463{464struct mv64xxx_i2c_data *drv_data = i2c_get_adapdata(adap);465int i, rc;466467for (i = 0; i < num; i++) {468rc = mv64xxx_i2c_execute_msg(drv_data, &msgs[i],469i == 0, i + 1 == num);470if (rc < 0)471return rc;472}473474return num;475}476477static const struct i2c_algorithm mv64xxx_i2c_algo = {478.master_xfer = mv64xxx_i2c_xfer,479.functionality = mv64xxx_i2c_functionality,480};481482/*483*****************************************************************************484*485* Driver Interface & Early Init Routines486*487*****************************************************************************488*/489static int __devinit490mv64xxx_i2c_map_regs(struct platform_device *pd,491struct mv64xxx_i2c_data *drv_data)492{493int size;494struct resource *r = platform_get_resource(pd, IORESOURCE_MEM, 0);495496if (!r)497return -ENODEV;498499size = resource_size(r);500501if (!request_mem_region(r->start, size, drv_data->adapter.name))502return -EBUSY;503504drv_data->reg_base = ioremap(r->start, size);505drv_data->reg_base_p = r->start;506drv_data->reg_size = size;507508return 0;509}510511static void512mv64xxx_i2c_unmap_regs(struct mv64xxx_i2c_data *drv_data)513{514if (drv_data->reg_base) {515iounmap(drv_data->reg_base);516release_mem_region(drv_data->reg_base_p, drv_data->reg_size);517}518519drv_data->reg_base = NULL;520drv_data->reg_base_p = 0;521}522523static int __devinit524mv64xxx_i2c_probe(struct platform_device *pd)525{526struct mv64xxx_i2c_data *drv_data;527struct mv64xxx_i2c_pdata *pdata = pd->dev.platform_data;528int rc;529530if ((pd->id != 0) || !pdata)531return -ENODEV;532533drv_data = kzalloc(sizeof(struct mv64xxx_i2c_data), GFP_KERNEL);534if (!drv_data)535return -ENOMEM;536537if (mv64xxx_i2c_map_regs(pd, drv_data)) {538rc = -ENODEV;539goto exit_kfree;540}541542strlcpy(drv_data->adapter.name, MV64XXX_I2C_CTLR_NAME " adapter",543sizeof(drv_data->adapter.name));544545init_waitqueue_head(&drv_data->waitq);546spin_lock_init(&drv_data->lock);547548drv_data->freq_m = pdata->freq_m;549drv_data->freq_n = pdata->freq_n;550drv_data->irq = platform_get_irq(pd, 0);551if (drv_data->irq < 0) {552rc = -ENXIO;553goto exit_unmap_regs;554}555drv_data->adapter.dev.parent = &pd->dev;556drv_data->adapter.algo = &mv64xxx_i2c_algo;557drv_data->adapter.owner = THIS_MODULE;558drv_data->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;559drv_data->adapter.timeout = msecs_to_jiffies(pdata->timeout);560drv_data->adapter.nr = pd->id;561platform_set_drvdata(pd, drv_data);562i2c_set_adapdata(&drv_data->adapter, drv_data);563564mv64xxx_i2c_hw_init(drv_data);565566if (request_irq(drv_data->irq, mv64xxx_i2c_intr, 0,567MV64XXX_I2C_CTLR_NAME, drv_data)) {568dev_err(&drv_data->adapter.dev,569"mv64xxx: Can't register intr handler irq: %d\n",570drv_data->irq);571rc = -EINVAL;572goto exit_unmap_regs;573} else if ((rc = i2c_add_numbered_adapter(&drv_data->adapter)) != 0) {574dev_err(&drv_data->adapter.dev,575"mv64xxx: Can't add i2c adapter, rc: %d\n", -rc);576goto exit_free_irq;577}578579return 0;580581exit_free_irq:582free_irq(drv_data->irq, drv_data);583exit_unmap_regs:584mv64xxx_i2c_unmap_regs(drv_data);585exit_kfree:586kfree(drv_data);587return rc;588}589590static int __devexit591mv64xxx_i2c_remove(struct platform_device *dev)592{593struct mv64xxx_i2c_data *drv_data = platform_get_drvdata(dev);594int rc;595596rc = i2c_del_adapter(&drv_data->adapter);597free_irq(drv_data->irq, drv_data);598mv64xxx_i2c_unmap_regs(drv_data);599kfree(drv_data);600601return rc;602}603604static struct platform_driver mv64xxx_i2c_driver = {605.probe = mv64xxx_i2c_probe,606.remove = __devexit_p(mv64xxx_i2c_remove),607.driver = {608.owner = THIS_MODULE,609.name = MV64XXX_I2C_CTLR_NAME,610},611};612613static int __init614mv64xxx_i2c_init(void)615{616return platform_driver_register(&mv64xxx_i2c_driver);617}618619static void __exit620mv64xxx_i2c_exit(void)621{622platform_driver_unregister(&mv64xxx_i2c_driver);623}624625module_init(mv64xxx_i2c_init);626module_exit(mv64xxx_i2c_exit);627628MODULE_AUTHOR("Mark A. Greer <[email protected]>");629MODULE_DESCRIPTION("Marvell mv64xxx host bridge i2c ctlr driver");630MODULE_LICENSE("GPL");631632633