int whitebox_user_source_produce(struct whitebox_user_source *user_source, size_t count) { d_printk(1, "user_source_buf_head was %08x, buf_size is %08lx\n", user_source->buf.head, user_source->buf_size); user_source->buf.head = (user_source->buf.head + count) & (user_source->buf_size - 4); d_printk(1, "head moved up %zu to %08x\n", count, user_source->buf.head); user_source->off += count; return 0; }
int whitebox_user_source_alloc(struct whitebox_user_source *user_source, unsigned long buf_addr) { // alloc circ buffer user_source->buf_size = PAGE_SIZE << user_source->order; user_source->buf.buf = (char*)buf_addr; if (!user_source->buf.buf) { d_printk(0, "failed to create port buffer\n"); return -ENOMEM; } d_printk(4, "%08lx\n", (unsigned long)user_source->buf.buf); user_source->buf.head = 0; user_source->buf.tail = 0; return 0; }
/* * Device open */ static int rcubusc_open(struct inode *inode, struct file *file) { int ret = 0; /* * One process at a time */ if (rcubusc_lock ++ > 0) { ret = -EBUSY; goto Done; } /* * Increment the module use counter */ try_module_get(THIS_MODULE); /* * Do open-time calculations */ rcubusc_end = rcubusc_str + strlen(rcubusc_str); Done: d_printk(2, "lock=%d\n", rcubusc_lock); return ret; }
static int __init rcubusc_init_module(void) { int ret = 0; /* * check that the user has supplied a correct major number */ if (rcubusc_major == 0) { printk(KERN_ALERT "%s: rcubusc_major can't be 0\n", __func__); ret = -EINVAL; goto Done; } /* * Register device */ ret = register_chrdev(rcubusc_major, rcubusc_name, &rcubusc_fops); if (ret < 0) { printk(KERN_ALERT "%s: registering device %s with major %d " "failed with %d\n", __func__, rcubusc_name, rcubusc_major, ret); goto Done; } Done: d_printk(1, "name=%s,major=%d\n", rcubusc_name, rcubusc_major); return ret; }
/* * Hardware shutdown of the I2C controller * @param c controller data structure */ static void i2c_stm32_hw_release(struct i2c_stm32 *c) { unsigned int v; /* * Disable the controller */ writel(readl(&I2C_STM32(c)->cr1) & ~I2C_STM32_CR1_PE, &I2C_STM32(c)->cr1); /* * Put the I2C controller into reset. * Disable clock to the I2C controller. */ if (c->bus == 0) { /* I2C1 */ v = readl(&STM32_RCC->apb1rstr); writel(v | RCC_APB1RSTR_I2C1, &STM32_RCC->apb1rstr); v = readl(&STM32_RCC->apb1enr); writel(v & ~RCC_APB1ENR_I2C1, &STM32_RCC->apb1enr); } else if (c->bus == 1) { /* I2C2 */ v = readl(&STM32_RCC->apb1rstr); writel(v | RCC_APB1RSTR_I2C2, &STM32_RCC->apb1rstr); v = readl(&STM32_RCC->apb1enr); writel(v & ~RCC_APB1ENR_I2C2, &STM32_RCC->apb1enr); } else if (c->bus == 2) { /* I2C3 */ v = readl(&STM32_RCC->apb1rstr); writel(v | RCC_APB1RSTR_I2C3, &STM32_RCC->apb1rstr); v = readl(&STM32_RCC->apb1enr); writel(v & ~RCC_APB1ENR_I2C3, &STM32_RCC->apb1enr); } d_printk(2, "bus=%d\n", c->bus); }
static void __exit rcubusc_cleanup_module(void) { /* * Unregister device */ unregister_chrdev(rcubusc_major, rcubusc_name); d_printk(1, "%s\n", "clean-up successful"); }
/* * Driver init */ static int __init i2c_stm32_module_init(void) { int ret; ret = platform_driver_register(&i2c_stm32_drv); d_printk(1, "drv=%s,ret=%d\n", i2c_stm32_drv.driver.name, ret); return ret; }
/* * Kernel module closure */ static void __exit envm_cleanup_module(void) { /* * Unregister device */ misc_deregister(&envm_dev); d_printk(1, "%s\n", "clean-up successful"); }
size_t whitebox_user_source_data_total(struct whitebox_user_source *user_source) { long head, tail, data; head = ACCESS_ONCE(user_source->buf.head); tail = user_source->buf.tail; data = CIRC_CNT(head, tail, user_source->buf_size); d_printk(3, "%ld\n", data); return data; }
size_t whitebox_user_source_space_available(struct whitebox_user_source *user_source, unsigned long *dest) { long tail, head, space; head = user_source->buf.head; tail = ACCESS_ONCE(user_source->buf.tail); space = CIRC_SPACE_TO_END(head, tail, user_source->buf_size) & ~3; *dest = (unsigned long)user_source->buf.buf + head; d_printk(7, "%ld\n", space); return space; }
size_t whitebox_user_source_data_available(struct whitebox_user_source *user_source, unsigned long *src) { long head, tail, data; head = ACCESS_ONCE(user_source->buf.head); tail = user_source->buf.tail; data = CIRC_CNT_TO_END(head, tail, user_source->buf_size); d_printk(7, "%ld\n", data); *src = (long)user_source->buf.buf + tail; return data; }
int whitebox_user_source_work(struct whitebox_user_source *user_source, unsigned long src, size_t src_count, unsigned long dest, size_t dest_count) { size_t count = min(src_count, dest_count); d_printk(1, "src=%08lx src_count=%zu dest=%08lx dest_count=%zu\n", src, src_count, dest, dest_count); /*d_printk(1, "values... %08x %08x %08x %08x\n", (u32)*(src + 0), (u32)*(src + 4), (u32)*(src + 8), (u32)*(src + 12));*/ if (!atomic_read(user_source->mapped)) { if (copy_from_user((void*)dest, (void*)src, count) != 0) { d_printk(0, "failed to copy data from user\n"); return -EFAULT; } } return (int)count; }
static int whitebox_release(struct inode* inode, struct file* filp) { struct whitebox_user_source *user_source = &whitebox_device->user_source; struct whitebox_rf_sink *rf_sink = &whitebox_device->rf_sink; struct whitebox_user_sink *user_sink = &whitebox_device->user_sink; struct whitebox_rf_source *rf_source = &whitebox_device->rf_source; d_printk(2, "whitebox release\n"); if (atomic_read(&use_count) != 1) { d_printk(0, "Device not in use"); return -ENOENT; } if (whitebox_device->state == WDS_TX || whitebox_device->state == WDS_TX_STREAMING) { while (tx_stop(whitebox_device) < 0) cpu_relax(); } if (whitebox_device->state == WDS_RX || whitebox_device->state == WDS_RX_STREAMING) { while (rx_stop(whitebox_device) < 0) cpu_relax(); } // Turn off LO whitebox_device->adf4351_regs[2] |= WA_PD_MASK; whitebox_gpio_adf4351_write(whitebox_device->platform_data, whitebox_device->adf4351_regs[2]); // Disable DAC whitebox_gpio_dac_disable(whitebox_device->platform_data); whitebox_rf_sink_free(rf_sink); whitebox_user_source_free(user_source); whitebox_rf_source_free(rf_source); whitebox_user_sink_free(user_sink); atomic_dec(&use_count); return 0; }
/* * Device close */ static int rcubusc_release(struct inode *inode, struct file *file) { /* * Release device */ rcubusc_lock = 0; /* * Decrement module use counter */ module_put(THIS_MODULE); d_printk(2, "lock=%d\n", rcubusc_lock); return 0; }
/* * Device close */ static int envm_release(struct inode *inode, struct file *file) { /* * Release device. Other processes can use it now. */ envm_lock = 0; /* * Decrement module use counter */ module_put(THIS_MODULE); d_printk(2, "lock=%d\n", envm_lock); return 0; }
/* * An auxilary service that performs a read or write access */ static ssize_t envm_read_or_write( int do_read, struct file *filp, char *buffer, size_t length, loff_t * offset) { unsigned int size; unsigned int len = 0; unsigned int addr = 0; int ret = 0; /* * Check that the user has supplied a valid buffer */ if (! access_ok(0, buffer, length)) { /* * TO-DO: is this the right errno? */ ret = -EINVAL; goto Done; } //addr = envm_base + *offset; addr = envm_base + filp->f_pos; size = mss_envm_size(); /* * Check for an EOF condition. */ if (addr >= size) { ret = 0; goto Done; } /* * Access the required or remaining number of bytes. */ len = addr + length < size ? length : size - addr; ret = do_read ? mss_envm_read(addr, buffer, len) : mss_envm_write(addr, buffer, len); *offset += ret; Done: d_printk(3, "do_r=%d,off=%x,addr=%x,len=%d,l=%d,ret=%d\n", do_read, (uint) *offset, addr, length, len, ret); return ret; }
/* * Device write */ static ssize_t rcubusc_write(struct file *filp, const char *buffer, size_t length, loff_t * offset) { int iResult=0; u32 lPos=0; //u32 u32Offset=0; u32 u32Count= 0; u32* pu32Target=NULL; u32 u32WriteAddress=0; if (filp==NULL) { return -EFAULT; } lPos=filp->f_pos; u32Count=length; u32WriteAddress=lPos; /* 1. Set target to mode register */ pu32Target = ADDR_REG + (MODE_REG)/sizeof(u32); dcs_write((u32)pu32Target, 1, &MODE); /* Set mode */ /* 2. Set target to address register */ pu32Target = ADDR_REG; dcs_write((u32)pu32Target, 2, &u32WriteAddress); /* Set mode */ /* 3. Write data into data out register */ pu32Target = ADDR_REG + (DATA_OUT_REG)/sizeof(u32); dcs_write((u32)pu32Target, u32Count, (u32*)buffer); /* 4. Check if Command mode */ if(MODE == COMMAND_MODE){ d_printk(1, "Command mode"); pu32Target = ADDR_REG + (CSR_REG)/sizeof(u32); dcs_write((u32)pu32Target, 1, &WRITE_CMD); } iResult=(int)u32Count; /* d_printk(3, "length=%d\n", length); */ return iResult; }
/* * Device open */ static int envm_open(struct inode *inode, struct file *file) { int ret = 0; /* * One process at a time */ if (envm_lock ++ > 0) { ret = -EBUSY; goto Done; } /* * Increment the module use counter */ try_module_get(THIS_MODULE); Done: d_printk(2, "lock=%d\n", envm_lock); return ret; }
void d_printk_loop(int level) { unsigned long src; struct circ_buf *mock_buf = &whitebox_device->mock_buf; struct whitebox_user_sink *user_sink = &whitebox_device->user_sink; struct whitebox_user_source *user_source = &whitebox_device->user_source; struct whitebox_rf_sink *rf_sink = &whitebox_device->rf_sink; struct whitebox_rf_source *rf_source = &whitebox_device->rf_source; u32 exciter_state = rf_sink->exciter->ops->get_state(rf_sink->exciter); u32 receiver_state = rf_source->receiver->ops->get_state(rf_source->receiver); d_printk(level, "stats %c%c user_source_data/space=%d/%d rf_sink_space=%d mock_data/space=%d/%d rf_source_data=%d user_sink_data/space=%d/%d\n", exciter_state & WES_TXEN ? 'T' : ' ', receiver_state & WRS_RXEN ? 'R' : ' ', whitebox_user_source_data_available(user_source, &src), whitebox_user_source_space_available(user_source, &src), whitebox_rf_sink_space_available(rf_sink, &src), CIRC_CNT_TO_END(mock_buf->head, mock_buf->tail, PAGE_SIZE << whitebox_mock_order), CIRC_SPACE_TO_END(mock_buf->head, mock_buf->tail, PAGE_SIZE << whitebox_mock_order), whitebox_rf_source_data_available(rf_source, &src), whitebox_user_sink_data_available(user_sink, &src), whitebox_user_sink_space_available(user_sink, &src)); }
/* * Initialize the kernel module */ static int __init envm_init_module(void) { int ret = 0; /* * Check that envm_base is within the eNVM region */ if (! (0 <= envm_base && envm_base < mss_envm_size())) { printk(KERN_ALERT "%s: envm_base out of range: %lx\n", __func__, envm_base); ret = -EINVAL; goto Done; } /* * Prepare the eNVM */ mss_envm_init(); /* * Register device */ ret = misc_register(&envm_dev); if (ret) { printk(KERN_ALERT "%s: registering device %s with minor %d " "failed with %d\n", __func__, ENVM_NAME, A2F_ENVM_MINOR, ret); goto Done; } Done: d_printk(1, "size=%lx,base=%lx,name=%s,minor=%d\n", mss_envm_size(), envm_base, ENVM_NAME, A2F_ENVM_MINOR); return ret; }
/* * Shutdown of an instance of the controller device * @dev I2C controller platform device * @returns 0->success, <0->error code */ static int __devexit i2c_stm32_remove(struct platform_device *dev) { struct i2c_stm32 *c = platform_get_drvdata(dev); int ret = 0; /* * Shut the hardware down */ i2c_stm32_hw_release(c); /* * Release kernel resources. */ platform_set_drvdata(dev, NULL); i2c_del_adapter(&c->adap); free_irq(c->irq, c); free_irq(c->irq + 1, c); iounmap(c->regs); release_mem_region(c->regs_base, c->regs_size); kfree(c); d_printk(1, "dev=%s,ret=%d\n", dev_name(&dev->dev), ret); return ret; }
/* * Instantiate a new instance of the I2C controller * @dev I2C controller platform device * @returns 0->success, <0->error code */ static int __devinit i2c_stm32_probe(struct platform_device *dev) { struct i2c_stm32 *c = NULL; struct i2c_stm32_data *d; struct resource *regs; int bus; int irq; int ret = 0; /* * Get the bus # from the platform device: */ bus = dev->id; if (! (0 <= bus && bus <= 2)) { dev_err(&dev->dev, "invalid bus number %d\n", bus); ret = -ENXIO; goto Error_release_nothing; } /* * Get the IRQ number from the platform device */ irq = platform_get_irq(dev, 0); if (irq < 0) { dev_err(&dev->dev, "invalid IRQ number %d\n", irq); ret = irq; goto Error_release_nothing; } /* * Get the register base from the platform device */ regs = platform_get_resource(dev, IORESOURCE_MEM, 0); if (!regs) { dev_err(&dev->dev, "no register base provided\n"); ret = -ENXIO; goto Error_release_nothing; } /* * Allocate the controller-private data structure */ c = kzalloc(sizeof(struct i2c_stm32), GFP_KERNEL); if (!c) { dev_err(&dev->dev, "unable to allocate memory\n"); ret = -ENOMEM; goto Error_release_nothing; } c->dev = dev; c->bus = bus; /* * Request a memory region for the CSR block */ if (!request_mem_region(regs->start, resource_size(regs), regs->name)) { dev_err(&dev->dev, "registers already in use\n"); ret = -ENOMEM; goto Error_release_memory; } c->regs_base = regs->start; c->regs_size = resource_size(regs); /* * Map in the CSR block */ c->regs = ioremap(regs->start, resource_size(regs)); if (!c->regs) { dev_err(&dev->dev, "unable to map registers\n"); ret = -EINVAL; goto Error_release_mem_region; } /* * Register interrupt handler for events */ ret = request_irq(irq, i2c_stm32_irq, 0, dev_name(&dev->dev), c); if (ret) { dev_err(&dev->dev, "request for IRQ %d failed\n", irq); goto Error_release_regs; } disable_irq_nosync(irq); c->irq = irq; /* * Register interrupt handler for errors */ ret = request_irq(irq + 1, i2c_stm32_irq, 0, dev_name(&dev->dev), c); if (ret) { dev_err(&dev->dev, "request for IRQ %d failed\n", irq + 1); goto Error_release_irq1; } /* * Retrieve the private parameters */ d = (struct i2c_stm32_data *) platform_get_drvdata(dev); c->ref_clk = d->ref_clk; c->i2c_clk = d->i2c_clk; /* * Link the private data to dev */ platform_set_drvdata(dev, c); /* * Initialize the I2C adapter data structure */ c->adap.owner = THIS_MODULE; c->adap.nr = bus; snprintf(c->adap.name, sizeof(c->adap.name), "i2c_stm32.%u", bus); c->adap.algo = &i2c_stm32_algorithm; c->adap.algo_data = c; c->adap.dev.parent = &dev->dev; /* * Initialize the controller hardware */ ret = i2c_stm32_hw_init(c); if (ret) { goto Error_release_irq2; } /* * Set up the wait queue */ init_waitqueue_head(&c->wait); /* * Register the I2C adapter */ if (i2c_add_numbered_adapter(&c->adap)) { dev_err(&dev->dev, "unable to add adapter\n"); ret = -ENXIO; goto Error_release_hw; } /* * If we are here, we are successful */ dev_info(&dev->dev, "I2C Controller %s at %p,irq=%d\n", dev_name(&c->adap.dev), c->regs, c->irq); goto Done; /* * Error processing */ Error_release_hw: i2c_stm32_hw_release(c); Error_release_irq2: free_irq(c->irq + 1, c); Error_release_irq1: free_irq(c->irq, c); Error_release_regs: iounmap(c->regs); Error_release_mem_region: release_mem_region(regs->start, resource_size(regs)); Error_release_memory: kfree(c); platform_set_drvdata(dev, NULL); Error_release_nothing: Done: d_printk(1, "dev=%s,regs=%p,irq=%d,ref_clk=%d,i2c_clk=%d,ret=%d\n", dev_name(&dev->dev), c ? c->regs : NULL, c ? c->irq : 0, c ? c->ref_clk : 0, c ? c->i2c_clk : 0, ret); return ret; }
static void whitebox_mmap_close(struct vm_area_struct *vma) { struct whitebox_device *wb = (struct whitebox_device*)vma->vm_private_data; d_printk(4, "\n"); atomic_dec(&wb->mapped); }
/* * Hardware initialization of the I2C controller * @param c controller data structure * @returns 0->success, <0->error code */ static int i2c_stm32_hw_init(struct i2c_stm32 *c) { unsigned int v; int ret = 0; /* * First, figure out if we are able to configure the clocks * If not, we want to bail out without enabling enything. */ if (c->i2c_clk != 100000) { dev_err(&c->dev->dev, "bus clock %d not supported\n", c->i2c_clk); ret = -ENXIO; goto Done; } /* * Reset the I2C controller and then bring it out of reset. * Enable the I2C controller clock. */ if (c->bus == 0) { /* I2C1 */ v = readl(&STM32_RCC->apb1rstr); writel(v | RCC_APB1RSTR_I2C1, &STM32_RCC->apb1rstr); writel(v & ~RCC_APB1RSTR_I2C1, &STM32_RCC->apb1rstr); v = readl(&STM32_RCC->apb1enr); writel(v | RCC_APB1ENR_I2C1, &STM32_RCC->apb1enr); } else if (c->bus == 1) { /* I2C2 */ v = readl(&STM32_RCC->apb1rstr); writel(v | RCC_APB1RSTR_I2C2, &STM32_RCC->apb1rstr); writel(v & ~RCC_APB1RSTR_I2C2, &STM32_RCC->apb1rstr); v = readl(&STM32_RCC->apb1enr); writel(v | RCC_APB1ENR_I2C2, &STM32_RCC->apb1enr); } else if (c->bus == 2) { /* I2C3 */ v = readl(&STM32_RCC->apb1rstr); writel(v | RCC_APB1RSTR_I2C3, &STM32_RCC->apb1rstr); writel(v & ~RCC_APB1RSTR_I2C3, &STM32_RCC->apb1rstr); v = readl(&STM32_RCC->apb1enr); writel(v | RCC_APB1ENR_I2C3, &STM32_RCC->apb1enr); } /* * Reset the controller to clear possible errors or locks */ writel(v | I2C_STM32_CR1_SWRST, &I2C_STM32(c)->cr1); writel(v & ~I2C_STM32_CR1_SWRST, &I2C_STM32(c)->cr1); /* * Set the clocks. * The following is valid only for Standard Mode (100Khz). */ v = c->ref_clk / MHZ(1); writel(I2C_STM32_CR2_FREQ(v), &I2C_STM32(c)->cr2); writel(I2C_STM32_TRISE_TRISE(v + 1), &I2C_STM32(c)->trise); v = c->ref_clk / (c->i2c_clk << 1); v = v < 0x04 ? 0x04 : v; writel(I2C_STM32_CCR_CCR(v), &I2C_STM32(c)->ccr); /* * Enable hardware interrupts, including for error conditions */ v = readl(&I2C_STM32(c)->cr2); writel(v | I2C_STM32_CR2_ITBUFEN | I2C_STM32_CR2_ITEVTEN | I2C_STM32_CR2_ITERREN, &I2C_STM32(c)->cr2); /* * Enable the I2C controller */ v = 0; writel(v | I2C_STM32_CR1_PE, &I2C_STM32(c)->cr1); Done: d_printk(2, "bus=%d," "cr1=0x%x,cr2=0x%x,sr1=0x%x,ccr=0x%x,trise=0x%x,ret=%d\n", c->bus, !ret ? readl(&I2C_STM32(c)->cr1) : 0, !ret ? readl(&I2C_STM32(c)->cr2) : 0, !ret ? readl(&I2C_STM32(c)->sr1) : 0, !ret ? readl(&I2C_STM32(c)->ccr) : 0, !ret ? readl(&I2C_STM32(c)->trise) : 0, ret); return ret; }
/* * Reset the I2C controller to known state * @param c controller data structure * @returns 0->success, <0->error code */ static inline void i2c_stm32_hw_clear(struct i2c_stm32 *c) { d_printk(3, "ok\n"); }
/* * Interrupt handler routine * @param irq IRQ number * @param d controller data structure * @returns IRQ handler exit code */ static irqreturn_t i2c_stm32_irq(int irq, void *d) { struct i2c_stm32 *c = (struct i2c_stm32 *) d; unsigned int cr1 = readl(&I2C_STM32(c)->cr1); unsigned int sr1 = readl(&I2C_STM32(c)->sr1); unsigned int sr2 = 0; int disable_intr = 0; irqreturn_t ret = IRQ_HANDLED; /* * Check if there is an interrupt event * pending at the controller. Bail out if there is none. * It does happen sometimes for some reason. */ if (!sr1) { ret = IRQ_NONE; goto Done; } /* * Implement the state machine defined by the I2C controller */ if (sr1 & I2C_STM32_SR1_SB) { /* * Remove the start condition */ writel(cr1 & ~I2C_STM32_CR1_STA, &I2C_STM32(c)->cr1); /* * Start sent -> send out addr and direction */ writel((c->msg->addr << 1) | (c->msg->flags & I2C_M_RD ? 1 : 0), &I2C_STM32(c)->dr); } else if (sr1 & I2C_STM32_SR1_AF) { /* * No ack -> let's stop and report a failure */ writel(sr1 & ~I2C_STM32_SR1_AF, &I2C_STM32(c)->sr1); c->msg_status = -ENODEV; disable_intr = 1; } else if ((sr1 & I2C_STM32_SR1_ADDR) || (sr1 & I2C_STM32_SR1_TXE) || (sr1 & I2C_STM32_SR1_BTF) || (sr1 & I2C_STM32_SR1_RXNE)) { /* * There is a pecularity in the hardware controller that * TXE can be set while BTF is not. Wait until BTF sets. * TO-DO: This is terribly bad of course. Waiting in an ISR * is out of question. Need to fix that somehow. */ while (sr1 == I2C_STM32_SR1_TXE) { sr1 = readl(&I2C_STM32(c)->sr1); } /* * Slave has acknowledged the address * or byte transfer has finished. * * If this is the master receiver mode, it is important * to set/reset ACK before clearing the interrupt condition: * * Will be receiving the last byte from the slave. * Return NACK to tell the slave to stop sending. */ if (c->msg_i + 1 == c->msg->len) { writel(cr1 & ~I2C_STM32_CR1_ACK, &I2C_STM32(c)->cr1); } /* * Will be receiving more data from the slave. * Return ACK to tell the slave to send more. */ else { writel(cr1 | I2C_STM32_CR1_ACK, &I2C_STM32(c)->cr1); } /* * Clear the interrupt condition */ sr2 = readl(&I2C_STM32(c)->sr2); /* * Depending on the direction, enter * transmitter or receiver mode. */ if (sr2 & I2C_STM32_SR2_TRA) { /* * This is the master transmiter mode: * If there is more data to send, send it. */ if (c->msg_i < c->msg->len) { writel(c->msg->buf[(c->msg_i)++], &I2C_STM32(c)->dr); } /* * If this is last transfer in the message, * report success. */ else if (--(c->msg_n) == 0) { c->msg_status = 0; disable_intr = 1; } /* * This is not the last transfer in the message. * Advance to the next segment and * initate a repeated start. */ else { c->msg++; c->msg_i = 0; writel(cr1 | I2C_STM32_CR1_STA, &I2C_STM32(c)->cr1); } } else if (sr1 & I2C_STM32_SR1_RXNE) { /* * This is the master receiver mode: * Retrieve the data. */ c->msg->buf[c->msg_i++] = readl(&I2C_STM32(c)->dr); /* * More data to get. Get out of IRQ and wait * for a next interrupt. */ if (c->msg_i < c->msg->len) { } /* * If this is last transfer in the message, * report success. */ else if (--(c->msg_n) == 0) { c->msg_status = 0; disable_intr = 1; } /* * This is not the last transfer in the message. * Advance to the next segment * and initate a repeated start. */ else { c->msg++; c->msg_i = 0; writel(cr1 | I2C_STM32_CR1_STA, &I2C_STM32(c)->cr1); } } } else { /* * Some error condition -> let's stop and report a failure */ c->msg_status = -EIO; disable_intr = 1; } /* * If the current transfer is done, disable interrupts */ if (disable_intr) { disable_irq_nosync(c->irq); } /* * Exit on failure or all bytes have been transferred */ if (c->msg_status != -EBUSY) { /* * Clear the interrupt condition */ i2c_stm32_hw_clear(c); wake_up(&c->wait); } Done: d_printk(4, "sr1=0x%x,sr2=0x%x,ret=%d\n", sr1, sr2, ret); return ret; }
/* * Adapter transfer callback * @param a I2C adapter * @param m array of messages * @param n number of messages * @returns message segments transferred or error code (<1) */ static int i2c_stm32_transfer(struct i2c_adapter *a, struct i2c_msg *m, int n) { #if defined(I2C_STM32_DEBUG) int i, j; #endif struct i2c_stm32 *c = a->algo_data; int ret = 0; /* * Store the software parameters of the message. * These will be used by the IRQ handler. */ c->msg = &m[0]; c->msg_i = 0; c->msg_n = n; c->msg_status = -EBUSY; /* * Reset the bus to a known state */ i2c_stm32_hw_clear(c); /* * A transfer is kicked off by initiating a start condition. * Actual transfer is handled by the state machine implemented * in the IRQ routine. */ writel(readl(&I2C_STM32(c)->cr1) | I2C_STM32_CR1_STA, &I2C_STM32(c)->cr1); /* * Let interrupts happen */ enable_irq(c->irq); /* * Wait for the transfer to complete, one way or another */ if (wait_event_timeout(c->wait, c->msg_status != -EBUSY, 5*HZ) == 0) { disable_irq_nosync(c->irq); ret = -ETIMEDOUT; } else { ret = c->msg_status; if (!ret) { ret = n; } } /* * Stop activity on the bus */ writel(readl(&I2C_STM32(c)->cr1) | I2C_STM32_CR1_STO, &I2C_STM32(c)->cr1); #if defined(I2C_STM32_DEBUG) for (i = 0; i < n; i++) { d_printk(4, "%d:flags=0x%x,addr=0x%x,len=%d\n", i, m[i].flags, m[i].addr, m[i].len); for (j = 0; j < m[i].len; j++) { d_printk(4, "%d=%x\n", j, m[i].buf[j]); } } #endif d_printk(3, "n=%d,ret=%d\n", n, ret); return ret; }
/* * Device read */ static ssize_t rcubusc_read(struct file *filp, char *buffer, size_t length, loff_t * offset) { /*Init*/ unsigned int len = 0; int ret = 0; u32 u32Count=0; u32 lPos=0; u32 u32ReadAddress = 0; u32* pu32Target = NULL; /* * Check that the user has supplied a valid buffer */ if (! access_ok(0, buffer, length)) { ret = -EINVAL; goto Done; } /* Set */ lPos = filp->f_pos; u32ReadAddress = lPos; u32Count = length; /* New scheme 1. write to mode register 2. write address into ADDR_REG 3. if command mode, write command to CSR register 4. read results from DATA_IN_REG */ /* 1. Set target to mode register */ pu32Target = ADDR_REG + (MODE_REG)/sizeof(u32); dcs_write((u32)pu32Target, 1, &MODE); /* Set mode */ /* 2. Set target to address register */ pu32Target = ADDR_REG; dcs_write((u32)pu32Target, 2, &u32ReadAddress); /* 3. Check if Command mode */ if(MODE == COMMAND_MODE){ d_printk(1, "Command mode"); pu32Target = ADDR_REG + (CSR_REG)/sizeof(u32); dcs_write((u32)pu32Target, 1, &READ_CMD); } /* 4. Read DATA_IN_REG */ pu32Target = ADDR_REG + (DATA_IN_REG)/sizeof(u32); dcs_read((u32)pu32Target, u32Count, (u32*) buffer); /* d_printk(0, "read data=0x%x (address = %p)\n", *buffer, pu32Source); */ ///////////////////////////////// // strncpy(buffer, addr, len); // *offset += len; len = (int)u32Count; ret = len; Done: /* d_printk(0, "length=%d,len=%d,ret=%d\n", length, len, ret); */ return ret; }
/* * Adapter functionality callback * @param a I2C adapter * @returns OR-ed functionality flags */ static unsigned int i2c_stm32_functionality(struct i2c_adapter *a) { d_printk(3, "ok\n" ); return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; }
/* * Driver clean-up */ static void __exit i2c_stm32_module_exit(void) { platform_driver_unregister(&i2c_stm32_drv); d_printk(1, "drv=%s\n", i2c_stm32_drv.driver.name); }