195d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller/* display7seg.c - Driver implementation for the 7-segment display 295d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller * present on Sun Microsystems CP1400 and CP1500 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (c) 2000 Eric Brower (ebrower@usa.net) 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/fs.h> 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h> 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/major.h> 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/miscdevice.h> 14fb911ee849756fc6c609dddded92d9207ff3fb29Peter Osterlund#include <linux/ioport.h> /* request_region */ 155a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 16a3108ca2323dec0f6321c3f7706cdaed51f694eaArnd Bergmann#include <linux/mutex.h> 1795d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller#include <linux/of.h> 1895d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller#include <linux/of_device.h> 1960063497a95e716c9a689af3be2687d261f115b4Arun Sharma#include <linux/atomic.h> 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h> /* put_/get_user */ 213049f89df13bb8f5ded8737631a6c2dd6209b5caDavid S. Miller#include <asm/io.h> 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/display7seg.h> 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define D7S_MINOR 193 2695d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller#define DRIVER_NAME "d7s" 2795d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller#define PFX DRIVER_NAME ": " 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 29a3108ca2323dec0f6321c3f7706cdaed51f694eaArnd Bergmannstatic DEFINE_MUTEX(d7s_mutex); 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sol_compat = 0; /* Solaris compatibility mode */ 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Solaris compatibility flag - 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The Solaris implementation omits support for several 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * documented driver features (ref Sun doc 806-0180-03). 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * By default, this module supports the documented driver 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * abilities, rather than the Solaris implementation: 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1) Device ALWAYS reverts to OBP-specified FLIPPED mode 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * upon closure of device or module unload. 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2) Device ioctls D7SIOCRD/D7SIOCWR honor toggling of 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FLIP bit 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If you wish the device to operate as under Solaris, 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * omitting above features, set this parameter to non-zero. 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4695d4390579e02e168a14f19506fbadd30daffcedDavid S. Millermodule_param(sol_compat, int, 0); 4795d4390579e02e168a14f19506fbadd30daffcedDavid S. MillerMODULE_PARM_DESC(sol_compat, 4895d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller "Disables documented functionality omitted from Solaris driver"); 4995d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller 5095d4390579e02e168a14f19506fbadd30daffcedDavid S. MillerMODULE_AUTHOR("Eric Brower <ebrower@usa.net>"); 5195d4390579e02e168a14f19506fbadd30daffcedDavid S. MillerMODULE_DESCRIPTION("7-Segment Display driver for Sun Microsystems CP1400/1500"); 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 5395d4390579e02e168a14f19506fbadd30daffcedDavid S. MillerMODULE_SUPPORTED_DEVICE("d7s"); 5495d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller 5595d4390579e02e168a14f19506fbadd30daffcedDavid S. Millerstruct d7s { 5695d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller void __iomem *regs; 5795d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller bool flipped; 5895d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller}; 5995d4390579e02e168a14f19506fbadd30daffcedDavid S. Millerstruct d7s *d7s_device; 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Register block address- see header for details 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ----------------------------------------- 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * | DP | ALARM | FLIP | 4 | 3 | 2 | 1 | 0 | 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ----------------------------------------- 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * DP - Toggles decimal point on/off 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ALARM - Toggles "Alarm" LED green/red 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FLIP - Inverts display for upside-down mounted board 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * bits 0-4 - 7-segment display contents 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic atomic_t d7s_users = ATOMIC_INIT(0); 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int d7s_open(struct inode *inode, struct file *f) 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (D7S_MINOR != iminor(inode)) 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_inc(&d7s_users); 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int d7s_release(struct inode *inode, struct file *f) 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Reset flipped state to OBP default only if 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * no other users have the device open and we 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * are not operating in solaris-compat mode 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (atomic_dec_and_test(&d7s_users) && !sol_compat) { 8995d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller struct d7s *p = d7s_device; 9095d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller u8 regval = 0; 9195d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller 9295d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller regval = readb(p->regs); 9395d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller if (p->flipped) 9495d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller regval |= D7S_FLIP; 9595d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller else 9695d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller regval &= ~D7S_FLIP; 9795d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller writeb(regval, p->regs); 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1031d5d00bd9c44ab4730d353ee6ba0c8ebbff295c7Christoph Hellwigstatic long d7s_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10595d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller struct d7s *p = d7s_device; 10695d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller u8 regs = readb(p->regs); 107a5aac37f1cdbbd1e587fc618e778ddae124e5ac3Andrew Morton int error = 0; 10895d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller u8 ireg = 0; 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1107fa95f726aba6033d7baffcfda484c31b8cfe153Josef Sipek if (D7S_MINOR != iminor(file->f_path.dentry->d_inode)) 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 113a3108ca2323dec0f6321c3f7706cdaed51f694eaArnd Bergmann mutex_lock(&d7s_mutex); 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (cmd) { 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case D7SIOCWR: 11695d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller /* assign device register values we mask-out D7S_FLIP 11795d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller * if in sol_compat mode 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1191d5d00bd9c44ab4730d353ee6ba0c8ebbff295c7Christoph Hellwig if (get_user(ireg, (int __user *) arg)) { 1201d5d00bd9c44ab4730d353ee6ba0c8ebbff295c7Christoph Hellwig error = -EFAULT; 1211d5d00bd9c44ab4730d353ee6ba0c8ebbff295c7Christoph Hellwig break; 1221d5d00bd9c44ab4730d353ee6ba0c8ebbff295c7Christoph Hellwig } 12395d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller if (sol_compat) { 12495d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller if (regs & D7S_FLIP) 12595d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller ireg |= D7S_FLIP; 12695d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller else 12795d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller ireg &= ~D7S_FLIP; 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12995d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller writeb(ireg, p->regs); 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case D7SIOCRD: 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* retrieve device register values 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NOTE: Solaris implementation returns D7S_FLIP bit 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * as toggled by user, even though it does not honor it. 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This driver will not misinform you about the state 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * of your hardware while in sol_compat mode 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1391d5d00bd9c44ab4730d353ee6ba0c8ebbff295c7Christoph Hellwig if (put_user(regs, (int __user *) arg)) { 1401d5d00bd9c44ab4730d353ee6ba0c8ebbff295c7Christoph Hellwig error = -EFAULT; 1411d5d00bd9c44ab4730d353ee6ba0c8ebbff295c7Christoph Hellwig break; 1421d5d00bd9c44ab4730d353ee6ba0c8ebbff295c7Christoph Hellwig } 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case D7SIOCTM: 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* toggle device mode-- flip display orientation */ 14795d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller if (regs & D7S_FLIP) 14895d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller regs &= ~D7S_FLIP; 14995d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller else 15095d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller regs |= D7S_FLIP; 15195d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller writeb(regs, p->regs); 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }; 154a3108ca2323dec0f6321c3f7706cdaed51f694eaArnd Bergmann mutex_unlock(&d7s_mutex); 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1561d5d00bd9c44ab4730d353ee6ba0c8ebbff295c7Christoph Hellwig return error; 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15900977a59b951207d38380c75f03a36829950265cArjan van de Venstatic const struct file_operations d7s_fops = { 1601d5d00bd9c44ab4730d353ee6ba0c8ebbff295c7Christoph Hellwig .owner = THIS_MODULE, 1611d5d00bd9c44ab4730d353ee6ba0c8ebbff295c7Christoph Hellwig .unlocked_ioctl = d7s_ioctl, 1621d5d00bd9c44ab4730d353ee6ba0c8ebbff295c7Christoph Hellwig .compat_ioctl = d7s_ioctl, 1631d5d00bd9c44ab4730d353ee6ba0c8ebbff295c7Christoph Hellwig .open = d7s_open, 1641d5d00bd9c44ab4730d353ee6ba0c8ebbff295c7Christoph Hellwig .release = d7s_release, 1656038f373a3dc1f1c26496e60b6c40b164716f07eArnd Bergmann .llseek = noop_llseek, 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16895d4390579e02e168a14f19506fbadd30daffcedDavid S. Millerstatic struct miscdevice d7s_miscdev = { 16995d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller .minor = D7S_MINOR, 17095d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller .name = DRIVER_NAME, 17195d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller .fops = &d7s_fops 17295d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller}; 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1744ebb24f707187196937607c60810d42f7112d7aaGrant Likelystatic int __devinit d7s_probe(struct platform_device *op) 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 17695d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller struct device_node *opts; 17795d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller int err = -EINVAL; 17895d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller struct d7s *p; 17995d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller u8 regs; 18095d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller 18195d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller if (d7s_device) 18295d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller goto out; 18395d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller 18495d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller p = kzalloc(sizeof(*p), GFP_KERNEL); 18595d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller err = -ENOMEM; 18695d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller if (!p) 18795d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller goto out; 18895d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller 18995d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller p->regs = of_ioremap(&op->resource[0], 0, sizeof(u8), "d7s"); 19095d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller if (!p->regs) { 19195d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller printk(KERN_ERR PFX "Cannot map chip registers\n"); 19295d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller goto out_free; 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19595d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller err = misc_register(&d7s_miscdev); 19695d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller if (err) { 19795d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller printk(KERN_ERR PFX "Unable to acquire miscdevice minor %i\n", 19895d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller D7S_MINOR); 19995d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller goto out_iounmap; 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20295d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller /* OBP option "d7s-flipped?" is honored as default for the 20395d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller * device, and reset default when detached 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 20595d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller regs = readb(p->regs); 20695d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller opts = of_find_node_by_path("/options"); 20795d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller if (opts && 20895d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller of_get_property(opts, "d7s-flipped?", NULL)) 20995d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller p->flipped = true; 21095d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller 21195d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller if (p->flipped) 21295d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller regs |= D7S_FLIP; 21395d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller else 21495d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller regs &= ~D7S_FLIP; 21595d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller 21695d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller writeb(regs, p->regs); 21795d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller 2183f4528d6e91cffde49894f5252e6657d420d3d74Sam Ravnborg printk(KERN_INFO PFX "7-Segment Display%s at [%s:0x%llx] %s\n", 21961c7a080a5a061c976988fd4b844dfb468dda255Grant Likely op->dev.of_node->full_name, 22095d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller (regs & D7S_FLIP) ? " (FLIPPED)" : "", 22195d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller op->resource[0].start, 22295d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller sol_compat ? "in sol_compat mode" : ""); 22395d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller 22495d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller dev_set_drvdata(&op->dev, p); 22595d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller d7s_device = p; 22695d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller err = 0; 22795d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller 22895d4390579e02e168a14f19506fbadd30daffcedDavid S. Millerout: 22995d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller return err; 23095d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller 23195d4390579e02e168a14f19506fbadd30daffcedDavid S. Millerout_iounmap: 23295d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller of_iounmap(&op->resource[0], p->regs, sizeof(u8)); 23395d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller 23495d4390579e02e168a14f19506fbadd30daffcedDavid S. Millerout_free: 23595d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller kfree(p); 23695d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller goto out; 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2392dc11581376829303b98eadb2de253bee065a56aGrant Likelystatic int __devexit d7s_remove(struct platform_device *op) 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 24195d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller struct d7s *p = dev_get_drvdata(&op->dev); 24295d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller u8 regs = readb(p->regs); 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Honor OBP d7s-flipped? unless operating in solaris-compat mode */ 24595d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller if (sol_compat) { 24695d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller if (p->flipped) 24795d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller regs |= D7S_FLIP; 24895d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller else 24995d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller regs &= ~D7S_FLIP; 25095d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller writeb(regs, p->regs); 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds misc_deregister(&d7s_miscdev); 25495d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller of_iounmap(&op->resource[0], p->regs, sizeof(u8)); 25595d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller kfree(p); 25695d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller 25795d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller return 0; 25895d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller} 25995d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller 260fd098316ef533e8441576f020ead4beab93154ceDavid S. Millerstatic const struct of_device_id d7s_match[] = { 26195d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller { 26295d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller .name = "display7seg", 26395d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller }, 26495d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller {}, 26595d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller}; 26695d4390579e02e168a14f19506fbadd30daffcedDavid S. MillerMODULE_DEVICE_TABLE(of, d7s_match); 26795d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller 2684ebb24f707187196937607c60810d42f7112d7aaGrant Likelystatic struct platform_driver d7s_driver = { 2694018294b53d1dae026880e45f174c1cc63b5d435Grant Likely .driver = { 2704018294b53d1dae026880e45f174c1cc63b5d435Grant Likely .name = DRIVER_NAME, 2714018294b53d1dae026880e45f174c1cc63b5d435Grant Likely .owner = THIS_MODULE, 2724018294b53d1dae026880e45f174c1cc63b5d435Grant Likely .of_match_table = d7s_match, 2734018294b53d1dae026880e45f174c1cc63b5d435Grant Likely }, 27495d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller .probe = d7s_probe, 27595d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller .remove = __devexit_p(d7s_remove), 27695d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller}; 27795d4390579e02e168a14f19506fbadd30daffcedDavid S. Miller 278dbf2b92d54e73e4a2524b90d29bd498ecc4aa593Axel Linmodule_platform_driver(d7s_driver); 279