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

cr_bllcd.c (6221B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Copyright (c) Intel Corp. 2007.
      4 * All Rights Reserved.
      5 *
      6 * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
      7 * develop this driver.
      8 *
      9 * This file is part of the Carillo Ranch video subsystem driver.
     10 *
     11 * Authors:
     12 *   Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
     13 *   Alan Hourihane <alanh-at-tungstengraphics-dot-com>
     14 */
     15
     16#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
     17
     18#include <linux/module.h>
     19#include <linux/kernel.h>
     20#include <linux/init.h>
     21#include <linux/platform_device.h>
     22#include <linux/mutex.h>
     23#include <linux/fb.h>
     24#include <linux/backlight.h>
     25#include <linux/lcd.h>
     26#include <linux/pci.h>
     27#include <linux/slab.h>
     28
     29/* The LVDS- and panel power controls sits on the
     30 * GPIO port of the ISA bridge.
     31 */
     32
     33#define CRVML_DEVICE_LPC    0x27B8
     34#define CRVML_REG_GPIOBAR   0x48
     35#define CRVML_REG_GPIOEN    0x4C
     36#define CRVML_GPIOEN_BIT    (1 << 4)
     37#define CRVML_PANEL_PORT    0x38
     38#define CRVML_LVDS_ON       0x00000001
     39#define CRVML_PANEL_ON      0x00000002
     40#define CRVML_BACKLIGHT_OFF 0x00000004
     41
     42/* The PLL Clock register sits on Host bridge */
     43#define CRVML_DEVICE_MCH   0x5001
     44#define CRVML_REG_MCHBAR   0x44
     45#define CRVML_REG_MCHEN    0x54
     46#define CRVML_MCHEN_BIT    (1 << 28)
     47#define CRVML_MCHMAP_SIZE  4096
     48#define CRVML_REG_CLOCK    0xc3c
     49#define CRVML_CLOCK_SHIFT  8
     50#define CRVML_CLOCK_MASK   0x00000f00
     51
     52static struct pci_dev *lpc_dev;
     53static u32 gpio_bar;
     54
     55struct cr_panel {
     56	struct backlight_device *cr_backlight_device;
     57	struct lcd_device *cr_lcd_device;
     58};
     59
     60static int cr_backlight_set_intensity(struct backlight_device *bd)
     61{
     62	u32 addr = gpio_bar + CRVML_PANEL_PORT;
     63	u32 cur = inl(addr);
     64
     65	if (backlight_get_brightness(bd) == 0) {
     66		/* OFF */
     67		cur |= CRVML_BACKLIGHT_OFF;
     68		outl(cur, addr);
     69	} else {
     70		/* FULL ON */
     71		cur &= ~CRVML_BACKLIGHT_OFF;
     72		outl(cur, addr);
     73	}
     74
     75	return 0;
     76}
     77
     78static int cr_backlight_get_intensity(struct backlight_device *bd)
     79{
     80	u32 addr = gpio_bar + CRVML_PANEL_PORT;
     81	u32 cur = inl(addr);
     82	u8 intensity;
     83
     84	if (cur & CRVML_BACKLIGHT_OFF)
     85		intensity = 0;
     86	else
     87		intensity = 1;
     88
     89	return intensity;
     90}
     91
     92static const struct backlight_ops cr_backlight_ops = {
     93	.get_brightness = cr_backlight_get_intensity,
     94	.update_status = cr_backlight_set_intensity,
     95};
     96
     97static void cr_panel_on(void)
     98{
     99	u32 addr = gpio_bar + CRVML_PANEL_PORT;
    100	u32 cur = inl(addr);
    101
    102	if (!(cur & CRVML_PANEL_ON)) {
    103		/* Make sure LVDS controller is down. */
    104		if (cur & 0x00000001) {
    105			cur &= ~CRVML_LVDS_ON;
    106			outl(cur, addr);
    107		}
    108		/* Power up Panel */
    109		schedule_timeout(HZ / 10);
    110		cur |= CRVML_PANEL_ON;
    111		outl(cur, addr);
    112	}
    113
    114	/* Power up LVDS controller */
    115
    116	if (!(cur & CRVML_LVDS_ON)) {
    117		schedule_timeout(HZ / 10);
    118		outl(cur | CRVML_LVDS_ON, addr);
    119	}
    120}
    121
    122static void cr_panel_off(void)
    123{
    124	u32 addr = gpio_bar + CRVML_PANEL_PORT;
    125	u32 cur = inl(addr);
    126
    127	/* Power down LVDS controller first to avoid high currents */
    128	if (cur & CRVML_LVDS_ON) {
    129		cur &= ~CRVML_LVDS_ON;
    130		outl(cur, addr);
    131	}
    132	if (cur & CRVML_PANEL_ON) {
    133		schedule_timeout(HZ / 10);
    134		outl(cur & ~CRVML_PANEL_ON, addr);
    135	}
    136}
    137
    138static int cr_lcd_set_power(struct lcd_device *ld, int power)
    139{
    140	if (power == FB_BLANK_UNBLANK)
    141		cr_panel_on();
    142	if (power == FB_BLANK_POWERDOWN)
    143		cr_panel_off();
    144
    145	return 0;
    146}
    147
    148static struct lcd_ops cr_lcd_ops = {
    149	.set_power = cr_lcd_set_power,
    150};
    151
    152static int cr_backlight_probe(struct platform_device *pdev)
    153{
    154	struct backlight_properties props;
    155	struct backlight_device *bdp;
    156	struct lcd_device *ldp;
    157	struct cr_panel *crp;
    158	u8 dev_en;
    159
    160	lpc_dev = pci_get_device(PCI_VENDOR_ID_INTEL,
    161					CRVML_DEVICE_LPC, NULL);
    162	if (!lpc_dev) {
    163		pr_err("INTEL CARILLO RANCH LPC not found.\n");
    164		return -ENODEV;
    165	}
    166
    167	pci_read_config_byte(lpc_dev, CRVML_REG_GPIOEN, &dev_en);
    168	if (!(dev_en & CRVML_GPIOEN_BIT)) {
    169		pr_err("Carillo Ranch GPIO device was not enabled.\n");
    170		pci_dev_put(lpc_dev);
    171		return -ENODEV;
    172	}
    173
    174	memset(&props, 0, sizeof(struct backlight_properties));
    175	props.type = BACKLIGHT_RAW;
    176	bdp = devm_backlight_device_register(&pdev->dev, "cr-backlight",
    177					&pdev->dev, NULL, &cr_backlight_ops,
    178					&props);
    179	if (IS_ERR(bdp)) {
    180		pci_dev_put(lpc_dev);
    181		return PTR_ERR(bdp);
    182	}
    183
    184	ldp = devm_lcd_device_register(&pdev->dev, "cr-lcd", &pdev->dev, NULL,
    185					&cr_lcd_ops);
    186	if (IS_ERR(ldp)) {
    187		pci_dev_put(lpc_dev);
    188		return PTR_ERR(ldp);
    189	}
    190
    191	pci_read_config_dword(lpc_dev, CRVML_REG_GPIOBAR,
    192			      &gpio_bar);
    193	gpio_bar &= ~0x3F;
    194
    195	crp = devm_kzalloc(&pdev->dev, sizeof(*crp), GFP_KERNEL);
    196	if (!crp) {
    197		pci_dev_put(lpc_dev);
    198		return -ENOMEM;
    199	}
    200
    201	crp->cr_backlight_device = bdp;
    202	crp->cr_lcd_device = ldp;
    203	crp->cr_backlight_device->props.power = FB_BLANK_UNBLANK;
    204	crp->cr_backlight_device->props.brightness = 0;
    205	cr_backlight_set_intensity(crp->cr_backlight_device);
    206	cr_lcd_set_power(crp->cr_lcd_device, FB_BLANK_UNBLANK);
    207
    208	platform_set_drvdata(pdev, crp);
    209
    210	return 0;
    211}
    212
    213static int cr_backlight_remove(struct platform_device *pdev)
    214{
    215	struct cr_panel *crp = platform_get_drvdata(pdev);
    216
    217	crp->cr_backlight_device->props.power = FB_BLANK_POWERDOWN;
    218	crp->cr_backlight_device->props.brightness = 0;
    219	crp->cr_backlight_device->props.max_brightness = 0;
    220	cr_backlight_set_intensity(crp->cr_backlight_device);
    221	cr_lcd_set_power(crp->cr_lcd_device, FB_BLANK_POWERDOWN);
    222	pci_dev_put(lpc_dev);
    223
    224	return 0;
    225}
    226
    227static struct platform_driver cr_backlight_driver = {
    228	.probe = cr_backlight_probe,
    229	.remove = cr_backlight_remove,
    230	.driver = {
    231		   .name = "cr_backlight",
    232		   },
    233};
    234
    235static struct platform_device *crp;
    236
    237static int __init cr_backlight_init(void)
    238{
    239	int ret = platform_driver_register(&cr_backlight_driver);
    240
    241	if (ret)
    242		return ret;
    243
    244	crp = platform_device_register_simple("cr_backlight", -1, NULL, 0);
    245	if (IS_ERR(crp)) {
    246		platform_driver_unregister(&cr_backlight_driver);
    247		return PTR_ERR(crp);
    248	}
    249
    250	pr_info("Carillo Ranch Backlight Driver Initialized.\n");
    251
    252	return 0;
    253}
    254
    255static void __exit cr_backlight_exit(void)
    256{
    257	platform_device_unregister(crp);
    258	platform_driver_unregister(&cr_backlight_driver);
    259}
    260
    261module_init(cr_backlight_init);
    262module_exit(cr_backlight_exit);
    263
    264MODULE_AUTHOR("Tungsten Graphics Inc.");
    265MODULE_DESCRIPTION("Carillo Ranch Backlight Driver");
    266MODULE_LICENSE("GPL");