Esempio n. 1
0
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;
}
Esempio n. 2
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;
}
Esempio n. 3
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;
}
Esempio n. 4
0
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);
}
Esempio n. 6
0
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;
}
Esempio n. 8
0
/*
 * Kernel module closure
 */
static void __exit envm_cleanup_module(void)
{
    /*
     * Unregister device
     */
    misc_deregister(&envm_dev);

    d_printk(1, "%s\n", "clean-up successful");
}
Esempio n. 9
0
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;
}
Esempio n. 10
0
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;
}
Esempio n. 11
0
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;
}
Esempio n. 12
0
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;
}
Esempio n. 13
0
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;
}
Esempio n. 14
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;
}
Esempio n. 15
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;
}
Esempio n. 16
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;
}
Esempio n. 17
0
/* 
 * 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;
}
Esempio n. 18
0
/*
 * 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;
}
Esempio n. 19
0
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));
}
Esempio n. 20
0
/*
 * 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;
}
Esempio n. 21
0
/*
 * 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;
}
Esempio n. 22
0
/*
 * 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;
}
Esempio n. 23
0
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);
}
Esempio n. 24
0
/*
 * 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;
}
Esempio n. 25
0
/*
 * 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"); 
}
Esempio n. 26
0
/*
 * 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;
}
Esempio n. 27
0
/*
 * 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;
}
Esempio n. 28
0
/* 
 * 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;
}
Esempio n. 29
0
/*
 * 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;
}
Esempio n. 30
0
/*
 * 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);
}