devices/ccat/update.c
branchstable-1.5
changeset 2567 d70aad2f131f
parent 2565 f7b06b264646
child 2569 720172a7563f
equal deleted inserted replaced
2566:0f39e1e7b288 2567:d70aad2f131f
    59 	size_t size;
    59 	size_t size;
    60 };
    60 };
    61 
    61 
    62 static void ccat_wait_status_cleared(void __iomem * const ioaddr);
    62 static void ccat_wait_status_cleared(void __iomem * const ioaddr);
    63 static int ccat_read_flash(void __iomem * const ioaddr, char __user * buf,
    63 static int ccat_read_flash(void __iomem * const ioaddr, char __user * buf,
    64 			   uint32_t len, loff_t * off);
    64 			   u32 len, loff_t * off);
    65 static void ccat_write_flash(const struct update_buffer *const buf);
    65 static void ccat_write_flash(const struct update_buffer *const buf);
    66 static void ccat_update_cmd(void __iomem * const ioaddr, uint8_t cmd,
    66 static void ccat_update_cmd(void __iomem * const ioaddr, u8 cmd, u16 clocks);
    67 			    uint16_t clocks);
       
    68 static void ccat_update_destroy(struct kref *ref);
    67 static void ccat_update_destroy(struct kref *ref);
    69 
    68 
    70 /**
    69 /**
    71  * wait_until_busy_reset() - wait until the busy flag was reset
    70  * wait_until_busy_reset() - wait until the busy flag was reset
    72  * @ioaddr: address of the CCAT Update function in PCI config space
    71  * @ioaddr: address of the CCAT Update function in PCI config space
    82 static int ccat_update_open(struct inode *const i, struct file *const f)
    81 static int ccat_update_open(struct inode *const i, struct file *const f)
    83 {
    82 {
    84 	struct ccat_update *update =
    83 	struct ccat_update *update =
    85 	    container_of(i->i_cdev, struct ccat_update, cdev);
    84 	    container_of(i->i_cdev, struct ccat_update, cdev);
    86 	struct update_buffer *buf;
    85 	struct update_buffer *buf;
       
    86 
    87 	kref_get(&update->refcount);
    87 	kref_get(&update->refcount);
    88 	if (atomic_read(&update->refcount.refcount) > 2) {
    88 	if (atomic_read(&update->refcount.refcount) > 2) {
    89 		kref_put(&update->refcount, ccat_update_destroy);
    89 		kref_put(&update->refcount, ccat_update_destroy);
    90 		return -EBUSY;
    90 		return -EBUSY;
    91 	}
    91 	}
   103 
   103 
   104 static int ccat_update_release(struct inode *const i, struct file *const f)
   104 static int ccat_update_release(struct inode *const i, struct file *const f)
   105 {
   105 {
   106 	const struct update_buffer *const buf = f->private_data;
   106 	const struct update_buffer *const buf = f->private_data;
   107 	struct ccat_update *const update = buf->update;
   107 	struct ccat_update *const update = buf->update;
       
   108 
   108 	if (buf->size > 0) {
   109 	if (buf->size > 0) {
   109 		ccat_update_cmd(update->ioaddr, CCAT_WRITE_ENABLE);
   110 		ccat_update_cmd(update->ioaddr, CCAT_WRITE_ENABLE);
   110 		ccat_update_cmd(update->ioaddr, CCAT_BULK_ERASE);
   111 		ccat_update_cmd(update->ioaddr, CCAT_BULK_ERASE);
   111 		ccat_wait_status_cleared(update->ioaddr);
   112 		ccat_wait_status_cleared(update->ioaddr);
   112 		ccat_write_flash(buf);
   113 		ccat_write_flash(buf);
   131  */
   132  */
   132 static ssize_t ccat_update_read(struct file *const f, char __user * buf,
   133 static ssize_t ccat_update_read(struct file *const f, char __user * buf,
   133 				size_t len, loff_t * off)
   134 				size_t len, loff_t * off)
   134 {
   135 {
   135 	struct update_buffer *update = f->private_data;
   136 	struct update_buffer *update = f->private_data;
       
   137 
   136 	if (!buf || !off) {
   138 	if (!buf || !off) {
   137 		return -EINVAL;
   139 		return -EINVAL;
   138 	}
   140 	}
   139 	if (*off >= CCAT_FLASH_SIZE) {
   141 	if (*off >= CCAT_FLASH_SIZE) {
   140 		return 0;
   142 		return 0;
   160 
   162 
   161 static ssize_t ccat_update_write(struct file *const f, const char __user * buf,
   163 static ssize_t ccat_update_write(struct file *const f, const char __user * buf,
   162 				 size_t len, loff_t * off)
   164 				 size_t len, loff_t * off)
   163 {
   165 {
   164 	struct update_buffer *const update = f->private_data;
   166 	struct update_buffer *const update = f->private_data;
       
   167 
   165 	if (*off + len > sizeof(update->data))
   168 	if (*off + len > sizeof(update->data))
   166 		return 0;
   169 		return 0;
   167 
   170 
   168 	if (copy_from_user(update->data + *off, buf, len)) {
   171 	if (copy_from_user(update->data + *off, buf, len)) {
   169 		return -EFAULT;
   172 		return -EFAULT;
   188  * @cmd: the command identifier
   191  * @cmd: the command identifier
   189  * @clocks: the number of clocks associated with the specified command
   192  * @clocks: the number of clocks associated with the specified command
   190  *
   193  *
   191  * no write memory barrier is called and the busy flag is not evaluated
   194  * no write memory barrier is called and the busy flag is not evaluated
   192  */
   195  */
   193 static inline void __ccat_update_cmd(void __iomem * const ioaddr, uint8_t cmd,
   196 static inline void __ccat_update_cmd(void __iomem * const ioaddr, u8 cmd,
   194 				     uint16_t clocks)
   197 				     u16 clocks)
   195 {
   198 {
   196 	iowrite8((0xff00 & clocks) >> 8, ioaddr);
   199 	iowrite8((0xff00 & clocks) >> 8, ioaddr);
   197 	iowrite8(0x00ff & clocks, ioaddr + 0x8);
   200 	iowrite8(0x00ff & clocks, ioaddr + 0x8);
   198 	iowrite8(cmd, ioaddr + 0x10);
   201 	iowrite8(cmd, ioaddr + 0x10);
   199 }
   202 }
   205  * @clocks: the number of clocks associated with the specified command
   208  * @clocks: the number of clocks associated with the specified command
   206  *
   209  *
   207  * Triggers a full flash command cycle with write memory barrier and
   210  * Triggers a full flash command cycle with write memory barrier and
   208  * command activate. This call blocks until the busy flag is reset.
   211  * command activate. This call blocks until the busy flag is reset.
   209  */
   212  */
   210 static inline void ccat_update_cmd(void __iomem * const ioaddr, uint8_t cmd,
   213 static inline void ccat_update_cmd(void __iomem * const ioaddr, u8 cmd,
   211 				   uint16_t clocks)
   214 				   u16 clocks)
   212 {
   215 {
   213 	__ccat_update_cmd(ioaddr, cmd, clocks);
   216 	__ccat_update_cmd(ioaddr, cmd, clocks);
   214 	wmb();
   217 	wmb();
   215 	iowrite8(0xff, ioaddr + 0x7f8);
   218 	iowrite8(0xff, ioaddr + 0x7f8);
   216 	wait_until_busy_reset(ioaddr);
   219 	wait_until_busy_reset(ioaddr);
   225  *
   228  *
   226  * Triggers a full flash command cycle with write memory barrier and
   229  * Triggers a full flash command cycle with write memory barrier and
   227  * command activate. This call blocks until the busy flag is reset.
   230  * command activate. This call blocks until the busy flag is reset.
   228  */
   231  */
   229 static inline void ccat_update_cmd_addr(void __iomem * const ioaddr,
   232 static inline void ccat_update_cmd_addr(void __iomem * const ioaddr,
   230 					uint8_t cmd, uint16_t clocks,
   233 					u8 cmd, u16 clocks, u32 addr)
   231 					uint32_t addr)
   234 {
   232 {
   235 	const u8 addr_0 = SWAP_BITS(addr & 0xff);
   233 	const uint8_t addr_0 = SWAP_BITS(addr & 0xff);
   236 	const u8 addr_1 = SWAP_BITS((addr & 0xff00) >> 8);
   234 	const uint8_t addr_1 = SWAP_BITS((addr & 0xff00) >> 8);
   237 	const u8 addr_2 = SWAP_BITS((addr & 0xff0000) >> 16);
   235 	const uint8_t addr_2 = SWAP_BITS((addr & 0xff0000) >> 16);
   238 
   236 	__ccat_update_cmd(ioaddr, cmd, clocks);
   239 	__ccat_update_cmd(ioaddr, cmd, clocks);
   237 	iowrite8(addr_2, ioaddr + 0x18);
   240 	iowrite8(addr_2, ioaddr + 0x18);
   238 	iowrite8(addr_1, ioaddr + 0x20);
   241 	iowrite8(addr_1, ioaddr + 0x20);
   239 	iowrite8(addr_0, ioaddr + 0x28);
   242 	iowrite8(addr_0, ioaddr + 0x28);
   240 	wmb();
   243 	wmb();
   246  * ccat_get_prom_id() - Read CCAT PROM ID
   249  * ccat_get_prom_id() - Read CCAT PROM ID
   247  * @ioaddr: address of the CCAT Update function in PCI config space
   250  * @ioaddr: address of the CCAT Update function in PCI config space
   248  *
   251  *
   249  * Return: the CCAT FPGA's PROM identifier
   252  * Return: the CCAT FPGA's PROM identifier
   250  */
   253  */
   251 uint8_t ccat_get_prom_id(void __iomem * const ioaddr)
   254 u8 ccat_get_prom_id(void __iomem * const ioaddr)
   252 {
   255 {
   253 	ccat_update_cmd(ioaddr, CCAT_GET_PROM_ID);
   256 	ccat_update_cmd(ioaddr, CCAT_GET_PROM_ID);
   254 	return ioread8(ioaddr + 0x38);
   257 	return ioread8(ioaddr + 0x38);
   255 }
   258 }
   256 
   259 
   258  * ccat_get_status() - Read CCAT Update status
   261  * ccat_get_status() - Read CCAT Update status
   259  * @ioaddr: address of the CCAT Update function in PCI config space
   262  * @ioaddr: address of the CCAT Update function in PCI config space
   260  *
   263  *
   261  * Return: the current status of the CCAT Update function
   264  * Return: the current status of the CCAT Update function
   262  */
   265  */
   263 static uint8_t ccat_get_status(void __iomem * const ioaddr)
   266 static u8 ccat_get_status(void __iomem * const ioaddr)
   264 {
   267 {
   265 	ccat_update_cmd(ioaddr, CCAT_READ_STATUS);
   268 	ccat_update_cmd(ioaddr, CCAT_READ_STATUS);
   266 	return ioread8(ioaddr + 0x20);
   269 	return ioread8(ioaddr + 0x20);
   267 }
   270 }
   268 
   271 
   270  * ccat_wait_status_cleared() - wait until CCAT status is cleared
   273  * ccat_wait_status_cleared() - wait until CCAT status is cleared
   271  * @ioaddr: address of the CCAT Update function in PCI config space
   274  * @ioaddr: address of the CCAT Update function in PCI config space
   272  *
   275  *
   273  * Blocks until bit 7 of the CCAT Update status is reset
   276  * Blocks until bit 7 of the CCAT Update status is reset
   274  */
   277  */
   275 
       
   276 static void ccat_wait_status_cleared(void __iomem * const ioaddr)
   278 static void ccat_wait_status_cleared(void __iomem * const ioaddr)
   277 {
   279 {
   278 	uint8_t status;
   280 	u8 status;
       
   281 
   279 	do {
   282 	do {
   280 		status = ccat_get_status(ioaddr);
   283 		status = ccat_get_status(ioaddr);
   281 	} while (status & (1 << 7));
   284 	} while (status & (1 << 7));
   282 }
   285 }
   283 
   286 
   294  * is very possible that the overall buffer ends with a lot of 0xff.
   297  * is very possible that the overall buffer ends with a lot of 0xff.
   295  *
   298  *
   296  * Return: the number of bytes copied
   299  * Return: the number of bytes copied
   297  */
   300  */
   298 static int ccat_read_flash_block(void __iomem * const ioaddr,
   301 static int ccat_read_flash_block(void __iomem * const ioaddr,
   299 				 const uint32_t addr, const uint16_t len,
   302 				 const u32 addr, const u16 len,
   300 				 char __user * const buf)
   303 				 char __user * const buf)
   301 {
   304 {
   302 	uint16_t i;
   305 	u16 i;
   303 	const uint16_t clocks = 8 * len;
   306 	const u16 clocks = 8 * len;
       
   307 
   304 	ccat_update_cmd_addr(ioaddr, CCAT_READ_FLASH + clocks, addr);
   308 	ccat_update_cmd_addr(ioaddr, CCAT_READ_FLASH + clocks, addr);
   305 	for (i = 0; i < len; i++) {
   309 	for (i = 0; i < len; i++) {
   306 		put_user(ioread8(ioaddr + CCAT_DATA_IN_4 + 8 * i), buf + i);
   310 		put_user(ioread8(ioaddr + CCAT_DATA_IN_4 + 8 * i), buf + i);
   307 	}
   311 	}
   308 	return len;
   312 	return len;
   319  * flash to the user space buffer.
   323  * flash to the user space buffer.
   320  *
   324  *
   321  * Return: the number of bytes copied
   325  * Return: the number of bytes copied
   322  */
   326  */
   323 static int ccat_read_flash(void __iomem * const ioaddr, char __user * buf,
   327 static int ccat_read_flash(void __iomem * const ioaddr, char __user * buf,
   324 			   uint32_t len, loff_t * off)
   328 			   u32 len, loff_t * off)
   325 {
   329 {
   326 	const loff_t start = *off;
   330 	const loff_t start = *off;
       
   331 
   327 	while (len > CCAT_DATA_BLOCK_SIZE) {
   332 	while (len > CCAT_DATA_BLOCK_SIZE) {
   328 		*off +=
   333 		*off +=
   329 		    ccat_read_flash_block(ioaddr, *off, CCAT_DATA_BLOCK_SIZE,
   334 		    ccat_read_flash_block(ioaddr, *off, CCAT_DATA_BLOCK_SIZE,
   330 					  buf);
   335 					  buf);
   331 		buf += CCAT_DATA_BLOCK_SIZE;
   336 		buf += CCAT_DATA_BLOCK_SIZE;
   345  * Copies one block of configuration data to the CCAT FPGA's flash
   350  * Copies one block of configuration data to the CCAT FPGA's flash
   346  *
   351  *
   347  * Return: the number of bytes copied
   352  * Return: the number of bytes copied
   348  */
   353  */
   349 static int ccat_write_flash_block(void __iomem * const ioaddr,
   354 static int ccat_write_flash_block(void __iomem * const ioaddr,
   350 				  const uint32_t addr, const uint16_t len,
   355 				  const u32 addr, const u16 len,
   351 				  const char *const buf)
   356 				  const char *const buf)
   352 {
   357 {
   353 	const uint16_t clocks = 8 * len;
   358 	const u16 clocks = 8 * len;
   354 	uint16_t i;
   359 	u16 i;
       
   360 
   355 	ccat_update_cmd(ioaddr, CCAT_WRITE_ENABLE);
   361 	ccat_update_cmd(ioaddr, CCAT_WRITE_ENABLE);
   356 	for (i = 0; i < len; i++) {
   362 	for (i = 0; i < len; i++) {
   357 		iowrite8(buf[i], ioaddr + CCAT_DATA_OUT_4 + 8 * i);
   363 		iowrite8(buf[i], ioaddr + CCAT_DATA_OUT_4 + 8 * i);
   358 	}
   364 	}
   359 	ccat_update_cmd_addr(ioaddr, CCAT_WRITE_FLASH + clocks, addr);
   365 	ccat_update_cmd_addr(ioaddr, CCAT_WRITE_FLASH + clocks, addr);
   366  * @update: a CCAT Update buffer containing the new FPGA configuration
   372  * @update: a CCAT Update buffer containing the new FPGA configuration
   367  */
   373  */
   368 static void ccat_write_flash(const struct update_buffer *const update)
   374 static void ccat_write_flash(const struct update_buffer *const update)
   369 {
   375 {
   370 	const char *buf = update->data;
   376 	const char *buf = update->data;
   371 	uint32_t off = 0;
   377 	u32 off = 0;
   372 	size_t len = update->size;
   378 	size_t len = update->size;
       
   379 
   373 	while (len > CCAT_WRITE_BLOCK_SIZE) {
   380 	while (len > CCAT_WRITE_BLOCK_SIZE) {
   374 		ccat_write_flash_block(update->update->ioaddr, off,
   381 		ccat_write_flash_block(update->update->ioaddr, off,
   375 				       (uint16_t) CCAT_WRITE_BLOCK_SIZE, buf);
   382 				       (u16) CCAT_WRITE_BLOCK_SIZE, buf);
   376 		off += CCAT_WRITE_BLOCK_SIZE;
   383 		off += CCAT_WRITE_BLOCK_SIZE;
   377 		buf += CCAT_WRITE_BLOCK_SIZE;
   384 		buf += CCAT_WRITE_BLOCK_SIZE;
   378 		len -= CCAT_WRITE_BLOCK_SIZE;
   385 		len -= CCAT_WRITE_BLOCK_SIZE;
   379 	}
   386 	}
   380 	ccat_write_flash_block(update->update->ioaddr, off, (uint16_t) len,
   387 	ccat_write_flash_block(update->update->ioaddr, off, (u16) len, buf);
   381 			       buf);
       
   382 }
   388 }
   383 
   389 
   384 /**
   390 /**
   385  * ccat_update_init() - Initialize the CCAT Update function
   391  * ccat_update_init() - Initialize the CCAT Update function
   386  */
   392  */
   387 struct ccat_update *ccat_update_init(const struct ccat_device *const ccatdev,
   393 struct ccat_update *ccat_update_init(const struct ccat_device *const ccatdev,
   388 				     void __iomem * const addr)
   394 				     void __iomem * const addr)
   389 {
   395 {
   390 	struct ccat_update *const update = kzalloc(sizeof(*update), GFP_KERNEL);
   396 	struct ccat_update *const update = kzalloc(sizeof(*update), GFP_KERNEL);
       
   397 
   391 	if (!update) {
   398 	if (!update) {
   392 		return NULL;
   399 		return NULL;
   393 	}
   400 	}
   394 	kref_init(&update->refcount);
   401 	kref_init(&update->refcount);
   395 	update->ioaddr = ccatdev->bar[0].ioaddr + ioread32(addr + 0x8);
   402 	update->ioaddr = ccatdev->bar[0].ioaddr + ioread32(addr + 0x8);
   441  */
   448  */
   442 static void ccat_update_destroy(struct kref *ref)
   449 static void ccat_update_destroy(struct kref *ref)
   443 {
   450 {
   444 	struct ccat_update *update =
   451 	struct ccat_update *update =
   445 	    container_of(ref, struct ccat_update, refcount);
   452 	    container_of(ref, struct ccat_update, refcount);
       
   453 
   446 	cdev_del(&update->cdev);
   454 	cdev_del(&update->cdev);
   447 	device_destroy(update->class, update->dev);
   455 	device_destroy(update->class, update->dev);
   448 	class_destroy(update->class);
   456 	class_destroy(update->class);
   449 	unregister_chrdev_region(update->dev, 1);
   457 	unregister_chrdev_region(update->dev, 1);
   450 	kfree(update);
   458 	kfree(update);