Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /*
  2  * AMD Geode southbridge support code
  3  * Copyright (C) 2006, Advanced Micro Devices, Inc.
  4  * Copyright (C) 2007, Andres Salomon <dilinger@debian.org>
  5  *
  6  * This program is free software; you can redistribute it and/or
  7  * modify it under the terms of version 2 of the GNU General Public License
  8  * as published by the Free Software Foundation.
  9  */
 10 
 11 #include <linux/kernel.h>
 12 #include <linux/module.h>
 13 #include <linux/ioport.h>
 14 #include <linux/io.h>
 15 #include <asm/msr.h>
 16 #include <asm/geode.h>
 17 
 18 static struct {
 19         char *name;
 20         u32 msr;
 21         int size;
 22         u32 base;
 23 } lbars[] = {
 24         { "geode-pms",   MSR_LBAR_PMS, LBAR_PMS_SIZE, 0 },
 25         { "geode-acpi",  MSR_LBAR_ACPI, LBAR_ACPI_SIZE, 0 },
 26         { "geode-gpio",  MSR_LBAR_GPIO, LBAR_GPIO_SIZE, 0 },
 27         { "geode-mfgpt", MSR_LBAR_MFGPT, LBAR_MFGPT_SIZE, 0 }
 28 };
 29 
 30 static void __init init_lbars(void)
 31 {
 32         u32 lo, hi;
 33         int i;
 34 
 35         for (i = 0; i < ARRAY_SIZE(lbars); i++) {
 36                 rdmsr(lbars[i].msr, lo, hi);
 37                 if (hi & 0x01)
 38                         lbars[i].base = lo & 0x0000ffff;
 39 
 40                 if (lbars[i].base == 0)
 41                         printk(KERN_ERR "geode:  Couldn't initialize '%s'\n",
 42                                         lbars[i].name);
 43         }
 44 }
 45 
 46 int geode_get_dev_base(unsigned int dev)
 47 {
 48         BUG_ON(dev >= ARRAY_SIZE(lbars));
 49         return lbars[dev].base;
 50 }
 51 EXPORT_SYMBOL_GPL(geode_get_dev_base);
 52 
 53 /* === GPIO API === */
 54 
 55 void geode_gpio_set(u32 gpio, unsigned int reg)
 56 {
 57         u32 base = geode_get_dev_base(GEODE_DEV_GPIO);
 58 
 59         if (!base)
 60                 return;
 61 
 62         /* low bank register */
 63         if (gpio & 0xFFFF)
 64                 outl(gpio & 0xFFFF, base + reg);
 65         /* high bank register */
 66         gpio >>= 16;
 67         if (gpio)
 68                 outl(gpio, base + 0x80 + reg);
 69 }
 70 EXPORT_SYMBOL_GPL(geode_gpio_set);
 71 
 72 void geode_gpio_clear(u32 gpio, unsigned int reg)
 73 {
 74         u32 base = geode_get_dev_base(GEODE_DEV_GPIO);
 75 
 76         if (!base)
 77                 return;
 78 
 79         /* low bank register */
 80         if (gpio & 0xFFFF)
 81                 outl((gpio & 0xFFFF) << 16, base + reg);
 82         /* high bank register */
 83         gpio &= (0xFFFF << 16);
 84         if (gpio)
 85                 outl(gpio, base + 0x80 + reg);
 86 }
 87 EXPORT_SYMBOL_GPL(geode_gpio_clear);
 88 
 89 int geode_gpio_isset(u32 gpio, unsigned int reg)
 90 {
 91         u32 base = geode_get_dev_base(GEODE_DEV_GPIO);
 92         u32 val;
 93 
 94         if (!base)
 95                 return 0;
 96 
 97         /* low bank register */
 98         if (gpio & 0xFFFF) {
 99                 val = inl(base + reg) & (gpio & 0xFFFF);
100                 if ((gpio & 0xFFFF) == val)
101                         return 1;
102         }
103         /* high bank register */
104         gpio >>= 16;
105         if (gpio) {
106                 val = inl(base + 0x80 + reg) & gpio;
107                 if (gpio == val)
108                         return 1;
109         }
110         return 0;
111 }
112 EXPORT_SYMBOL_GPL(geode_gpio_isset);
113 
114 void geode_gpio_set_irq(unsigned int group, unsigned int irq)
115 {
116         u32 lo, hi;
117 
118         if (group > 7 || irq > 15)
119                 return;
120 
121         rdmsr(MSR_PIC_ZSEL_HIGH, lo, hi);
122 
123         lo &= ~(0xF << (group * 4));
124         lo |= (irq & 0xF) << (group * 4);
125 
126         wrmsr(MSR_PIC_ZSEL_HIGH, lo, hi);
127 }
128 EXPORT_SYMBOL_GPL(geode_gpio_set_irq);
129 
130 void geode_gpio_setup_event(unsigned int gpio, int pair, int pme)
131 {
132         u32 base = geode_get_dev_base(GEODE_DEV_GPIO);
133         u32 offset, shift, val;
134 
135         if (gpio >= 24)
136                 offset = GPIO_MAP_W;
137         else if (gpio >= 16)
138                 offset = GPIO_MAP_Z;
139         else if (gpio >= 8)
140                 offset = GPIO_MAP_Y;
141         else
142                 offset = GPIO_MAP_X;
143 
144         shift = (gpio % 8) * 4;
145 
146         val = inl(base + offset);
147 
148         /* Clear whatever was there before */
149         val &= ~(0xF << shift);
150 
151         /* And set the new value */
152 
153         val |= ((pair & 7) << shift);
154 
155         /* Set the PME bit if this is a PME event */
156 
157         if (pme)
158                 val |= (1 << (shift + 3));
159 
160         outl(val, base + offset);
161 }
162 EXPORT_SYMBOL_GPL(geode_gpio_setup_event);
163 
164 static int __init geode_southbridge_init(void)
165 {
166         if (!is_geode())
167                 return -ENODEV;
168 
169         init_lbars();
170         (void) mfgpt_timer_setup();
171         return 0;
172 }
173 
174 postcore_initcall(geode_southbridge_init);
175 
  This page was automatically generated by the LXR engine.