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

ks0108.c (4181B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 *    Filename: ks0108.c
      4 *     Version: 0.1.0
      5 * Description: ks0108 LCD Controller driver
      6 *     Depends: parport
      7 *
      8 *      Author: Copyright (C) Miguel Ojeda <ojeda@kernel.org>
      9 *        Date: 2006-10-31
     10 */
     11
     12#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
     13
     14#include <linux/init.h>
     15#include <linux/module.h>
     16#include <linux/kernel.h>
     17#include <linux/delay.h>
     18#include <linux/parport.h>
     19#include <linux/ks0108.h>
     20
     21#define KS0108_NAME "ks0108"
     22
     23/*
     24 * Module Parameters
     25 */
     26
     27static unsigned int ks0108_port = CONFIG_KS0108_PORT;
     28module_param(ks0108_port, uint, 0444);
     29MODULE_PARM_DESC(ks0108_port, "Parallel port where the LCD is connected");
     30
     31static unsigned int ks0108_delay = CONFIG_KS0108_DELAY;
     32module_param(ks0108_delay, uint, 0444);
     33MODULE_PARM_DESC(ks0108_delay, "Delay between each control writing (microseconds)");
     34
     35/*
     36 * Device
     37 */
     38
     39static struct parport *ks0108_parport;
     40static struct pardevice *ks0108_pardevice;
     41
     42/*
     43 * ks0108 Exported Commands (don't lock)
     44 *
     45 *   You _should_ lock in the top driver: This functions _should not_
     46 *   get race conditions in any way. Locking for each byte here would be
     47 *   so slow and useless.
     48 *
     49 *   There are not bit definitions because they are not flags,
     50 *   just arbitrary combinations defined by the documentation for each
     51 *   function in the ks0108 LCD controller. If you want to know what means
     52 *   a specific combination, look at the function's name.
     53 *
     54 *   The ks0108_writecontrol bits need to be reverted ^(0,1,3) because
     55 *   the parallel port also revert them using a "not" logic gate.
     56 */
     57
     58#define bit(n) (((unsigned char)1)<<(n))
     59
     60void ks0108_writedata(unsigned char byte)
     61{
     62	parport_write_data(ks0108_parport, byte);
     63}
     64
     65void ks0108_writecontrol(unsigned char byte)
     66{
     67	udelay(ks0108_delay);
     68	parport_write_control(ks0108_parport, byte ^ (bit(0) | bit(1) | bit(3)));
     69}
     70
     71void ks0108_displaystate(unsigned char state)
     72{
     73	ks0108_writedata((state ? bit(0) : 0) | bit(1) | bit(2) | bit(3) | bit(4) | bit(5));
     74}
     75
     76void ks0108_startline(unsigned char startline)
     77{
     78	ks0108_writedata(min_t(unsigned char, startline, 63) | bit(6) |
     79			 bit(7));
     80}
     81
     82void ks0108_address(unsigned char address)
     83{
     84	ks0108_writedata(min_t(unsigned char, address, 63) | bit(6));
     85}
     86
     87void ks0108_page(unsigned char page)
     88{
     89	ks0108_writedata(min_t(unsigned char, page, 7) | bit(3) | bit(4) |
     90			 bit(5) | bit(7));
     91}
     92
     93EXPORT_SYMBOL_GPL(ks0108_writedata);
     94EXPORT_SYMBOL_GPL(ks0108_writecontrol);
     95EXPORT_SYMBOL_GPL(ks0108_displaystate);
     96EXPORT_SYMBOL_GPL(ks0108_startline);
     97EXPORT_SYMBOL_GPL(ks0108_address);
     98EXPORT_SYMBOL_GPL(ks0108_page);
     99
    100/*
    101 * Is the module inited?
    102 */
    103
    104static unsigned char ks0108_inited;
    105unsigned char ks0108_isinited(void)
    106{
    107	return ks0108_inited;
    108}
    109EXPORT_SYMBOL_GPL(ks0108_isinited);
    110
    111static void ks0108_parport_attach(struct parport *port)
    112{
    113	struct pardev_cb ks0108_cb;
    114
    115	if (port->base != ks0108_port)
    116		return;
    117
    118	memset(&ks0108_cb, 0, sizeof(ks0108_cb));
    119	ks0108_cb.flags = PARPORT_DEV_EXCL;
    120	ks0108_pardevice = parport_register_dev_model(port, KS0108_NAME,
    121						      &ks0108_cb, 0);
    122	if (!ks0108_pardevice) {
    123		pr_err("ERROR: parport didn't register new device\n");
    124		return;
    125	}
    126	if (parport_claim(ks0108_pardevice)) {
    127		pr_err("could not claim access to parport %i. Aborting.\n",
    128		       ks0108_port);
    129		goto err_unreg_device;
    130	}
    131
    132	ks0108_parport = port;
    133	ks0108_inited = 1;
    134	return;
    135
    136err_unreg_device:
    137	parport_unregister_device(ks0108_pardevice);
    138	ks0108_pardevice = NULL;
    139}
    140
    141static void ks0108_parport_detach(struct parport *port)
    142{
    143	if (port->base != ks0108_port)
    144		return;
    145
    146	if (!ks0108_pardevice) {
    147		pr_err("%s: already unregistered.\n", KS0108_NAME);
    148		return;
    149	}
    150
    151	parport_release(ks0108_pardevice);
    152	parport_unregister_device(ks0108_pardevice);
    153	ks0108_pardevice = NULL;
    154	ks0108_parport = NULL;
    155}
    156
    157/*
    158 * Module Init & Exit
    159 */
    160
    161static struct parport_driver ks0108_parport_driver = {
    162	.name = "ks0108",
    163	.match_port = ks0108_parport_attach,
    164	.detach = ks0108_parport_detach,
    165	.devmodel = true,
    166};
    167module_parport_driver(ks0108_parport_driver);
    168
    169MODULE_LICENSE("GPL v2");
    170MODULE_AUTHOR("Miguel Ojeda <ojeda@kernel.org>");
    171MODULE_DESCRIPTION("ks0108 LCD Controller driver");
    172