123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209 |
- /*
- * Copyright (c) Intel Corp. 2007.
- * All Rights Reserved.
- *
- * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
- * develop this driver.
- *
- * This file is part of the Carillo Ranch video subsystem driver.
- * The Carillo Ranch video subsystem driver is free software;
- * you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * The Carillo Ranch video subsystem driver is distributed
- * in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this driver; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Authors:
- * Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
- * Alan Hourihane <alanh-at-tungstengraphics-dot-com>
- */
- #include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/pci.h>
- #include <linux/errno.h>
- #include <linux/fb.h>
- #include "vermilion.h"
- /* The PLL Clock register sits on Host bridge */
- #define CRVML_DEVICE_MCH 0x5001
- #define CRVML_REG_MCHBAR 0x44
- #define CRVML_REG_MCHEN 0x54
- #define CRVML_MCHEN_BIT (1 << 28)
- #define CRVML_MCHMAP_SIZE 4096
- #define CRVML_REG_CLOCK 0xc3c
- #define CRVML_CLOCK_SHIFT 8
- #define CRVML_CLOCK_MASK 0x00000f00
- static struct pci_dev *mch_dev;
- static u32 mch_bar;
- static void __iomem *mch_regs_base;
- static u32 saved_clock;
- static const unsigned crvml_clocks[] = {
- 6750,
- 13500,
- 27000,
- 29700,
- 37125,
- 54000,
- 59400,
- 74250,
- 120000
- /*
- * There are more clocks, but they are disabled on the CR board.
- */
- };
- static const u32 crvml_clock_bits[] = {
- 0x0a,
- 0x09,
- 0x08,
- 0x07,
- 0x06,
- 0x05,
- 0x04,
- 0x03,
- 0x0b
- };
- static const unsigned crvml_num_clocks = ARRAY_SIZE(crvml_clocks);
- static int crvml_sys_restore(struct vml_sys *sys)
- {
- void __iomem *clock_reg = mch_regs_base + CRVML_REG_CLOCK;
- iowrite32(saved_clock, clock_reg);
- ioread32(clock_reg);
- return 0;
- }
- static int crvml_sys_save(struct vml_sys *sys)
- {
- void __iomem *clock_reg = mch_regs_base + CRVML_REG_CLOCK;
- saved_clock = ioread32(clock_reg);
- return 0;
- }
- static int crvml_nearest_index(const struct vml_sys *sys, int clock)
- {
- int i;
- int cur_index = 0;
- int cur_diff;
- int diff;
- cur_diff = clock - crvml_clocks[0];
- cur_diff = (cur_diff < 0) ? -cur_diff : cur_diff;
- for (i = 1; i < crvml_num_clocks; ++i) {
- diff = clock - crvml_clocks[i];
- diff = (diff < 0) ? -diff : diff;
- if (diff < cur_diff) {
- cur_index = i;
- cur_diff = diff;
- }
- }
- return cur_index;
- }
- static int crvml_nearest_clock(const struct vml_sys *sys, int clock)
- {
- return crvml_clocks[crvml_nearest_index(sys, clock)];
- }
- static int crvml_set_clock(struct vml_sys *sys, int clock)
- {
- void __iomem *clock_reg = mch_regs_base + CRVML_REG_CLOCK;
- int index;
- u32 clock_val;
- index = crvml_nearest_index(sys, clock);
- if (crvml_clocks[index] != clock)
- return -EINVAL;
- clock_val = ioread32(clock_reg) & ~CRVML_CLOCK_MASK;
- clock_val = crvml_clock_bits[index] << CRVML_CLOCK_SHIFT;
- iowrite32(clock_val, clock_reg);
- ioread32(clock_reg);
- return 0;
- }
- static struct vml_sys cr_pll_ops = {
- .name = "Carillo Ranch",
- .save = crvml_sys_save,
- .restore = crvml_sys_restore,
- .set_clock = crvml_set_clock,
- .nearest_clock = crvml_nearest_clock,
- };
- static int __init cr_pll_init(void)
- {
- int err;
- u32 dev_en;
- mch_dev = pci_get_device(PCI_VENDOR_ID_INTEL,
- CRVML_DEVICE_MCH, NULL);
- if (!mch_dev) {
- printk(KERN_ERR
- "Could not find Carillo Ranch MCH device.\n");
- return -ENODEV;
- }
- pci_read_config_dword(mch_dev, CRVML_REG_MCHEN, &dev_en);
- if (!(dev_en & CRVML_MCHEN_BIT)) {
- printk(KERN_ERR
- "Carillo Ranch MCH device was not enabled.\n");
- pci_dev_put(mch_dev);
- return -ENODEV;
- }
- pci_read_config_dword(mch_dev, CRVML_REG_MCHBAR,
- &mch_bar);
- mch_regs_base =
- ioremap_nocache(mch_bar, CRVML_MCHMAP_SIZE);
- if (!mch_regs_base) {
- printk(KERN_ERR
- "Carillo Ranch MCH device was not enabled.\n");
- pci_dev_put(mch_dev);
- return -ENODEV;
- }
- err = vmlfb_register_subsys(&cr_pll_ops);
- if (err) {
- printk(KERN_ERR
- "Carillo Ranch failed to initialize vml_sys.\n");
- pci_dev_put(mch_dev);
- return err;
- }
- return 0;
- }
- static void __exit cr_pll_exit(void)
- {
- vmlfb_unregister_subsys(&cr_pll_ops);
- iounmap(mch_regs_base);
- pci_dev_put(mch_dev);
- }
- module_init(cr_pll_init);
- module_exit(cr_pll_exit);
- MODULE_AUTHOR("Tungsten Graphics Inc.");
- MODULE_DESCRIPTION("Carillo Ranch PLL Driver");
- MODULE_LICENSE("GPL");
|