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

am300epd.c (6597B)


      1/*
      2 * am300epd.c -- Platform device for AM300 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 * This work was made possible by help and equipment support from E-Ink
     11 * Corporation. http://support.eink.com/community
     12 *
     13 * This driver is written to be used with the Broadsheet display controller.
     14 * on the AM300 EPD prototype kit/development kit with an E-Ink 800x600
     15 * Vizplex EPD on a Gumstix board using the Broadsheet interface board.
     16 *
     17 */
     18
     19#include <linux/module.h>
     20#include <linux/kernel.h>
     21#include <linux/errno.h>
     22#include <linux/string.h>
     23#include <linux/delay.h>
     24#include <linux/interrupt.h>
     25#include <linux/fb.h>
     26#include <linux/init.h>
     27#include <linux/platform_device.h>
     28#include <linux/irq.h>
     29#include <linux/gpio.h>
     30
     31#include "gumstix.h"
     32#include "mfp-pxa25x.h"
     33#include "irqs.h"
     34#include <linux/platform_data/video-pxafb.h>
     35
     36#include "generic.h"
     37
     38#include <video/broadsheetfb.h>
     39
     40static unsigned int panel_type = 6;
     41static struct platform_device *am300_device;
     42static struct broadsheet_board am300_board;
     43
     44static unsigned long am300_pin_config[] __initdata = {
     45	GPIO16_GPIO,
     46	GPIO17_GPIO,
     47	GPIO32_GPIO,
     48	GPIO48_GPIO,
     49	GPIO49_GPIO,
     50	GPIO51_GPIO,
     51	GPIO74_GPIO,
     52	GPIO75_GPIO,
     53	GPIO76_GPIO,
     54	GPIO77_GPIO,
     55
     56	/* this is the 16-bit hdb bus 58-73 */
     57	GPIO58_GPIO,
     58	GPIO59_GPIO,
     59	GPIO60_GPIO,
     60	GPIO61_GPIO,
     61
     62	GPIO62_GPIO,
     63	GPIO63_GPIO,
     64	GPIO64_GPIO,
     65	GPIO65_GPIO,
     66
     67	GPIO66_GPIO,
     68	GPIO67_GPIO,
     69	GPIO68_GPIO,
     70	GPIO69_GPIO,
     71
     72	GPIO70_GPIO,
     73	GPIO71_GPIO,
     74	GPIO72_GPIO,
     75	GPIO73_GPIO,
     76};
     77
     78/* register offsets for gpio control */
     79#define PWR_GPIO_PIN	16
     80#define CFG_GPIO_PIN	17
     81#define RDY_GPIO_PIN	32
     82#define DC_GPIO_PIN	48
     83#define RST_GPIO_PIN	49
     84#define LED_GPIO_PIN	51
     85#define RD_GPIO_PIN	74
     86#define WR_GPIO_PIN	75
     87#define CS_GPIO_PIN	76
     88#define IRQ_GPIO_PIN	77
     89
     90/* hdb bus */
     91#define DB0_GPIO_PIN	58
     92#define DB15_GPIO_PIN	73
     93
     94static int gpios[] = { PWR_GPIO_PIN, CFG_GPIO_PIN, RDY_GPIO_PIN, DC_GPIO_PIN,
     95			RST_GPIO_PIN, RD_GPIO_PIN, WR_GPIO_PIN, CS_GPIO_PIN,
     96			IRQ_GPIO_PIN, LED_GPIO_PIN };
     97static char *gpio_names[] = { "PWR", "CFG", "RDY", "DC", "RST", "RD", "WR",
     98				"CS", "IRQ", "LED" };
     99
    100static int am300_wait_event(struct broadsheetfb_par *par)
    101{
    102	/* todo: improve err recovery */
    103	wait_event(par->waitq, gpio_get_value(RDY_GPIO_PIN));
    104	return 0;
    105}
    106
    107static int am300_init_gpio_regs(struct broadsheetfb_par *par)
    108{
    109	int i;
    110	int err;
    111	char dbname[8];
    112
    113	for (i = 0; i < ARRAY_SIZE(gpios); i++) {
    114		err = gpio_request(gpios[i], gpio_names[i]);
    115		if (err) {
    116			dev_err(&am300_device->dev, "failed requesting "
    117				"gpio %s, err=%d\n", gpio_names[i], err);
    118			goto err_req_gpio;
    119		}
    120	}
    121
    122	/* we also need to take care of the hdb bus */
    123	for (i = DB0_GPIO_PIN; i <= DB15_GPIO_PIN; i++) {
    124		sprintf(dbname, "DB%d", i);
    125		err = gpio_request(i, dbname);
    126		if (err) {
    127			dev_err(&am300_device->dev, "failed requesting "
    128				"gpio %d, err=%d\n", i, err);
    129			goto err_req_gpio2;
    130		}
    131	}
    132
    133	/* setup the outputs and init values */
    134	gpio_direction_output(PWR_GPIO_PIN, 0);
    135	gpio_direction_output(CFG_GPIO_PIN, 1);
    136	gpio_direction_output(DC_GPIO_PIN, 0);
    137	gpio_direction_output(RD_GPIO_PIN, 1);
    138	gpio_direction_output(WR_GPIO_PIN, 1);
    139	gpio_direction_output(CS_GPIO_PIN, 1);
    140	gpio_direction_output(RST_GPIO_PIN, 0);
    141
    142	/* setup the inputs */
    143	gpio_direction_input(RDY_GPIO_PIN);
    144	gpio_direction_input(IRQ_GPIO_PIN);
    145
    146	/* start the hdb bus as an input */
    147	for (i = DB0_GPIO_PIN; i <= DB15_GPIO_PIN; i++)
    148		gpio_direction_output(i, 0);
    149
    150	/* go into command mode */
    151	gpio_set_value(CFG_GPIO_PIN, 1);
    152	gpio_set_value(RST_GPIO_PIN, 0);
    153	msleep(10);
    154	gpio_set_value(RST_GPIO_PIN, 1);
    155	msleep(10);
    156	am300_wait_event(par);
    157
    158	return 0;
    159
    160err_req_gpio2:
    161	while (--i >= DB0_GPIO_PIN)
    162		gpio_free(i);
    163	i = ARRAY_SIZE(gpios);
    164err_req_gpio:
    165	while (--i >= 0)
    166		gpio_free(gpios[i]);
    167
    168	return err;
    169}
    170
    171static int am300_init_board(struct broadsheetfb_par *par)
    172{
    173	return am300_init_gpio_regs(par);
    174}
    175
    176static void am300_cleanup(struct broadsheetfb_par *par)
    177{
    178	int i;
    179
    180	free_irq(PXA_GPIO_TO_IRQ(RDY_GPIO_PIN), par);
    181
    182	for (i = 0; i < ARRAY_SIZE(gpios); i++)
    183		gpio_free(gpios[i]);
    184
    185	for (i = DB0_GPIO_PIN; i <= DB15_GPIO_PIN; i++)
    186		gpio_free(i);
    187
    188}
    189
    190static u16 am300_get_hdb(struct broadsheetfb_par *par)
    191{
    192	u16 res = 0;
    193	int i;
    194
    195	for (i = 0; i <= (DB15_GPIO_PIN - DB0_GPIO_PIN) ; i++)
    196		res |= (gpio_get_value(DB0_GPIO_PIN + i)) ? (1 << i) : 0;
    197
    198	return res;
    199}
    200
    201static void am300_set_hdb(struct broadsheetfb_par *par, u16 data)
    202{
    203	int i;
    204
    205	for (i = 0; i <= (DB15_GPIO_PIN - DB0_GPIO_PIN) ; i++)
    206		gpio_set_value(DB0_GPIO_PIN + i, (data >> i) & 0x01);
    207}
    208
    209
    210static void am300_set_ctl(struct broadsheetfb_par *par, unsigned char bit,
    211				u8 state)
    212{
    213	switch (bit) {
    214	case BS_CS:
    215		gpio_set_value(CS_GPIO_PIN, state);
    216		break;
    217	case BS_DC:
    218		gpio_set_value(DC_GPIO_PIN, state);
    219		break;
    220	case BS_WR:
    221		gpio_set_value(WR_GPIO_PIN, state);
    222		break;
    223	}
    224}
    225
    226static int am300_get_panel_type(void)
    227{
    228	return panel_type;
    229}
    230
    231static irqreturn_t am300_handle_irq(int irq, void *dev_id)
    232{
    233	struct broadsheetfb_par *par = dev_id;
    234
    235	wake_up(&par->waitq);
    236	return IRQ_HANDLED;
    237}
    238
    239static int am300_setup_irq(struct fb_info *info)
    240{
    241	int ret;
    242	struct broadsheetfb_par *par = info->par;
    243
    244	ret = request_irq(PXA_GPIO_TO_IRQ(RDY_GPIO_PIN), am300_handle_irq,
    245				IRQF_TRIGGER_RISING, "AM300", par);
    246	if (ret)
    247		dev_err(&am300_device->dev, "request_irq failed: %d\n", ret);
    248
    249	return ret;
    250}
    251
    252static struct broadsheet_board am300_board = {
    253	.owner			= THIS_MODULE,
    254	.init			= am300_init_board,
    255	.cleanup		= am300_cleanup,
    256	.set_hdb		= am300_set_hdb,
    257	.get_hdb		= am300_get_hdb,
    258	.set_ctl		= am300_set_ctl,
    259	.wait_for_rdy		= am300_wait_event,
    260	.get_panel_type		= am300_get_panel_type,
    261	.setup_irq		= am300_setup_irq,
    262};
    263
    264int __init am300_init(void)
    265{
    266	int ret;
    267
    268	pxa2xx_mfp_config(ARRAY_AND_SIZE(am300_pin_config));
    269
    270	/* request our platform independent driver */
    271	request_module("broadsheetfb");
    272
    273	am300_device = platform_device_alloc("broadsheetfb", -1);
    274	if (!am300_device)
    275		return -ENOMEM;
    276
    277	/* the am300_board that will be seen by broadsheetfb is a copy */
    278	platform_device_add_data(am300_device, &am300_board,
    279					sizeof(am300_board));
    280
    281	ret = platform_device_add(am300_device);
    282
    283	if (ret) {
    284		platform_device_put(am300_device);
    285		return ret;
    286	}
    287
    288	return 0;
    289}
    290
    291module_param(panel_type, uint, 0);
    292MODULE_PARM_DESC(panel_type, "Select the panel type: 37, 6, 97");
    293
    294MODULE_DESCRIPTION("board driver for am300 epd kit");
    295MODULE_AUTHOR("Jaya Kumar");
    296MODULE_LICENSE("GPL");