Path: blob/master/drivers/misc/c2port/c2port-duramar2150.c
15111 views
/*1* Silicon Labs C2 port Linux support for Eurotech Duramar 21502*3* Copyright (c) 2008 Rodolfo Giometti <[email protected]>4* Copyright (c) 2008 Eurotech S.p.A. <[email protected]>5*6* This program is free software; you can redistribute it and/or modify it7* under the terms of the GNU General Public License version 2 as published by8* the Free Software Foundation9*/1011#include <linux/errno.h>12#include <linux/init.h>13#include <linux/kernel.h>14#include <linux/module.h>15#include <linux/delay.h>16#include <linux/io.h>17#include <linux/c2port.h>1819#define DATA_PORT 0x32520#define DIR_PORT 0x32621#define C2D (1 << 0)22#define C2CK (1 << 1)2324static DEFINE_MUTEX(update_lock);2526/*27* C2 port operations28*/2930static void duramar2150_c2port_access(struct c2port_device *dev, int status)31{32u8 v;3334mutex_lock(&update_lock);3536v = inb(DIR_PORT);3738/* 0 = input, 1 = output */39if (status)40outb(v | (C2D | C2CK), DIR_PORT);41else42/* When access is "off" is important that both lines are set43* as inputs or hi-impedance */44outb(v & ~(C2D | C2CK), DIR_PORT);4546mutex_unlock(&update_lock);47}4849static void duramar2150_c2port_c2d_dir(struct c2port_device *dev, int dir)50{51u8 v;5253mutex_lock(&update_lock);5455v = inb(DIR_PORT);5657if (dir)58outb(v & ~C2D, DIR_PORT);59else60outb(v | C2D, DIR_PORT);6162mutex_unlock(&update_lock);63}6465static int duramar2150_c2port_c2d_get(struct c2port_device *dev)66{67return inb(DATA_PORT) & C2D;68}6970static void duramar2150_c2port_c2d_set(struct c2port_device *dev, int status)71{72u8 v;7374mutex_lock(&update_lock);7576v = inb(DATA_PORT);7778if (status)79outb(v | C2D, DATA_PORT);80else81outb(v & ~C2D, DATA_PORT);8283mutex_unlock(&update_lock);84}8586static void duramar2150_c2port_c2ck_set(struct c2port_device *dev, int status)87{88u8 v;8990mutex_lock(&update_lock);9192v = inb(DATA_PORT);9394if (status)95outb(v | C2CK, DATA_PORT);96else97outb(v & ~C2CK, DATA_PORT);9899mutex_unlock(&update_lock);100}101102static struct c2port_ops duramar2150_c2port_ops = {103.block_size = 512, /* bytes */104.blocks_num = 30, /* total flash size: 15360 bytes */105106.access = duramar2150_c2port_access,107.c2d_dir = duramar2150_c2port_c2d_dir,108.c2d_get = duramar2150_c2port_c2d_get,109.c2d_set = duramar2150_c2port_c2d_set,110.c2ck_set = duramar2150_c2port_c2ck_set,111};112113static struct c2port_device *duramar2150_c2port_dev;114115/*116* Module stuff117*/118119static int __init duramar2150_c2port_init(void)120{121struct resource *res;122int ret = 0;123124res = request_region(0x325, 2, "c2port");125if (!res)126return -EBUSY;127128duramar2150_c2port_dev = c2port_device_register("uc",129&duramar2150_c2port_ops, NULL);130if (!duramar2150_c2port_dev) {131ret = -ENODEV;132goto free_region;133}134135return 0;136137free_region:138release_region(0x325, 2);139return ret;140}141142static void __exit duramar2150_c2port_exit(void)143{144/* Setup the GPIOs as input by default (access = 0) */145duramar2150_c2port_access(duramar2150_c2port_dev, 0);146147c2port_device_unregister(duramar2150_c2port_dev);148149release_region(0x325, 2);150}151152module_init(duramar2150_c2port_init);153module_exit(duramar2150_c2port_exit);154155MODULE_AUTHOR("Rodolfo Giometti <[email protected]>");156MODULE_DESCRIPTION("Silicon Labs C2 port Linux support for Duramar 2150");157MODULE_LICENSE("GPL");158159160