cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

n411.c (5018B)


      1/*
      2 * linux/drivers/video/n411.c -- Platform device for N411 EPD kit
      3 *
      4 * Copyright (C) 2008, Jaya Kumar
      5 *
      6 * This file is subject to the terms and conditions of the GNU General Public
      7 * License. See the file COPYING in the main directory of this archive for
      8 * more details.
      9 *
     10 * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
     11 *
     12 * This driver is written to be used with the Hecuba display controller
     13 * board, and tested with the EInk 800x600 display in 1 bit mode.
     14 * The interface between Hecuba and the host is TTL based GPIO. The
     15 * GPIO requirements are 8 writable data lines and 6 lines for control.
     16 * Only 4 of the controls are actually used here but 6 for future use.
     17 * The driver requires the IO addresses for data and control GPIO at
     18 * load time. It is also possible to use this display with a standard
     19 * PC parallel port.
     20 *
     21 * General notes:
     22 * - User must set dio_addr=0xIOADDR cio_addr=0xIOADDR c2io_addr=0xIOADDR
     23 *
     24 */
     25
     26#include <linux/module.h>
     27#include <linux/kernel.h>
     28#include <linux/errno.h>
     29#include <linux/string.h>
     30#include <linux/delay.h>
     31#include <linux/interrupt.h>
     32#include <linux/fb.h>
     33#include <linux/init.h>
     34#include <linux/platform_device.h>
     35#include <linux/list.h>
     36#include <linux/uaccess.h>
     37#include <linux/irq.h>
     38
     39#include <video/hecubafb.h>
     40
     41static unsigned long dio_addr;
     42static unsigned long cio_addr;
     43static unsigned long c2io_addr;
     44static unsigned long splashval;
     45static unsigned int nosplash;
     46static unsigned char ctl;
     47
     48static void n411_set_ctl(struct hecubafb_par *par, unsigned char bit, unsigned
     49							char state)
     50{
     51	switch (bit) {
     52	case HCB_CD_BIT:
     53		if (state)
     54			ctl &= ~(HCB_CD_BIT);
     55		else
     56			ctl |= HCB_CD_BIT;
     57		break;
     58	case HCB_DS_BIT:
     59		if (state)
     60			ctl &= ~(HCB_DS_BIT);
     61		else
     62			ctl |= HCB_DS_BIT;
     63		break;
     64	}
     65	outb(ctl, cio_addr);
     66}
     67
     68static unsigned char n411_get_ctl(struct hecubafb_par *par)
     69{
     70	return inb(c2io_addr);
     71}
     72
     73static void n411_set_data(struct hecubafb_par *par, unsigned char value)
     74{
     75	outb(value, dio_addr);
     76}
     77
     78static void n411_wait_for_ack(struct hecubafb_par *par, int clear)
     79{
     80	int timeout;
     81	unsigned char tmp;
     82
     83	timeout = 500;
     84	do {
     85		tmp = n411_get_ctl(par);
     86		if ((tmp & HCB_ACK_BIT) && (!clear))
     87			return;
     88		else if (!(tmp & HCB_ACK_BIT) && (clear))
     89			return;
     90		udelay(1);
     91	} while (timeout--);
     92	printk(KERN_ERR "timed out waiting for ack\n");
     93}
     94
     95static int n411_init_control(struct hecubafb_par *par)
     96{
     97	unsigned char tmp;
     98	/* for init, we want the following setup to be set:
     99	WUP = lo
    100	ACK = hi
    101	DS = hi
    102	RW = hi
    103	CD = lo
    104	*/
    105
    106	/* write WUP to lo, DS to hi, RW to hi, CD to lo */
    107	ctl = HCB_WUP_BIT | HCB_RW_BIT | HCB_CD_BIT ;
    108	n411_set_ctl(par, HCB_DS_BIT, 1);
    109
    110	/* check ACK is not lo */
    111	tmp = n411_get_ctl(par);
    112	if (tmp & HCB_ACK_BIT) {
    113		printk(KERN_ERR "Fail because ACK is already low\n");
    114		return -ENXIO;
    115	}
    116
    117	return 0;
    118}
    119
    120
    121static int n411_init_board(struct hecubafb_par *par)
    122{
    123	int retval;
    124
    125	retval = n411_init_control(par);
    126	if (retval)
    127		return retval;
    128
    129	par->send_command(par, APOLLO_INIT_DISPLAY);
    130	par->send_data(par, 0x81);
    131
    132	/* have to wait while display resets */
    133	udelay(1000);
    134
    135	/* if we were told to splash the screen, we just clear it */
    136	if (!nosplash) {
    137		par->send_command(par, APOLLO_ERASE_DISPLAY);
    138		par->send_data(par, splashval);
    139	}
    140
    141	return 0;
    142}
    143
    144static struct hecuba_board n411_board = {
    145	.owner			= THIS_MODULE,
    146	.init			= n411_init_board,
    147	.set_ctl		= n411_set_ctl,
    148	.set_data		= n411_set_data,
    149	.wait_for_ack		= n411_wait_for_ack,
    150};
    151
    152static struct platform_device *n411_device;
    153static int __init n411_init(void)
    154{
    155	int ret;
    156	if (!dio_addr || !cio_addr || !c2io_addr) {
    157		printk(KERN_WARNING "no IO addresses supplied\n");
    158		return -EINVAL;
    159	}
    160
    161	/* request our platform independent driver */
    162	request_module("hecubafb");
    163
    164	n411_device = platform_device_alloc("hecubafb", -1);
    165	if (!n411_device)
    166		return -ENOMEM;
    167
    168	ret = platform_device_add_data(n411_device, &n411_board,
    169				       sizeof(n411_board));
    170	if (ret)
    171		goto put_plat_device;
    172
    173	/* this _add binds hecubafb to n411. hecubafb refcounts n411 */
    174	ret = platform_device_add(n411_device);
    175
    176	if (ret)
    177		goto put_plat_device;
    178
    179	return 0;
    180
    181put_plat_device:
    182	platform_device_put(n411_device);
    183	return ret;
    184}
    185
    186static void __exit n411_exit(void)
    187{
    188	platform_device_unregister(n411_device);
    189}
    190
    191module_init(n411_init);
    192module_exit(n411_exit);
    193
    194module_param(nosplash, uint, 0);
    195MODULE_PARM_DESC(nosplash, "Disable doing the splash screen");
    196module_param_hw(dio_addr, ulong, ioport, 0);
    197MODULE_PARM_DESC(dio_addr, "IO address for data, eg: 0x480");
    198module_param_hw(cio_addr, ulong, ioport, 0);
    199MODULE_PARM_DESC(cio_addr, "IO address for control, eg: 0x400");
    200module_param_hw(c2io_addr, ulong, ioport, 0);
    201MODULE_PARM_DESC(c2io_addr, "IO address for secondary control, eg: 0x408");
    202module_param(splashval, ulong, 0);
    203MODULE_PARM_DESC(splashval, "Splash pattern: 0x00 is black, 0x01 is white");
    204
    205MODULE_DESCRIPTION("board driver for n411 hecuba/apollo epd kit");
    206MODULE_AUTHOR("Jaya Kumar");
    207MODULE_LICENSE("GPL");
    208