diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/subdev/gpio/nv10.c')
| -rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/gpio/nv10.c | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/nv10.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/nv10.c new file mode 100644 index 000000000000..27ad23eaf185 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/nv10.c | |||
| @@ -0,0 +1,116 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2009 Francisco Jerez. | ||
| 3 | * All Rights Reserved. | ||
| 4 | * | ||
| 5 | * Permission is hereby granted, free of charge, to any person obtaining | ||
| 6 | * a copy of this software and associated documentation files (the | ||
| 7 | * "Software"), to deal in the Software without restriction, including | ||
| 8 | * without limitation the rights to use, copy, modify, merge, publish, | ||
| 9 | * distribute, sublicense, and/or sell copies of the Software, and to | ||
| 10 | * permit persons to whom the Software is furnished to do so, subject to | ||
| 11 | * the following conditions: | ||
| 12 | * | ||
| 13 | * The above copyright notice and this permission notice (including the | ||
| 14 | * next paragraph) shall be included in all copies or substantial | ||
| 15 | * portions of the Software. | ||
| 16 | * | ||
| 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
| 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
| 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||
| 20 | * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE | ||
| 21 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | ||
| 22 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | ||
| 23 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 24 | * | ||
| 25 | */ | ||
| 26 | |||
| 27 | #include "priv.h" | ||
| 28 | |||
| 29 | static int | ||
| 30 | nv10_gpio_sense(struct nouveau_gpio *gpio, int line) | ||
| 31 | { | ||
| 32 | if (line < 2) { | ||
| 33 | line = line * 16; | ||
| 34 | line = nv_rd32(gpio, 0x600818) >> line; | ||
| 35 | return !!(line & 0x0100); | ||
| 36 | } else | ||
| 37 | if (line < 10) { | ||
| 38 | line = (line - 2) * 4; | ||
| 39 | line = nv_rd32(gpio, 0x60081c) >> line; | ||
| 40 | return !!(line & 0x04); | ||
| 41 | } else | ||
| 42 | if (line < 14) { | ||
| 43 | line = (line - 10) * 4; | ||
| 44 | line = nv_rd32(gpio, 0x600850) >> line; | ||
| 45 | return !!(line & 0x04); | ||
| 46 | } | ||
| 47 | |||
| 48 | return -EINVAL; | ||
| 49 | } | ||
| 50 | |||
| 51 | static int | ||
| 52 | nv10_gpio_drive(struct nouveau_gpio *gpio, int line, int dir, int out) | ||
| 53 | { | ||
| 54 | u32 reg, mask, data; | ||
| 55 | |||
| 56 | if (line < 2) { | ||
| 57 | line = line * 16; | ||
| 58 | reg = 0x600818; | ||
| 59 | mask = 0x00000011; | ||
| 60 | data = (dir << 4) | out; | ||
| 61 | } else | ||
| 62 | if (line < 10) { | ||
| 63 | line = (line - 2) * 4; | ||
| 64 | reg = 0x60081c; | ||
| 65 | mask = 0x00000003; | ||
| 66 | data = (dir << 1) | out; | ||
| 67 | } else | ||
| 68 | if (line < 14) { | ||
| 69 | line = (line - 10) * 4; | ||
| 70 | reg = 0x600850; | ||
| 71 | mask = 0x00000003; | ||
| 72 | data = (dir << 1) | out; | ||
| 73 | } else { | ||
| 74 | return -EINVAL; | ||
| 75 | } | ||
| 76 | |||
| 77 | nv_mask(gpio, reg, mask << line, data << line); | ||
| 78 | return 0; | ||
| 79 | } | ||
| 80 | |||
| 81 | static void | ||
| 82 | nv10_gpio_intr_stat(struct nouveau_gpio *gpio, u32 *hi, u32 *lo) | ||
| 83 | { | ||
| 84 | u32 intr = nv_rd32(gpio, 0x001104); | ||
| 85 | u32 stat = nv_rd32(gpio, 0x001144) & intr; | ||
| 86 | *lo = (stat & 0xffff0000) >> 16; | ||
| 87 | *hi = (stat & 0x0000ffff); | ||
| 88 | nv_wr32(gpio, 0x001104, intr); | ||
| 89 | } | ||
| 90 | |||
| 91 | static void | ||
| 92 | nv10_gpio_intr_mask(struct nouveau_gpio *gpio, u32 type, u32 mask, u32 data) | ||
| 93 | { | ||
| 94 | u32 inte = nv_rd32(gpio, 0x001144); | ||
| 95 | if (type & NVKM_GPIO_LO) | ||
| 96 | inte = (inte & ~(mask << 16)) | (data << 16); | ||
| 97 | if (type & NVKM_GPIO_HI) | ||
| 98 | inte = (inte & ~mask) | data; | ||
| 99 | nv_wr32(gpio, 0x001144, inte); | ||
| 100 | } | ||
| 101 | |||
| 102 | struct nouveau_oclass * | ||
| 103 | nv10_gpio_oclass = &(struct nouveau_gpio_impl) { | ||
| 104 | .base.handle = NV_SUBDEV(GPIO, 0x10), | ||
| 105 | .base.ofuncs = &(struct nouveau_ofuncs) { | ||
| 106 | .ctor = _nouveau_gpio_ctor, | ||
| 107 | .dtor = _nouveau_gpio_dtor, | ||
| 108 | .init = _nouveau_gpio_init, | ||
| 109 | .fini = _nouveau_gpio_fini, | ||
| 110 | }, | ||
| 111 | .lines = 16, | ||
| 112 | .intr_stat = nv10_gpio_intr_stat, | ||
| 113 | .intr_mask = nv10_gpio_intr_mask, | ||
| 114 | .drive = nv10_gpio_drive, | ||
| 115 | .sense = nv10_gpio_sense, | ||
| 116 | }.base; | ||
